Passed
Push — master ( e95921...ddbd1b )
by Dimas
13:28 queued 05:15
created

assets/mdb-dashboard/js/modules/addons/datatables.js   F

Complexity

Total Complexity 1444
Complexity/F 3.01

Size

Lines of Code 15456
Function Count 479

Duplication

Duplicated Lines 15456
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 4909
dl 15456
loc 15456
rs 0.8
c 0
b 0
f 0
wmc 1444
mnd 965
bc 965
fnc 479
bpm 2.0146
cpm 3.0146
noi 92

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 assets/mdb-dashboard/js/modules/addons/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
/*
2
 * MDBootstrap integration with Datatables
3
 * Learn more: https://mdbootstrap.com/docs/jquery/tables/datatables/
4
 * About MDBootstrap: https://mdbootstrap.com/
5
 *
6
 * This combined file was created by the DataTables downloader builder:
7
 *   https://datatables.net/download
8
 *
9
 * To rebuild or modify this file with the latest versions of the included
10
 * software please visit:
11
 *   https://datatables.net/download/#bs4/dt-1.10.18
12
 *
13
 * Included libraries:
14
 *   DataTables 1.10.18
15
 */
16
17
/*! DataTables 1.10.18
18
 * ©2008-2018 SpryMedia Ltd - datatables.net/license
19
 */
20
21
/**
22
 * @summary     DataTables
23
 * @description Paginate, search and order HTML tables
24
 * @version     1.10.18
25
 * @file        jquery.dataTables.js
26
 * @author      SpryMedia Ltd
27
 * @contact     www.datatables.net
28
 * @copyright   Copyright 2008-2018 SpryMedia Ltd.
29
 *
30
 * This source file is free software, available under the following license:
31
 *   MIT license - http://datatables.net/license
32
 *
33
 * This source file is distributed in the hope that it will be useful, but
34
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
35
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
36
 *
37
 * For details please refer to: http://www.datatables.net
38
 */
39
40
/*jslint evil: true, undef: true, browser: true */
41
/*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*/
42
43
(function( factory ) {
44
	"use strict";
45
46
	if ( typeof define === 'function' && define.amd ) {
47
		// AMD
48
		define( ['jquery'], function ( $ ) {
49
			return factory( $, window, document );
50
		} );
51
	}
52
	else if ( typeof exports === 'object' ) {
53
		// CommonJS
54
		module.exports = function (root, $) {
55
			if ( ! root ) {
56
				// CommonJS environments without a window global must pass a
57
				// root. This will give an error otherwise
58
				root = window;
59
			}
60
61
			if ( ! $ ) {
62
				$ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
63
					require('jquery') :
64
					require('jquery')( root );
65
			}
66
67
			return factory( $, root, root.document );
68
		};
69
	}
70
	else {
71
		// Browser
72
		factory( jQuery, window, document );
73
	}
74
}
75
(function( $, window, document, undefined ) {
76
	"use strict";
77
78
	/**
79
	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
80
	 * flexible tool, based upon the foundations of progressive enhancement,
81
	 * which will add advanced interaction controls to any HTML table. For a
82
	 * full list of features please refer to
83
	 * [DataTables.net](href="http://datatables.net).
84
	 *
85
	 * Note that the `DataTable` object is not a global variable but is aliased
86
	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
87
	 * be  accessed.
88
	 *
89
	 *  @class
90
	 *  @param {object} [init={}] Configuration object for DataTables. Options
91
	 *    are defined by {@link DataTable.defaults}
92
	 *  @requires jQuery 1.7+
93
	 *
94
	 *  @example
95
	 *    // Basic initialisation
96
	 *    $(document).ready( function {
97
	 *      $('#example').dataTable();
98
	 *    } );
99
	 *
100
	 *  @example
101
	 *    // Initialisation with configuration options - in this case, disable
102
	 *    // pagination and sorting.
103
	 *    $(document).ready( function {
104
	 *      $('#example').dataTable( {
105
	 *        "paginate": false,
106
	 *        "sort": false
107
	 *      } );
108
	 *    } );
109
	 */
110
	var DataTable = function ( options )
111
	{
112
		/**
113
		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
114
		 * return the resulting jQuery object.
115
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
116
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
117
		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
118
		 *    criterion ("applied") or all TR elements (i.e. no filter).
119
		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
120
		 *    Can be either 'current', whereby the current sorting of the table is used, or
121
		 *    'original' whereby the original order the data was read into the table is used.
122
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
123
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
124
		 *    'current' and filter is 'applied', regardless of what they might be given as.
125
		 *  @returns {object} jQuery object, filtered by the given selector.
126
		 *  @dtopt API
127
		 *  @deprecated Since v1.10
128
		 *
129
		 *  @example
130
		 *    $(document).ready(function() {
131
		 *      var oTable = $('#example').dataTable();
132
		 *
133
		 *      // Highlight every second row
134
		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
135
		 *    } );
136
		 *
137
		 *  @example
138
		 *    $(document).ready(function() {
139
		 *      var oTable = $('#example').dataTable();
140
		 *
141
		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
142
		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
143
		 *      oTable.fnFilter('Webkit');
144
		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
145
		 *      oTable.fnFilter('');
146
		 *    } );
147
		 */
148
		this.$ = function ( sSelector, oOpts )
149
		{
150
			return this.api(true).$( sSelector, oOpts );
151
		};
152
		
153
		
154
		/**
155
		 * Almost identical to $ in operation, but in this case returns the data for the matched
156
		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
157
		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
158
		 * rows are found, the data returned is the original data array/object that was used to
159
		 * create the row (or a generated array if from a DOM source).
160
		 *
161
		 * This method is often useful in-combination with $ where both functions are given the
162
		 * same parameters and the array indexes will match identically.
163
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
164
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
165
		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
166
		 *    criterion ("applied") or all elements (i.e. no filter).
167
		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
168
		 *    Can be either 'current', whereby the current sorting of the table is used, or
169
		 *    'original' whereby the original order the data was read into the table is used.
170
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
171
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
172
		 *    'current' and filter is 'applied', regardless of what they might be given as.
173
		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
174
		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
175
		 *    entry in the array.
176
		 *  @dtopt API
177
		 *  @deprecated Since v1.10
178
		 *
179
		 *  @example
180
		 *    $(document).ready(function() {
181
		 *      var oTable = $('#example').dataTable();
182
		 *
183
		 *      // Get the data from the first row in the table
184
		 *      var data = oTable._('tr:first');
185
		 *
186
		 *      // Do something useful with the data
187
		 *      alert( "First cell is: "+data[0] );
188
		 *    } );
189
		 *
190
		 *  @example
191
		 *    $(document).ready(function() {
192
		 *      var oTable = $('#example').dataTable();
193
		 *
194
		 *      // Filter to 'Webkit' and get all data for
195
		 *      oTable.fnFilter('Webkit');
196
		 *      var data = oTable._('tr', {"search": "applied"});
197
		 *
198
		 *      // Do something with the data
199
		 *      alert( data.length+" rows matched the search" );
200
		 *    } );
201
		 */
202
		this._ = function ( sSelector, oOpts )
203
		{
204
			return this.api(true).rows( sSelector, oOpts ).data();
205
		};
206
		
207
		
208
		/**
209
		 * Create a DataTables Api instance, with the currently selected tables for
210
		 * the Api's context.
211
		 * @param {boolean} [traditional=false] Set the API instance's context to be
212
		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
213
		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
214
		 *   or if all tables captured in the jQuery object should be used.
215
		 * @return {DataTables.Api}
216
		 */
217
		this.api = function ( traditional )
218
		{
219
			return traditional ?
220
				new _Api(
221
					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
222
				) :
223
				new _Api( this );
224
		};
225
		
226
		
227
		/**
228
		 * Add a single new row or multiple rows of data to the table. Please note
229
		 * that this is suitable for client-side processing only - if you are using
230
		 * server-side processing (i.e. "bServerSide": true), then to add data, you
231
		 * must add it to the data source, i.e. the server-side, through an Ajax call.
232
		 *  @param {array|object} data The data to be added to the table. This can be:
233
		 *    <ul>
234
		 *      <li>1D array of data - add a single row with the data provided</li>
235
		 *      <li>2D array of arrays - add multiple rows in a single call</li>
236
		 *      <li>object - data object when using <i>mData</i></li>
237
		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
238
		 *    </ul>
239
		 *  @param {bool} [redraw=true] redraw the table or not
240
		 *  @returns {array} An array of integers, representing the list of indexes in
241
		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
242
		 *    the table.
243
		 *  @dtopt API
244
		 *  @deprecated Since v1.10
245
		 *
246
		 *  @example
247
		 *    // Global var for counter
248
		 *    var giCount = 2;
249
		 *
250
		 *    $(document).ready(function() {
251
		 *      $('#example').dataTable();
252
		 *    } );
253
		 *
254
		 *    function fnClickAddRow() {
255
		 *      $('#example').dataTable().fnAddData( [
256
		 *        giCount+".1",
257
		 *        giCount+".2",
258
		 *        giCount+".3",
259
		 *        giCount+".4" ]
260
		 *      );
261
		 *
262
		 *      giCount++;
263
		 *    }
264
		 */
265
		this.fnAddData = function( data, redraw )
266
		{
267
			var api = this.api( true );
268
		
269
			/* Check if we want to add multiple rows or not */
270
			var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
271
				api.rows.add( data ) :
272
				api.row.add( data );
273
		
274
			if ( redraw === undefined || redraw ) {
275
				api.draw();
276
			}
277
		
278
			return rows.flatten().toArray();
279
		};
280
		
281
		
282
		/**
283
		 * This function will make DataTables recalculate the column sizes, based on the data
284
		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
285
		 * through the sWidth parameter). This can be useful when the width of the table's
286
		 * parent element changes (for example a window resize).
287
		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
288
		 *  @dtopt API
289
		 *  @deprecated Since v1.10
290
		 *
291
		 *  @example
292
		 *    $(document).ready(function() {
293
		 *      var oTable = $('#example').dataTable( {
294
		 *        "sScrollY": "200px",
295
		 *        "bPaginate": false
296
		 *      } );
297
		 *
298
		 *      $(window).on('resize', function () {
299
		 *        oTable.fnAdjustColumnSizing();
300
		 *      } );
301
		 *    } );
302
		 */
303
		this.fnAdjustColumnSizing = function ( bRedraw )
304
		{
305
			var api = this.api( true ).columns.adjust();
306
			var settings = api.settings()[0];
307
			var scroll = settings.oScroll;
308
		
309
			if ( bRedraw === undefined || bRedraw ) {
310
				api.draw( false );
311
			}
312
			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
313
				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
314
				_fnScrollDraw( settings );
315
			}
316
		};
317
		
318
		
319
		/**
320
		 * Quickly and simply clear a table
321
		 *  @param {bool} [bRedraw=true] redraw the table or not
322
		 *  @dtopt API
323
		 *  @deprecated Since v1.10
324
		 *
325
		 *  @example
326
		 *    $(document).ready(function() {
327
		 *      var oTable = $('#example').dataTable();
328
		 *
329
		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
330
		 *      oTable.fnClearTable();
331
		 *    } );
332
		 */
333
		this.fnClearTable = function( bRedraw )
334
		{
335
			var api = this.api( true ).clear();
336
		
337
			if ( bRedraw === undefined || bRedraw ) {
338
				api.draw();
339
			}
340
		};
341
		
342
		
343
		/**
344
		 * The exact opposite of 'opening' a row, this function will close any rows which
345
		 * are currently 'open'.
346
		 *  @param {node} nTr the table row to 'close'
347
		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
348
		 *  @dtopt API
349
		 *  @deprecated Since v1.10
350
		 *
351
		 *  @example
352
		 *    $(document).ready(function() {
353
		 *      var oTable;
354
		 *
355
		 *      // 'open' an information row when a row is clicked on
356
		 *      $('#example tbody tr').click( function () {
357
		 *        if ( oTable.fnIsOpen(this) ) {
358
		 *          oTable.fnClose( this );
359
		 *        } else {
360
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
361
		 *        }
362
		 *      } );
363
		 *
364
		 *      oTable = $('#example').dataTable();
365
		 *    } );
366
		 */
367
		this.fnClose = function( nTr )
368
		{
369
			this.api( true ).row( nTr ).child.hide();
370
		};
371
		
372
		
373
		/**
374
		 * Remove a row for the table
375
		 *  @param {mixed} target The index of the row from aoData to be deleted, or
376
		 *    the TR element you want to delete
377
		 *  @param {function|null} [callBack] Callback function
378
		 *  @param {bool} [redraw=true] Redraw the table or not
379
		 *  @returns {array} The row that was deleted
380
		 *  @dtopt API
381
		 *  @deprecated Since v1.10
382
		 *
383
		 *  @example
384
		 *    $(document).ready(function() {
385
		 *      var oTable = $('#example').dataTable();
386
		 *
387
		 *      // Immediately remove the first row
388
		 *      oTable.fnDeleteRow( 0 );
389
		 *    } );
390
		 */
391
		this.fnDeleteRow = function( target, callback, redraw )
392
		{
393
			var api = this.api( true );
394
			var rows = api.rows( target );
395
			var settings = rows.settings()[0];
396
			var data = settings.aoData[ rows[0][0] ];
397
		
398
			rows.remove();
399
		
400
			if ( callback ) {
401
				callback.call( this, settings, data );
402
			}
403
		
404
			if ( redraw === undefined || redraw ) {
405
				api.draw();
406
			}
407
		
408
			return data;
409
		};
410
		
411
		
412
		/**
413
		 * Restore the table to it's original state in the DOM by removing all of DataTables
414
		 * enhancements, alterations to the DOM structure of the table and event listeners.
415
		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
416
		 *  @dtopt API
417
		 *  @deprecated Since v1.10
418
		 *
419
		 *  @example
420
		 *    $(document).ready(function() {
421
		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
422
		 *      var oTable = $('#example').dataTable();
423
		 *      oTable.fnDestroy();
424
		 *    } );
425
		 */
426
		this.fnDestroy = function ( remove )
427
		{
428
			this.api( true ).destroy( remove );
429
		};
430
		
431
		
432
		/**
433
		 * Redraw the table
434
		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
435
		 *  @dtopt API
436
		 *  @deprecated Since v1.10
437
		 *
438
		 *  @example
439
		 *    $(document).ready(function() {
440
		 *      var oTable = $('#example').dataTable();
441
		 *
442
		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
443
		 *      oTable.fnDraw();
444
		 *    } );
445
		 */
446
		this.fnDraw = function( complete )
447
		{
448
			// Note that this isn't an exact match to the old call to _fnDraw - it takes
449
			// into account the new data, but can hold position.
450
			this.api( true ).draw( complete );
451
		};
452
		
453
		
454
		/**
455
		 * Filter the input based on data
456
		 *  @param {string} sInput String to filter the table on
457
		 *  @param {int|null} [iColumn] Column to limit filtering to
458
		 *  @param {bool} [bRegex=false] Treat as regular expression or not
459
		 *  @param {bool} [bSmart=true] Perform smart filtering or not
460
		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
461
		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
462
		 *  @dtopt API
463
		 *  @deprecated Since v1.10
464
		 *
465
		 *  @example
466
		 *    $(document).ready(function() {
467
		 *      var oTable = $('#example').dataTable();
468
		 *
469
		 *      // Sometime later - filter...
470
		 *      oTable.fnFilter( 'test string' );
471
		 *    } );
472
		 */
473
		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
474
		{
475
			var api = this.api( true );
476
		
477
			if ( iColumn === null || iColumn === undefined ) {
478
				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
479
			}
480
			else {
481
				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
482
			}
483
		
484
			api.draw();
485
		};
486
		
487
		
488
		/**
489
		 * Get the data for the whole table, an individual row or an individual cell based on the
490
		 * provided parameters.
491
		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
492
		 *    a TR node then the data source for the whole row will be returned. If given as a
493
		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
494
		 *    cell returned. If given as an integer, then this is treated as the aoData internal
495
		 *    data index for the row (see fnGetPosition) and the data for that row used.
496
		 *  @param {int} [col] Optional column index that you want the data of.
497
		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
498
		 *    returned. If mRow is defined, just data for that row, and is iCol is
499
		 *    defined, only data for the designated cell is returned.
500
		 *  @dtopt API
501
		 *  @deprecated Since v1.10
502
		 *
503
		 *  @example
504
		 *    // Row data
505
		 *    $(document).ready(function() {
506
		 *      oTable = $('#example').dataTable();
507
		 *
508
		 *      oTable.$('tr').click( function () {
509
		 *        var data = oTable.fnGetData( this );
510
		 *        // ... do something with the array / object of data for the row
511
		 *      } );
512
		 *    } );
513
		 *
514
		 *  @example
515
		 *    // Individual cell data
516
		 *    $(document).ready(function() {
517
		 *      oTable = $('#example').dataTable();
518
		 *
519
		 *      oTable.$('td').click( function () {
520
		 *        var sData = oTable.fnGetData( this );
521
		 *        alert( 'The cell clicked on had the value of '+sData );
522
		 *      } );
523
		 *    } );
524
		 */
525
		this.fnGetData = function( src, col )
526
		{
527
			var api = this.api( true );
528
		
529
			if ( src !== undefined ) {
530
				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
531
		
532
				return col !== undefined || type == 'td' || type == 'th' ?
533
					api.cell( src, col ).data() :
534
					api.row( src ).data() || null;
535
			}
536
		
537
			return api.data().toArray();
538
		};
539
		
540
		
541
		/**
542
		 * Get an array of the TR nodes that are used in the table's body. Note that you will
543
		 * typically want to use the '$' API method in preference to this as it is more
544
		 * flexible.
545
		 *  @param {int} [iRow] Optional row index for the TR element you want
546
		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
547
		 *    in the table's body, or iRow is defined, just the TR element requested.
548
		 *  @dtopt API
549
		 *  @deprecated Since v1.10
550
		 *
551
		 *  @example
552
		 *    $(document).ready(function() {
553
		 *      var oTable = $('#example').dataTable();
554
		 *
555
		 *      // Get the nodes from the table
556
		 *      var nNodes = oTable.fnGetNodes( );
557
		 *    } );
558
		 */
559
		this.fnGetNodes = function( iRow )
560
		{
561
			var api = this.api( true );
562
		
563
			return iRow !== undefined ?
564
				api.row( iRow ).node() :
565
				api.rows().nodes().flatten().toArray();
566
		};
567
		
568
		
569
		/**
570
		 * Get the array indexes of a particular cell from it's DOM element
571
		 * and column index including hidden columns
572
		 *  @param {node} node this can either be a TR, TD or TH in the table's body
573
		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
574
		 *    if given as a cell, an array of [row index, column index (visible),
575
		 *    column index (all)] is given.
576
		 *  @dtopt API
577
		 *  @deprecated Since v1.10
578
		 *
579
		 *  @example
580
		 *    $(document).ready(function() {
581
		 *      $('#example tbody td').click( function () {
582
		 *        // Get the position of the current data from the node
583
		 *        var aPos = oTable.fnGetPosition( this );
584
		 *
585
		 *        // Get the data array for this row
586
		 *        var aData = oTable.fnGetData( aPos[0] );
587
		 *
588
		 *        // Update the data array and return the value
589
		 *        aData[ aPos[1] ] = 'clicked';
590
		 *        this.innerHTML = 'clicked';
591
		 *      } );
592
		 *
593
		 *      // Init DataTables
594
		 *      oTable = $('#example').dataTable();
595
		 *    } );
596
		 */
597
		this.fnGetPosition = function( node )
598
		{
599
			var api = this.api( true );
600
			var nodeName = node.nodeName.toUpperCase();
601
		
602
			if ( nodeName == 'TR' ) {
603
				return api.row( node ).index();
604
			}
605
			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
606
				var cell = api.cell( node ).index();
607
		
608
				return [
609
					cell.row,
610
					cell.columnVisible,
611
					cell.column
612
				];
613
			}
614
			return null;
615
		};
616
		
617
		
618
		/**
619
		 * Check to see if a row is 'open' or not.
620
		 *  @param {node} nTr the table row to check
621
		 *  @returns {boolean} true if the row is currently open, false otherwise
622
		 *  @dtopt API
623
		 *  @deprecated Since v1.10
624
		 *
625
		 *  @example
626
		 *    $(document).ready(function() {
627
		 *      var oTable;
628
		 *
629
		 *      // 'open' an information row when a row is clicked on
630
		 *      $('#example tbody tr').click( function () {
631
		 *        if ( oTable.fnIsOpen(this) ) {
632
		 *          oTable.fnClose( this );
633
		 *        } else {
634
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
635
		 *        }
636
		 *      } );
637
		 *
638
		 *      oTable = $('#example').dataTable();
639
		 *    } );
640
		 */
641
		this.fnIsOpen = function( nTr )
642
		{
643
			return this.api( true ).row( nTr ).child.isShown();
644
		};
645
		
646
		
647
		/**
648
		 * This function will place a new row directly after a row which is currently
649
		 * on display on the page, with the HTML contents that is passed into the
650
		 * function. This can be used, for example, to ask for confirmation that a
651
		 * particular record should be deleted.
652
		 *  @param {node} nTr The table row to 'open'
653
		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
654
		 *  @param {string} sClass Class to give the new TD cell
655
		 *  @returns {node} The row opened. Note that if the table row passed in as the
656
		 *    first parameter, is not found in the table, this method will silently
657
		 *    return.
658
		 *  @dtopt API
659
		 *  @deprecated Since v1.10
660
		 *
661
		 *  @example
662
		 *    $(document).ready(function() {
663
		 *      var oTable;
664
		 *
665
		 *      // 'open' an information row when a row is clicked on
666
		 *      $('#example tbody tr').click( function () {
667
		 *        if ( oTable.fnIsOpen(this) ) {
668
		 *          oTable.fnClose( this );
669
		 *        } else {
670
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
671
		 *        }
672
		 *      } );
673
		 *
674
		 *      oTable = $('#example').dataTable();
675
		 *    } );
676
		 */
677
		this.fnOpen = function( nTr, mHtml, sClass )
678
		{
679
			return this.api( true )
680
				.row( nTr )
681
				.child( mHtml, sClass )
682
				.show()
683
				.child()[0];
684
		};
685
		
686
		
687
		/**
688
		 * Change the pagination - provides the internal logic for pagination in a simple API
689
		 * function. With this function you can have a DataTables table go to the next,
690
		 * previous, first or last pages.
691
		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
692
		 *    or page number to jump to (integer), note that page 0 is the first page.
693
		 *  @param {bool} [bRedraw=true] Redraw the table or not
694
		 *  @dtopt API
695
		 *  @deprecated Since v1.10
696
		 *
697
		 *  @example
698
		 *    $(document).ready(function() {
699
		 *      var oTable = $('#example').dataTable();
700
		 *      oTable.fnPageChange( 'next' );
701
		 *    } );
702
		 */
703
		this.fnPageChange = function ( mAction, bRedraw )
704
		{
705
			var api = this.api( true ).page( mAction );
706
		
707
			if ( bRedraw === undefined || bRedraw ) {
708
				api.draw(false);
709
			}
710
		};
711
		
712
		
713
		/**
714
		 * Show a particular column
715
		 *  @param {int} iCol The column whose display should be changed
716
		 *  @param {bool} bShow Show (true) or hide (false) the column
717
		 *  @param {bool} [bRedraw=true] Redraw the table or not
718
		 *  @dtopt API
719
		 *  @deprecated Since v1.10
720
		 *
721
		 *  @example
722
		 *    $(document).ready(function() {
723
		 *      var oTable = $('#example').dataTable();
724
		 *
725
		 *      // Hide the second column after initialisation
726
		 *      oTable.fnSetColumnVis( 1, false );
727
		 *    } );
728
		 */
729
		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
730
		{
731
			var api = this.api( true ).column( iCol ).visible( bShow );
732
		
733
			if ( bRedraw === undefined || bRedraw ) {
734
				api.columns.adjust().draw();
735
			}
736
		};
737
		
738
		
739
		/**
740
		 * Get the settings for a particular table for external manipulation
741
		 *  @returns {object} DataTables settings object. See
742
		 *    {@link DataTable.models.oSettings}
743
		 *  @dtopt API
744
		 *  @deprecated Since v1.10
745
		 *
746
		 *  @example
747
		 *    $(document).ready(function() {
748
		 *      var oTable = $('#example').dataTable();
749
		 *      var oSettings = oTable.fnSettings();
750
		 *
751
		 *      // Show an example parameter from the settings
752
		 *      alert( oSettings._iDisplayStart );
753
		 *    } );
754
		 */
755
		this.fnSettings = function()
756
		{
757
			return _fnSettingsFromNode( this[_ext.iApiIndex] );
758
		};
759
		
760
		
761
		/**
762
		 * Sort the table by a particular column
763
		 *  @param {int} iCol the data index to sort on. Note that this will not match the
764
		 *    'display index' if you have hidden data entries
765
		 *  @dtopt API
766
		 *  @deprecated Since v1.10
767
		 *
768
		 *  @example
769
		 *    $(document).ready(function() {
770
		 *      var oTable = $('#example').dataTable();
771
		 *
772
		 *      // Sort immediately with columns 0 and 1
773
		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
774
		 *    } );
775
		 */
776
		this.fnSort = function( aaSort )
777
		{
778
			this.api( true ).order( aaSort ).draw();
779
		};
780
		
781
		
782
		/**
783
		 * Attach a sort listener to an element for a given column
784
		 *  @param {node} nNode the element to attach the sort listener to
785
		 *  @param {int} iColumn the column that a click on this node will sort on
786
		 *  @param {function} [fnCallback] callback function when sort is run
787
		 *  @dtopt API
788
		 *  @deprecated Since v1.10
789
		 *
790
		 *  @example
791
		 *    $(document).ready(function() {
792
		 *      var oTable = $('#example').dataTable();
793
		 *
794
		 *      // Sort on column 1, when 'sorter' is clicked on
795
		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
796
		 *    } );
797
		 */
798
		this.fnSortListener = function( nNode, iColumn, fnCallback )
799
		{
800
			this.api( true ).order.listener( nNode, iColumn, fnCallback );
801
		};
802
		
803
		
804
		/**
805
		 * Update a table cell or row - this method will accept either a single value to
806
		 * update the cell with, an array of values with one element for each column or
807
		 * an object in the same format as the original data source. The function is
808
		 * self-referencing in order to make the multi column updates easier.
809
		 *  @param {object|array|string} mData Data to update the cell/row with
810
		 *  @param {node|int} mRow TR element you want to update or the aoData index
811
		 *  @param {int} [iColumn] The column to update, give as null or undefined to
812
		 *    update a whole row.
813
		 *  @param {bool} [bRedraw=true] Redraw the table or not
814
		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
815
		 *  @returns {int} 0 on success, 1 on error
816
		 *  @dtopt API
817
		 *  @deprecated Since v1.10
818
		 *
819
		 *  @example
820
		 *    $(document).ready(function() {
821
		 *      var oTable = $('#example').dataTable();
822
		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
823
		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
824
		 *    } );
825
		 */
826
		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
827
		{
828
			var api = this.api( true );
829
		
830
			if ( iColumn === undefined || iColumn === null ) {
831
				api.row( mRow ).data( mData );
832
			}
833
			else {
834
				api.cell( mRow, iColumn ).data( mData );
835
			}
836
		
837
			if ( bAction === undefined || bAction ) {
838
				api.columns.adjust();
839
			}
840
		
841
			if ( bRedraw === undefined || bRedraw ) {
842
				api.draw();
843
			}
844
			return 0;
845
		};
846
		
847
		
848
		/**
849
		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
850
		 * to ensure compatibility.
851
		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
852
		 *    formats "X" and "X.Y" are also acceptable.
853
		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
854
		 *    version, or false if this version of DataTales is not suitable
855
		 *  @method
856
		 *  @dtopt API
857
		 *  @deprecated Since v1.10
858
		 *
859
		 *  @example
860
		 *    $(document).ready(function() {
861
		 *      var oTable = $('#example').dataTable();
862
		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
863
		 *    } );
864
		 */
865
		this.fnVersionCheck = _ext.fnVersionCheck;
866
		
867
868
		var _that = this;
869
		var emptyInit = options === undefined;
870
		var len = this.length;
871
872
		if ( emptyInit ) {
873
			options = {};
874
		}
875
876
		this.oApi = this.internal = _ext.internal;
877
878
		// Extend with old style plug-in API methods
879
		for ( var fn in DataTable.ext.internal ) {
880
			if ( fn ) {
881
				this[fn] = _fnExternApiFunc(fn);
882
			}
883
		}
884
885
		this.each(function() {
886
			// For each initialisation we want to give it a clean initialisation
887
			// object that can be bashed around
888
			var o = {};
889
			var oInit = len > 1 ? // optimisation for single table case
890
				_fnExtend( o, options, true ) :
891
				options;
892
893
			/*global oInit,_that,emptyInit*/
894
			var i=0, iLen, j, jLen, k, kLen;
895
			var sId = this.getAttribute( 'id' );
896
			var bInitHandedOff = false;
897
			var defaults = DataTable.defaults;
898
			var $this = $(this);
899
			
900
			
901
			/* Sanity check */
902
			if ( this.nodeName.toLowerCase() != 'table' )
903
			{
904
				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
905
				return;
906
			}
907
			
908
			/* Backwards compatibility for the defaults */
909
			_fnCompatOpts( defaults );
910
			_fnCompatCols( defaults.column );
911
			
912
			/* Convert the camel-case defaults to Hungarian */
913
			_fnCamelToHungarian( defaults, defaults, true );
914
			_fnCamelToHungarian( defaults.column, defaults.column, true );
915
			
916
			/* Setting up the initialisation object */
917
			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
918
			
919
			
920
			
921
			/* Check to see if we are re-initialising a table */
922
			var allSettings = DataTable.settings;
923
			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
924
			{
925
				var s = allSettings[i];
926
			
927
				/* Base check on table node */
928
				if (
929
					s.nTable == this ||
930
					(s.nTHead && s.nTHead.parentNode == this) ||
931
					(s.nTFoot && s.nTFoot.parentNode == this)
932
				) {
933
					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
934
					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
935
			
936
					if ( emptyInit || bRetrieve )
937
					{
938
						return s.oInstance;
939
					}
940
					else if ( bDestroy )
941
					{
942
						s.oInstance.fnDestroy();
943
						break;
944
					}
945
					else
946
					{
947
						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
948
						return;
949
					}
950
				}
951
			
952
				/* If the element we are initialising has the same ID as a table which was previously
953
				 * initialised, but the table nodes don't match (from before) then we destroy the old
954
				 * instance by simply deleting it. This is under the assumption that the table has been
955
				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
956
				 */
957
				if ( s.sTableId == this.id )
958
				{
959
					allSettings.splice( i, 1 );
960
					break;
961
				}
962
			}
963
			
964
			/* Ensure the table has an ID - required for accessibility */
965
			if ( sId === null || sId === "" )
966
			{
967
				sId = "DataTables_Table_"+(DataTable.ext._unique++);
968
				this.id = sId;
969
			}
970
			
971
			/* Create the settings object for this table and set some of the default parameters */
972
			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
973
				"sDestroyWidth": $this[0].style.width,
974
				"sInstance":     sId,
975
				"sTableId":      sId
976
			} );
977
			oSettings.nTable = this;
978
			oSettings.oApi   = _that.internal;
979
			oSettings.oInit  = oInit;
980
			
981
			allSettings.push( oSettings );
982
			
983
			// Need to add the instance after the instance after the settings object has been added
984
			// to the settings array, so we can self reference the table instance if more than one
985
			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
986
			
987
			// Backwards compatibility, before we apply all the defaults
988
			_fnCompatOpts( oInit );
989
			_fnLanguageCompat( oInit.oLanguage );
990
			
991
			// If the length menu is given, but the init display length is not, use the length menu
992
			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
993
			{
994
				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
995
					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
996
			}
997
			
998
			// Apply the defaults and init options to make a single init object will all
999
			// options defined from defaults and instance options.
1000
			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
1001
			
1002
			
1003
			// Map the initialisation options onto the settings object
1004
			_fnMap( oSettings.oFeatures, oInit, [
1005
				"bPaginate",
1006
				"bLengthChange",
1007
				"bFilter",
1008
				"bSort",
1009
				"bSortMulti",
1010
				"bInfo",
1011
				"bProcessing",
1012
				"bAutoWidth",
1013
				"bSortClasses",
1014
				"bServerSide",
1015
				"bDeferRender"
1016
			] );
1017
			_fnMap( oSettings, oInit, [
1018
				"asStripeClasses",
1019
				"ajax",
1020
				"fnServerData",
1021
				"fnFormatNumber",
1022
				"sServerMethod",
1023
				"aaSorting",
1024
				"aaSortingFixed",
1025
				"aLengthMenu",
1026
				"sPaginationType",
1027
				"sAjaxSource",
1028
				"sAjaxDataProp",
1029
				"iStateDuration",
1030
				"sDom",
1031
				"bSortCellsTop",
1032
				"iTabIndex",
1033
				"fnStateLoadCallback",
1034
				"fnStateSaveCallback",
1035
				"renderer",
1036
				"searchDelay",
1037
				"rowId",
1038
				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1039
				[ "oSearch", "oPreviousSearch" ],
1040
				[ "aoSearchCols", "aoPreSearchCols" ],
1041
				[ "iDisplayLength", "_iDisplayLength" ]
1042
			] );
1043
			_fnMap( oSettings.oScroll, oInit, [
1044
				[ "sScrollX", "sX" ],
1045
				[ "sScrollXInner", "sXInner" ],
1046
				[ "sScrollY", "sY" ],
1047
				[ "bScrollCollapse", "bCollapse" ]
1048
			] );
1049
			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1050
			
1051
			/* Callback functions which are array driven */
1052
			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1053
			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1054
			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1055
			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1056
			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1057
			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1058
			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1059
			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1060
			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1061
			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1062
			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1063
			
1064
			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1065
			
1066
			/* Browser support detection */
1067
			_fnBrowserDetect( oSettings );
1068
			
1069
			var oClasses = oSettings.oClasses;
1070
			
1071
			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1072
			$this.addClass( oClasses.sTable );
1073
			
1074
			
1075
			if ( oSettings.iInitDisplayStart === undefined )
1076
			{
1077
				/* Display start point, taking into account the save saving */
1078
				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1079
				oSettings._iDisplayStart = oInit.iDisplayStart;
1080
			}
1081
			
1082
			if ( oInit.iDeferLoading !== null )
1083
			{
1084
				oSettings.bDeferLoading = true;
1085
				var tmp = $.isArray( oInit.iDeferLoading );
1086
				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1087
				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1088
			}
1089
			
1090
			/* Language definitions */
1091
			var oLanguage = oSettings.oLanguage;
1092
			$.extend( true, oLanguage, oInit.oLanguage );
1093
			
1094
			if ( oLanguage.sUrl )
1095
			{
1096
				/* Get the language definitions from a file - because this Ajax call makes the language
1097
				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1098
				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1099
				 */
1100
				$.ajax( {
1101
					dataType: 'json',
1102
					url: oLanguage.sUrl,
1103
					success: function ( json ) {
1104
						_fnLanguageCompat( json );
1105
						_fnCamelToHungarian( defaults.oLanguage, json );
1106
						$.extend( true, oLanguage, json );
1107
						_fnInitialise( oSettings );
1108
					},
1109
					error: function () {
1110
						// Error occurred loading language file, continue on as best we can
1111
						_fnInitialise( oSettings );
1112
					}
1113
				} );
1114
				bInitHandedOff = true;
1115
			}
1116
			
1117
			/*
1118
			 * Stripes
1119
			 */
1120
			if ( oInit.asStripeClasses === null )
1121
			{
1122
				oSettings.asStripeClasses =[
1123
					oClasses.sStripeOdd,
1124
					oClasses.sStripeEven
1125
				];
1126
			}
1127
			
1128
			/* Remove row stripe classes if they are already on the table row */
1129
			var stripeClasses = oSettings.asStripeClasses;
1130
			var rowOne = $this.children('tbody').find('tr').eq(0);
1131
			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1132
				return rowOne.hasClass(el);
1133
			} ) ) !== -1 ) {
1134
				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1135
				oSettings.asDestroyStripes = stripeClasses.slice();
1136
			}
1137
			
1138
			/*
1139
			 * Columns
1140
			 * See if we should load columns automatically or use defined ones
1141
			 */
1142
			var anThs = [];
1143
			var aoColumnsInit;
1144
			var nThead = this.getElementsByTagName('thead');
1145
			if ( nThead.length !== 0 )
1146
			{
1147
				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1148
				anThs = _fnGetUniqueThs( oSettings );
1149
			}
1150
			
1151
			/* If not given a column array, generate one with nulls */
1152
			if ( oInit.aoColumns === null )
1153
			{
1154
				aoColumnsInit = [];
1155
				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1156
				{
1157
					aoColumnsInit.push( null );
1158
				}
1159
			}
1160
			else
1161
			{
1162
				aoColumnsInit = oInit.aoColumns;
1163
			}
1164
			
1165
			/* Add the columns */
1166
			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1167
			{
1168
				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1169
			}
1170
			
1171
			/* Apply the column definitions */
1172
			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1173
				_fnColumnOptions( oSettings, iCol, oDef );
1174
			} );
1175
			
1176
			/* HTML5 attribute detection - build an mData object automatically if the
1177
			 * attributes are found
1178
			 */
1179
			if ( rowOne.length ) {
1180
				var a = function ( cell, name ) {
1181
					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1182
				};
1183
			
1184
				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1185
					var col = oSettings.aoColumns[i];
1186
			
1187
					if ( col.mData === i ) {
1188
						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1189
						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1190
			
1191
						if ( sort !== null || filter !== null ) {
1192
							col.mData = {
1193
								_:      i+'.display',
1194
								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1195
								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1196
								filter: filter !== null ? i+'.@data-'+filter : undefined
1197
							};
1198
			
1199
							_fnColumnOptions( oSettings, i );
1200
						}
1201
					}
1202
				} );
1203
			}
1204
			
1205
			var features = oSettings.oFeatures;
1206
			var loadedInit = function () {
1207
				/*
1208
				 * Sorting
1209
				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1210
				 */
1211
			
1212
				// If aaSorting is not defined, then we use the first indicator in asSorting
1213
				// in case that has been altered, so the default sort reflects that option
1214
				if ( oInit.aaSorting === undefined ) {
1215
					var sorting = oSettings.aaSorting;
1216
					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1217
						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1218
					}
1219
				}
1220
			
1221
				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1222
				 * account, and also will apply sorting disabled classes if disabled
1223
				 */
1224
				_fnSortingClasses( oSettings );
1225
			
1226
				if ( features.bSort ) {
1227
					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1228
						if ( oSettings.bSorted ) {
1229
							var aSort = _fnSortFlatten( oSettings );
1230
							var sortedColumns = {};
1231
			
1232
							$.each( aSort, function (i, val) {
1233
								sortedColumns[ val.src ] = val.dir;
1234
							} );
1235
			
1236
							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1237
							_fnSortAria( oSettings );
1238
						}
1239
					} );
1240
				}
1241
			
1242
				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1243
					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1244
						_fnSortingClasses( oSettings );
1245
					}
1246
				}, 'sc' );
1247
			
1248
			
1249
				/*
1250
				 * Final init
1251
				 * Cache the header, body and footer as required, creating them if needed
1252
				 */
1253
			
1254
				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1255
				var captions = $this.children('caption').each( function () {
1256
					this._captionSide = $(this).css('caption-side');
1257
				} );
1258
			
1259
				var thead = $this.children('thead');
1260
				if ( thead.length === 0 ) {
1261
					thead = $('<thead/>').appendTo($this);
1262
				}
1263
				oSettings.nTHead = thead[0];
1264
			
1265
				var tbody = $this.children('tbody');
1266
				if ( tbody.length === 0 ) {
1267
					tbody = $('<tbody/>').appendTo($this);
1268
				}
1269
				oSettings.nTBody = tbody[0];
1270
			
1271
				var tfoot = $this.children('tfoot');
1272
				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1273
					// If we are a scrolling table, and no footer has been given, then we need to create
1274
					// a tfoot element for the caption element to be appended to
1275
					tfoot = $('<tfoot/>').appendTo($this);
1276
				}
1277
			
1278
				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1279
					$this.addClass( oClasses.sNoFooter );
1280
				}
1281
				else if ( tfoot.length > 0 ) {
1282
					oSettings.nTFoot = tfoot[0];
1283
					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1284
				}
1285
			
1286
				/* Check if there is data passing into the constructor */
1287
				if ( oInit.aaData ) {
1288
					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1289
						_fnAddData( oSettings, oInit.aaData[ i ] );
1290
					}
1291
				}
1292
				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1293
					/* Grab the data from the page - only do this when deferred loading or no Ajax
1294
					 * source since there is no point in reading the DOM data if we are then going
1295
					 * to replace it with Ajax data
1296
					 */
1297
					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1298
				}
1299
			
1300
				/* Copy the data index array */
1301
				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1302
			
1303
				/* Initialisation complete - table can be drawn */
1304
				oSettings.bInitialised = true;
1305
			
1306
				/* Check if we need to initialise the table (it might not have been handed off to the
1307
				 * language processor)
1308
				 */
1309
				if ( bInitHandedOff === false ) {
1310
					_fnInitialise( oSettings );
1311
				}
1312
			};
1313
			
1314
			/* Must be done after everything which can be overridden by the state saving! */
1315
			if ( oInit.bStateSave )
1316
			{
1317
				features.bStateSave = true;
1318
				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1319
				_fnLoadState( oSettings, oInit, loadedInit );
1320
			}
1321
			else {
1322
				loadedInit();
1323
			}
1324
			
1325
		} );
1326
		_that = null;
1327
		return this;
1328
	};
1329
1330
	
1331
	/*
1332
	 * It is useful to have variables which are scoped locally so only the
1333
	 * DataTables functions can access them and they don't leak into global space.
1334
	 * At the same time these functions are often useful over multiple files in the
1335
	 * core and API, so we list, or at least document, all variables which are used
1336
	 * by DataTables as private variables here. This also ensures that there is no
1337
	 * clashing of variable names and that they can easily referenced for reuse.
1338
	 */
1339
	
1340
	
1341
	// Defined else where
1342
	//  _selector_run
1343
	//  _selector_opts
1344
	//  _selector_first
1345
	//  _selector_row_indexes
1346
	
1347
	var _ext; // DataTable.ext
1348
	var _Api; // DataTable.Api
1349
	var _api_register; // DataTable.Api.register
1350
	var _api_registerPlural; // DataTable.Api.registerPlural
1351
	
1352
	var _re_dic = {};
1353
	var _re_new_lines = /[\r\n]/g;
1354
	var _re_html = /<.*?>/g;
1355
	
1356
	// This is not strict ISO8601 - Date.parse() is quite lax, although
1357
	// implementations differ between browsers.
1358
	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1359
	
1360
	// Escape regular expression special characters
1361
	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1362
	
1363
	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1364
	// - \u20BD - Russian ruble.
1365
	// - \u20a9 - South Korean Won
1366
	// - \u20BA - Turkish Lira
1367
	// - \u20B9 - Indian Rupee
1368
	// - R - Brazil (R$) and South Africa
1369
	// - fr - Swiss Franc
1370
	// - kr - Swedish krona, Norwegian krone and Danish krone
1371
	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1372
	// - Ƀ - Bitcoin
1373
	// - Ξ - Ethereum
1374
	//   standards as thousands separators.
1375
	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1376
	
1377
	
1378
	var _empty = function ( d ) {
1379
		return !d || d === true || d === '-' ? true : false;
1380
	};
1381
	
1382
	
1383
	var _intVal = function ( s ) {
1384
		var integer = parseInt( s, 10 );
1385
		return !isNaN(integer) && isFinite(s) ? integer : null;
1386
	};
1387
	
1388
	// Convert from a formatted number with characters other than `.` as the
1389
	// decimal place, to a Javascript number
1390
	var _numToDecimal = function ( num, decimalPoint ) {
1391
		// Cache created regular expressions for speed as this function is called often
1392
		if ( ! _re_dic[ decimalPoint ] ) {
1393
			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1394
		}
1395
		return typeof num === 'string' && decimalPoint !== '.' ?
1396
			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1397
			num;
1398
	};
1399
	
1400
	
1401
	var _isNumber = function ( d, decimalPoint, formatted ) {
1402
		var strType = typeof d === 'string';
1403
	
1404
		// If empty return immediately so there must be a number if it is a
1405
		// formatted string (this stops the string "k", or "kr", etc being detected
1406
		// as a formatted number for currency
1407
		if ( _empty( d ) ) {
1408
			return true;
1409
		}
1410
	
1411
		if ( decimalPoint && strType ) {
1412
			d = _numToDecimal( d, decimalPoint );
1413
		}
1414
	
1415
		if ( formatted && strType ) {
1416
			d = d.replace( _re_formatted_numeric, '' );
1417
		}
1418
	
1419
		return !isNaN( parseFloat(d) ) && isFinite( d );
1420
	};
1421
	
1422
	
1423
	// A string without HTML in it can be considered to be HTML still
1424
	var _isHtml = function ( d ) {
1425
		return _empty( d ) || typeof d === 'string';
1426
	};
1427
	
1428
	
1429
	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1430
		if ( _empty( d ) ) {
1431
			return true;
1432
		}
1433
	
1434
		var html = _isHtml( d );
1435
		return ! html ?
1436
			null :
1437
			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1438
				true :
1439
				null;
1440
	};
1441
	
1442
	
1443
	var _pluck = function ( a, prop, prop2 ) {
1444
		var out = [];
1445
		var i=0, ien=a.length;
1446
	
1447
		// Could have the test in the loop for slightly smaller code, but speed
1448
		// is essential here
1449
		if ( prop2 !== undefined ) {
1450
			for ( ; i<ien ; i++ ) {
1451
				if ( a[i] && a[i][ prop ] ) {
1452
					out.push( a[i][ prop ][ prop2 ] );
1453
				}
1454
			}
1455
		}
1456
		else {
1457
			for ( ; i<ien ; i++ ) {
1458
				if ( a[i] ) {
1459
					out.push( a[i][ prop ] );
1460
				}
1461
			}
1462
		}
1463
	
1464
		return out;
1465
	};
1466
	
1467
	
1468
	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1469
	// as the indexes to pick from `a`
1470
	var _pluck_order = function ( a, order, prop, prop2 )
1471
	{
1472
		var out = [];
1473
		var i=0, ien=order.length;
1474
	
1475
		// Could have the test in the loop for slightly smaller code, but speed
1476
		// is essential here
1477
		if ( prop2 !== undefined ) {
1478
			for ( ; i<ien ; i++ ) {
1479
				if ( a[ order[i] ][ prop ] ) {
1480
					out.push( a[ order[i] ][ prop ][ prop2 ] );
1481
				}
1482
			}
1483
		}
1484
		else {
1485
			for ( ; i<ien ; i++ ) {
1486
				out.push( a[ order[i] ][ prop ] );
1487
			}
1488
		}
1489
	
1490
		return out;
1491
	};
1492
	
1493
	
1494
	var _range = function ( len, start )
1495
	{
1496
		var out = [];
1497
		var end;
1498
	
1499
		if ( start === undefined ) {
1500
			start = 0;
1501
			end = len;
1502
		}
1503
		else {
1504
			end = start;
1505
			start = len;
1506
		}
1507
	
1508
		for ( var i=start ; i<end ; i++ ) {
1509
			out.push( i );
1510
		}
1511
	
1512
		return out;
1513
	};
1514
	
1515
	
1516
	var _removeEmpty = function ( a )
1517
	{
1518
		var out = [];
1519
	
1520
		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1521
			if ( a[i] ) { // careful - will remove all falsy values!
1522
				out.push( a[i] );
1523
			}
1524
		}
1525
	
1526
		return out;
1527
	};
1528
	
1529
	
1530
	var _stripHtml = function ( d ) {
1531
		return d.replace( _re_html, '' );
1532
	};
1533
	
1534
	
1535
	/**
1536
	 * Determine if all values in the array are unique. This means we can short
1537
	 * cut the _unique method at the cost of a single loop. A sorted array is used
1538
	 * to easily check the values.
1539
	 *
1540
	 * @param  {array} src Source array
1541
	 * @return {boolean} true if all unique, false otherwise
1542
	 * @ignore
1543
	 */
1544
	var _areAllUnique = function ( src ) {
1545
		if ( src.length < 2 ) {
1546
			return true;
1547
		}
1548
	
1549
		var sorted = src.slice().sort();
1550
		var last = sorted[0];
1551
	
1552
		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1553
			if ( sorted[i] === last ) {
1554
				return false;
1555
			}
1556
	
1557
			last = sorted[i];
1558
		}
1559
	
1560
		return true;
1561
	};
1562
	
1563
	
1564
	/**
1565
	 * Find the unique elements in a source array.
1566
	 *
1567
	 * @param  {array} src Source array
1568
	 * @return {array} Array of unique items
1569
	 * @ignore
1570
	 */
1571
	var _unique = function ( src )
1572
	{
1573
		if ( _areAllUnique( src ) ) {
1574
			return src.slice();
1575
		}
1576
	
1577
		// A faster unique method is to use object keys to identify used values,
1578
		// but this doesn't work with arrays or objects, which we must also
1579
		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1580
		// information.
1581
		var
1582
			out = [],
1583
			val,
1584
			i, ien=src.length,
1585
			j, k=0;
1586
	
1587
		again: for ( i=0 ; i<ien ; i++ ) {
1588
			val = src[i];
1589
	
1590
			for ( j=0 ; j<k ; j++ ) {
1591
				if ( out[j] === val ) {
1592
					continue again;
1593
				}
1594
			}
1595
	
1596
			out.push( val );
1597
			k++;
1598
		}
1599
	
1600
		return out;
1601
	};
1602
	
1603
	
1604
	/**
1605
	 * DataTables utility methods
1606
	 * 
1607
	 * This namespace provides helper methods that DataTables uses internally to
1608
	 * create a DataTable, but which are not exclusively used only for DataTables.
1609
	 * These methods can be used by extension authors to save the duplication of
1610
	 * code.
1611
	 *
1612
	 *  @namespace
1613
	 */
1614
	DataTable.util = {
1615
		/**
1616
		 * Throttle the calls to a function. Arguments and context are maintained
1617
		 * for the throttled function.
1618
		 *
1619
		 * @param {function} fn Function to be called
1620
		 * @param {integer} freq Call frequency in mS
1621
		 * @return {function} Wrapped function
1622
		 */
1623
		throttle: function ( fn, freq ) {
1624
			var
1625
				frequency = freq !== undefined ? freq : 200,
1626
				last,
1627
				timer;
1628
	
1629
			return function () {
1630
				var
1631
					that = this,
1632
					now  = +new Date(),
1633
					args = arguments;
1634
	
1635
				if ( last && now < last + frequency ) {
1636
					clearTimeout( timer );
1637
	
1638
					timer = setTimeout( function () {
1639
						last = undefined;
1640
						fn.apply( that, args );
1641
					}, frequency );
1642
				}
1643
				else {
1644
					last = now;
1645
					fn.apply( that, args );
1646
				}
1647
			};
1648
		},
1649
	
1650
	
1651
		/**
1652
		 * Escape a string such that it can be used in a regular expression
1653
		 *
1654
		 *  @param {string} val string to escape
1655
		 *  @returns {string} escaped string
1656
		 */
1657
		escapeRegex: function ( val ) {
1658
			return val.replace( _re_escape_regex, '\\$1' );
1659
		}
1660
	};
1661
	
1662
	
1663
	
1664
	/**
1665
	 * Create a mapping object that allows camel case parameters to be looked up
1666
	 * for their Hungarian counterparts. The mapping is stored in a private
1667
	 * parameter called `_hungarianMap` which can be accessed on the source object.
1668
	 *  @param {object} o
1669
	 *  @memberof DataTable#oApi
1670
	 */
1671
	function _fnHungarianMap ( o )
1672
	{
1673
		var
1674
			hungarian = 'a aa ai ao as b fn i m o s ',
1675
			match,
1676
			newKey,
1677
			map = {};
1678
	
1679
		$.each( o, function (key, val) {
1680
			match = key.match(/^([^A-Z]+?)([A-Z])/);
1681
	
1682
			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1683
			{
1684
				newKey = key.replace( match[0], match[2].toLowerCase() );
1685
				map[ newKey ] = key;
1686
	
1687
				if ( match[1] === 'o' )
1688
				{
1689
					_fnHungarianMap( o[key] );
1690
				}
1691
			}
1692
		} );
1693
	
1694
		o._hungarianMap = map;
1695
	}
1696
	
1697
	
1698
	/**
1699
	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1700
	 * created by _fnHungarianMap.
1701
	 *  @param {object} src The model object which holds all parameters that can be
1702
	 *    mapped.
1703
	 *  @param {object} user The object to convert from camel case to Hungarian.
1704
	 *  @param {boolean} force When set to `true`, properties which already have a
1705
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1706
	 *    won't be.
1707
	 *  @memberof DataTable#oApi
1708
	 */
1709
	function _fnCamelToHungarian ( src, user, force )
1710
	{
1711
		if ( ! src._hungarianMap ) {
1712
			_fnHungarianMap( src );
1713
		}
1714
	
1715
		var hungarianKey;
1716
	
1717
		$.each( user, function (key, val) {
1718
			hungarianKey = src._hungarianMap[ key ];
1719
	
1720
			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1721
			{
1722
				// For objects, we need to buzz down into the object to copy parameters
1723
				if ( hungarianKey.charAt(0) === 'o' )
1724
				{
1725
					// Copy the camelCase options over to the hungarian
1726
					if ( ! user[ hungarianKey ] ) {
1727
						user[ hungarianKey ] = {};
1728
					}
1729
					$.extend( true, user[hungarianKey], user[key] );
1730
	
1731
					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1732
				}
1733
				else {
1734
					user[hungarianKey] = user[ key ];
1735
				}
1736
			}
1737
		} );
1738
	}
1739
	
1740
	
1741
	/**
1742
	 * Language compatibility - when certain options are given, and others aren't, we
1743
	 * need to duplicate the values over, in order to provide backwards compatibility
1744
	 * with older language files.
1745
	 *  @param {object} oSettings dataTables settings object
1746
	 *  @memberof DataTable#oApi
1747
	 */
1748
	function _fnLanguageCompat( lang )
1749
	{
1750
		// Note the use of the Hungarian notation for the parameters in this method as
1751
		// this is called after the mapping of camelCase to Hungarian
1752
		var defaults = DataTable.defaults.oLanguage;
1753
	
1754
		// Default mapping
1755
		var defaultDecimal = defaults.sDecimal;
1756
		if ( defaultDecimal ) {
1757
			_addNumericSort( defaultDecimal );
1758
		}
1759
	
1760
		if ( lang ) {
1761
			var zeroRecords = lang.sZeroRecords;
1762
	
1763
			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
1764
			// sZeroRecords - assuming that is given.
1765
			if ( ! lang.sEmptyTable && zeroRecords &&
1766
				defaults.sEmptyTable === "No data available in table" )
1767
			{
1768
				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1769
			}
1770
	
1771
			// Likewise with loading records
1772
			if ( ! lang.sLoadingRecords && zeroRecords &&
1773
				defaults.sLoadingRecords === "Loading..." )
1774
			{
1775
				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1776
			}
1777
	
1778
			// Old parameter name of the thousands separator mapped onto the new
1779
			if ( lang.sInfoThousands ) {
1780
				lang.sThousands = lang.sInfoThousands;
1781
			}
1782
	
1783
			var decimal = lang.sDecimal;
1784
			if ( decimal && defaultDecimal !== decimal ) {
1785
				_addNumericSort( decimal );
1786
			}
1787
		}
1788
	}
1789
	
1790
	
1791
	/**
1792
	 * Map one parameter onto another
1793
	 *  @param {object} o Object to map
1794
	 *  @param {*} knew The new parameter name
1795
	 *  @param {*} old The old parameter name
1796
	 */
1797
	var _fnCompatMap = function ( o, knew, old ) {
1798
		if ( o[ knew ] !== undefined ) {
1799
			o[ old ] = o[ knew ];
1800
		}
1801
	};
1802
	
1803
	
1804
	/**
1805
	 * Provide backwards compatibility for the main DT options. Note that the new
1806
	 * options are mapped onto the old parameters, so this is an external interface
1807
	 * change only.
1808
	 *  @param {object} init Object to map
1809
	 */
1810
	function _fnCompatOpts ( init )
1811
	{
1812
		_fnCompatMap( init, 'ordering',      'bSort' );
1813
		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1814
		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1815
		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1816
		_fnCompatMap( init, 'order',         'aaSorting' );
1817
		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1818
		_fnCompatMap( init, 'paging',        'bPaginate' );
1819
		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
1820
		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1821
		_fnCompatMap( init, 'searching',     'bFilter' );
1822
	
1823
		// Boolean initialisation of x-scrolling
1824
		if ( typeof init.sScrollX === 'boolean' ) {
1825
			init.sScrollX = init.sScrollX ? '100%' : '';
1826
		}
1827
		if ( typeof init.scrollX === 'boolean' ) {
1828
			init.scrollX = init.scrollX ? '100%' : '';
1829
		}
1830
	
1831
		// Column search objects are in an array, so it needs to be converted
1832
		// element by element
1833
		var searchCols = init.aoSearchCols;
1834
	
1835
		if ( searchCols ) {
1836
			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1837
				if ( searchCols[i] ) {
1838
					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1839
				}
1840
			}
1841
		}
1842
	}
1843
	
1844
	
1845
	/**
1846
	 * Provide backwards compatibility for column options. Note that the new options
1847
	 * are mapped onto the old parameters, so this is an external interface change
1848
	 * only.
1849
	 *  @param {object} init Object to map
1850
	 */
1851
	function _fnCompatCols ( init )
1852
	{
1853
		_fnCompatMap( init, 'orderable',     'bSortable' );
1854
		_fnCompatMap( init, 'orderData',     'aDataSort' );
1855
		_fnCompatMap( init, 'orderSequence', 'asSorting' );
1856
		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
1857
	
1858
		// orderData can be given as an integer
1859
		var dataSort = init.aDataSort;
1860
		if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
1861
			init.aDataSort = [ dataSort ];
1862
		}
1863
	}
1864
	
1865
	
1866
	/**
1867
	 * Browser feature detection for capabilities, quirks
1868
	 *  @param {object} settings dataTables settings object
1869
	 *  @memberof DataTable#oApi
1870
	 */
1871
	function _fnBrowserDetect( settings )
1872
	{
1873
		// We don't need to do this every time DataTables is constructed, the values
1874
		// calculated are specific to the browser and OS configuration which we
1875
		// don't expect to change between initialisations
1876
		if ( ! DataTable.__browser ) {
1877
			var browser = {};
1878
			DataTable.__browser = browser;
1879
	
1880
			// Scrolling feature / quirks detection
1881
			var n = $('<div/>')
1882
				.css( {
1883
					position: 'fixed',
1884
					top: 0,
1885
					left: $(window).scrollLeft()*-1, // allow for scrolling
1886
					height: 1,
1887
					width: 1,
1888
					overflow: 'hidden'
1889
				} )
1890
				.append(
1891
					$('<div/>')
1892
						.css( {
1893
							position: 'absolute',
1894
							top: 1,
1895
							left: 1,
1896
							width: 100,
1897
							overflow: 'scroll'
1898
						} )
1899
						.append(
1900
							$('<div/>')
1901
								.css( {
1902
									width: '100%',
1903
									height: 10
1904
								} )
1905
						)
1906
				)
1907
				.appendTo( 'body' );
1908
	
1909
			var outer = n.children();
1910
			var inner = outer.children();
1911
	
1912
			// Numbers below, in order, are:
1913
			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1914
			//
1915
			// IE6 XP:                           100 100 100  83
1916
			// IE7 Vista:                        100 100 100  83
1917
			// IE 8+ Windows:                     83  83 100  83
1918
			// Evergreen Windows:                 83  83 100  83
1919
			// Evergreen Mac with scrollbars:     85  85 100  85
1920
			// Evergreen Mac without scrollbars: 100 100 100 100
1921
	
1922
			// Get scrollbar width
1923
			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1924
	
1925
			// IE6/7 will oversize a width 100% element inside a scrolling element, to
1926
			// include the width of the scrollbar, while other browsers ensure the inner
1927
			// element is contained without forcing scrolling
1928
			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1929
	
1930
			// In rtl text layout, some browsers (most, but not all) will place the
1931
			// scrollbar on the left, rather than the right.
1932
			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1933
	
1934
			// IE8- don't provide height and width for getBoundingClientRect
1935
			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1936
	
1937
			n.remove();
1938
		}
1939
	
1940
		$.extend( settings.oBrowser, DataTable.__browser );
1941
		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1942
	}
1943
	
1944
	
1945
	/**
1946
	 * Array.prototype reduce[Right] method, used for browsers which don't support
1947
	 * JS 1.6. Done this way to reduce code size, since we iterate either way
1948
	 *  @param {object} settings dataTables settings object
1949
	 *  @memberof DataTable#oApi
1950
	 */
1951
	function _fnReduce ( that, fn, init, start, end, inc )
1952
	{
1953
		var
1954
			i = start,
1955
			value,
1956
			isSet = false;
1957
	
1958
		if ( init !== undefined ) {
1959
			value = init;
1960
			isSet = true;
1961
		}
1962
	
1963
		while ( i !== end ) {
1964
			if ( ! that.hasOwnProperty(i) ) {
1965
				continue;
1966
			}
1967
	
1968
			value = isSet ?
1969
				fn( value, that[i], i, that ) :
1970
				that[i];
1971
	
1972
			isSet = true;
1973
			i += inc;
1974
		}
1975
	
1976
		return value;
1977
	}
1978
	
1979
	/**
1980
	 * Add a column to the list used for the table with default values
1981
	 *  @param {object} oSettings dataTables settings object
1982
	 *  @param {node} nTh The th element for this column
1983
	 *  @memberof DataTable#oApi
1984
	 */
1985
	function _fnAddColumn( oSettings, nTh )
1986
	{
1987
		// Add column to aoColumns array
1988
		var oDefaults = DataTable.defaults.column;
1989
		var iCol = oSettings.aoColumns.length;
1990
		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1991
			"nTh": nTh ? nTh : document.createElement('th'),
1992
			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1993
			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1994
			"mData": oDefaults.mData ? oDefaults.mData : iCol,
1995
			idx: iCol
1996
		} );
1997
		oSettings.aoColumns.push( oCol );
1998
	
1999
		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
2000
		// passed into extend can be undefined. This allows the user to give a default
2001
		// with only some of the parameters defined, and also not give a default
2002
		var searchCols = oSettings.aoPreSearchCols;
2003
		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2004
	
2005
		// Use the default column options function to initialise classes etc
2006
		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2007
	}
2008
	
2009
	
2010
	/**
2011
	 * Apply options for a column
2012
	 *  @param {object} oSettings dataTables settings object
2013
	 *  @param {int} iCol column index to consider
2014
	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2015
	 *  @memberof DataTable#oApi
2016
	 */
2017
	function _fnColumnOptions( oSettings, iCol, oOptions )
2018
	{
2019
		var oCol = oSettings.aoColumns[ iCol ];
2020
		var oClasses = oSettings.oClasses;
2021
		var th = $(oCol.nTh);
2022
	
2023
		// Try to get width information from the DOM. We can't get it from CSS
2024
		// as we'd need to parse the CSS stylesheet. `width` option can override
2025
		if ( ! oCol.sWidthOrig ) {
2026
			// Width attribute
2027
			oCol.sWidthOrig = th.attr('width') || null;
2028
	
2029
			// Style attribute
2030
			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2031
			if ( t ) {
2032
				oCol.sWidthOrig = t[1];
2033
			}
2034
		}
2035
	
2036
		/* User specified column options */
2037
		if ( oOptions !== undefined && oOptions !== null )
2038
		{
2039
			// Backwards compatibility
2040
			_fnCompatCols( oOptions );
2041
	
2042
			// Map camel case parameters to their Hungarian counterparts
2043
			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
2044
	
2045
			/* Backwards compatibility for mDataProp */
2046
			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2047
			{
2048
				oOptions.mData = oOptions.mDataProp;
2049
			}
2050
	
2051
			if ( oOptions.sType )
2052
			{
2053
				oCol._sManualType = oOptions.sType;
2054
			}
2055
	
2056
			// `class` is a reserved word in Javascript, so we need to provide
2057
			// the ability to use a valid name for the camel case input
2058
			if ( oOptions.className && ! oOptions.sClass )
2059
			{
2060
				oOptions.sClass = oOptions.className;
2061
			}
2062
			if ( oOptions.sClass ) {
2063
				th.addClass( oOptions.sClass );
2064
			}
2065
	
2066
			$.extend( oCol, oOptions );
2067
			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2068
	
2069
			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2070
			 * priority if defined
2071
			 */
2072
			if ( oOptions.iDataSort !== undefined )
2073
			{
2074
				oCol.aDataSort = [ oOptions.iDataSort ];
2075
			}
2076
			_fnMap( oCol, oOptions, "aDataSort" );
2077
		}
2078
	
2079
		/* Cache the data get and set functions for speed */
2080
		var mDataSrc = oCol.mData;
2081
		var mData = _fnGetObjectDataFn( mDataSrc );
2082
		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2083
	
2084
		var attrTest = function( src ) {
2085
			return typeof src === 'string' && src.indexOf('@') !== -1;
2086
		};
2087
		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2088
			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2089
		);
2090
		oCol._setter = null;
2091
	
2092
		oCol.fnGetData = function (rowData, type, meta) {
2093
			var innerData = mData( rowData, type, undefined, meta );
2094
	
2095
			return mRender && type ?
2096
				mRender( innerData, type, rowData, meta ) :
2097
				innerData;
2098
		};
2099
		oCol.fnSetData = function ( rowData, val, meta ) {
2100
			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2101
		};
2102
	
2103
		// Indicate if DataTables should read DOM data as an object or array
2104
		// Used in _fnGetRowElements
2105
		if ( typeof mDataSrc !== 'number' ) {
2106
			oSettings._rowReadObject = true;
2107
		}
2108
	
2109
		/* Feature sorting overrides column specific when off */
2110
		if ( !oSettings.oFeatures.bSort )
2111
		{
2112
			oCol.bSortable = false;
2113
			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2114
		}
2115
	
2116
		/* Check that the class assignment is correct for sorting */
2117
		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2118
		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2119
		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2120
		{
2121
			oCol.sSortingClass = oClasses.sSortableNone;
2122
			oCol.sSortingClassJUI = "";
2123
		}
2124
		else if ( bAsc && !bDesc )
2125
		{
2126
			oCol.sSortingClass = oClasses.sSortableAsc;
2127
			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2128
		}
2129
		else if ( !bAsc && bDesc )
2130
		{
2131
			oCol.sSortingClass = oClasses.sSortableDesc;
2132
			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2133
		}
2134
		else
2135
		{
2136
			oCol.sSortingClass = oClasses.sSortable;
2137
			oCol.sSortingClassJUI = oClasses.sSortJUI;
2138
		}
2139
	}
2140
	
2141
	
2142
	/**
2143
	 * Adjust the table column widths for new data. Note: you would probably want to
2144
	 * do a redraw after calling this function!
2145
	 *  @param {object} settings dataTables settings object
2146
	 *  @memberof DataTable#oApi
2147
	 */
2148
	function _fnAdjustColumnSizing ( settings )
2149
	{
2150
		/* Not interested in doing column width calculation if auto-width is disabled */
2151
		if ( settings.oFeatures.bAutoWidth !== false )
2152
		{
2153
			var columns = settings.aoColumns;
2154
	
2155
			_fnCalculateColumnWidths( settings );
2156
			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2157
			{
2158
				columns[i].nTh.style.width = columns[i].sWidth;
2159
			}
2160
		}
2161
	
2162
		var scroll = settings.oScroll;
2163
		if ( scroll.sY !== '' || scroll.sX !== '')
2164
		{
2165
			_fnScrollDraw( settings );
2166
		}
2167
	
2168
		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2169
	}
2170
	
2171
	
2172
	/**
2173
	 * Covert the index of a visible column to the index in the data array (take account
2174
	 * of hidden columns)
2175
	 *  @param {object} oSettings dataTables settings object
2176
	 *  @param {int} iMatch Visible column index to lookup
2177
	 *  @returns {int} i the data index
2178
	 *  @memberof DataTable#oApi
2179
	 */
2180
	function _fnVisibleToColumnIndex( oSettings, iMatch )
2181
	{
2182
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2183
	
2184
		return typeof aiVis[iMatch] === 'number' ?
2185
			aiVis[iMatch] :
2186
			null;
2187
	}
2188
	
2189
	
2190
	/**
2191
	 * Covert the index of an index in the data array and convert it to the visible
2192
	 *   column index (take account of hidden columns)
2193
	 *  @param {int} iMatch Column index to lookup
2194
	 *  @param {object} oSettings dataTables settings object
2195
	 *  @returns {int} i the data index
2196
	 *  @memberof DataTable#oApi
2197
	 */
2198
	function _fnColumnIndexToVisible( oSettings, iMatch )
2199
	{
2200
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2201
		var iPos = $.inArray( iMatch, aiVis );
2202
	
2203
		return iPos !== -1 ? iPos : null;
2204
	}
2205
	
2206
	
2207
	/**
2208
	 * Get the number of visible columns
2209
	 *  @param {object} oSettings dataTables settings object
2210
	 *  @returns {int} i the number of visible columns
2211
	 *  @memberof DataTable#oApi
2212
	 */
2213
	function _fnVisbleColumns( oSettings )
2214
	{
2215
		var vis = 0;
2216
	
2217
		// No reduce in IE8, use a loop for now
2218
		$.each( oSettings.aoColumns, function ( i, col ) {
2219
			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2220
				vis++;
2221
			}
2222
		} );
2223
	
2224
		return vis;
2225
	}
2226
	
2227
	
2228
	/**
2229
	 * Get an array of column indexes that match a given property
2230
	 *  @param {object} oSettings dataTables settings object
2231
	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2232
	 *    bVisible or bSearchable
2233
	 *  @returns {array} Array of indexes with matched properties
2234
	 *  @memberof DataTable#oApi
2235
	 */
2236
	function _fnGetColumns( oSettings, sParam )
2237
	{
2238
		var a = [];
2239
	
2240
		$.map( oSettings.aoColumns, function(val, i) {
2241
			if ( val[sParam] ) {
2242
				a.push( i );
2243
			}
2244
		} );
2245
	
2246
		return a;
2247
	}
2248
	
2249
	
2250
	/**
2251
	 * Calculate the 'type' of a column
2252
	 *  @param {object} settings dataTables settings object
2253
	 *  @memberof DataTable#oApi
2254
	 */
2255
	function _fnColumnTypes ( settings )
2256
	{
2257
		var columns = settings.aoColumns;
2258
		var data = settings.aoData;
2259
		var types = DataTable.ext.type.detect;
2260
		var i, ien, j, jen, k, ken;
2261
		var col, cell, detectedType, cache;
2262
	
2263
		// For each column, spin over the 
2264
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2265
			col = columns[i];
2266
			cache = [];
2267
	
2268
			if ( ! col.sType && col._sManualType ) {
2269
				col.sType = col._sManualType;
2270
			}
2271
			else if ( ! col.sType ) {
2272
				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2273
					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2274
						// Use a cache array so we only need to get the type data
2275
						// from the formatter once (when using multiple detectors)
2276
						if ( cache[k] === undefined ) {
2277
							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2278
						}
2279
	
2280
						detectedType = types[j]( cache[k], settings );
2281
	
2282
						// If null, then this type can't apply to this column, so
2283
						// rather than testing all cells, break out. There is an
2284
						// exception for the last type which is `html`. We need to
2285
						// scan all rows since it is possible to mix string and HTML
2286
						// types
2287
						if ( ! detectedType && j !== types.length-1 ) {
2288
							break;
2289
						}
2290
	
2291
						// Only a single match is needed for html type since it is
2292
						// bottom of the pile and very similar to string
2293
						if ( detectedType === 'html' ) {
2294
							break;
2295
						}
2296
					}
2297
	
2298
					// Type is valid for all data points in the column - use this
2299
					// type
2300
					if ( detectedType ) {
2301
						col.sType = detectedType;
2302
						break;
2303
					}
2304
				}
2305
	
2306
				// Fall back - if no type was detected, always use string
2307
				if ( ! col.sType ) {
2308
					col.sType = 'string';
2309
				}
2310
			}
2311
		}
2312
	}
2313
	
2314
	
2315
	/**
2316
	 * Take the column definitions and static columns arrays and calculate how
2317
	 * they relate to column indexes. The callback function will then apply the
2318
	 * definition found for a column to a suitable configuration object.
2319
	 *  @param {object} oSettings dataTables settings object
2320
	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2321
	 *  @param {array} aoCols The aoColumns array that defines columns individually
2322
	 *  @param {function} fn Callback function - takes two parameters, the calculated
2323
	 *    column index and the definition for that column.
2324
	 *  @memberof DataTable#oApi
2325
	 */
2326
	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2327
	{
2328
		var i, iLen, j, jLen, k, kLen, def;
2329
		var columns = oSettings.aoColumns;
2330
	
2331
		// Column definitions with aTargets
2332
		if ( aoColDefs )
2333
		{
2334
			/* Loop over the definitions array - loop in reverse so first instance has priority */
2335
			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2336
			{
2337
				def = aoColDefs[i];
2338
	
2339
				/* Each definition can target multiple columns, as it is an array */
2340
				var aTargets = def.targets !== undefined ?
2341
					def.targets :
2342
					def.aTargets;
2343
	
2344
				if ( ! $.isArray( aTargets ) )
2345
				{
2346
					aTargets = [ aTargets ];
2347
				}
2348
	
2349
				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2350
				{
2351
					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2352
					{
2353
						/* Add columns that we don't yet know about */
2354
						while( columns.length <= aTargets[j] )
2355
						{
2356
							_fnAddColumn( oSettings );
2357
						}
2358
	
2359
						/* Integer, basic index */
2360
						fn( aTargets[j], def );
2361
					}
2362
					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2363
					{
2364
						/* Negative integer, right to left column counting */
2365
						fn( columns.length+aTargets[j], def );
2366
					}
2367
					else if ( typeof aTargets[j] === 'string' )
2368
					{
2369
						/* Class name matching on TH element */
2370
						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2371
						{
2372
							if ( aTargets[j] == "_all" ||
2373
							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2374
							{
2375
								fn( k, def );
2376
							}
2377
						}
2378
					}
2379
				}
2380
			}
2381
		}
2382
	
2383
		// Statically defined columns array
2384
		if ( aoCols )
2385
		{
2386
			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2387
			{
2388
				fn( i, aoCols[i] );
2389
			}
2390
		}
2391
	}
2392
	
2393
	/**
2394
	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2395
	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2396
	 * DOM source.
2397
	 *  @param {object} oSettings dataTables settings object
2398
	 *  @param {array} aData data array to be added
2399
	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2400
	 *    DataTables will create a row automatically
2401
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2402
	 *    if nTr is.
2403
	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2404
	 *  @memberof DataTable#oApi
2405
	 */
2406
	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2407
	{
2408
		/* Create the object for storing information about this new row */
2409
		var iRow = oSettings.aoData.length;
2410
		var oData = $.extend( true, {}, DataTable.models.oRow, {
2411
			src: nTr ? 'dom' : 'data',
2412
			idx: iRow
2413
		} );
2414
	
2415
		oData._aData = aDataIn;
2416
		oSettings.aoData.push( oData );
2417
	
2418
		/* Create the cells */
2419
		var nTd, sThisType;
2420
		var columns = oSettings.aoColumns;
2421
	
2422
		// Invalidate the column types as the new data needs to be revalidated
2423
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2424
		{
2425
			columns[i].sType = null;
2426
		}
2427
	
2428
		/* Add to the display array */
2429
		oSettings.aiDisplayMaster.push( iRow );
2430
	
2431
		var id = oSettings.rowIdFn( aDataIn );
2432
		if ( id !== undefined ) {
2433
			oSettings.aIds[ id ] = oData;
2434
		}
2435
	
2436
		/* Create the DOM information, or register it if already present */
2437
		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2438
		{
2439
			_fnCreateTr( oSettings, iRow, nTr, anTds );
2440
		}
2441
	
2442
		return iRow;
2443
	}
2444
	
2445
	
2446
	/**
2447
	 * Add one or more TR elements to the table. Generally we'd expect to
2448
	 * use this for reading data from a DOM sourced table, but it could be
2449
	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2450
	 * it is not cloned).
2451
	 *  @param {object} settings dataTables settings object
2452
	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2453
	 *  @returns {array} Array of indexes for the added rows
2454
	 *  @memberof DataTable#oApi
2455
	 */
2456
	function _fnAddTr( settings, trs )
2457
	{
2458
		var row;
2459
	
2460
		// Allow an individual node to be passed in
2461
		if ( ! (trs instanceof $) ) {
2462
			trs = $(trs);
2463
		}
2464
	
2465
		return trs.map( function (i, el) {
2466
			row = _fnGetRowElements( settings, el );
2467
			return _fnAddData( settings, row.data, el, row.cells );
2468
		} );
2469
	}
2470
	
2471
	
2472
	/**
2473
	 * Take a TR element and convert it to an index in aoData
2474
	 *  @param {object} oSettings dataTables settings object
2475
	 *  @param {node} n the TR element to find
2476
	 *  @returns {int} index if the node is found, null if not
2477
	 *  @memberof DataTable#oApi
2478
	 */
2479
	function _fnNodeToDataIndex( oSettings, n )
2480
	{
2481
		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2482
	}
2483
	
2484
	
2485
	/**
2486
	 * Take a TD element and convert it into a column data index (not the visible index)
2487
	 *  @param {object} oSettings dataTables settings object
2488
	 *  @param {int} iRow The row number the TD/TH can be found in
2489
	 *  @param {node} n The TD/TH element to find
2490
	 *  @returns {int} index if the node is found, -1 if not
2491
	 *  @memberof DataTable#oApi
2492
	 */
2493
	function _fnNodeToColumnIndex( oSettings, iRow, n )
2494
	{
2495
		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2496
	}
2497
	
2498
	
2499
	/**
2500
	 * Get the data for a given cell from the internal cache, taking into account data mapping
2501
	 *  @param {object} settings dataTables settings object
2502
	 *  @param {int} rowIdx aoData row id
2503
	 *  @param {int} colIdx Column index
2504
	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2505
	 *  @returns {*} Cell data
2506
	 *  @memberof DataTable#oApi
2507
	 */
2508
	function _fnGetCellData( settings, rowIdx, colIdx, type )
2509
	{
2510
		var draw           = settings.iDraw;
2511
		var col            = settings.aoColumns[colIdx];
2512
		var rowData        = settings.aoData[rowIdx]._aData;
2513
		var defaultContent = col.sDefaultContent;
2514
		var cellData       = col.fnGetData( rowData, type, {
2515
			settings: settings,
2516
			row:      rowIdx,
2517
			col:      colIdx
2518
		} );
2519
	
2520
		if ( cellData === undefined ) {
2521
			if ( settings.iDrawError != draw && defaultContent === null ) {
2522
				_fnLog( settings, 0, "Requested unknown parameter "+
2523
					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2524
					" for row "+rowIdx+", column "+colIdx, 4 );
2525
				settings.iDrawError = draw;
2526
			}
2527
			return defaultContent;
2528
		}
2529
	
2530
		// When the data source is null and a specific data type is requested (i.e.
2531
		// not the original data), we can use default column data
2532
		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2533
			cellData = defaultContent;
2534
		}
2535
		else if ( typeof cellData === 'function' ) {
2536
			// If the data source is a function, then we run it and use the return,
2537
			// executing in the scope of the data object (for instances)
2538
			return cellData.call( rowData );
2539
		}
2540
	
2541
		if ( cellData === null && type == 'display' ) {
2542
			return '';
2543
		}
2544
		return cellData;
2545
	}
2546
	
2547
	
2548
	/**
2549
	 * Set the value for a specific cell, into the internal data cache
2550
	 *  @param {object} settings dataTables settings object
2551
	 *  @param {int} rowIdx aoData row id
2552
	 *  @param {int} colIdx Column index
2553
	 *  @param {*} val Value to set
2554
	 *  @memberof DataTable#oApi
2555
	 */
2556
	function _fnSetCellData( settings, rowIdx, colIdx, val )
2557
	{
2558
		var col     = settings.aoColumns[colIdx];
2559
		var rowData = settings.aoData[rowIdx]._aData;
2560
	
2561
		col.fnSetData( rowData, val, {
2562
			settings: settings,
2563
			row:      rowIdx,
2564
			col:      colIdx
2565
		}  );
2566
	}
2567
	
2568
	
2569
	// Private variable that is used to match action syntax in the data property object
2570
	var __reArray = /\[.*?\]$/;
2571
	var __reFn = /\(\)$/;
2572
	
2573
	/**
2574
	 * Split string on periods, taking into account escaped periods
2575
	 * @param  {string} str String to split
2576
	 * @return {array} Split string
2577
	 */
2578
	function _fnSplitObjNotation( str )
2579
	{
2580
		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2581
			return s.replace(/\\\./g, '.');
2582
		} );
2583
	}
2584
	
2585
	
2586
	/**
2587
	 * Return a function that can be used to get data from a source object, taking
2588
	 * into account the ability to use nested objects as a source
2589
	 *  @param {string|int|function} mSource The data source for the object
2590
	 *  @returns {function} Data get function
2591
	 *  @memberof DataTable#oApi
2592
	 */
2593
	function _fnGetObjectDataFn( mSource )
2594
	{
2595
		if ( $.isPlainObject( mSource ) )
2596
		{
2597
			/* Build an object of get functions, and wrap them in a single call */
2598
			var o = {};
2599
			$.each( mSource, function (key, val) {
2600
				if ( val ) {
2601
					o[key] = _fnGetObjectDataFn( val );
2602
				}
2603
			} );
2604
	
2605
			return function (data, type, row, meta) {
2606
				var t = o[type] || o._;
2607
				return t !== undefined ?
2608
					t(data, type, row, meta) :
2609
					data;
2610
			};
2611
		}
2612
		else if ( mSource === null )
2613
		{
2614
			/* Give an empty string for rendering / sorting etc */
2615
			return function (data) { // type, row and meta also passed, but not used
2616
				return data;
2617
			};
2618
		}
2619
		else if ( typeof mSource === 'function' )
2620
		{
2621
			return function (data, type, row, meta) {
2622
				return mSource( data, type, row, meta );
2623
			};
2624
		}
2625
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2626
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2627
		{
2628
			/* If there is a . in the source string then the data source is in a
2629
			 * nested object so we loop over the data for each level to get the next
2630
			 * level down. On each loop we test for undefined, and if found immediately
2631
			 * return. This allows entire objects to be missing and sDefaultContent to
2632
			 * be used if defined, rather than throwing an error
2633
			 */
2634
			var fetchData = function (data, type, src) {
2635
				var arrayNotation, funcNotation, out, innerSrc;
2636
	
2637
				if ( src !== "" )
2638
				{
2639
					var a = _fnSplitObjNotation( src );
2640
	
2641
					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2642
					{
2643
						// Check if we are dealing with special notation
2644
						arrayNotation = a[i].match(__reArray);
2645
						funcNotation = a[i].match(__reFn);
2646
	
2647
						if ( arrayNotation )
2648
						{
2649
							// Array notation
2650
							a[i] = a[i].replace(__reArray, '');
2651
	
2652
							// Condition allows simply [] to be passed in
2653
							if ( a[i] !== "" ) {
2654
								data = data[ a[i] ];
2655
							}
2656
							out = [];
2657
	
2658
							// Get the remainder of the nested object to get
2659
							a.splice( 0, i+1 );
2660
							innerSrc = a.join('.');
2661
	
2662
							// Traverse each entry in the array getting the properties requested
2663
							if ( $.isArray( data ) ) {
2664
								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2665
									out.push( fetchData( data[j], type, innerSrc ) );
2666
								}
2667
							}
2668
	
2669
							// If a string is given in between the array notation indicators, that
2670
							// is used to join the strings together, otherwise an array is returned
2671
							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2672
							data = (join==="") ? out : out.join(join);
2673
	
2674
							// The inner call to fetchData has already traversed through the remainder
2675
							// of the source requested, so we exit from the loop
2676
							break;
2677
						}
2678
						else if ( funcNotation )
2679
						{
2680
							// Function call
2681
							a[i] = a[i].replace(__reFn, '');
2682
							data = data[ a[i] ]();
2683
							continue;
2684
						}
2685
	
2686
						if ( data === null || data[ a[i] ] === undefined )
2687
						{
2688
							return undefined;
2689
						}
2690
						data = data[ a[i] ];
2691
					}
2692
				}
2693
	
2694
				return data;
2695
			};
2696
	
2697
			return function (data, type) { // row and meta also passed, but not used
2698
				return fetchData( data, type, mSource );
2699
			};
2700
		}
2701
		else
2702
		{
2703
			/* Array or flat object mapping */
2704
			return function (data, type) { // row and meta also passed, but not used
2705
				return data[mSource];
2706
			};
2707
		}
2708
	}
2709
	
2710
	
2711
	/**
2712
	 * Return a function that can be used to set data from a source object, taking
2713
	 * into account the ability to use nested objects as a source
2714
	 *  @param {string|int|function} mSource The data source for the object
2715
	 *  @returns {function} Data set function
2716
	 *  @memberof DataTable#oApi
2717
	 */
2718
	function _fnSetObjectDataFn( mSource )
2719
	{
2720
		if ( $.isPlainObject( mSource ) )
2721
		{
2722
			/* Unlike get, only the underscore (global) option is used for for
2723
			 * setting data since we don't know the type here. This is why an object
2724
			 * option is not documented for `mData` (which is read/write), but it is
2725
			 * for `mRender` which is read only.
2726
			 */
2727
			return _fnSetObjectDataFn( mSource._ );
2728
		}
2729
		else if ( mSource === null )
2730
		{
2731
			/* Nothing to do when the data source is null */
2732
			return function () {};
2733
		}
2734
		else if ( typeof mSource === 'function' )
2735
		{
2736
			return function (data, val, meta) {
2737
				mSource( data, 'set', val, meta );
2738
			};
2739
		}
2740
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2741
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2742
		{
2743
			/* Like the get, we need to get data from a nested object */
2744
			var setData = function (data, val, src) {
2745
				var a = _fnSplitObjNotation( src ), b;
2746
				var aLast = a[a.length-1];
2747
				var arrayNotation, funcNotation, o, innerSrc;
2748
	
2749
				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2750
				{
2751
					// Check if we are dealing with an array notation request
2752
					arrayNotation = a[i].match(__reArray);
2753
					funcNotation = a[i].match(__reFn);
2754
	
2755
					if ( arrayNotation )
2756
					{
2757
						a[i] = a[i].replace(__reArray, '');
2758
						data[ a[i] ] = [];
2759
	
2760
						// Get the remainder of the nested object to set so we can recurse
2761
						b = a.slice();
2762
						b.splice( 0, i+1 );
2763
						innerSrc = b.join('.');
2764
	
2765
						// Traverse each entry in the array setting the properties requested
2766
						if ( $.isArray( val ) )
2767
						{
2768
							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2769
							{
2770
								o = {};
2771
								setData( o, val[j], innerSrc );
2772
								data[ a[i] ].push( o );
2773
							}
2774
						}
2775
						else
2776
						{
2777
							// We've been asked to save data to an array, but it
2778
							// isn't array data to be saved. Best that can be done
2779
							// is to just save the value.
2780
							data[ a[i] ] = val;
2781
						}
2782
	
2783
						// The inner call to setData has already traversed through the remainder
2784
						// of the source and has set the data, thus we can exit here
2785
						return;
2786
					}
2787
					else if ( funcNotation )
2788
					{
2789
						// Function call
2790
						a[i] = a[i].replace(__reFn, '');
2791
						data = data[ a[i] ]( val );
2792
					}
2793
	
2794
					// If the nested object doesn't currently exist - since we are
2795
					// trying to set the value - create it
2796
					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2797
					{
2798
						data[ a[i] ] = {};
2799
					}
2800
					data = data[ a[i] ];
2801
				}
2802
	
2803
				// Last item in the input - i.e, the actual set
2804
				if ( aLast.match(__reFn ) )
2805
				{
2806
					// Function call
2807
					data = data[ aLast.replace(__reFn, '') ]( val );
2808
				}
2809
				else
2810
				{
2811
					// If array notation is used, we just want to strip it and use the property name
2812
					// and assign the value. If it isn't used, then we get the result we want anyway
2813
					data[ aLast.replace(__reArray, '') ] = val;
2814
				}
2815
			};
2816
	
2817
			return function (data, val) { // meta is also passed in, but not used
2818
				return setData( data, val, mSource );
2819
			};
2820
		}
2821
		else
2822
		{
2823
			/* Array or flat object mapping */
2824
			return function (data, val) { // meta is also passed in, but not used
2825
				data[mSource] = val;
2826
			};
2827
		}
2828
	}
2829
	
2830
	
2831
	/**
2832
	 * Return an array with the full table data
2833
	 *  @param {object} oSettings dataTables settings object
2834
	 *  @returns array {array} aData Master data array
2835
	 *  @memberof DataTable#oApi
2836
	 */
2837
	function _fnGetDataMaster ( settings )
2838
	{
2839
		return _pluck( settings.aoData, '_aData' );
2840
	}
2841
	
2842
	
2843
	/**
2844
	 * Nuke the table
2845
	 *  @param {object} oSettings dataTables settings object
2846
	 *  @memberof DataTable#oApi
2847
	 */
2848
	function _fnClearTable( settings )
2849
	{
2850
		settings.aoData.length = 0;
2851
		settings.aiDisplayMaster.length = 0;
2852
		settings.aiDisplay.length = 0;
2853
		settings.aIds = {};
2854
	}
2855
	
2856
	
2857
	 /**
2858
	 * Take an array of integers (index array) and remove a target integer (value - not
2859
	 * the key!)
2860
	 *  @param {array} a Index array to target
2861
	 *  @param {int} iTarget value to find
2862
	 *  @memberof DataTable#oApi
2863
	 */
2864
	function _fnDeleteIndex( a, iTarget, splice )
2865
	{
2866
		var iTargetIndex = -1;
2867
	
2868
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2869
		{
2870
			if ( a[i] == iTarget )
2871
			{
2872
				iTargetIndex = i;
2873
			}
2874
			else if ( a[i] > iTarget )
2875
			{
2876
				a[i]--;
2877
			}
2878
		}
2879
	
2880
		if ( iTargetIndex != -1 && splice === undefined )
2881
		{
2882
			a.splice( iTargetIndex, 1 );
2883
		}
2884
	}
2885
	
2886
	
2887
	/**
2888
	 * Mark cached data as invalid such that a re-read of the data will occur when
2889
	 * the cached data is next requested. Also update from the data source object.
2890
	 *
2891
	 * @param {object} settings DataTables settings object
2892
	 * @param {int}    rowIdx   Row index to invalidate
2893
	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2894
	 *     or 'data'
2895
	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2896
	 *     row will be invalidated
2897
	 * @memberof DataTable#oApi
2898
	 *
2899
	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2900
	 *   the sort and filter methods can subscribe to it. That will required
2901
	 *   initialisation options for sorting, which is why it is not already baked in
2902
	 */
2903
	function _fnInvalidate( settings, rowIdx, src, colIdx )
2904
	{
2905
		var row = settings.aoData[ rowIdx ];
2906
		var i, ien;
2907
		var cellWrite = function ( cell, col ) {
2908
			// This is very frustrating, but in IE if you just write directly
2909
			// to innerHTML, and elements that are overwritten are GC'ed,
2910
			// even if there is a reference to them elsewhere
2911
			while ( cell.childNodes.length ) {
2912
				cell.removeChild( cell.firstChild );
2913
			}
2914
	
2915
			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2916
		};
2917
	
2918
		// Are we reading last data from DOM or the data object?
2919
		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2920
			// Read the data from the DOM
2921
			row._aData = _fnGetRowElements(
2922
					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2923
				)
2924
				.data;
2925
		}
2926
		else {
2927
			// Reading from data object, update the DOM
2928
			var cells = row.anCells;
2929
	
2930
			if ( cells ) {
2931
				if ( colIdx !== undefined ) {
2932
					cellWrite( cells[colIdx], colIdx );
2933
				}
2934
				else {
2935
					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2936
						cellWrite( cells[i], i );
2937
					}
2938
				}
2939
			}
2940
		}
2941
	
2942
		// For both row and cell invalidation, the cached data for sorting and
2943
		// filtering is nulled out
2944
		row._aSortData = null;
2945
		row._aFilterData = null;
2946
	
2947
		// Invalidate the type for a specific column (if given) or all columns since
2948
		// the data might have changed
2949
		var cols = settings.aoColumns;
2950
		if ( colIdx !== undefined ) {
2951
			cols[ colIdx ].sType = null;
2952
		}
2953
		else {
2954
			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2955
				cols[i].sType = null;
2956
			}
2957
	
2958
			// Update DataTables special `DT_*` attributes for the row
2959
			_fnRowAttributes( settings, row );
2960
		}
2961
	}
2962
	
2963
	
2964
	/**
2965
	 * Build a data source object from an HTML row, reading the contents of the
2966
	 * cells that are in the row.
2967
	 *
2968
	 * @param {object} settings DataTables settings object
2969
	 * @param {node|object} TR element from which to read data or existing row
2970
	 *   object from which to re-read the data from the cells
2971
	 * @param {int} [colIdx] Optional column index
2972
	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
2973
	 *   parameter should also be given and will be used to write the data into.
2974
	 *   Only the column in question will be written
2975
	 * @returns {object} Object with two parameters: `data` the data read, in
2976
	 *   document order, and `cells` and array of nodes (they can be useful to the
2977
	 *   caller, so rather than needing a second traversal to get them, just return
2978
	 *   them from here).
2979
	 * @memberof DataTable#oApi
2980
	 */
2981
	function _fnGetRowElements( settings, row, colIdx, d )
2982
	{
2983
		var
2984
			tds = [],
2985
			td = row.firstChild,
2986
			name, col, o, i=0, contents,
2987
			columns = settings.aoColumns,
2988
			objectRead = settings._rowReadObject;
2989
	
2990
		// Allow the data object to be passed in, or construct
2991
		d = d !== undefined ?
2992
			d :
2993
			objectRead ?
2994
				{} :
2995
				[];
2996
	
2997
		var attr = function ( str, td  ) {
2998
			if ( typeof str === 'string' ) {
2999
				var idx = str.indexOf('@');
3000
	
3001
				if ( idx !== -1 ) {
3002
					var attr = str.substring( idx+1 );
3003
					var setter = _fnSetObjectDataFn( str );
3004
					setter( d, td.getAttribute( attr ) );
3005
				}
3006
			}
3007
		};
3008
	
3009
		// Read data from a cell and store into the data object
3010
		var cellProcess = function ( cell ) {
3011
			if ( colIdx === undefined || colIdx === i ) {
3012
				col = columns[i];
3013
				contents = $.trim(cell.innerHTML);
3014
	
3015
				if ( col && col._bAttrSrc ) {
3016
					var setter = _fnSetObjectDataFn( col.mData._ );
3017
					setter( d, contents );
3018
	
3019
					attr( col.mData.sort, cell );
3020
					attr( col.mData.type, cell );
3021
					attr( col.mData.filter, cell );
3022
				}
3023
				else {
3024
					// Depending on the `data` option for the columns the data can
3025
					// be read to either an object or an array.
3026
					if ( objectRead ) {
3027
						if ( ! col._setter ) {
3028
							// Cache the setter function
3029
							col._setter = _fnSetObjectDataFn( col.mData );
3030
						}
3031
						col._setter( d, contents );
3032
					}
3033
					else {
3034
						d[i] = contents;
3035
					}
3036
				}
3037
			}
3038
	
3039
			i++;
3040
		};
3041
	
3042
		if ( td ) {
3043
			// `tr` element was passed in
3044
			while ( td ) {
3045
				name = td.nodeName.toUpperCase();
3046
	
3047
				if ( name == "TD" || name == "TH" ) {
3048
					cellProcess( td );
3049
					tds.push( td );
3050
				}
3051
	
3052
				td = td.nextSibling;
3053
			}
3054
		}
3055
		else {
3056
			// Existing row object passed in
3057
			tds = row.anCells;
3058
	
3059
			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3060
				cellProcess( tds[j] );
3061
			}
3062
		}
3063
	
3064
		// Read the ID from the DOM if present
3065
		var rowNode = row.firstChild ? row : row.nTr;
3066
	
3067
		if ( rowNode ) {
3068
			var id = rowNode.getAttribute( 'id' );
3069
	
3070
			if ( id ) {
3071
				_fnSetObjectDataFn( settings.rowId )( d, id );
3072
			}
3073
		}
3074
	
3075
		return {
3076
			data: d,
3077
			cells: tds
3078
		};
3079
	}
3080
	/**
3081
	 * Create a new TR element (and it's TD children) for a row
3082
	 *  @param {object} oSettings dataTables settings object
3083
	 *  @param {int} iRow Row to consider
3084
	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3085
	 *    DataTables will create a row automatically
3086
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3087
	 *    if nTr is.
3088
	 *  @memberof DataTable#oApi
3089
	 */
3090
	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3091
	{
3092
		var
3093
			row = oSettings.aoData[iRow],
3094
			rowData = row._aData,
3095
			cells = [],
3096
			nTr, nTd, oCol,
3097
			i, iLen;
3098
	
3099
		if ( row.nTr === null )
3100
		{
3101
			nTr = nTrIn || document.createElement('tr');
3102
	
3103
			row.nTr = nTr;
3104
			row.anCells = cells;
3105
	
3106
			/* Use a private property on the node to allow reserve mapping from the node
3107
			 * to the aoData array for fast look up
3108
			 */
3109
			nTr._DT_RowIndex = iRow;
3110
	
3111
			/* Special parameters can be given by the data source to be used on the row */
3112
			_fnRowAttributes( oSettings, row );
3113
	
3114
			/* Process each column */
3115
			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3116
			{
3117
				oCol = oSettings.aoColumns[i];
3118
	
3119
				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3120
				nTd._DT_CellIndex = {
3121
					row: iRow,
3122
					column: i
3123
				};
3124
				
3125
				cells.push( nTd );
3126
	
3127
				// Need to create the HTML if new, or if a rendering function is defined
3128
				if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3129
					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3130
				) {
3131
					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3132
				}
3133
	
3134
				/* Add user defined class */
3135
				if ( oCol.sClass )
3136
				{
3137
					nTd.className += ' '+oCol.sClass;
3138
				}
3139
	
3140
				// Visibility - add or remove as required
3141
				if ( oCol.bVisible && ! nTrIn )
3142
				{
3143
					nTr.appendChild( nTd );
3144
				}
3145
				else if ( ! oCol.bVisible && nTrIn )
3146
				{
3147
					nTd.parentNode.removeChild( nTd );
3148
				}
3149
	
3150
				if ( oCol.fnCreatedCell )
3151
				{
3152
					oCol.fnCreatedCell.call( oSettings.oInstance,
3153
						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3154
					);
3155
				}
3156
			}
3157
	
3158
			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3159
		}
3160
	
3161
		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3162
		// and deployed
3163
		row.nTr.setAttribute( 'role', 'row' );
3164
	}
3165
	
3166
	
3167
	/**
3168
	 * Add attributes to a row based on the special `DT_*` parameters in a data
3169
	 * source object.
3170
	 *  @param {object} settings DataTables settings object
3171
	 *  @param {object} DataTables row object for the row to be modified
3172
	 *  @memberof DataTable#oApi
3173
	 */
3174
	function _fnRowAttributes( settings, row )
3175
	{
3176
		var tr = row.nTr;
3177
		var data = row._aData;
3178
	
3179
		if ( tr ) {
3180
			var id = settings.rowIdFn( data );
3181
	
3182
			if ( id ) {
3183
				tr.id = id;
3184
			}
3185
	
3186
			if ( data.DT_RowClass ) {
3187
				// Remove any classes added by DT_RowClass before
3188
				var a = data.DT_RowClass.split(' ');
3189
				row.__rowc = row.__rowc ?
3190
					_unique( row.__rowc.concat( a ) ) :
3191
					a;
3192
	
3193
				$(tr)
3194
					.removeClass( row.__rowc.join(' ') )
3195
					.addClass( data.DT_RowClass );
3196
			}
3197
	
3198
			if ( data.DT_RowAttr ) {
3199
				$(tr).attr( data.DT_RowAttr );
3200
			}
3201
	
3202
			if ( data.DT_RowData ) {
3203
				$(tr).data( data.DT_RowData );
3204
			}
3205
		}
3206
	}
3207
	
3208
	
3209
	/**
3210
	 * Create the HTML header for the table
3211
	 *  @param {object} oSettings dataTables settings object
3212
	 *  @memberof DataTable#oApi
3213
	 */
3214
	function _fnBuildHead( oSettings )
3215
	{
3216
		var i, ien, cell, row, column;
3217
		var thead = oSettings.nTHead;
3218
		var tfoot = oSettings.nTFoot;
3219
		var createHeader = $('th, td', thead).length === 0;
3220
		var classes = oSettings.oClasses;
3221
		var columns = oSettings.aoColumns;
3222
	
3223
		if ( createHeader ) {
3224
			row = $('<tr/>').appendTo( thead );
3225
		}
3226
	
3227
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3228
			column = columns[i];
3229
			cell = $( column.nTh ).addClass( column.sClass );
3230
	
3231
			if ( createHeader ) {
3232
				cell.appendTo( row );
3233
			}
3234
	
3235
			// 1.11 move into sorting
3236
			if ( oSettings.oFeatures.bSort ) {
3237
				cell.addClass( column.sSortingClass );
3238
	
3239
				if ( column.bSortable !== false ) {
3240
					cell
3241
						.attr( 'tabindex', oSettings.iTabIndex )
3242
						.attr( 'aria-controls', oSettings.sTableId );
3243
	
3244
					_fnSortAttachListener( oSettings, column.nTh, i );
3245
				}
3246
			}
3247
	
3248
			if ( column.sTitle != cell[0].innerHTML ) {
3249
				cell.html( column.sTitle );
3250
			}
3251
	
3252
			_fnRenderer( oSettings, 'header' )(
3253
				oSettings, cell, column, classes
3254
			);
3255
		}
3256
	
3257
		if ( createHeader ) {
3258
			_fnDetectHeader( oSettings.aoHeader, thead );
3259
		}
3260
		
3261
		/* ARIA role for the rows */
3262
	 	$(thead).find('>tr').attr('role', 'row');
3263
	
3264
		/* Deal with the footer - add classes if required */
3265
		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3266
		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3267
	
3268
		// Cache the footer cells. Note that we only take the cells from the first
3269
		// row in the footer. If there is more than one row the user wants to
3270
		// interact with, they need to use the table().foot() method. Note also this
3271
		// allows cells to be used for multiple columns using colspan
3272
		if ( tfoot !== null ) {
3273
			var cells = oSettings.aoFooter[0];
3274
	
3275
			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3276
				column = columns[i];
3277
				column.nTf = cells[i].cell;
3278
	
3279
				if ( column.sClass ) {
3280
					$(column.nTf).addClass( column.sClass );
3281
				}
3282
			}
3283
		}
3284
	}
3285
	
3286
	
3287
	/**
3288
	 * Draw the header (or footer) element based on the column visibility states. The
3289
	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3290
	 * the instantaneous column visibility, to construct the new layout. The grid is
3291
	 * traversed over cell at a time in a rows x columns grid fashion, although each
3292
	 * cell insert can cover multiple elements in the grid - which is tracks using the
3293
	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3294
	 * already a cell in that position.
3295
	 *  @param {object} oSettings dataTables settings object
3296
	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3297
	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3298
	 *  @memberof DataTable#oApi
3299
	 */
3300
	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3301
	{
3302
		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3303
		var aoLocal = [];
3304
		var aApplied = [];
3305
		var iColumns = oSettings.aoColumns.length;
3306
		var iRowspan, iColspan;
3307
	
3308
		if ( ! aoSource )
3309
		{
3310
			return;
3311
		}
3312
	
3313
		if (  bIncludeHidden === undefined )
3314
		{
3315
			bIncludeHidden = false;
3316
		}
3317
	
3318
		/* Make a copy of the master layout array, but without the visible columns in it */
3319
		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3320
		{
3321
			aoLocal[i] = aoSource[i].slice();
3322
			aoLocal[i].nTr = aoSource[i].nTr;
3323
	
3324
			/* Remove any columns which are currently hidden */
3325
			for ( j=iColumns-1 ; j>=0 ; j-- )
3326
			{
3327
				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3328
				{
3329
					aoLocal[i].splice( j, 1 );
3330
				}
3331
			}
3332
	
3333
			/* Prep the applied array - it needs an element for each row */
3334
			aApplied.push( [] );
3335
		}
3336
	
3337
		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3338
		{
3339
			nLocalTr = aoLocal[i].nTr;
3340
	
3341
			/* All cells are going to be replaced, so empty out the row */
3342
			if ( nLocalTr )
3343
			{
3344
				while( (n = nLocalTr.firstChild) )
3345
				{
3346
					nLocalTr.removeChild( n );
3347
				}
3348
			}
3349
	
3350
			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3351
			{
3352
				iRowspan = 1;
3353
				iColspan = 1;
3354
	
3355
				/* Check to see if there is already a cell (row/colspan) covering our target
3356
				 * insert point. If there is, then there is nothing to do.
3357
				 */
3358
				if ( aApplied[i][j] === undefined )
3359
				{
3360
					nLocalTr.appendChild( aoLocal[i][j].cell );
3361
					aApplied[i][j] = 1;
3362
	
3363
					/* Expand the cell to cover as many rows as needed */
3364
					while ( aoLocal[i+iRowspan] !== undefined &&
3365
					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3366
					{
3367
						aApplied[i+iRowspan][j] = 1;
3368
						iRowspan++;
3369
					}
3370
	
3371
					/* Expand the cell to cover as many columns as needed */
3372
					while ( aoLocal[i][j+iColspan] !== undefined &&
3373
					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3374
					{
3375
						/* Must update the applied array over the rows for the columns */
3376
						for ( k=0 ; k<iRowspan ; k++ )
3377
						{
3378
							aApplied[i+k][j+iColspan] = 1;
3379
						}
3380
						iColspan++;
3381
					}
3382
	
3383
					/* Do the actual expansion in the DOM */
3384
					$(aoLocal[i][j].cell)
3385
						.attr('rowspan', iRowspan)
3386
						.attr('colspan', iColspan);
3387
				}
3388
			}
3389
		}
3390
	}
3391
	
3392
	
3393
	/**
3394
	 * Insert the required TR nodes into the table for display
3395
	 *  @param {object} oSettings dataTables settings object
3396
	 *  @memberof DataTable#oApi
3397
	 */
3398
	function _fnDraw( oSettings )
3399
	{
3400
		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3401
		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3402
		if ( $.inArray( false, aPreDraw ) !== -1 )
3403
		{
3404
			_fnProcessingDisplay( oSettings, false );
3405
			return;
3406
		}
3407
	
3408
		var i, iLen, n;
3409
		var anRows = [];
3410
		var iRowCount = 0;
3411
		var asStripeClasses = oSettings.asStripeClasses;
3412
		var iStripes = asStripeClasses.length;
3413
		var iOpenRows = oSettings.aoOpenRows.length;
3414
		var oLang = oSettings.oLanguage;
3415
		var iInitDisplayStart = oSettings.iInitDisplayStart;
3416
		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3417
		var aiDisplay = oSettings.aiDisplay;
3418
	
3419
		oSettings.bDrawing = true;
3420
	
3421
		/* Check and see if we have an initial draw position from state saving */
3422
		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3423
		{
3424
			oSettings._iDisplayStart = bServerSide ?
3425
				iInitDisplayStart :
3426
				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3427
					0 :
3428
					iInitDisplayStart;
3429
	
3430
			oSettings.iInitDisplayStart = -1;
3431
		}
3432
	
3433
		var iDisplayStart = oSettings._iDisplayStart;
3434
		var iDisplayEnd = oSettings.fnDisplayEnd();
3435
	
3436
		/* Server-side processing draw intercept */
3437
		if ( oSettings.bDeferLoading )
3438
		{
3439
			oSettings.bDeferLoading = false;
3440
			oSettings.iDraw++;
3441
			_fnProcessingDisplay( oSettings, false );
3442
		}
3443
		else if ( !bServerSide )
3444
		{
3445
			oSettings.iDraw++;
3446
		}
3447
		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3448
		{
3449
			return;
3450
		}
3451
	
3452
		if ( aiDisplay.length !== 0 )
3453
		{
3454
			var iStart = bServerSide ? 0 : iDisplayStart;
3455
			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3456
	
3457
			for ( var j=iStart ; j<iEnd ; j++ )
3458
			{
3459
				var iDataIndex = aiDisplay[j];
3460
				var aoData = oSettings.aoData[ iDataIndex ];
3461
				if ( aoData.nTr === null )
3462
				{
3463
					_fnCreateTr( oSettings, iDataIndex );
3464
				}
3465
	
3466
				var nRow = aoData.nTr;
3467
	
3468
				/* Remove the old striping classes and then add the new one */
3469
				if ( iStripes !== 0 )
3470
				{
3471
					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3472
					if ( aoData._sRowStripe != sStripe )
3473
					{
3474
						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3475
						aoData._sRowStripe = sStripe;
3476
					}
3477
				}
3478
	
3479
				// Row callback functions - might want to manipulate the row
3480
				// iRowCount and j are not currently documented. Are they at all
3481
				// useful?
3482
				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3483
					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3484
	
3485
				anRows.push( nRow );
3486
				iRowCount++;
3487
			}
3488
		}
3489
		else
3490
		{
3491
			/* Table is empty - create a row with an empty message in it */
3492
			var sZero = oLang.sZeroRecords;
3493
			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3494
			{
3495
				sZero = oLang.sLoadingRecords;
3496
			}
3497
			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3498
			{
3499
				sZero = oLang.sEmptyTable;
3500
			}
3501
	
3502
			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3503
				.append( $('<td />', {
3504
					'valign':  'top',
3505
					'colSpan': _fnVisbleColumns( oSettings ),
3506
					'class':   oSettings.oClasses.sRowEmpty
3507
				} ).html( sZero ) )[0];
3508
		}
3509
	
3510
		/* Header and footer callbacks */
3511
		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3512
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3513
	
3514
		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3515
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3516
	
3517
		var body = $(oSettings.nTBody);
3518
	
3519
		body.children().detach();
3520
		body.append( $(anRows) );
3521
	
3522
		/* Call all required callback functions for the end of a draw */
3523
		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3524
	
3525
		/* Draw is complete, sorting and filtering must be as well */
3526
		oSettings.bSorted = false;
3527
		oSettings.bFiltered = false;
3528
		oSettings.bDrawing = false;
3529
	}
3530
	
3531
	
3532
	/**
3533
	 * Redraw the table - taking account of the various features which are enabled
3534
	 *  @param {object} oSettings dataTables settings object
3535
	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3536
	 *    the paging is reset to the first page
3537
	 *  @memberof DataTable#oApi
3538
	 */
3539
	function _fnReDraw( settings, holdPosition )
3540
	{
3541
		var
3542
			features = settings.oFeatures,
3543
			sort     = features.bSort,
3544
			filter   = features.bFilter;
3545
	
3546
		if ( sort ) {
3547
			_fnSort( settings );
3548
		}
3549
	
3550
		if ( filter ) {
3551
			_fnFilterComplete( settings, settings.oPreviousSearch );
3552
		}
3553
		else {
3554
			// No filtering, so we want to just use the display master
3555
			settings.aiDisplay = settings.aiDisplayMaster.slice();
3556
		}
3557
	
3558
		if ( holdPosition !== true ) {
3559
			settings._iDisplayStart = 0;
3560
		}
3561
	
3562
		// Let any modules know about the draw hold position state (used by
3563
		// scrolling internally)
3564
		settings._drawHold = holdPosition;
3565
	
3566
		_fnDraw( settings );
3567
	
3568
		settings._drawHold = false;
3569
	}
3570
	
3571
	
3572
	/**
3573
	 * Add the options to the page HTML for the table
3574
	 *  @param {object} oSettings dataTables settings object
3575
	 *  @memberof DataTable#oApi
3576
	 */
3577
	function _fnAddOptionsHtml ( oSettings )
3578
	{
3579
		var classes = oSettings.oClasses;
3580
		var table = $(oSettings.nTable);
3581
		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3582
		var features = oSettings.oFeatures;
3583
	
3584
		// All DataTables are wrapped in a div
3585
		var insert = $('<div/>', {
3586
			id:      oSettings.sTableId+'_wrapper',
3587
			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3588
		} );
3589
	
3590
		oSettings.nHolding = holding[0];
3591
		oSettings.nTableWrapper = insert[0];
3592
		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3593
	
3594
		/* Loop over the user set positioning and place the elements as needed */
3595
		var aDom = oSettings.sDom.split('');
3596
		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3597
		for ( var i=0 ; i<aDom.length ; i++ )
3598
		{
3599
			featureNode = null;
3600
			cOption = aDom[i];
3601
	
3602
			if ( cOption == '<' )
3603
			{
3604
				/* New container div */
3605
				nNewNode = $('<div/>')[0];
3606
	
3607
				/* Check to see if we should append an id and/or a class name to the container */
3608
				cNext = aDom[i+1];
3609
				if ( cNext == "'" || cNext == '"' )
3610
				{
3611
					sAttr = "";
3612
					j = 2;
3613
					while ( aDom[i+j] != cNext )
3614
					{
3615
						sAttr += aDom[i+j];
3616
						j++;
3617
					}
3618
	
3619
					/* Replace jQuery UI constants @todo depreciated */
3620
					if ( sAttr == "H" )
3621
					{
3622
						sAttr = classes.sJUIHeader;
3623
					}
3624
					else if ( sAttr == "F" )
3625
					{
3626
						sAttr = classes.sJUIFooter;
3627
					}
3628
	
3629
					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3630
					 * breaks the string into parts and applies them as needed
3631
					 */
3632
					if ( sAttr.indexOf('.') != -1 )
3633
					{
3634
						var aSplit = sAttr.split('.');
3635
						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3636
						nNewNode.className = aSplit[1];
3637
					}
3638
					else if ( sAttr.charAt(0) == "#" )
3639
					{
3640
						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3641
					}
3642
					else
3643
					{
3644
						nNewNode.className = sAttr;
3645
					}
3646
	
3647
					i += j; /* Move along the position array */
3648
				}
3649
	
3650
				insert.append( nNewNode );
3651
				insert = $(nNewNode);
3652
			}
3653
			else if ( cOption == '>' )
3654
			{
3655
				/* End container div */
3656
				insert = insert.parent();
3657
			}
3658
			// @todo Move options into their own plugins?
3659
			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3660
			{
3661
				/* Length */
3662
				featureNode = _fnFeatureHtmlLength( oSettings );
3663
			}
3664
			else if ( cOption == 'f' && features.bFilter )
3665
			{
3666
				/* Filter */
3667
				featureNode = _fnFeatureHtmlFilter( oSettings );
3668
			}
3669
			else if ( cOption == 'r' && features.bProcessing )
3670
			{
3671
				/* pRocessing */
3672
				featureNode = _fnFeatureHtmlProcessing( oSettings );
3673
			}
3674
			else if ( cOption == 't' )
3675
			{
3676
				/* Table */
3677
				featureNode = _fnFeatureHtmlTable( oSettings );
3678
			}
3679
			else if ( cOption ==  'i' && features.bInfo )
3680
			{
3681
				/* Info */
3682
				featureNode = _fnFeatureHtmlInfo( oSettings );
3683
			}
3684
			else if ( cOption == 'p' && features.bPaginate )
3685
			{
3686
				/* Pagination */
3687
				featureNode = _fnFeatureHtmlPaginate( oSettings );
3688
			}
3689
			else if ( DataTable.ext.feature.length !== 0 )
3690
			{
3691
				/* Plug-in features */
3692
				var aoFeatures = DataTable.ext.feature;
3693
				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3694
				{
3695
					if ( cOption == aoFeatures[k].cFeature )
3696
					{
3697
						featureNode = aoFeatures[k].fnInit( oSettings );
3698
						break;
3699
					}
3700
				}
3701
			}
3702
	
3703
			/* Add to the 2D features array */
3704
			if ( featureNode )
3705
			{
3706
				var aanFeatures = oSettings.aanFeatures;
3707
	
3708
				if ( ! aanFeatures[cOption] )
3709
				{
3710
					aanFeatures[cOption] = [];
3711
				}
3712
	
3713
				aanFeatures[cOption].push( featureNode );
3714
				insert.append( featureNode );
3715
			}
3716
		}
3717
	
3718
		/* Built our DOM structure - replace the holding div with what we want */
3719
		holding.replaceWith( insert );
3720
		oSettings.nHolding = null;
3721
	}
3722
	
3723
	
3724
	/**
3725
	 * Use the DOM source to create up an array of header cells. The idea here is to
3726
	 * create a layout grid (array) of rows x columns, which contains a reference
3727
	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3728
	 * any column / row could be removed and the new grid constructed
3729
	 *  @param array {object} aLayout Array to store the calculated layout in
3730
	 *  @param {node} nThead The header/footer element for the table
3731
	 *  @memberof DataTable#oApi
3732
	 */
3733
	function _fnDetectHeader ( aLayout, nThead )
3734
	{
3735
		var nTrs = $(nThead).children('tr');
3736
		var nTr, nCell;
3737
		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3738
		var bUnique;
3739
		var fnShiftCol = function ( a, i, j ) {
3740
			var k = a[i];
3741
	                while ( k[j] ) {
3742
				j++;
3743
			}
3744
			return j;
3745
		};
3746
	
3747
		aLayout.splice( 0, aLayout.length );
3748
	
3749
		/* We know how many rows there are in the layout - so prep it */
3750
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3751
		{
3752
			aLayout.push( [] );
3753
		}
3754
	
3755
		/* Calculate a layout array */
3756
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3757
		{
3758
			nTr = nTrs[i];
3759
			iColumn = 0;
3760
	
3761
			/* For every cell in the row... */
3762
			nCell = nTr.firstChild;
3763
			while ( nCell ) {
3764
				if ( nCell.nodeName.toUpperCase() == "TD" ||
3765
				     nCell.nodeName.toUpperCase() == "TH" )
3766
				{
3767
					/* Get the col and rowspan attributes from the DOM and sanitise them */
3768
					iColspan = nCell.getAttribute('colspan') * 1;
3769
					iRowspan = nCell.getAttribute('rowspan') * 1;
3770
					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3771
					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3772
	
3773
					/* There might be colspan cells already in this row, so shift our target
3774
					 * accordingly
3775
					 */
3776
					iColShifted = fnShiftCol( aLayout, i, iColumn );
3777
	
3778
					/* Cache calculation for unique columns */
3779
					bUnique = iColspan === 1 ? true : false;
3780
	
3781
					/* If there is col / rowspan, copy the information into the layout grid */
3782
					for ( l=0 ; l<iColspan ; l++ )
3783
					{
3784
						for ( k=0 ; k<iRowspan ; k++ )
3785
						{
3786
							aLayout[i+k][iColShifted+l] = {
3787
								"cell": nCell,
3788
								"unique": bUnique
3789
							};
3790
							aLayout[i+k].nTr = nTr;
3791
						}
3792
					}
3793
				}
3794
				nCell = nCell.nextSibling;
3795
			}
3796
		}
3797
	}
3798
	
3799
	
3800
	/**
3801
	 * Get an array of unique th elements, one for each column
3802
	 *  @param {object} oSettings dataTables settings object
3803
	 *  @param {node} nHeader automatically detect the layout from this node - optional
3804
	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3805
	 *  @returns array {node} aReturn list of unique th's
3806
	 *  @memberof DataTable#oApi
3807
	 */
3808
	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3809
	{
3810
		var aReturn = [];
3811
		if ( !aLayout )
3812
		{
3813
			aLayout = oSettings.aoHeader;
3814
			if ( nHeader )
3815
			{
3816
				aLayout = [];
3817
				_fnDetectHeader( aLayout, nHeader );
3818
			}
3819
		}
3820
	
3821
		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3822
		{
3823
			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3824
			{
3825
				if ( aLayout[i][j].unique &&
3826
					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3827
				{
3828
					aReturn[j] = aLayout[i][j].cell;
3829
				}
3830
			}
3831
		}
3832
	
3833
		return aReturn;
3834
	}
3835
	
3836
	/**
3837
	 * Create an Ajax call based on the table's settings, taking into account that
3838
	 * parameters can have multiple forms, and backwards compatibility.
3839
	 *
3840
	 * @param {object} oSettings dataTables settings object
3841
	 * @param {array} data Data to send to the server, required by
3842
	 *     DataTables - may be augmented by developer callbacks
3843
	 * @param {function} fn Callback function to run when data is obtained
3844
	 */
3845
	function _fnBuildAjax( oSettings, data, fn )
3846
	{
3847
		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3848
		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3849
	
3850
		// Convert to object based for 1.10+ if using the old array scheme which can
3851
		// come from server-side processing or serverParams
3852
		if ( data && $.isArray(data) ) {
3853
			var tmp = {};
3854
			var rbracket = /(.*?)\[\]$/;
3855
	
3856
			$.each( data, function (key, val) {
3857
				var match = val.name.match(rbracket);
3858
	
3859
				if ( match ) {
3860
					// Support for arrays
3861
					var name = match[0];
3862
	
3863
					if ( ! tmp[ name ] ) {
3864
						tmp[ name ] = [];
3865
					}
3866
					tmp[ name ].push( val.value );
3867
				}
3868
				else {
3869
					tmp[val.name] = val.value;
3870
				}
3871
			} );
3872
			data = tmp;
3873
		}
3874
	
3875
		var ajaxData;
3876
		var ajax = oSettings.ajax;
3877
		var instance = oSettings.oInstance;
3878
		var callback = function ( json ) {
3879
			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3880
			fn( json );
3881
		};
3882
	
3883
		if ( $.isPlainObject( ajax ) && ajax.data )
3884
		{
3885
			ajaxData = ajax.data;
3886
	
3887
			var newData = typeof ajaxData === 'function' ?
3888
				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3889
				ajaxData;                      // an object object or array to merge
3890
	
3891
			// If the function returned something, use that alone
3892
			data = typeof ajaxData === 'function' && newData ?
3893
				newData :
3894
				$.extend( true, data, newData );
3895
	
3896
			// Remove the data property as we've resolved it already and don't want
3897
			// jQuery to do it again (it is restored at the end of the function)
3898
			delete ajax.data;
3899
		}
3900
	
3901
		var baseAjax = {
3902
			"data": data,
3903
			"success": function (json) {
3904
				var error = json.error || json.sError;
3905
				if ( error ) {
3906
					_fnLog( oSettings, 0, error );
3907
				}
3908
	
3909
				oSettings.json = json;
3910
				callback( json );
3911
			},
3912
			"dataType": "json",
3913
			"cache": false,
3914
			"type": oSettings.sServerMethod,
3915
			"error": function (xhr, error, thrown) {
3916
				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3917
	
3918
				if ( $.inArray( true, ret ) === -1 ) {
3919
					if ( error == "parsererror" ) {
3920
						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3921
					}
3922
					else if ( xhr.readyState === 4 ) {
3923
						_fnLog( oSettings, 0, 'Ajax error', 7 );
3924
					}
3925
				}
3926
	
3927
				_fnProcessingDisplay( oSettings, false );
3928
			}
3929
		};
3930
	
3931
		// Store the data submitted for the API
3932
		oSettings.oAjaxData = data;
3933
	
3934
		// Allow plug-ins and external processes to modify the data
3935
		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3936
	
3937
		if ( oSettings.fnServerData )
3938
		{
3939
			// DataTables 1.9- compatibility
3940
			oSettings.fnServerData.call( instance,
3941
				oSettings.sAjaxSource,
3942
				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3943
					return { name: key, value: val };
3944
				} ),
3945
				callback,
3946
				oSettings
3947
			);
3948
		}
3949
		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3950
		{
3951
			// DataTables 1.9- compatibility
3952
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3953
				url: ajax || oSettings.sAjaxSource
3954
			} ) );
3955
		}
3956
		else if ( typeof ajax === 'function' )
3957
		{
3958
			// Is a function - let the caller define what needs to be done
3959
			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3960
		}
3961
		else
3962
		{
3963
			// Object to extend the base settings
3964
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3965
	
3966
			// Restore for next time around
3967
			ajax.data = ajaxData;
3968
		}
3969
	}
3970
	
3971
	
3972
	/**
3973
	 * Update the table using an Ajax call
3974
	 *  @param {object} settings dataTables settings object
3975
	 *  @returns {boolean} Block the table drawing or not
3976
	 *  @memberof DataTable#oApi
3977
	 */
3978
	function _fnAjaxUpdate( settings )
3979
	{
3980
		if ( settings.bAjaxDataGet ) {
3981
			settings.iDraw++;
3982
			_fnProcessingDisplay( settings, true );
3983
	
3984
			_fnBuildAjax(
3985
				settings,
3986
				_fnAjaxParameters( settings ),
3987
				function(json) {
3988
					_fnAjaxUpdateDraw( settings, json );
3989
				}
3990
			);
3991
	
3992
			return false;
3993
		}
3994
		return true;
3995
	}
3996
	
3997
	
3998
	/**
3999
	 * Build up the parameters in an object needed for a server-side processing
4000
	 * request. Note that this is basically done twice, is different ways - a modern
4001
	 * method which is used by default in DataTables 1.10 which uses objects and
4002
	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4003
	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4004
	 * option is set.
4005
	 *  @param {object} oSettings dataTables settings object
4006
	 *  @returns {bool} block the table drawing or not
4007
	 *  @memberof DataTable#oApi
4008
	 */
4009
	function _fnAjaxParameters( settings )
4010
	{
4011
		var
4012
			columns = settings.aoColumns,
4013
			columnCount = columns.length,
4014
			features = settings.oFeatures,
4015
			preSearch = settings.oPreviousSearch,
4016
			preColSearch = settings.aoPreSearchCols,
4017
			i, data = [], dataProp, column, columnSearch,
4018
			sort = _fnSortFlatten( settings ),
4019
			displayStart = settings._iDisplayStart,
4020
			displayLength = features.bPaginate !== false ?
4021
				settings._iDisplayLength :
4022
				-1;
4023
	
4024
		var param = function ( name, value ) {
4025
			data.push( { 'name': name, 'value': value } );
4026
		};
4027
	
4028
		// DataTables 1.9- compatible method
4029
		param( 'sEcho',          settings.iDraw );
4030
		param( 'iColumns',       columnCount );
4031
		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4032
		param( 'iDisplayStart',  displayStart );
4033
		param( 'iDisplayLength', displayLength );
4034
	
4035
		// DataTables 1.10+ method
4036
		var d = {
4037
			draw:    settings.iDraw,
4038
			columns: [],
4039
			order:   [],
4040
			start:   displayStart,
4041
			length:  displayLength,
4042
			search:  {
4043
				value: preSearch.sSearch,
4044
				regex: preSearch.bRegex
4045
			}
4046
		};
4047
	
4048
		for ( i=0 ; i<columnCount ; i++ ) {
4049
			column = columns[i];
4050
			columnSearch = preColSearch[i];
4051
			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4052
	
4053
			d.columns.push( {
4054
				data:       dataProp,
4055
				name:       column.sName,
4056
				searchable: column.bSearchable,
4057
				orderable:  column.bSortable,
4058
				search:     {
4059
					value: columnSearch.sSearch,
4060
					regex: columnSearch.bRegex
4061
				}
4062
			} );
4063
	
4064
			param( "mDataProp_"+i, dataProp );
4065
	
4066
			if ( features.bFilter ) {
4067
				param( 'sSearch_'+i,     columnSearch.sSearch );
4068
				param( 'bRegex_'+i,      columnSearch.bRegex );
4069
				param( 'bSearchable_'+i, column.bSearchable );
4070
			}
4071
	
4072
			if ( features.bSort ) {
4073
				param( 'bSortable_'+i, column.bSortable );
4074
			}
4075
		}
4076
	
4077
		if ( features.bFilter ) {
4078
			param( 'sSearch', preSearch.sSearch );
4079
			param( 'bRegex', preSearch.bRegex );
4080
		}
4081
	
4082
		if ( features.bSort ) {
4083
			$.each( sort, function ( i, val ) {
4084
				d.order.push( { column: val.col, dir: val.dir } );
4085
	
4086
				param( 'iSortCol_'+i, val.col );
4087
				param( 'sSortDir_'+i, val.dir );
4088
			} );
4089
	
4090
			param( 'iSortingCols', sort.length );
4091
		}
4092
	
4093
		// If the legacy.ajax parameter is null, then we automatically decide which
4094
		// form to use, based on sAjaxSource
4095
		var legacy = DataTable.ext.legacy.ajax;
4096
		if ( legacy === null ) {
4097
			return settings.sAjaxSource ? data : d;
4098
		}
4099
	
4100
		// Otherwise, if legacy has been specified then we use that to decide on the
4101
		// form
4102
		return legacy ? data : d;
4103
	}
4104
	
4105
	
4106
	/**
4107
	 * Data the data from the server (nuking the old) and redraw the table
4108
	 *  @param {object} oSettings dataTables settings object
4109
	 *  @param {object} json json data return from the server.
4110
	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4111
	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4112
	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4113
	 *  @param {array} json.aaData The data to display on this page
4114
	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4115
	 *  @memberof DataTable#oApi
4116
	 */
4117
	function _fnAjaxUpdateDraw ( settings, json )
4118
	{
4119
		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4120
		// Support both
4121
		var compat = function ( old, modern ) {
4122
			return json[old] !== undefined ? json[old] : json[modern];
4123
		};
4124
	
4125
		var data = _fnAjaxDataSrc( settings, json );
4126
		var draw            = compat( 'sEcho',                'draw' );
4127
		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4128
		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4129
	
4130
		if ( draw ) {
4131
			// Protect against out of sequence returns
4132
			if ( draw*1 < settings.iDraw ) {
4133
				return;
4134
			}
4135
			settings.iDraw = draw * 1;
4136
		}
4137
	
4138
		_fnClearTable( settings );
4139
		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4140
		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4141
	
4142
		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4143
			_fnAddData( settings, data[i] );
4144
		}
4145
		settings.aiDisplay = settings.aiDisplayMaster.slice();
4146
	
4147
		settings.bAjaxDataGet = false;
4148
		_fnDraw( settings );
4149
	
4150
		if ( ! settings._bInitComplete ) {
4151
			_fnInitComplete( settings, json );
4152
		}
4153
	
4154
		settings.bAjaxDataGet = true;
4155
		_fnProcessingDisplay( settings, false );
4156
	}
4157
	
4158
	
4159
	/**
4160
	 * Get the data from the JSON data source to use for drawing a table. Using
4161
	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4162
	 * source object, or from a processing function.
4163
	 *  @param {object} oSettings dataTables settings object
4164
	 *  @param  {object} json Data source object / array from the server
4165
	 *  @return {array} Array of data to use
4166
	 */
4167
	function _fnAjaxDataSrc ( oSettings, json )
4168
	{
4169
		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4170
			oSettings.ajax.dataSrc :
4171
			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4172
	
4173
		// Compatibility with 1.9-. In order to read from aaData, check if the
4174
		// default has been changed, if not, check for aaData
4175
		if ( dataSrc === 'data' ) {
4176
			return json.aaData || json[dataSrc];
4177
		}
4178
	
4179
		return dataSrc !== "" ?
4180
			_fnGetObjectDataFn( dataSrc )( json ) :
4181
			json;
4182
	}
4183
	
4184
	/**
4185
	 * Generate the node required for filtering text
4186
	 *  @returns {node} Filter control element
4187
	 *  @param {object} oSettings dataTables settings object
4188
	 *  @memberof DataTable#oApi
4189
	 */
4190
	function _fnFeatureHtmlFilter ( settings )
4191
	{
4192
		var classes = settings.oClasses;
4193
		var tableId = settings.sTableId;
4194
		var language = settings.oLanguage;
4195
		var previousSearch = settings.oPreviousSearch;
4196
		var features = settings.aanFeatures;
4197
		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4198
	
4199
		var str = language.sSearch;
4200
		str = str.match(/_INPUT_/) ?
4201
			str.replace('_INPUT_', input) :
4202
			str+input;
4203
	
4204
		var filter = $('<div/>', {
4205
				'id': ! features.f ? tableId+'_filter' : null,
4206
				'class': classes.sFilter
4207
			} )
4208
			.append( $('<label/>' ).append( str ) );
4209
	
4210
		var searchFn = function() {
4211
			/* Update all other filter input elements for the new display */
4212
			var n = features.f;
4213
			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4214
	
4215
			/* Now do the filter */
4216
			if ( val != previousSearch.sSearch ) {
4217
				_fnFilterComplete( settings, {
4218
					"sSearch": val,
4219
					"bRegex": previousSearch.bRegex,
4220
					"bSmart": previousSearch.bSmart ,
4221
					"bCaseInsensitive": previousSearch.bCaseInsensitive
4222
				} );
4223
	
4224
				// Need to redraw, without resorting
4225
				settings._iDisplayStart = 0;
4226
				_fnDraw( settings );
4227
			}
4228
		};
4229
	
4230
		var searchDelay = settings.searchDelay !== null ?
4231
			settings.searchDelay :
4232
			_fnDataSource( settings ) === 'ssp' ?
4233
				400 :
4234
				0;
4235
	
4236
		var jqFilter = $('input', filter)
4237
			.val( previousSearch.sSearch )
4238
			.attr( 'placeholder', language.sSearchPlaceholder )
4239
			.on(
4240
				'keyup.DT search.DT input.DT paste.DT cut.DT',
4241
				searchDelay ?
4242
					_fnThrottle( searchFn, searchDelay ) :
4243
					searchFn
4244
			)
4245
			.on( 'keypress.DT', function(e) {
4246
				/* Prevent form submission */
4247
				if ( e.keyCode == 13 ) {
4248
					return false;
4249
				}
4250
			} )
4251
			.attr('aria-controls', tableId);
4252
	
4253
		// Update the input elements whenever the table is filtered
4254
		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4255
			if ( settings === s ) {
4256
				// IE9 throws an 'unknown error' if document.activeElement is used
4257
				// inside an iframe or frame...
4258
				try {
4259
					if ( jqFilter[0] !== document.activeElement ) {
4260
						jqFilter.val( previousSearch.sSearch );
4261
					}
4262
				}
4263
				catch ( e ) {}
4264
			}
4265
		} );
4266
	
4267
		return filter[0];
4268
	}
4269
	
4270
	
4271
	/**
4272
	 * Filter the table using both the global filter and column based filtering
4273
	 *  @param {object} oSettings dataTables settings object
4274
	 *  @param {object} oSearch search information
4275
	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4276
	 *  @memberof DataTable#oApi
4277
	 */
4278
	function _fnFilterComplete ( oSettings, oInput, iForce )
4279
	{
4280
		var oPrevSearch = oSettings.oPreviousSearch;
4281
		var aoPrevSearch = oSettings.aoPreSearchCols;
4282
		var fnSaveFilter = function ( oFilter ) {
4283
			/* Save the filtering values */
4284
			oPrevSearch.sSearch = oFilter.sSearch;
4285
			oPrevSearch.bRegex = oFilter.bRegex;
4286
			oPrevSearch.bSmart = oFilter.bSmart;
4287
			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4288
		};
4289
		var fnRegex = function ( o ) {
4290
			// Backwards compatibility with the bEscapeRegex option
4291
			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4292
		};
4293
	
4294
		// Resolve any column types that are unknown due to addition or invalidation
4295
		// @todo As per sort - can this be moved into an event handler?
4296
		_fnColumnTypes( oSettings );
4297
	
4298
		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4299
		if ( _fnDataSource( oSettings ) != 'ssp' )
4300
		{
4301
			/* Global filter */
4302
			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4303
			fnSaveFilter( oInput );
4304
	
4305
			/* Now do the individual column filter */
4306
			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4307
			{
4308
				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4309
					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4310
			}
4311
	
4312
			/* Custom filtering */
4313
			_fnFilterCustom( oSettings );
4314
		}
4315
		else
4316
		{
4317
			fnSaveFilter( oInput );
4318
		}
4319
	
4320
		/* Tell the draw function we have been filtering */
4321
		oSettings.bFiltered = true;
4322
		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4323
	}
4324
	
4325
	
4326
	/**
4327
	 * Apply custom filtering functions
4328
	 *  @param {object} oSettings dataTables settings object
4329
	 *  @memberof DataTable#oApi
4330
	 */
4331
	function _fnFilterCustom( settings )
4332
	{
4333
		var filters = DataTable.ext.search;
4334
		var displayRows = settings.aiDisplay;
4335
		var row, rowIdx;
4336
	
4337
		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4338
			var rows = [];
4339
	
4340
			// Loop over each row and see if it should be included
4341
			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4342
				rowIdx = displayRows[ j ];
4343
				row = settings.aoData[ rowIdx ];
4344
	
4345
				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4346
					rows.push( rowIdx );
4347
				}
4348
			}
4349
	
4350
			// So the array reference doesn't break set the results into the
4351
			// existing array
4352
			displayRows.length = 0;
4353
			$.merge( displayRows, rows );
4354
		}
4355
	}
4356
	
4357
	
4358
	/**
4359
	 * Filter the table on a per-column basis
4360
	 *  @param {object} oSettings dataTables settings object
4361
	 *  @param {string} sInput string to filter on
4362
	 *  @param {int} iColumn column to filter
4363
	 *  @param {bool} bRegex treat search string as a regular expression or not
4364
	 *  @param {bool} bSmart use smart filtering or not
4365
	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4366
	 *  @memberof DataTable#oApi
4367
	 */
4368
	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4369
	{
4370
		if ( searchStr === '' ) {
4371
			return;
4372
		}
4373
	
4374
		var data;
4375
		var out = [];
4376
		var display = settings.aiDisplay;
4377
		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4378
	
4379
		for ( var i=0 ; i<display.length ; i++ ) {
4380
			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4381
	
4382
			if ( rpSearch.test( data ) ) {
4383
				out.push( display[i] );
4384
			}
4385
		}
4386
	
4387
		settings.aiDisplay = out;
4388
	}
4389
	
4390
	
4391
	/**
4392
	 * Filter the data table based on user input and draw the table
4393
	 *  @param {object} settings dataTables settings object
4394
	 *  @param {string} input string to filter on
4395
	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4396
	 *  @param {bool} regex treat as a regular expression or not
4397
	 *  @param {bool} smart perform smart filtering or not
4398
	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4399
	 *  @memberof DataTable#oApi
4400
	 */
4401
	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4402
	{
4403
		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4404
		var prevSearch = settings.oPreviousSearch.sSearch;
4405
		var displayMaster = settings.aiDisplayMaster;
4406
		var display, invalidated, i;
4407
		var filtered = [];
4408
	
4409
		// Need to take account of custom filtering functions - always filter
4410
		if ( DataTable.ext.search.length !== 0 ) {
4411
			force = true;
4412
		}
4413
	
4414
		// Check if any of the rows were invalidated
4415
		invalidated = _fnFilterData( settings );
4416
	
4417
		// If the input is blank - we just want the full data set
4418
		if ( input.length <= 0 ) {
4419
			settings.aiDisplay = displayMaster.slice();
4420
		}
4421
		else {
4422
			// New search - start from the master array
4423
			if ( invalidated ||
4424
				 force ||
4425
				 prevSearch.length > input.length ||
4426
				 input.indexOf(prevSearch) !== 0 ||
4427
				 settings.bSorted // On resort, the display master needs to be
4428
				                  // re-filtered since indexes will have changed
4429
			) {
4430
				settings.aiDisplay = displayMaster.slice();
4431
			}
4432
	
4433
			// Search the display array
4434
			display = settings.aiDisplay;
4435
	
4436
			for ( i=0 ; i<display.length ; i++ ) {
4437
				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4438
					filtered.push( display[i] );
4439
				}
4440
			}
4441
	
4442
			settings.aiDisplay = filtered;
4443
		}
4444
	}
4445
	
4446
	
4447
	/**
4448
	 * Build a regular expression object suitable for searching a table
4449
	 *  @param {string} sSearch string to search for
4450
	 *  @param {bool} bRegex treat as a regular expression or not
4451
	 *  @param {bool} bSmart perform smart filtering or not
4452
	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4453
	 *  @returns {RegExp} constructed object
4454
	 *  @memberof DataTable#oApi
4455
	 */
4456
	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4457
	{
4458
		search = regex ?
4459
			search :
4460
			_fnEscapeRegex( search );
4461
		
4462
		if ( smart ) {
4463
			/* For smart filtering we want to allow the search to work regardless of
4464
			 * word order. We also want double quoted text to be preserved, so word
4465
			 * order is important - a la google. So this is what we want to
4466
			 * generate:
4467
			 * 
4468
			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4469
			 */
4470
			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4471
				if ( word.charAt(0) === '"' ) {
4472
					var m = word.match( /^"(.*)"$/ );
4473
					word = m ? m[1] : word;
4474
				}
4475
	
4476
				return word.replace('"', '');
4477
			} );
4478
	
4479
			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4480
		}
4481
	
4482
		return new RegExp( search, caseInsensitive ? 'i' : '' );
4483
	}
4484
	
4485
	
4486
	/**
4487
	 * Escape a string such that it can be used in a regular expression
4488
	 *  @param {string} sVal string to escape
4489
	 *  @returns {string} escaped string
4490
	 *  @memberof DataTable#oApi
4491
	 */
4492
	var _fnEscapeRegex = DataTable.util.escapeRegex;
4493
	
4494
	var __filter_div = $('<div>')[0];
4495
	var __filter_div_textContent = __filter_div.textContent !== undefined;
4496
	
4497
	// Update the filtering data for each row if needed (by invalidation or first run)
4498
	function _fnFilterData ( settings )
4499
	{
4500
		var columns = settings.aoColumns;
4501
		var column;
4502
		var i, j, ien, jen, filterData, cellData, row;
4503
		var fomatters = DataTable.ext.type.search;
4504
		var wasInvalidated = false;
4505
	
4506
		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4507
			row = settings.aoData[i];
4508
	
4509
			if ( ! row._aFilterData ) {
4510
				filterData = [];
4511
	
4512
				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4513
					column = columns[j];
4514
	
4515
					if ( column.bSearchable ) {
4516
						cellData = _fnGetCellData( settings, i, j, 'filter' );
4517
	
4518
						if ( fomatters[ column.sType ] ) {
4519
							cellData = fomatters[ column.sType ]( cellData );
4520
						}
4521
	
4522
						// Search in DataTables 1.10 is string based. In 1.11 this
4523
						// should be altered to also allow strict type checking.
4524
						if ( cellData === null ) {
4525
							cellData = '';
4526
						}
4527
	
4528
						if ( typeof cellData !== 'string' && cellData.toString ) {
4529
							cellData = cellData.toString();
4530
						}
4531
					}
4532
					else {
4533
						cellData = '';
4534
					}
4535
	
4536
					// If it looks like there is an HTML entity in the string,
4537
					// attempt to decode it so sorting works as expected. Note that
4538
					// we could use a single line of jQuery to do this, but the DOM
4539
					// method used here is much faster http://jsperf.com/html-decode
4540
					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4541
						__filter_div.innerHTML = cellData;
4542
						cellData = __filter_div_textContent ?
4543
							__filter_div.textContent :
4544
							__filter_div.innerText;
4545
					}
4546
	
4547
					if ( cellData.replace ) {
4548
						cellData = cellData.replace(/[\r\n]/g, '');
4549
					}
4550
	
4551
					filterData.push( cellData );
4552
				}
4553
	
4554
				row._aFilterData = filterData;
4555
				row._sFilterRow = filterData.join('  ');
4556
				wasInvalidated = true;
4557
			}
4558
		}
4559
	
4560
		return wasInvalidated;
4561
	}
4562
	
4563
	
4564
	/**
4565
	 * Convert from the internal Hungarian notation to camelCase for external
4566
	 * interaction
4567
	 *  @param {object} obj Object to convert
4568
	 *  @returns {object} Inverted object
4569
	 *  @memberof DataTable#oApi
4570
	 */
4571
	function _fnSearchToCamel ( obj )
4572
	{
4573
		return {
4574
			search:          obj.sSearch,
4575
			smart:           obj.bSmart,
4576
			regex:           obj.bRegex,
4577
			caseInsensitive: obj.bCaseInsensitive
4578
		};
4579
	}
4580
	
4581
	
4582
	
4583
	/**
4584
	 * Convert from camelCase notation to the internal Hungarian. We could use the
4585
	 * Hungarian convert function here, but this is cleaner
4586
	 *  @param {object} obj Object to convert
4587
	 *  @returns {object} Inverted object
4588
	 *  @memberof DataTable#oApi
4589
	 */
4590
	function _fnSearchToHung ( obj )
4591
	{
4592
		return {
4593
			sSearch:          obj.search,
4594
			bSmart:           obj.smart,
4595
			bRegex:           obj.regex,
4596
			bCaseInsensitive: obj.caseInsensitive
4597
		};
4598
	}
4599
	
4600
	/**
4601
	 * Generate the node required for the info display
4602
	 *  @param {object} oSettings dataTables settings object
4603
	 *  @returns {node} Information element
4604
	 *  @memberof DataTable#oApi
4605
	 */
4606
	function _fnFeatureHtmlInfo ( settings )
4607
	{
4608
		var
4609
			tid = settings.sTableId,
4610
			nodes = settings.aanFeatures.i,
4611
			n = $('<div/>', {
4612
				'class': settings.oClasses.sInfo,
4613
				'id': ! nodes ? tid+'_info' : null
4614
			} );
4615
	
4616
		if ( ! nodes ) {
4617
			// Update display on each draw
4618
			settings.aoDrawCallback.push( {
4619
				"fn": _fnUpdateInfo,
4620
				"sName": "information"
4621
			} );
4622
	
4623
			n
4624
				.attr( 'role', 'status' )
4625
				.attr( 'aria-live', 'polite' );
4626
	
4627
			// Table is described by our info div
4628
			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4629
		}
4630
	
4631
		return n[0];
4632
	}
4633
	
4634
	
4635
	/**
4636
	 * Update the information elements in the display
4637
	 *  @param {object} settings dataTables settings object
4638
	 *  @memberof DataTable#oApi
4639
	 */
4640
	function _fnUpdateInfo ( settings )
4641
	{
4642
		/* Show information about the table */
4643
		var nodes = settings.aanFeatures.i;
4644
		if ( nodes.length === 0 ) {
4645
			return;
4646
		}
4647
	
4648
		var
4649
			lang  = settings.oLanguage,
4650
			start = settings._iDisplayStart+1,
4651
			end   = settings.fnDisplayEnd(),
4652
			max   = settings.fnRecordsTotal(),
4653
			total = settings.fnRecordsDisplay(),
4654
			out   = total ?
4655
				lang.sInfo :
4656
				lang.sInfoEmpty;
4657
	
4658
		if ( total !== max ) {
4659
			/* Record set after filtering */
4660
			out += ' ' + lang.sInfoFiltered;
4661
		}
4662
	
4663
		// Convert the macros
4664
		out += lang.sInfoPostFix;
4665
		out = _fnInfoMacros( settings, out );
4666
	
4667
		var callback = lang.fnInfoCallback;
4668
		if ( callback !== null ) {
4669
			out = callback.call( settings.oInstance,
4670
				settings, start, end, max, total, out
4671
			);
4672
		}
4673
	
4674
		$(nodes).html( out );
4675
	}
4676
	
4677
	
4678
	function _fnInfoMacros ( settings, str )
4679
	{
4680
		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4681
		// internally
4682
		var
4683
			formatter  = settings.fnFormatNumber,
4684
			start      = settings._iDisplayStart+1,
4685
			len        = settings._iDisplayLength,
4686
			vis        = settings.fnRecordsDisplay(),
4687
			all        = len === -1;
4688
	
4689
		return str.
4690
			replace(/_START_/g, formatter.call( settings, start ) ).
4691
			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4692
			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4693
			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4694
			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4695
			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4696
	}
4697
	
4698
	
4699
	
4700
	/**
4701
	 * Draw the table for the first time, adding all required features
4702
	 *  @param {object} settings dataTables settings object
4703
	 *  @memberof DataTable#oApi
4704
	 */
4705
	function _fnInitialise ( settings )
4706
	{
4707
		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4708
		var columns = settings.aoColumns, column;
4709
		var features = settings.oFeatures;
4710
		var deferLoading = settings.bDeferLoading; // value modified by the draw
4711
	
4712
		/* Ensure that the table data is fully initialised */
4713
		if ( ! settings.bInitialised ) {
4714
			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4715
			return;
4716
		}
4717
	
4718
		/* Show the display HTML options */
4719
		_fnAddOptionsHtml( settings );
4720
	
4721
		/* Build and draw the header / footer for the table */
4722
		_fnBuildHead( settings );
4723
		_fnDrawHead( settings, settings.aoHeader );
4724
		_fnDrawHead( settings, settings.aoFooter );
4725
	
4726
		/* Okay to show that something is going on now */
4727
		_fnProcessingDisplay( settings, true );
4728
	
4729
		/* Calculate sizes for columns */
4730
		if ( features.bAutoWidth ) {
4731
			_fnCalculateColumnWidths( settings );
4732
		}
4733
	
4734
		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4735
			column = columns[i];
4736
	
4737
			if ( column.sWidth ) {
4738
				column.nTh.style.width = _fnStringToCss( column.sWidth );
4739
			}
4740
		}
4741
	
4742
		_fnCallbackFire( settings, null, 'preInit', [settings] );
4743
	
4744
		// If there is default sorting required - let's do it. The sort function
4745
		// will do the drawing for us. Otherwise we draw the table regardless of the
4746
		// Ajax source - this allows the table to look initialised for Ajax sourcing
4747
		// data (show 'loading' message possibly)
4748
		_fnReDraw( settings );
4749
	
4750
		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4751
		var dataSrc = _fnDataSource( settings );
4752
		if ( dataSrc != 'ssp' || deferLoading ) {
4753
			// if there is an ajax source load the data
4754
			if ( dataSrc == 'ajax' ) {
4755
				_fnBuildAjax( settings, [], function(json) {
4756
					var aData = _fnAjaxDataSrc( settings, json );
4757
	
4758
					// Got the data - add it to the table
4759
					for ( i=0 ; i<aData.length ; i++ ) {
4760
						_fnAddData( settings, aData[i] );
4761
					}
4762
	
4763
					// Reset the init display for cookie saving. We've already done
4764
					// a filter, and therefore cleared it before. So we need to make
4765
					// it appear 'fresh'
4766
					settings.iInitDisplayStart = iAjaxStart;
4767
	
4768
					_fnReDraw( settings );
4769
	
4770
					_fnProcessingDisplay( settings, false );
4771
					_fnInitComplete( settings, json );
4772
				}, settings );
4773
			}
4774
			else {
4775
				_fnProcessingDisplay( settings, false );
4776
				_fnInitComplete( settings );
4777
			}
4778
		}
4779
	}
4780
	
4781
	
4782
	/**
4783
	 * Draw the table for the first time, adding all required features
4784
	 *  @param {object} oSettings dataTables settings object
4785
	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4786
	 *    with client-side processing (optional)
4787
	 *  @memberof DataTable#oApi
4788
	 */
4789
	function _fnInitComplete ( settings, json )
4790
	{
4791
		settings._bInitComplete = true;
4792
	
4793
		// When data was added after the initialisation (data or Ajax) we need to
4794
		// calculate the column sizing
4795
		if ( json || settings.oInit.aaData ) {
4796
			_fnAdjustColumnSizing( settings );
4797
		}
4798
	
4799
		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4800
		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4801
	}
4802
	
4803
	
4804
	function _fnLengthChange ( settings, val )
4805
	{
4806
		var len = parseInt( val, 10 );
4807
		settings._iDisplayLength = len;
4808
	
4809
		_fnLengthOverflow( settings );
4810
	
4811
		// Fire length change event
4812
		_fnCallbackFire( settings, null, 'length', [settings, len] );
4813
	}
4814
	
4815
	
4816
	/**
4817
	 * Generate the node required for user display length changing
4818
	 *  @param {object} settings dataTables settings object
4819
	 *  @returns {node} Display length feature node
4820
	 *  @memberof DataTable#oApi
4821
	 */
4822
	function _fnFeatureHtmlLength ( settings )
4823
	{
4824
		var
4825
			classes  = settings.oClasses,
4826
			tableId  = settings.sTableId,
4827
			menu     = settings.aLengthMenu,
4828
			d2       = $.isArray( menu[0] ),
4829
			lengths  = d2 ? menu[0] : menu,
4830
			language = d2 ? menu[1] : menu;
4831
	
4832
		var select = $('<select/>', {
4833
			'name':          tableId+'_length',
4834
			'aria-controls': tableId,
4835
			'class':         classes.sLengthSelect
4836
		} );
4837
	
4838
		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4839
			select[0][ i ] = new Option(
4840
				typeof language[i] === 'number' ?
4841
					settings.fnFormatNumber( language[i] ) :
4842
					language[i],
4843
				lengths[i]
4844
			);
4845
		}
4846
	
4847
		var div = $('<div><label/></div>').addClass( classes.sLength );
4848
		if ( ! settings.aanFeatures.l ) {
4849
			div[0].id = tableId+'_length';
4850
		}
4851
	
4852
		div.children().append(
4853
			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4854
		);
4855
	
4856
		// Can't use `select` variable as user might provide their own and the
4857
		// reference is broken by the use of outerHTML
4858
		$('select', div)
4859
			.val( settings._iDisplayLength )
4860
			.on( 'change.DT', function(e) {
4861
				_fnLengthChange( settings, $(this).val() );
4862
				_fnDraw( settings );
4863
			} );
4864
	
4865
		// Update node value whenever anything changes the table's length
4866
		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4867
			if ( settings === s ) {
4868
				$('select', div).val( len );
4869
			}
4870
		} );
4871
	
4872
		return div[0];
4873
	}
4874
	
4875
	
4876
	
4877
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4878
	 * Note that most of the paging logic is done in
4879
	 * DataTable.ext.pager
4880
	 */
4881
	
4882
	/**
4883
	 * Generate the node required for default pagination
4884
	 *  @param {object} oSettings dataTables settings object
4885
	 *  @returns {node} Pagination feature node
4886
	 *  @memberof DataTable#oApi
4887
	 */
4888
	function _fnFeatureHtmlPaginate ( settings )
4889
	{
4890
		var
4891
			type   = settings.sPaginationType,
4892
			plugin = DataTable.ext.pager[ type ],
4893
			modern = typeof plugin === 'function',
4894
			redraw = function( settings ) {
4895
				_fnDraw( settings );
4896
			},
4897
			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4898
			features = settings.aanFeatures;
4899
	
4900
		if ( ! modern ) {
4901
			plugin.fnInit( settings, node, redraw );
4902
		}
4903
	
4904
		/* Add a draw callback for the pagination on first instance, to update the paging display */
4905
		if ( ! features.p )
4906
		{
4907
			node.id = settings.sTableId+'_paginate';
4908
	
4909
			settings.aoDrawCallback.push( {
4910
				"fn": function( settings ) {
4911
					if ( modern ) {
4912
						var
4913
							start      = settings._iDisplayStart,
4914
							len        = settings._iDisplayLength,
4915
							visRecords = settings.fnRecordsDisplay(),
4916
							all        = len === -1,
4917
							page = all ? 0 : Math.ceil( start / len ),
4918
							pages = all ? 1 : Math.ceil( visRecords / len ),
4919
							buttons = plugin(page, pages),
4920
							i, ien;
4921
	
4922
						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4923
							_fnRenderer( settings, 'pageButton' )(
4924
								settings, features.p[i], i, buttons, page, pages
4925
							);
4926
						}
4927
					}
4928
					else {
4929
						plugin.fnUpdate( settings, redraw );
4930
					}
4931
				},
4932
				"sName": "pagination"
4933
			} );
4934
		}
4935
	
4936
		return node;
4937
	}
4938
	
4939
	
4940
	/**
4941
	 * Alter the display settings to change the page
4942
	 *  @param {object} settings DataTables settings object
4943
	 *  @param {string|int} action Paging action to take: "first", "previous",
4944
	 *    "next" or "last" or page number to jump to (integer)
4945
	 *  @param [bool] redraw Automatically draw the update or not
4946
	 *  @returns {bool} true page has changed, false - no change
4947
	 *  @memberof DataTable#oApi
4948
	 */
4949
	function _fnPageChange ( settings, action, redraw )
4950
	{
4951
		var
4952
			start     = settings._iDisplayStart,
4953
			len       = settings._iDisplayLength,
4954
			records   = settings.fnRecordsDisplay();
4955
	
4956
		if ( records === 0 || len === -1 )
4957
		{
4958
			start = 0;
4959
		}
4960
		else if ( typeof action === "number" )
4961
		{
4962
			start = action * len;
4963
	
4964
			if ( start > records )
4965
			{
4966
				start = 0;
4967
			}
4968
		}
4969
		else if ( action == "first" )
4970
		{
4971
			start = 0;
4972
		}
4973
		else if ( action == "previous" )
4974
		{
4975
			start = len >= 0 ?
4976
				start - len :
4977
				0;
4978
	
4979
			if ( start < 0 )
4980
			{
4981
			  start = 0;
4982
			}
4983
		}
4984
		else if ( action == "next" )
4985
		{
4986
			if ( start + len < records )
4987
			{
4988
				start += len;
4989
			}
4990
		}
4991
		else if ( action == "last" )
4992
		{
4993
			start = Math.floor( (records-1) / len) * len;
4994
		}
4995
		else
4996
		{
4997
			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4998
		}
4999
	
5000
		var changed = settings._iDisplayStart !== start;
5001
		settings._iDisplayStart = start;
5002
	
5003
		if ( changed ) {
5004
			_fnCallbackFire( settings, null, 'page', [settings] );
5005
	
5006
			if ( redraw ) {
5007
				_fnDraw( settings );
5008
			}
5009
		}
5010
	
5011
		return changed;
5012
	}
5013
	
5014
	
5015
	
5016
	/**
5017
	 * Generate the node required for the processing node
5018
	 *  @param {object} settings dataTables settings object
5019
	 *  @returns {node} Processing element
5020
	 *  @memberof DataTable#oApi
5021
	 */
5022
	function _fnFeatureHtmlProcessing ( settings )
5023
	{
5024
		return $('<div/>', {
5025
				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5026
				'class': settings.oClasses.sProcessing
5027
			} )
5028
			.html( settings.oLanguage.sProcessing )
5029
			.insertBefore( settings.nTable )[0];
5030
	}
5031
	
5032
	
5033
	/**
5034
	 * Display or hide the processing indicator
5035
	 *  @param {object} settings dataTables settings object
5036
	 *  @param {bool} show Show the processing indicator (true) or not (false)
5037
	 *  @memberof DataTable#oApi
5038
	 */
5039
	function _fnProcessingDisplay ( settings, show )
5040
	{
5041
		if ( settings.oFeatures.bProcessing ) {
5042
			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5043
		}
5044
	
5045
		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5046
	}
5047
	
5048
	/**
5049
	 * Add any control elements for the table - specifically scrolling
5050
	 *  @param {object} settings dataTables settings object
5051
	 *  @returns {node} Node to add to the DOM
5052
	 *  @memberof DataTable#oApi
5053
	 */
5054
	function _fnFeatureHtmlTable ( settings )
5055
	{
5056
		var table = $(settings.nTable);
5057
	
5058
		// Add the ARIA grid role to the table
5059
		table.attr( 'role', 'grid' );
5060
	
5061
		// Scrolling from here on in
5062
		var scroll = settings.oScroll;
5063
	
5064
		if ( scroll.sX === '' && scroll.sY === '' ) {
5065
			return settings.nTable;
5066
		}
5067
	
5068
		var scrollX = scroll.sX;
5069
		var scrollY = scroll.sY;
5070
		var classes = settings.oClasses;
5071
		var caption = table.children('caption');
5072
		var captionSide = caption.length ? caption[0]._captionSide : null;
5073
		var headerClone = $( table[0].cloneNode(false) );
5074
		var footerClone = $( table[0].cloneNode(false) );
5075
		var footer = table.children('tfoot');
5076
		var _div = '<div/>';
5077
		var size = function ( s ) {
5078
			return !s ? null : _fnStringToCss( s );
5079
		};
5080
	
5081
		if ( ! footer.length ) {
5082
			footer = null;
5083
		}
5084
	
5085
		/*
5086
		 * The HTML structure that we want to generate in this function is:
5087
		 *  div - scroller
5088
		 *    div - scroll head
5089
		 *      div - scroll head inner
5090
		 *        table - scroll head table
5091
		 *          thead - thead
5092
		 *    div - scroll body
5093
		 *      table - table (master table)
5094
		 *        thead - thead clone for sizing
5095
		 *        tbody - tbody
5096
		 *    div - scroll foot
5097
		 *      div - scroll foot inner
5098
		 *        table - scroll foot table
5099
		 *          tfoot - tfoot
5100
		 */
5101
		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5102
			.append(
5103
				$(_div, { 'class': classes.sScrollHead } )
5104
					.css( {
5105
						overflow: 'hidden',
5106
						position: 'relative',
5107
						border: 0,
5108
						width: scrollX ? size(scrollX) : '100%'
5109
					} )
5110
					.append(
5111
						$(_div, { 'class': classes.sScrollHeadInner } )
5112
							.css( {
5113
								'box-sizing': 'content-box',
5114
								width: scroll.sXInner || '100%'
5115
							} )
5116
							.append(
5117
								headerClone
5118
									.removeAttr('id')
5119
									.css( 'margin-left', 0 )
5120
									.append( captionSide === 'top' ? caption : null )
5121
									.append(
5122
										table.children('thead')
5123
									)
5124
							)
5125
					)
5126
			)
5127
			.append(
5128
				$(_div, { 'class': classes.sScrollBody } )
5129
					.css( {
5130
						position: 'relative',
5131
						overflow: 'auto',
5132
						width: size( scrollX )
5133
					} )
5134
					.append( table )
5135
			);
5136
	
5137
		if ( footer ) {
5138
			scroller.append(
5139
				$(_div, { 'class': classes.sScrollFoot } )
5140
					.css( {
5141
						overflow: 'hidden',
5142
						border: 0,
5143
						width: scrollX ? size(scrollX) : '100%'
5144
					} )
5145
					.append(
5146
						$(_div, { 'class': classes.sScrollFootInner } )
5147
							.append(
5148
								footerClone
5149
									.removeAttr('id')
5150
									.css( 'margin-left', 0 )
5151
									.append( captionSide === 'bottom' ? caption : null )
5152
									.append(
5153
										table.children('tfoot')
5154
									)
5155
							)
5156
					)
5157
			);
5158
		}
5159
	
5160
		var children = scroller.children();
5161
		var scrollHead = children[0];
5162
		var scrollBody = children[1];
5163
		var scrollFoot = footer ? children[2] : null;
5164
	
5165
		// When the body is scrolled, then we also want to scroll the headers
5166
		if ( scrollX ) {
5167
			$(scrollBody).on( 'scroll.DT', function (e) {
5168
				var scrollLeft = this.scrollLeft;
5169
	
5170
				scrollHead.scrollLeft = scrollLeft;
5171
	
5172
				if ( footer ) {
5173
					scrollFoot.scrollLeft = scrollLeft;
5174
				}
5175
			} );
5176
		}
5177
	
5178
		$(scrollBody).css(
5179
			scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5180
			scrollY
5181
		);
5182
	
5183
		settings.nScrollHead = scrollHead;
5184
		settings.nScrollBody = scrollBody;
5185
		settings.nScrollFoot = scrollFoot;
5186
	
5187
		// On redraw - align columns
5188
		settings.aoDrawCallback.push( {
5189
			"fn": _fnScrollDraw,
5190
			"sName": "scrolling"
5191
		} );
5192
	
5193
		return scroller[0];
5194
	}
5195
	
5196
	
5197
	
5198
	/**
5199
	 * Update the header, footer and body tables for resizing - i.e. column
5200
	 * alignment.
5201
	 *
5202
	 * Welcome to the most horrible function DataTables. The process that this
5203
	 * function follows is basically:
5204
	 *   1. Re-create the table inside the scrolling div
5205
	 *   2. Take live measurements from the DOM
5206
	 *   3. Apply the measurements to align the columns
5207
	 *   4. Clean up
5208
	 *
5209
	 *  @param {object} settings dataTables settings object
5210
	 *  @memberof DataTable#oApi
5211
	 */
5212
	function _fnScrollDraw ( settings )
5213
	{
5214
		// Given that this is such a monster function, a lot of variables are use
5215
		// to try and keep the minimised size as small as possible
5216
		var
5217
			scroll         = settings.oScroll,
5218
			scrollX        = scroll.sX,
5219
			scrollXInner   = scroll.sXInner,
5220
			scrollY        = scroll.sY,
5221
			barWidth       = scroll.iBarWidth,
5222
			divHeader      = $(settings.nScrollHead),
5223
			divHeaderStyle = divHeader[0].style,
5224
			divHeaderInner = divHeader.children('div'),
5225
			divHeaderInnerStyle = divHeaderInner[0].style,
5226
			divHeaderTable = divHeaderInner.children('table'),
5227
			divBodyEl      = settings.nScrollBody,
5228
			divBody        = $(divBodyEl),
5229
			divBodyStyle   = divBodyEl.style,
5230
			divFooter      = $(settings.nScrollFoot),
5231
			divFooterInner = divFooter.children('div'),
5232
			divFooterTable = divFooterInner.children('table'),
5233
			header         = $(settings.nTHead),
5234
			table          = $(settings.nTable),
5235
			tableEl        = table[0],
5236
			tableStyle     = tableEl.style,
5237
			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5238
			browser        = settings.oBrowser,
5239
			ie67           = browser.bScrollOversize,
5240
			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5241
			headerTrgEls, footerTrgEls,
5242
			headerSrcEls, footerSrcEls,
5243
			headerCopy, footerCopy,
5244
			headerWidths=[], footerWidths=[],
5245
			headerContent=[], footerContent=[],
5246
			idx, correction, sanityWidth,
5247
			zeroOut = function(nSizer) {
5248
				var style = nSizer.style;
5249
				style.paddingTop = "0";
5250
				style.paddingBottom = "0";
5251
				style.borderTopWidth = "0";
5252
				style.borderBottomWidth = "0";
5253
				style.height = 0;
5254
			};
5255
	
5256
		// If the scrollbar visibility has changed from the last draw, we need to
5257
		// adjust the column sizes as the table width will have changed to account
5258
		// for the scrollbar
5259
		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5260
		
5261
		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5262
			settings.scrollBarVis = scrollBarVis;
5263
			_fnAdjustColumnSizing( settings );
5264
			return; // adjust column sizing will call this function again
5265
		}
5266
		else {
5267
			settings.scrollBarVis = scrollBarVis;
5268
		}
5269
	
5270
		/*
5271
		 * 1. Re-create the table inside the scrolling div
5272
		 */
5273
	
5274
		// Remove the old minimised thead and tfoot elements in the inner table
5275
		table.children('thead, tfoot').remove();
5276
	
5277
		if ( footer ) {
5278
			footerCopy = footer.clone().prependTo( table );
5279
			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5280
			footerSrcEls = footerCopy.find('tr');
5281
		}
5282
	
5283
		// Clone the current header and footer elements and then place it into the inner table
5284
		headerCopy = header.clone().prependTo( table );
5285
		headerTrgEls = header.find('tr'); // original header is in its own table
5286
		headerSrcEls = headerCopy.find('tr');
5287
		headerCopy.find('th, td').removeAttr('tabindex');
5288
	
5289
	
5290
		/*
5291
		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5292
		 */
5293
	
5294
		// Remove old sizing and apply the calculated column widths
5295
		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5296
		// calculated sizes to this header
5297
		if ( ! scrollX )
5298
		{
5299
			divBodyStyle.width = '100%';
5300
			divHeader[0].style.width = '100%';
5301
		}
5302
	
5303
		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5304
			idx = _fnVisibleToColumnIndex( settings, i );
5305
			el.style.width = settings.aoColumns[idx].sWidth;
5306
		} );
5307
	
5308
		if ( footer ) {
5309
			_fnApplyToChildren( function(n) {
5310
				n.style.width = "";
5311
			}, footerSrcEls );
5312
		}
5313
	
5314
		// Size the table as a whole
5315
		sanityWidth = table.outerWidth();
5316
		if ( scrollX === "" ) {
5317
			// No x scrolling
5318
			tableStyle.width = "100%";
5319
	
5320
			// IE7 will make the width of the table when 100% include the scrollbar
5321
			// - which is shouldn't. When there is a scrollbar we need to take this
5322
			// into account.
5323
			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5324
				divBody.css('overflow-y') == "scroll")
5325
			) {
5326
				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5327
			}
5328
	
5329
			// Recalculate the sanity width
5330
			sanityWidth = table.outerWidth();
5331
		}
5332
		else if ( scrollXInner !== "" ) {
5333
			// legacy x scroll inner has been given - use it
5334
			tableStyle.width = _fnStringToCss(scrollXInner);
5335
	
5336
			// Recalculate the sanity width
5337
			sanityWidth = table.outerWidth();
5338
		}
5339
	
5340
		// Hidden header should have zero height, so remove padding and borders. Then
5341
		// set the width based on the real headers
5342
	
5343
		// Apply all styles in one pass
5344
		_fnApplyToChildren( zeroOut, headerSrcEls );
5345
	
5346
		// Read all widths in next pass
5347
		_fnApplyToChildren( function(nSizer) {
5348
			headerContent.push( nSizer.innerHTML );
5349
			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5350
		}, headerSrcEls );
5351
	
5352
		// Apply all widths in final pass
5353
		_fnApplyToChildren( function(nToSize, i) {
5354
			// Only apply widths to the DataTables detected header cells - this
5355
			// prevents complex headers from having contradictory sizes applied
5356
			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5357
				nToSize.style.width = headerWidths[i];
5358
			}
5359
		}, headerTrgEls );
5360
	
5361
		$(headerSrcEls).height(0);
5362
	
5363
		/* Same again with the footer if we have one */
5364
		if ( footer )
5365
		{
5366
			_fnApplyToChildren( zeroOut, footerSrcEls );
5367
	
5368
			_fnApplyToChildren( function(nSizer) {
5369
				footerContent.push( nSizer.innerHTML );
5370
				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5371
			}, footerSrcEls );
5372
	
5373
			_fnApplyToChildren( function(nToSize, i) {
5374
				nToSize.style.width = footerWidths[i];
5375
			}, footerTrgEls );
5376
	
5377
			$(footerSrcEls).height(0);
5378
		}
5379
	
5380
	
5381
		/*
5382
		 * 3. Apply the measurements
5383
		 */
5384
	
5385
		// "Hide" the header and footer that we used for the sizing. We need to keep
5386
		// the content of the cell so that the width applied to the header and body
5387
		// both match, but we want to hide it completely. We want to also fix their
5388
		// width to what they currently are
5389
		_fnApplyToChildren( function(nSizer, i) {
5390
			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5391
			nSizer.childNodes[0].style.height = "0";
5392
			nSizer.childNodes[0].style.overflow = "hidden";
5393
			nSizer.style.width = headerWidths[i];
5394
		}, headerSrcEls );
5395
	
5396
		if ( footer )
5397
		{
5398
			_fnApplyToChildren( function(nSizer, i) {
5399
				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5400
				nSizer.childNodes[0].style.height = "0";
5401
				nSizer.childNodes[0].style.overflow = "hidden";
5402
				nSizer.style.width = footerWidths[i];
5403
			}, footerSrcEls );
5404
		}
5405
	
5406
		// Sanity check that the table is of a sensible width. If not then we are going to get
5407
		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5408
		if ( table.outerWidth() < sanityWidth )
5409
		{
5410
			// The min width depends upon if we have a vertical scrollbar visible or not */
5411
			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5412
				divBody.css('overflow-y') == "scroll")) ?
5413
					sanityWidth+barWidth :
5414
					sanityWidth;
5415
	
5416
			// IE6/7 are a law unto themselves...
5417
			if ( ie67 && (divBodyEl.scrollHeight >
5418
				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5419
			) {
5420
				tableStyle.width = _fnStringToCss( correction-barWidth );
5421
			}
5422
	
5423
			// And give the user a warning that we've stopped the table getting too small
5424
			if ( scrollX === "" || scrollXInner !== "" ) {
5425
				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5426
			}
5427
		}
5428
		else
5429
		{
5430
			correction = '100%';
5431
		}
5432
	
5433
		// Apply to the container elements
5434
		divBodyStyle.width = _fnStringToCss( correction );
5435
		divHeaderStyle.width = _fnStringToCss( correction );
5436
	
5437
		if ( footer ) {
5438
			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5439
		}
5440
	
5441
	
5442
		/*
5443
		 * 4. Clean up
5444
		 */
5445
		if ( ! scrollY ) {
5446
			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5447
			 * the scrollbar height from the visible display, rather than adding it on. We need to
5448
			 * set the height in order to sort this. Don't want to do it in any other browsers.
5449
			 */
5450
			if ( ie67 ) {
5451
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5452
			}
5453
		}
5454
	
5455
		/* Finally set the width's of the header and footer tables */
5456
		var iOuterWidth = table.outerWidth();
5457
		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5458
		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5459
	
5460
		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5461
		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5462
		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5463
		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5464
		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5465
	
5466
		if ( footer ) {
5467
			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5468
			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5469
			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5470
		}
5471
	
5472
		// Correct DOM ordering for colgroup - comes before the thead
5473
		table.children('colgroup').insertBefore( table.children('thead') );
5474
	
5475
		/* Adjust the position of the header in case we loose the y-scrollbar */
5476
		divBody.scroll();
5477
	
5478
		// If sorting or filtering has occurred, jump the scrolling back to the top
5479
		// only if we aren't holding the position
5480
		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5481
			divBodyEl.scrollTop = 0;
5482
		}
5483
	}
5484
	
5485
	
5486
	
5487
	/**
5488
	 * Apply a given function to the display child nodes of an element array (typically
5489
	 * TD children of TR rows
5490
	 *  @param {function} fn Method to apply to the objects
5491
	 *  @param array {nodes} an1 List of elements to look through for display children
5492
	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5493
	 *  @memberof DataTable#oApi
5494
	 */
5495
	function _fnApplyToChildren( fn, an1, an2 )
5496
	{
5497
		var index=0, i=0, iLen=an1.length;
5498
		var nNode1, nNode2;
5499
	
5500
		while ( i < iLen ) {
5501
			nNode1 = an1[i].firstChild;
5502
			nNode2 = an2 ? an2[i].firstChild : null;
5503
	
5504
			while ( nNode1 ) {
5505
				if ( nNode1.nodeType === 1 ) {
5506
					if ( an2 ) {
5507
						fn( nNode1, nNode2, index );
5508
					}
5509
					else {
5510
						fn( nNode1, index );
5511
					}
5512
	
5513
					index++;
5514
				}
5515
	
5516
				nNode1 = nNode1.nextSibling;
5517
				nNode2 = an2 ? nNode2.nextSibling : null;
5518
			}
5519
	
5520
			i++;
5521
		}
5522
	}
5523
	
5524
	
5525
	
5526
	var __re_html_remove = /<.*?>/g;
5527
	
5528
	
5529
	/**
5530
	 * Calculate the width of columns for the table
5531
	 *  @param {object} oSettings dataTables settings object
5532
	 *  @memberof DataTable#oApi
5533
	 */
5534
	function _fnCalculateColumnWidths ( oSettings )
5535
	{
5536
		var
5537
			table = oSettings.nTable,
5538
			columns = oSettings.aoColumns,
5539
			scroll = oSettings.oScroll,
5540
			scrollY = scroll.sY,
5541
			scrollX = scroll.sX,
5542
			scrollXInner = scroll.sXInner,
5543
			columnCount = columns.length,
5544
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5545
			headerCells = $('th', oSettings.nTHead),
5546
			tableWidthAttr = table.getAttribute('width'), // from DOM element
5547
			tableContainer = table.parentNode,
5548
			userInputs = false,
5549
			i, column, columnIdx, width, outerWidth,
5550
			browser = oSettings.oBrowser,
5551
			ie67 = browser.bScrollOversize;
5552
	
5553
		var styleWidth = table.style.width;
5554
		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5555
			tableWidthAttr = styleWidth;
5556
		}
5557
	
5558
		/* Convert any user input sizes into pixel sizes */
5559
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5560
			column = columns[ visibleColumns[i] ];
5561
	
5562
			if ( column.sWidth !== null ) {
5563
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5564
	
5565
				userInputs = true;
5566
			}
5567
		}
5568
	
5569
		/* If the number of columns in the DOM equals the number that we have to
5570
		 * process in DataTables, then we can use the offsets that are created by
5571
		 * the web- browser. No custom sizes can be set in order for this to happen,
5572
		 * nor scrolling used
5573
		 */
5574
		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5575
		     columnCount == _fnVisbleColumns( oSettings ) &&
5576
		     columnCount == headerCells.length
5577
		) {
5578
			for ( i=0 ; i<columnCount ; i++ ) {
5579
				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5580
	
5581
				if ( colIdx !== null ) {
5582
					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5583
				}
5584
			}
5585
		}
5586
		else
5587
		{
5588
			// Otherwise construct a single row, worst case, table with the widest
5589
			// node in the data, assign any user defined widths, then insert it into
5590
			// the DOM and allow the browser to do all the hard work of calculating
5591
			// table widths
5592
			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5593
				.css( 'visibility', 'hidden' )
5594
				.removeAttr( 'id' );
5595
	
5596
			// Clean up the table body
5597
			tmpTable.find('tbody tr').remove();
5598
			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5599
	
5600
			// Clone the table header and footer - we can't use the header / footer
5601
			// from the cloned table, since if scrolling is active, the table's
5602
			// real header and footer are contained in different table tags
5603
			tmpTable.find('thead, tfoot').remove();
5604
			tmpTable
5605
				.append( $(oSettings.nTHead).clone() )
5606
				.append( $(oSettings.nTFoot).clone() );
5607
	
5608
			// Remove any assigned widths from the footer (from scrolling)
5609
			tmpTable.find('tfoot th, tfoot td').css('width', '');
5610
	
5611
			// Apply custom sizing to the cloned header
5612
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5613
	
5614
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5615
				column = columns[ visibleColumns[i] ];
5616
	
5617
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5618
					_fnStringToCss( column.sWidthOrig ) :
5619
					'';
5620
	
5621
				// For scrollX we need to force the column width otherwise the
5622
				// browser will collapse it. If this width is smaller than the
5623
				// width the column requires, then it will have no effect
5624
				if ( column.sWidthOrig && scrollX ) {
5625
					$( headerCells[i] ).append( $('<div/>').css( {
5626
						width: column.sWidthOrig,
5627
						margin: 0,
5628
						padding: 0,
5629
						border: 0,
5630
						height: 1
5631
					} ) );
5632
				}
5633
			}
5634
	
5635
			// Find the widest cell for each column and put it into the table
5636
			if ( oSettings.aoData.length ) {
5637
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5638
					columnIdx = visibleColumns[i];
5639
					column = columns[ columnIdx ];
5640
	
5641
					$( _fnGetWidestNode( oSettings, columnIdx ) )
5642
						.clone( false )
5643
						.append( column.sContentPadding )
5644
						.appendTo( tr );
5645
				}
5646
			}
5647
	
5648
			// Tidy the temporary table - remove name attributes so there aren't
5649
			// duplicated in the dom (radio elements for example)
5650
			$('[name]', tmpTable).removeAttr('name');
5651
	
5652
			// Table has been built, attach to the document so we can work with it.
5653
			// A holding element is used, positioned at the top of the container
5654
			// with minimal height, so it has no effect on if the container scrolls
5655
			// or not. Otherwise it might trigger scrolling when it actually isn't
5656
			// needed
5657
			var holder = $('<div/>').css( scrollX || scrollY ?
5658
					{
5659
						position: 'absolute',
5660
						top: 0,
5661
						left: 0,
5662
						height: 1,
5663
						right: 0,
5664
						overflow: 'hidden'
5665
					} :
5666
					{}
5667
				)
5668
				.append( tmpTable )
5669
				.appendTo( tableContainer );
5670
	
5671
			// When scrolling (X or Y) we want to set the width of the table as 
5672
			// appropriate. However, when not scrolling leave the table width as it
5673
			// is. This results in slightly different, but I think correct behaviour
5674
			if ( scrollX && scrollXInner ) {
5675
				tmpTable.width( scrollXInner );
5676
			}
5677
			else if ( scrollX ) {
5678
				tmpTable.css( 'width', 'auto' );
5679
				tmpTable.removeAttr('width');
5680
	
5681
				// If there is no width attribute or style, then allow the table to
5682
				// collapse
5683
				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5684
					tmpTable.width( tableContainer.clientWidth );
5685
				}
5686
			}
5687
			else if ( scrollY ) {
5688
				tmpTable.width( tableContainer.clientWidth );
5689
			}
5690
			else if ( tableWidthAttr ) {
5691
				tmpTable.width( tableWidthAttr );
5692
			}
5693
	
5694
			// Get the width of each column in the constructed table - we need to
5695
			// know the inner width (so it can be assigned to the other table's
5696
			// cells) and the outer width so we can calculate the full width of the
5697
			// table. This is safe since DataTables requires a unique cell for each
5698
			// column, but if ever a header can span multiple columns, this will
5699
			// need to be modified.
5700
			var total = 0;
5701
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5702
				var cell = $(headerCells[i]);
5703
				var border = cell.outerWidth() - cell.width();
5704
	
5705
				// Use getBounding... where possible (not IE8-) because it can give
5706
				// sub-pixel accuracy, which we then want to round up!
5707
				var bounding = browser.bBounding ?
5708
					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5709
					cell.outerWidth();
5710
	
5711
				// Total is tracked to remove any sub-pixel errors as the outerWidth
5712
				// of the table might not equal the total given here (IE!).
5713
				total += bounding;
5714
	
5715
				// Width for each column to use
5716
				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5717
			}
5718
	
5719
			table.style.width = _fnStringToCss( total );
5720
	
5721
			// Finished with the table - ditch it
5722
			holder.remove();
5723
		}
5724
	
5725
		// If there is a width attr, we want to attach an event listener which
5726
		// allows the table sizing to automatically adjust when the window is
5727
		// resized. Use the width attr rather than CSS, since we can't know if the
5728
		// CSS is a relative value or absolute - DOM read is always px.
5729
		if ( tableWidthAttr ) {
5730
			table.style.width = _fnStringToCss( tableWidthAttr );
5731
		}
5732
	
5733
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5734
			var bindResize = function () {
5735
				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5736
					_fnAdjustColumnSizing( oSettings );
5737
				} ) );
5738
			};
5739
	
5740
			// IE6/7 will crash if we bind a resize event handler on page load.
5741
			// To be removed in 1.11 which drops IE6/7 support
5742
			if ( ie67 ) {
5743
				setTimeout( bindResize, 1000 );
5744
			}
5745
			else {
5746
				bindResize();
5747
			}
5748
	
5749
			oSettings._reszEvt = true;
5750
		}
5751
	}
5752
	
5753
	
5754
	/**
5755
	 * Throttle the calls to a function. Arguments and context are maintained for
5756
	 * the throttled function
5757
	 *  @param {function} fn Function to be called
5758
	 *  @param {int} [freq=200] call frequency in mS
5759
	 *  @returns {function} wrapped function
5760
	 *  @memberof DataTable#oApi
5761
	 */
5762
	var _fnThrottle = DataTable.util.throttle;
5763
	
5764
	
5765
	/**
5766
	 * Convert a CSS unit width to pixels (e.g. 2em)
5767
	 *  @param {string} width width to be converted
5768
	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5769
	 *  @returns {int} width in pixels
5770
	 *  @memberof DataTable#oApi
5771
	 */
5772
	function _fnConvertToWidth ( width, parent )
5773
	{
5774
		if ( ! width ) {
5775
			return 0;
5776
		}
5777
	
5778
		var n = $('<div/>')
5779
			.css( 'width', _fnStringToCss( width ) )
5780
			.appendTo( parent || document.body );
5781
	
5782
		var val = n[0].offsetWidth;
5783
		n.remove();
5784
	
5785
		return val;
5786
	}
5787
	
5788
	
5789
	/**
5790
	 * Get the widest node
5791
	 *  @param {object} settings dataTables settings object
5792
	 *  @param {int} colIdx column of interest
5793
	 *  @returns {node} widest table node
5794
	 *  @memberof DataTable#oApi
5795
	 */
5796
	function _fnGetWidestNode( settings, colIdx )
5797
	{
5798
		var idx = _fnGetMaxLenString( settings, colIdx );
5799
		if ( idx < 0 ) {
5800
			return null;
5801
		}
5802
	
5803
		var data = settings.aoData[ idx ];
5804
		return ! data.nTr ? // Might not have been created when deferred rendering
5805
			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5806
			data.anCells[ colIdx ];
5807
	}
5808
	
5809
	
5810
	/**
5811
	 * Get the maximum strlen for each data column
5812
	 *  @param {object} settings dataTables settings object
5813
	 *  @param {int} colIdx column of interest
5814
	 *  @returns {string} max string length for each column
5815
	 *  @memberof DataTable#oApi
5816
	 */
5817
	function _fnGetMaxLenString( settings, colIdx )
5818
	{
5819
		var s, max=-1, maxIdx = -1;
5820
	
5821
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5822
			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5823
			s = s.replace( __re_html_remove, '' );
5824
			s = s.replace( /&nbsp;/g, ' ' );
5825
	
5826
			if ( s.length > max ) {
5827
				max = s.length;
5828
				maxIdx = i;
5829
			}
5830
		}
5831
	
5832
		return maxIdx;
5833
	}
5834
	
5835
	
5836
	/**
5837
	 * Append a CSS unit (only if required) to a string
5838
	 *  @param {string} value to css-ify
5839
	 *  @returns {string} value with css unit
5840
	 *  @memberof DataTable#oApi
5841
	 */
5842
	function _fnStringToCss( s )
5843
	{
5844
		if ( s === null ) {
5845
			return '0px';
5846
		}
5847
	
5848
		if ( typeof s == 'number' ) {
5849
			return s < 0 ?
5850
				'0px' :
5851
				s+'px';
5852
		}
5853
	
5854
		// Check it has a unit character already
5855
		return s.match(/\d$/) ?
5856
			s+'px' :
5857
			s;
5858
	}
5859
	
5860
	
5861
	
5862
	function _fnSortFlatten ( settings )
5863
	{
5864
		var
5865
			i, iLen, k, kLen,
5866
			aSort = [],
5867
			aiOrig = [],
5868
			aoColumns = settings.aoColumns,
5869
			aDataSort, iCol, sType, srcCol,
5870
			fixed = settings.aaSortingFixed,
5871
			fixedObj = $.isPlainObject( fixed ),
5872
			nestedSort = [],
5873
			add = function ( a ) {
5874
				if ( a.length && ! $.isArray( a[0] ) ) {
5875
					// 1D array
5876
					nestedSort.push( a );
5877
				}
5878
				else {
5879
					// 2D array
5880
					$.merge( nestedSort, a );
5881
				}
5882
			};
5883
	
5884
		// Build the sort array, with pre-fix and post-fix options if they have been
5885
		// specified
5886
		if ( $.isArray( fixed ) ) {
5887
			add( fixed );
5888
		}
5889
	
5890
		if ( fixedObj && fixed.pre ) {
5891
			add( fixed.pre );
5892
		}
5893
	
5894
		add( settings.aaSorting );
5895
	
5896
		if (fixedObj && fixed.post ) {
5897
			add( fixed.post );
5898
		}
5899
	
5900
		for ( i=0 ; i<nestedSort.length ; i++ )
5901
		{
5902
			srcCol = nestedSort[i][0];
5903
			aDataSort = aoColumns[ srcCol ].aDataSort;
5904
	
5905
			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5906
			{
5907
				iCol = aDataSort[k];
5908
				sType = aoColumns[ iCol ].sType || 'string';
5909
	
5910
				if ( nestedSort[i]._idx === undefined ) {
5911
					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5912
				}
5913
	
5914
				aSort.push( {
5915
					src:       srcCol,
5916
					col:       iCol,
5917
					dir:       nestedSort[i][1],
5918
					index:     nestedSort[i]._idx,
5919
					type:      sType,
5920
					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5921
				} );
5922
			}
5923
		}
5924
	
5925
		return aSort;
5926
	}
5927
	
5928
	/**
5929
	 * Change the order of the table
5930
	 *  @param {object} oSettings dataTables settings object
5931
	 *  @memberof DataTable#oApi
5932
	 *  @todo This really needs split up!
5933
	 */
5934
	function _fnSort ( oSettings )
5935
	{
5936
		var
5937
			i, ien, iLen, j, jLen, k, kLen,
5938
			sDataType, nTh,
5939
			aiOrig = [],
5940
			oExtSort = DataTable.ext.type.order,
5941
			aoData = oSettings.aoData,
5942
			aoColumns = oSettings.aoColumns,
5943
			aDataSort, data, iCol, sType, oSort,
5944
			formatters = 0,
5945
			sortCol,
5946
			displayMaster = oSettings.aiDisplayMaster,
5947
			aSort;
5948
	
5949
		// Resolve any column types that are unknown due to addition or invalidation
5950
		// @todo Can this be moved into a 'data-ready' handler which is called when
5951
		//   data is going to be used in the table?
5952
		_fnColumnTypes( oSettings );
5953
	
5954
		aSort = _fnSortFlatten( oSettings );
5955
	
5956
		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5957
			sortCol = aSort[i];
5958
	
5959
			// Track if we can use the fast sort algorithm
5960
			if ( sortCol.formatter ) {
5961
				formatters++;
5962
			}
5963
	
5964
			// Load the data needed for the sort, for each cell
5965
			_fnSortData( oSettings, sortCol.col );
5966
		}
5967
	
5968
		/* No sorting required if server-side or no sorting array */
5969
		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5970
		{
5971
			// Create a value - key array of the current row positions such that we can use their
5972
			// current position during the sort, if values match, in order to perform stable sorting
5973
			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5974
				aiOrig[ displayMaster[i] ] = i;
5975
			}
5976
	
5977
			/* Do the sort - here we want multi-column sorting based on a given data source (column)
5978
			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5979
			 * follow on it's own, but this is what we want (example two column sorting):
5980
			 *  fnLocalSorting = function(a,b){
5981
			 *    var iTest;
5982
			 *    iTest = oSort['string-asc']('data11', 'data12');
5983
			 *      if (iTest !== 0)
5984
			 *        return iTest;
5985
			 *    iTest = oSort['numeric-desc']('data21', 'data22');
5986
			 *    if (iTest !== 0)
5987
			 *      return iTest;
5988
			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5989
			 *  }
5990
			 * Basically we have a test for each sorting column, if the data in that column is equal,
5991
			 * test the next column. If all columns match, then we use a numeric sort on the row
5992
			 * positions in the original data array to provide a stable sort.
5993
			 *
5994
			 * Note - I know it seems excessive to have two sorting methods, but the first is around
5995
			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
5996
			 * methods which do not have a pre-sort formatting function.
5997
			 */
5998
			if ( formatters === aSort.length ) {
5999
				// All sort types have formatting functions
6000
				displayMaster.sort( function ( a, b ) {
6001
					var
6002
						x, y, k, test, sort,
6003
						len=aSort.length,
6004
						dataA = aoData[a]._aSortData,
6005
						dataB = aoData[b]._aSortData;
6006
	
6007
					for ( k=0 ; k<len ; k++ ) {
6008
						sort = aSort[k];
6009
	
6010
						x = dataA[ sort.col ];
6011
						y = dataB[ sort.col ];
6012
	
6013
						test = x<y ? -1 : x>y ? 1 : 0;
6014
						if ( test !== 0 ) {
6015
							return sort.dir === 'asc' ? test : -test;
6016
						}
6017
					}
6018
	
6019
					x = aiOrig[a];
6020
					y = aiOrig[b];
6021
					return x<y ? -1 : x>y ? 1 : 0;
6022
				} );
6023
			}
6024
			else {
6025
				// Depreciated - remove in 1.11 (providing a plug-in option)
6026
				// Not all sort types have formatting methods, so we have to call their sorting
6027
				// methods.
6028
				displayMaster.sort( function ( a, b ) {
6029
					var
6030
						x, y, k, l, test, sort, fn,
6031
						len=aSort.length,
6032
						dataA = aoData[a]._aSortData,
6033
						dataB = aoData[b]._aSortData;
6034
	
6035
					for ( k=0 ; k<len ; k++ ) {
6036
						sort = aSort[k];
6037
	
6038
						x = dataA[ sort.col ];
6039
						y = dataB[ sort.col ];
6040
	
6041
						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6042
						test = fn( x, y );
6043
						if ( test !== 0 ) {
6044
							return test;
6045
						}
6046
					}
6047
	
6048
					x = aiOrig[a];
6049
					y = aiOrig[b];
6050
					return x<y ? -1 : x>y ? 1 : 0;
6051
				} );
6052
			}
6053
		}
6054
	
6055
		/* Tell the draw function that we have sorted the data */
6056
		oSettings.bSorted = true;
6057
	}
6058
	
6059
	
6060
	function _fnSortAria ( settings )
6061
	{
6062
		var label;
6063
		var nextSort;
6064
		var columns = settings.aoColumns;
6065
		var aSort = _fnSortFlatten( settings );
6066
		var oAria = settings.oLanguage.oAria;
6067
	
6068
		// ARIA attributes - need to loop all columns, to update all (removing old
6069
		// attributes as needed)
6070
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6071
		{
6072
			var col = columns[i];
6073
			var asSorting = col.asSorting;
6074
			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6075
			var th = col.nTh;
6076
	
6077
			// IE7 is throwing an error when setting these properties with jQuery's
6078
			// attr() and removeAttr() methods...
6079
			th.removeAttribute('aria-sort');
6080
	
6081
			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6082
			if ( col.bSortable ) {
6083
				if ( aSort.length > 0 && aSort[0].col == i ) {
6084
					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6085
					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6086
				}
6087
				else {
6088
					nextSort = asSorting[0];
6089
				}
6090
	
6091
				label = sTitle + ( nextSort === "asc" ?
6092
					oAria.sSortAscending :
6093
					oAria.sSortDescending
6094
				);
6095
			}
6096
			else {
6097
				label = sTitle;
6098
			}
6099
	
6100
			th.setAttribute('aria-label', label);
6101
		}
6102
	}
6103
	
6104
	
6105
	/**
6106
	 * Function to run on user sort request
6107
	 *  @param {object} settings dataTables settings object
6108
	 *  @param {node} attachTo node to attach the handler to
6109
	 *  @param {int} colIdx column sorting index
6110
	 *  @param {boolean} [append=false] Append the requested sort to the existing
6111
	 *    sort if true (i.e. multi-column sort)
6112
	 *  @param {function} [callback] callback function
6113
	 *  @memberof DataTable#oApi
6114
	 */
6115
	function _fnSortListener ( settings, colIdx, append, callback )
6116
	{
6117
		var col = settings.aoColumns[ colIdx ];
6118
		var sorting = settings.aaSorting;
6119
		var asSorting = col.asSorting;
6120
		var nextSortIdx;
6121
		var next = function ( a, overflow ) {
6122
			var idx = a._idx;
6123
			if ( idx === undefined ) {
6124
				idx = $.inArray( a[1], asSorting );
6125
			}
6126
	
6127
			return idx+1 < asSorting.length ?
6128
				idx+1 :
6129
				overflow ?
6130
					null :
6131
					0;
6132
		};
6133
	
6134
		// Convert to 2D array if needed
6135
		if ( typeof sorting[0] === 'number' ) {
6136
			sorting = settings.aaSorting = [ sorting ];
6137
		}
6138
	
6139
		// If appending the sort then we are multi-column sorting
6140
		if ( append && settings.oFeatures.bSortMulti ) {
6141
			// Are we already doing some kind of sort on this column?
6142
			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6143
	
6144
			if ( sortIdx !== -1 ) {
6145
				// Yes, modify the sort
6146
				nextSortIdx = next( sorting[sortIdx], true );
6147
	
6148
				if ( nextSortIdx === null && sorting.length === 1 ) {
6149
					nextSortIdx = 0; // can't remove sorting completely
6150
				}
6151
	
6152
				if ( nextSortIdx === null ) {
6153
					sorting.splice( sortIdx, 1 );
6154
				}
6155
				else {
6156
					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6157
					sorting[sortIdx]._idx = nextSortIdx;
6158
				}
6159
			}
6160
			else {
6161
				// No sort on this column yet
6162
				sorting.push( [ colIdx, asSorting[0], 0 ] );
6163
				sorting[sorting.length-1]._idx = 0;
6164
			}
6165
		}
6166
		else if ( sorting.length && sorting[0][0] == colIdx ) {
6167
			// Single column - already sorting on this column, modify the sort
6168
			nextSortIdx = next( sorting[0] );
6169
	
6170
			sorting.length = 1;
6171
			sorting[0][1] = asSorting[ nextSortIdx ];
6172
			sorting[0]._idx = nextSortIdx;
6173
		}
6174
		else {
6175
			// Single column - sort only on this column
6176
			sorting.length = 0;
6177
			sorting.push( [ colIdx, asSorting[0] ] );
6178
			sorting[0]._idx = 0;
6179
		}
6180
	
6181
		// Run the sort by calling a full redraw
6182
		_fnReDraw( settings );
6183
	
6184
		// callback used for async user interaction
6185
		if ( typeof callback == 'function' ) {
6186
			callback( settings );
6187
		}
6188
	}
6189
	
6190
	
6191
	/**
6192
	 * Attach a sort handler (click) to a node
6193
	 *  @param {object} settings dataTables settings object
6194
	 *  @param {node} attachTo node to attach the handler to
6195
	 *  @param {int} colIdx column sorting index
6196
	 *  @param {function} [callback] callback function
6197
	 *  @memberof DataTable#oApi
6198
	 */
6199
	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6200
	{
6201
		var col = settings.aoColumns[ colIdx ];
6202
	
6203
		_fnBindAction( attachTo, {}, function (e) {
6204
			/* If the column is not sortable - don't to anything */
6205
			if ( col.bSortable === false ) {
6206
				return;
6207
			}
6208
	
6209
			// If processing is enabled use a timeout to allow the processing
6210
			// display to be shown - otherwise to it synchronously
6211
			if ( settings.oFeatures.bProcessing ) {
6212
				_fnProcessingDisplay( settings, true );
6213
	
6214
				setTimeout( function() {
6215
					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6216
	
6217
					// In server-side processing, the draw callback will remove the
6218
					// processing display
6219
					if ( _fnDataSource( settings ) !== 'ssp' ) {
6220
						_fnProcessingDisplay( settings, false );
6221
					}
6222
				}, 0 );
6223
			}
6224
			else {
6225
				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6226
			}
6227
		} );
6228
	}
6229
	
6230
	
6231
	/**
6232
	 * Set the sorting classes on table's body, Note: it is safe to call this function
6233
	 * when bSort and bSortClasses are false
6234
	 *  @param {object} oSettings dataTables settings object
6235
	 *  @memberof DataTable#oApi
6236
	 */
6237
	function _fnSortingClasses( settings )
6238
	{
6239
		var oldSort = settings.aLastSort;
6240
		var sortClass = settings.oClasses.sSortColumn;
6241
		var sort = _fnSortFlatten( settings );
6242
		var features = settings.oFeatures;
6243
		var i, ien, colIdx;
6244
	
6245
		if ( features.bSort && features.bSortClasses ) {
6246
			// Remove old sorting classes
6247
			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6248
				colIdx = oldSort[i].src;
6249
	
6250
				// Remove column sorting
6251
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6252
					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6253
			}
6254
	
6255
			// Add new column sorting
6256
			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6257
				colIdx = sort[i].src;
6258
	
6259
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6260
					.addClass( sortClass + (i<2 ? i+1 : 3) );
6261
			}
6262
		}
6263
	
6264
		settings.aLastSort = sort;
6265
	}
6266
	
6267
	
6268
	// Get the data to sort a column, be it from cache, fresh (populating the
6269
	// cache), or from a sort formatter
6270
	function _fnSortData( settings, idx )
6271
	{
6272
		// Custom sorting function - provided by the sort data type
6273
		var column = settings.aoColumns[ idx ];
6274
		var customSort = DataTable.ext.order[ column.sSortDataType ];
6275
		var customData;
6276
	
6277
		if ( customSort ) {
6278
			customData = customSort.call( settings.oInstance, settings, idx,
6279
				_fnColumnIndexToVisible( settings, idx )
6280
			);
6281
		}
6282
	
6283
		// Use / populate cache
6284
		var row, cellData;
6285
		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6286
	
6287
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6288
			row = settings.aoData[i];
6289
	
6290
			if ( ! row._aSortData ) {
6291
				row._aSortData = [];
6292
			}
6293
	
6294
			if ( ! row._aSortData[idx] || customSort ) {
6295
				cellData = customSort ?
6296
					customData[i] : // If there was a custom sort function, use data from there
6297
					_fnGetCellData( settings, i, idx, 'sort' );
6298
	
6299
				row._aSortData[ idx ] = formatter ?
6300
					formatter( cellData ) :
6301
					cellData;
6302
			}
6303
		}
6304
	}
6305
	
6306
	
6307
	
6308
	/**
6309
	 * Save the state of a table
6310
	 *  @param {object} oSettings dataTables settings object
6311
	 *  @memberof DataTable#oApi
6312
	 */
6313
	function _fnSaveState ( settings )
6314
	{
6315
		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6316
		{
6317
			return;
6318
		}
6319
	
6320
		/* Store the interesting variables */
6321
		var state = {
6322
			time:    +new Date(),
6323
			start:   settings._iDisplayStart,
6324
			length:  settings._iDisplayLength,
6325
			order:   $.extend( true, [], settings.aaSorting ),
6326
			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6327
			columns: $.map( settings.aoColumns, function ( col, i ) {
6328
				return {
6329
					visible: col.bVisible,
6330
					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6331
				};
6332
			} )
6333
		};
6334
	
6335
		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6336
	
6337
		settings.oSavedState = state;
6338
		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6339
	}
6340
	
6341
	
6342
	/**
6343
	 * Attempt to load a saved table state
6344
	 *  @param {object} oSettings dataTables settings object
6345
	 *  @param {object} oInit DataTables init object so we can override settings
6346
	 *  @param {function} callback Callback to execute when the state has been loaded
6347
	 *  @memberof DataTable#oApi
6348
	 */
6349
	function _fnLoadState ( settings, oInit, callback )
6350
	{
6351
		var i, ien;
6352
		var columns = settings.aoColumns;
6353
		var loaded = function ( s ) {
6354
			if ( ! s || ! s.time ) {
6355
				callback();
6356
				return;
6357
			}
6358
	
6359
			// Allow custom and plug-in manipulation functions to alter the saved data set and
6360
			// cancelling of loading by returning false
6361
			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6362
			if ( $.inArray( false, abStateLoad ) !== -1 ) {
6363
				callback();
6364
				return;
6365
			}
6366
	
6367
			// Reject old data
6368
			var duration = settings.iStateDuration;
6369
			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6370
				callback();
6371
				return;
6372
			}
6373
	
6374
			// Number of columns have changed - all bets are off, no restore of settings
6375
			if ( s.columns && columns.length !== s.columns.length ) {
6376
				callback();
6377
				return;
6378
			}
6379
	
6380
			// Store the saved state so it might be accessed at any time
6381
			settings.oLoadedState = $.extend( true, {}, s );
6382
	
6383
			// Restore key features - todo - for 1.11 this needs to be done by
6384
			// subscribed events
6385
			if ( s.start !== undefined ) {
6386
				settings._iDisplayStart    = s.start;
6387
				settings.iInitDisplayStart = s.start;
6388
			}
6389
			if ( s.length !== undefined ) {
6390
				settings._iDisplayLength   = s.length;
6391
			}
6392
	
6393
			// Order
6394
			if ( s.order !== undefined ) {
6395
				settings.aaSorting = [];
6396
				$.each( s.order, function ( i, col ) {
6397
					settings.aaSorting.push( col[0] >= columns.length ?
6398
						[ 0, col[1] ] :
6399
						col
6400
					);
6401
				} );
6402
			}
6403
	
6404
			// Search
6405
			if ( s.search !== undefined ) {
6406
				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6407
			}
6408
	
6409
			// Columns
6410
			//
6411
			if ( s.columns ) {
6412
				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6413
					var col = s.columns[i];
6414
	
6415
					// Visibility
6416
					if ( col.visible !== undefined ) {
6417
						columns[i].bVisible = col.visible;
6418
					}
6419
	
6420
					// Search
6421
					if ( col.search !== undefined ) {
6422
						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6423
					}
6424
				}
6425
			}
6426
	
6427
			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6428
			callback();
6429
		}
6430
	
6431
		if ( ! settings.oFeatures.bStateSave ) {
6432
			callback();
6433
			return;
6434
		}
6435
	
6436
		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6437
	
6438
		if ( state !== undefined ) {
6439
			loaded( state );
6440
		}
6441
		// otherwise, wait for the loaded callback to be executed
6442
	}
6443
	
6444
	
6445
	/**
6446
	 * Return the settings object for a particular table
6447
	 *  @param {node} table table we are using as a dataTable
6448
	 *  @returns {object} Settings object - or null if not found
6449
	 *  @memberof DataTable#oApi
6450
	 */
6451
	function _fnSettingsFromNode ( table )
6452
	{
6453
		var settings = DataTable.settings;
6454
		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6455
	
6456
		return idx !== -1 ?
6457
			settings[ idx ] :
6458
			null;
6459
	}
6460
	
6461
	
6462
	/**
6463
	 * Log an error message
6464
	 *  @param {object} settings dataTables settings object
6465
	 *  @param {int} level log error messages, or display them to the user
6466
	 *  @param {string} msg error message
6467
	 *  @param {int} tn Technical note id to get more information about the error.
6468
	 *  @memberof DataTable#oApi
6469
	 */
6470
	function _fnLog( settings, level, msg, tn )
6471
	{
6472
		msg = 'DataTables warning: '+
6473
			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6474
	
6475
		if ( tn ) {
6476
			msg += '. For more information about this error, please see '+
6477
			'http://datatables.net/tn/'+tn;
6478
		}
6479
	
6480
		if ( ! level  ) {
6481
			// Backwards compatibility pre 1.10
6482
			var ext = DataTable.ext;
6483
			var type = ext.sErrMode || ext.errMode;
6484
	
6485
			if ( settings ) {
6486
				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6487
			}
6488
	
6489
			if ( type == 'alert' ) {
6490
				alert( msg );
6491
			}
6492
			else if ( type == 'throw' ) {
6493
				throw new Error(msg);
6494
			}
6495
			else if ( typeof type == 'function' ) {
6496
				type( settings, tn, msg );
6497
			}
6498
		}
6499
		else if ( window.console && console.log ) {
6500
			console.log( msg );
6501
		}
6502
	}
6503
	
6504
	
6505
	/**
6506
	 * See if a property is defined on one object, if so assign it to the other object
6507
	 *  @param {object} ret target object
6508
	 *  @param {object} src source object
6509
	 *  @param {string} name property
6510
	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6511
	 *  @memberof DataTable#oApi
6512
	 */
6513
	function _fnMap( ret, src, name, mappedName )
6514
	{
6515
		if ( $.isArray( name ) ) {
6516
			$.each( name, function (i, val) {
6517
				if ( $.isArray( val ) ) {
6518
					_fnMap( ret, src, val[0], val[1] );
6519
				}
6520
				else {
6521
					_fnMap( ret, src, val );
6522
				}
6523
			} );
6524
	
6525
			return;
6526
		}
6527
	
6528
		if ( mappedName === undefined ) {
6529
			mappedName = name;
6530
		}
6531
	
6532
		if ( src[name] !== undefined ) {
6533
			ret[mappedName] = src[name];
6534
		}
6535
	}
6536
	
6537
	
6538
	/**
6539
	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6540
	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6541
	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6542
	 * able to override them, but we do want to deep copy arrays.
6543
	 *  @param {object} out Object to extend
6544
	 *  @param {object} extender Object from which the properties will be applied to
6545
	 *      out
6546
	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6547
	 *      independent copy with the exception of the `data` or `aaData` parameters
6548
	 *      if they are present. This is so you can pass in a collection to
6549
	 *      DataTables and have that used as your data source without breaking the
6550
	 *      references
6551
	 *  @returns {object} out Reference, just for convenience - out === the return.
6552
	 *  @memberof DataTable#oApi
6553
	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6554
	 */
6555
	function _fnExtend( out, extender, breakRefs )
6556
	{
6557
		var val;
6558
	
6559
		for ( var prop in extender ) {
6560
			if ( extender.hasOwnProperty(prop) ) {
6561
				val = extender[prop];
6562
	
6563
				if ( $.isPlainObject( val ) ) {
6564
					if ( ! $.isPlainObject( out[prop] ) ) {
6565
						out[prop] = {};
6566
					}
6567
					$.extend( true, out[prop], val );
6568
				}
6569
				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6570
					out[prop] = val.slice();
6571
				}
6572
				else {
6573
					out[prop] = val;
6574
				}
6575
			}
6576
		}
6577
	
6578
		return out;
6579
	}
6580
	
6581
	
6582
	/**
6583
	 * Bind an event handers to allow a click or return key to activate the callback.
6584
	 * This is good for accessibility since a return on the keyboard will have the
6585
	 * same effect as a click, if the element has focus.
6586
	 *  @param {element} n Element to bind the action to
6587
	 *  @param {object} oData Data object to pass to the triggered function
6588
	 *  @param {function} fn Callback function for when the event is triggered
6589
	 *  @memberof DataTable#oApi
6590
	 */
6591
	function _fnBindAction( n, oData, fn )
6592
	{
6593
		$(n)
6594
			.on( 'click.DT', oData, function (e) {
6595
					$(n).blur(); // Remove focus outline for mouse users
6596
					fn(e);
6597
				} )
6598
			.on( 'keypress.DT', oData, function (e){
6599
					if ( e.which === 13 ) {
6600
						e.preventDefault();
6601
						fn(e);
6602
					}
6603
				} )
6604
			.on( 'selectstart.DT', function () {
6605
					/* Take the brutal approach to cancelling text selection */
6606
					return false;
6607
				} );
6608
	}
6609
	
6610
	
6611
	/**
6612
	 * Register a callback function. Easily allows a callback function to be added to
6613
	 * an array store of callback functions that can then all be called together.
6614
	 *  @param {object} oSettings dataTables settings object
6615
	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6616
	 *  @param {function} fn Function to be called back
6617
	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6618
	 *  @memberof DataTable#oApi
6619
	 */
6620
	function _fnCallbackReg( oSettings, sStore, fn, sName )
6621
	{
6622
		if ( fn )
6623
		{
6624
			oSettings[sStore].push( {
6625
				"fn": fn,
6626
				"sName": sName
6627
			} );
6628
		}
6629
	}
6630
	
6631
	
6632
	/**
6633
	 * Fire callback functions and trigger events. Note that the loop over the
6634
	 * callback array store is done backwards! Further note that you do not want to
6635
	 * fire off triggers in time sensitive applications (for example cell creation)
6636
	 * as its slow.
6637
	 *  @param {object} settings dataTables settings object
6638
	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6639
	 *      oSettings
6640
	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6641
	 *      null no trigger is fired
6642
	 *  @param {array} args Array of arguments to pass to the callback function /
6643
	 *      trigger
6644
	 *  @memberof DataTable#oApi
6645
	 */
6646
	function _fnCallbackFire( settings, callbackArr, eventName, args )
6647
	{
6648
		var ret = [];
6649
	
6650
		if ( callbackArr ) {
6651
			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6652
				return val.fn.apply( settings.oInstance, args );
6653
			} );
6654
		}
6655
	
6656
		if ( eventName !== null ) {
6657
			var e = $.Event( eventName+'.dt' );
6658
	
6659
			$(settings.nTable).trigger( e, args );
6660
	
6661
			ret.push( e.result );
6662
		}
6663
	
6664
		return ret;
6665
	}
6666
	
6667
	
6668
	function _fnLengthOverflow ( settings )
6669
	{
6670
		var
6671
			start = settings._iDisplayStart,
6672
			end = settings.fnDisplayEnd(),
6673
			len = settings._iDisplayLength;
6674
	
6675
		/* If we have space to show extra rows (backing up from the end point - then do so */
6676
		if ( start >= end )
6677
		{
6678
			start = end - len;
6679
		}
6680
	
6681
		// Keep the start record on the current page
6682
		start -= (start % len);
6683
	
6684
		if ( len === -1 || start < 0 )
6685
		{
6686
			start = 0;
6687
		}
6688
	
6689
		settings._iDisplayStart = start;
6690
	}
6691
	
6692
	
6693
	function _fnRenderer( settings, type )
6694
	{
6695
		var renderer = settings.renderer;
6696
		var host = DataTable.ext.renderer[type];
6697
	
6698
		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6699
			// Specific renderer for this type. If available use it, otherwise use
6700
			// the default.
6701
			return host[renderer[type]] || host._;
6702
		}
6703
		else if ( typeof renderer === 'string' ) {
6704
			// Common renderer - if there is one available for this type use it,
6705
			// otherwise use the default
6706
			return host[renderer] || host._;
6707
		}
6708
	
6709
		// Use the default
6710
		return host._;
6711
	}
6712
	
6713
	
6714
	/**
6715
	 * Detect the data source being used for the table. Used to simplify the code
6716
	 * a little (ajax) and to make it compress a little smaller.
6717
	 *
6718
	 *  @param {object} settings dataTables settings object
6719
	 *  @returns {string} Data source
6720
	 *  @memberof DataTable#oApi
6721
	 */
6722
	function _fnDataSource ( settings )
6723
	{
6724
		if ( settings.oFeatures.bServerSide ) {
6725
			return 'ssp';
6726
		}
6727
		else if ( settings.ajax || settings.sAjaxSource ) {
6728
			return 'ajax';
6729
		}
6730
		return 'dom';
6731
	}
6732
	
6733
6734
	
6735
	
6736
	/**
6737
	 * Computed structure of the DataTables API, defined by the options passed to
6738
	 * `DataTable.Api.register()` when building the API.
6739
	 *
6740
	 * The structure is built in order to speed creation and extension of the Api
6741
	 * objects since the extensions are effectively pre-parsed.
6742
	 *
6743
	 * The array is an array of objects with the following structure, where this
6744
	 * base array represents the Api prototype base:
6745
	 *
6746
	 *     [
6747
	 *       {
6748
	 *         name:      'data'                -- string   - Property name
6749
	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6750
	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6751
	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6752
	 *       },
6753
	 *       {
6754
	 *         name:     'row'
6755
	 *         val:       {},
6756
	 *         methodExt: [ ... ],
6757
	 *         propExt:   [
6758
	 *           {
6759
	 *             name:      'data'
6760
	 *             val:       function () {},
6761
	 *             methodExt: [ ... ],
6762
	 *             propExt:   [ ... ]
6763
	 *           },
6764
	 *           ...
6765
	 *         ]
6766
	 *       }
6767
	 *     ]
6768
	 *
6769
	 * @type {Array}
6770
	 * @ignore
6771
	 */
6772
	var __apiStruct = [];
6773
	
6774
	
6775
	/**
6776
	 * `Array.prototype` reference.
6777
	 *
6778
	 * @type object
6779
	 * @ignore
6780
	 */
6781
	var __arrayProto = Array.prototype;
6782
	
6783
	
6784
	/**
6785
	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6786
	 * take several different forms for ease of use.
6787
	 *
6788
	 * Each of the input parameter types will be converted to a DataTables settings
6789
	 * object where possible.
6790
	 *
6791
	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6792
	 *   of:
6793
	 *
6794
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6795
	 *     with be found and used.
6796
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6797
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6798
	 *   * `object` - DataTables settings object
6799
	 *   * `DataTables.Api` - API instance
6800
	 * @return {array|null} Matching DataTables settings objects. `null` or
6801
	 *   `undefined` is returned if no matching DataTable is found.
6802
	 * @ignore
6803
	 */
6804
	var _toSettings = function ( mixed )
6805
	{
6806
		var idx, jq;
6807
		var settings = DataTable.settings;
6808
		var tables = $.map( settings, function (el, i) {
6809
			return el.nTable;
6810
		} );
6811
	
6812
		if ( ! mixed ) {
6813
			return [];
6814
		}
6815
		else if ( mixed.nTable && mixed.oApi ) {
6816
			// DataTables settings object
6817
			return [ mixed ];
6818
		}
6819
		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6820
			// Table node
6821
			idx = $.inArray( mixed, tables );
6822
			return idx !== -1 ? [ settings[idx] ] : null;
6823
		}
6824
		else if ( mixed && typeof mixed.settings === 'function' ) {
6825
			return mixed.settings().toArray();
6826
		}
6827
		else if ( typeof mixed === 'string' ) {
6828
			// jQuery selector
6829
			jq = $(mixed);
6830
		}
6831
		else if ( mixed instanceof $ ) {
6832
			// jQuery object (also DataTables instance)
6833
			jq = mixed;
6834
		}
6835
	
6836
		if ( jq ) {
6837
			return jq.map( function(i) {
6838
				idx = $.inArray( this, tables );
6839
				return idx !== -1 ? settings[idx] : null;
6840
			} ).toArray();
6841
		}
6842
	};
6843
	
6844
	
6845
	/**
6846
	 * DataTables API class - used to control and interface with  one or more
6847
	 * DataTables enhanced tables.
6848
	 *
6849
	 * The API class is heavily based on jQuery, presenting a chainable interface
6850
	 * that you can use to interact with tables. Each instance of the API class has
6851
	 * a "context" - i.e. the tables that it will operate on. This could be a single
6852
	 * table, all tables on a page or a sub-set thereof.
6853
	 *
6854
	 * Additionally the API is designed to allow you to easily work with the data in
6855
	 * the tables, retrieving and manipulating it as required. This is done by
6856
	 * presenting the API class as an array like interface. The contents of the
6857
	 * array depend upon the actions requested by each method (for example
6858
	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6859
	 * return an array of objects or arrays depending upon your table's
6860
	 * configuration). The API object has a number of array like methods (`push`,
6861
	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6862
	 * `unique` etc) to assist your working with the data held in a table.
6863
	 *
6864
	 * Most methods (those which return an Api instance) are chainable, which means
6865
	 * the return from a method call also has all of the methods available that the
6866
	 * top level object had. For example, these two calls are equivalent:
6867
	 *
6868
	 *     // Not chained
6869
	 *     api.row.add( {...} );
6870
	 *     api.draw();
6871
	 *
6872
	 *     // Chained
6873
	 *     api.row.add( {...} ).draw();
6874
	 *
6875
	 * @class DataTable.Api
6876
	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6877
	 *   used to define which DataTables enhanced tables this API will operate on.
6878
	 *   Can be one of:
6879
	 *
6880
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6881
	 *     with be found and used.
6882
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6883
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6884
	 *   * `object` - DataTables settings object
6885
	 * @param {array} [data] Data to initialise the Api instance with.
6886
	 *
6887
	 * @example
6888
	 *   // Direct initialisation during DataTables construction
6889
	 *   var api = $('#example').DataTable();
6890
	 *
6891
	 * @example
6892
	 *   // Initialisation using a DataTables jQuery object
6893
	 *   var api = $('#example').dataTable().api();
6894
	 *
6895
	 * @example
6896
	 *   // Initialisation as a constructor
6897
	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6898
	 */
6899
	_Api = function ( context, data )
6900
	{
6901
		if ( ! (this instanceof _Api) ) {
6902
			return new _Api( context, data );
6903
		}
6904
	
6905
		var settings = [];
6906
		var ctxSettings = function ( o ) {
6907
			var a = _toSettings( o );
6908
			if ( a ) {
6909
				settings = settings.concat( a );
6910
			}
6911
		};
6912
	
6913
		if ( $.isArray( context ) ) {
6914
			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6915
				ctxSettings( context[i] );
6916
			}
6917
		}
6918
		else {
6919
			ctxSettings( context );
6920
		}
6921
	
6922
		// Remove duplicates
6923
		this.context = _unique( settings );
6924
	
6925
		// Initial data
6926
		if ( data ) {
6927
			$.merge( this, data );
6928
		}
6929
	
6930
		// selector
6931
		this.selector = {
6932
			rows: null,
6933
			cols: null,
6934
			opts: null
6935
		};
6936
	
6937
		_Api.extend( this, this, __apiStruct );
6938
	};
6939
	
6940
	DataTable.Api = _Api;
6941
	
6942
	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6943
	// isPlainObject.
6944
	$.extend( _Api.prototype, {
6945
		any: function ()
6946
		{
6947
			return this.count() !== 0;
6948
		},
6949
	
6950
	
6951
		concat:  __arrayProto.concat,
6952
	
6953
	
6954
		context: [], // array of table settings objects
6955
	
6956
	
6957
		count: function ()
6958
		{
6959
			return this.flatten().length;
6960
		},
6961
	
6962
	
6963
		each: function ( fn )
6964
		{
6965
			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6966
				fn.call( this, this[i], i, this );
6967
			}
6968
	
6969
			return this;
6970
		},
6971
	
6972
	
6973
		eq: function ( idx )
6974
		{
6975
			var ctx = this.context;
6976
	
6977
			return ctx.length > idx ?
6978
				new _Api( ctx[idx], this[idx] ) :
6979
				null;
6980
		},
6981
	
6982
	
6983
		filter: function ( fn )
6984
		{
6985
			var a = [];
6986
	
6987
			if ( __arrayProto.filter ) {
6988
				a = __arrayProto.filter.call( this, fn, this );
6989
			}
6990
			else {
6991
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6992
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6993
					if ( fn.call( this, this[i], i, this ) ) {
6994
						a.push( this[i] );
6995
					}
6996
				}
6997
			}
6998
	
6999
			return new _Api( this.context, a );
7000
		},
7001
	
7002
	
7003
		flatten: function ()
7004
		{
7005
			var a = [];
7006
			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7007
		},
7008
	
7009
	
7010
		join:    __arrayProto.join,
7011
	
7012
	
7013
		indexOf: __arrayProto.indexOf || function (obj, start)
7014
		{
7015
			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7016
				if ( this[i] === obj ) {
7017
					return i;
7018
				}
7019
			}
7020
			return -1;
7021
		},
7022
	
7023
		iterator: function ( flatten, type, fn, alwaysNew ) {
7024
			var
7025
				a = [], ret,
7026
				i, ien, j, jen,
7027
				context = this.context,
7028
				rows, items, item,
7029
				selector = this.selector;
7030
	
7031
			// Argument shifting
7032
			if ( typeof flatten === 'string' ) {
7033
				alwaysNew = fn;
7034
				fn = type;
7035
				type = flatten;
7036
				flatten = false;
7037
			}
7038
	
7039
			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7040
				var apiInst = new _Api( context[i] );
7041
	
7042
				if ( type === 'table' ) {
7043
					ret = fn.call( apiInst, context[i], i );
7044
	
7045
					if ( ret !== undefined ) {
7046
						a.push( ret );
7047
					}
7048
				}
7049
				else if ( type === 'columns' || type === 'rows' ) {
7050
					// this has same length as context - one entry for each table
7051
					ret = fn.call( apiInst, context[i], this[i], i );
7052
	
7053
					if ( ret !== undefined ) {
7054
						a.push( ret );
7055
					}
7056
				}
7057
				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7058
					// columns and rows share the same structure.
7059
					// 'this' is an array of column indexes for each context
7060
					items = this[i];
7061
	
7062
					if ( type === 'column-rows' ) {
7063
						rows = _selector_row_indexes( context[i], selector.opts );
7064
					}
7065
	
7066
					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7067
						item = items[j];
7068
	
7069
						if ( type === 'cell' ) {
7070
							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7071
						}
7072
						else {
7073
							ret = fn.call( apiInst, context[i], item, i, j, rows );
7074
						}
7075
	
7076
						if ( ret !== undefined ) {
7077
							a.push( ret );
7078
						}
7079
					}
7080
				}
7081
			}
7082
	
7083
			if ( a.length || alwaysNew ) {
7084
				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7085
				var apiSelector = api.selector;
7086
				apiSelector.rows = selector.rows;
7087
				apiSelector.cols = selector.cols;
7088
				apiSelector.opts = selector.opts;
7089
				return api;
7090
			}
7091
			return this;
7092
		},
7093
	
7094
	
7095
		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7096
		{
7097
			// Bit cheeky...
7098
			return this.indexOf.apply( this.toArray.reverse(), arguments );
7099
		},
7100
	
7101
	
7102
		length:  0,
7103
	
7104
	
7105
		map: function ( fn )
7106
		{
7107
			var a = [];
7108
	
7109
			if ( __arrayProto.map ) {
7110
				a = __arrayProto.map.call( this, fn, this );
7111
			}
7112
			else {
7113
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7114
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7115
					a.push( fn.call( this, this[i], i ) );
7116
				}
7117
			}
7118
	
7119
			return new _Api( this.context, a );
7120
		},
7121
	
7122
	
7123
		pluck: function ( prop )
7124
		{
7125
			return this.map( function ( el ) {
7126
				return el[ prop ];
7127
			} );
7128
		},
7129
	
7130
		pop:     __arrayProto.pop,
7131
	
7132
	
7133
		push:    __arrayProto.push,
7134
	
7135
	
7136
		// Does not return an API instance
7137
		reduce: __arrayProto.reduce || function ( fn, init )
7138
		{
7139
			return _fnReduce( this, fn, init, 0, this.length, 1 );
7140
		},
7141
	
7142
	
7143
		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7144
		{
7145
			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7146
		},
7147
	
7148
	
7149
		reverse: __arrayProto.reverse,
7150
	
7151
	
7152
		// Object with rows, columns and opts
7153
		selector: null,
7154
	
7155
	
7156
		shift:   __arrayProto.shift,
7157
	
7158
	
7159
		slice: function () {
7160
			return new _Api( this.context, this );
7161
		},
7162
	
7163
	
7164
		sort:    __arrayProto.sort, // ? name - order?
7165
	
7166
	
7167
		splice:  __arrayProto.splice,
7168
	
7169
	
7170
		toArray: function ()
7171
		{
7172
			return __arrayProto.slice.call( this );
7173
		},
7174
	
7175
	
7176
		to$: function ()
7177
		{
7178
			return $( this );
7179
		},
7180
	
7181
	
7182
		toJQuery: function ()
7183
		{
7184
			return $( this );
7185
		},
7186
	
7187
	
7188
		unique: function ()
7189
		{
7190
			return new _Api( this.context, _unique(this) );
7191
		},
7192
	
7193
	
7194
		unshift: __arrayProto.unshift
7195
	} );
7196
	
7197
	
7198
	_Api.extend = function ( scope, obj, ext )
7199
	{
7200
		// Only extend API instances and static properties of the API
7201
		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7202
			return;
7203
		}
7204
	
7205
		var
7206
			i, ien,
7207
			j, jen,
7208
			struct, inner,
7209
			methodScoping = function ( scope, fn, struc ) {
7210
				return function () {
7211
					var ret = fn.apply( scope, arguments );
7212
	
7213
					// Method extension
7214
					_Api.extend( ret, ret, struc.methodExt );
7215
					return ret;
7216
				};
7217
			};
7218
	
7219
		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7220
			struct = ext[i];
7221
	
7222
			// Value
7223
			obj[ struct.name ] = typeof struct.val === 'function' ?
7224
				methodScoping( scope, struct.val, struct ) :
7225
				$.isPlainObject( struct.val ) ?
7226
					{} :
7227
					struct.val;
7228
	
7229
			obj[ struct.name ].__dt_wrapper = true;
7230
	
7231
			// Property extension
7232
			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7233
		}
7234
	};
7235
	
7236
	
7237
	// @todo - Is there need for an augment function?
7238
	// _Api.augment = function ( inst, name )
7239
	// {
7240
	// 	// Find src object in the structure from the name
7241
	// 	var parts = name.split('.');
7242
	
7243
	// 	_Api.extend( inst, obj );
7244
	// };
7245
	
7246
	
7247
	//     [
7248
	//       {
7249
	//         name:      'data'                -- string   - Property name
7250
	//         val:       function () {},       -- function - Api method (or undefined if just an object
7251
	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7252
	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7253
	//       },
7254
	//       {
7255
	//         name:     'row'
7256
	//         val:       {},
7257
	//         methodExt: [ ... ],
7258
	//         propExt:   [
7259
	//           {
7260
	//             name:      'data'
7261
	//             val:       function () {},
7262
	//             methodExt: [ ... ],
7263
	//             propExt:   [ ... ]
7264
	//           },
7265
	//           ...
7266
	//         ]
7267
	//       }
7268
	//     ]
7269
	
7270
	_Api.register = _api_register = function ( name, val )
7271
	{
7272
		if ( $.isArray( name ) ) {
7273
			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7274
				_Api.register( name[j], val );
7275
			}
7276
			return;
7277
		}
7278
	
7279
		var
7280
			i, ien,
7281
			heir = name.split('.'),
7282
			struct = __apiStruct,
7283
			key, method;
7284
	
7285
		var find = function ( src, name ) {
7286
			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7287
				if ( src[i].name === name ) {
7288
					return src[i];
7289
				}
7290
			}
7291
			return null;
7292
		};
7293
	
7294
		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7295
			method = heir[i].indexOf('()') !== -1;
7296
			key = method ?
7297
				heir[i].replace('()', '') :
7298
				heir[i];
7299
	
7300
			var src = find( struct, key );
7301
			if ( ! src ) {
7302
				src = {
7303
					name:      key,
7304
					val:       {},
7305
					methodExt: [],
7306
					propExt:   []
7307
				};
7308
				struct.push( src );
7309
			}
7310
	
7311
			if ( i === ien-1 ) {
7312
				src.val = val;
7313
			}
7314
			else {
7315
				struct = method ?
7316
					src.methodExt :
7317
					src.propExt;
7318
			}
7319
		}
7320
	};
7321
	
7322
	
7323
	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7324
		_Api.register( pluralName, val );
7325
	
7326
		_Api.register( singularName, function () {
7327
			var ret = val.apply( this, arguments );
7328
	
7329
			if ( ret === this ) {
7330
				// Returned item is the API instance that was passed in, return it
7331
				return this;
7332
			}
7333
			else if ( ret instanceof _Api ) {
7334
				// New API instance returned, want the value from the first item
7335
				// in the returned array for the singular result.
7336
				return ret.length ?
7337
					$.isArray( ret[0] ) ?
7338
						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7339
						ret[0] :
7340
					undefined;
7341
			}
7342
	
7343
			// Non-API return - just fire it back
7344
			return ret;
7345
		} );
7346
	};
7347
	
7348
	
7349
	/**
7350
	 * Selector for HTML tables. Apply the given selector to the give array of
7351
	 * DataTables settings objects.
7352
	 *
7353
	 * @param {string|integer} [selector] jQuery selector string or integer
7354
	 * @param  {array} Array of DataTables settings objects to be filtered
7355
	 * @return {array}
7356
	 * @ignore
7357
	 */
7358
	var __table_selector = function ( selector, a )
7359
	{
7360
		// Integer is used to pick out a table by index
7361
		if ( typeof selector === 'number' ) {
7362
			return [ a[ selector ] ];
7363
		}
7364
	
7365
		// Perform a jQuery selector on the table nodes
7366
		var nodes = $.map( a, function (el, i) {
7367
			return el.nTable;
7368
		} );
7369
	
7370
		return $(nodes)
7371
			.filter( selector )
7372
			.map( function (i) {
7373
				// Need to translate back from the table node to the settings
7374
				var idx = $.inArray( this, nodes );
7375
				return a[ idx ];
7376
			} )
7377
			.toArray();
7378
	};
7379
	
7380
	
7381
	
7382
	/**
7383
	 * Context selector for the API's context (i.e. the tables the API instance
7384
	 * refers to.
7385
	 *
7386
	 * @name    DataTable.Api#tables
7387
	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7388
	 *   should operate on. If not given, all tables in the current context are
7389
	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7390
	 *   select multiple tables or as an integer to select a single table.
7391
	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7392
	 */
7393
	_api_register( 'tables()', function ( selector ) {
7394
		// A new instance is created if there was a selector specified
7395
		return selector ?
7396
			new _Api( __table_selector( selector, this.context ) ) :
7397
			this;
7398
	} );
7399
	
7400
	
7401
	_api_register( 'table()', function ( selector ) {
7402
		var tables = this.tables( selector );
7403
		var ctx = tables.context;
7404
	
7405
		// Truncate to the first matched table
7406
		return ctx.length ?
7407
			new _Api( ctx[0] ) :
7408
			tables;
7409
	} );
7410
	
7411
	
7412
	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7413
		return this.iterator( 'table', function ( ctx ) {
7414
			return ctx.nTable;
7415
		}, 1 );
7416
	} );
7417
	
7418
	
7419
	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7420
		return this.iterator( 'table', function ( ctx ) {
7421
			return ctx.nTBody;
7422
		}, 1 );
7423
	} );
7424
	
7425
	
7426
	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7427
		return this.iterator( 'table', function ( ctx ) {
7428
			return ctx.nTHead;
7429
		}, 1 );
7430
	} );
7431
	
7432
	
7433
	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7434
		return this.iterator( 'table', function ( ctx ) {
7435
			return ctx.nTFoot;
7436
		}, 1 );
7437
	} );
7438
	
7439
	
7440
	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7441
		return this.iterator( 'table', function ( ctx ) {
7442
			return ctx.nTableWrapper;
7443
		}, 1 );
7444
	} );
7445
	
7446
	
7447
	
7448
	/**
7449
	 * Redraw the tables in the current context.
7450
	 */
7451
	_api_register( 'draw()', function ( paging ) {
7452
		return this.iterator( 'table', function ( settings ) {
7453
			if ( paging === 'page' ) {
7454
				_fnDraw( settings );
7455
			}
7456
			else {
7457
				if ( typeof paging === 'string' ) {
7458
					paging = paging === 'full-hold' ?
7459
						false :
7460
						true;
7461
				}
7462
	
7463
				_fnReDraw( settings, paging===false );
7464
			}
7465
		} );
7466
	} );
7467
	
7468
	
7469
	
7470
	/**
7471
	 * Get the current page index.
7472
	 *
7473
	 * @return {integer} Current page index (zero based)
7474
	 *//**
7475
	 * Set the current page.
7476
	 *
7477
	 * Note that if you attempt to show a page which does not exist, DataTables will
7478
	 * not throw an error, but rather reset the paging.
7479
	 *
7480
	 * @param {integer|string} action The paging action to take. This can be one of:
7481
	 *  * `integer` - The page index to jump to
7482
	 *  * `string` - An action to take:
7483
	 *    * `first` - Jump to first page.
7484
	 *    * `next` - Jump to the next page
7485
	 *    * `previous` - Jump to previous page
7486
	 *    * `last` - Jump to the last page.
7487
	 * @returns {DataTables.Api} this
7488
	 */
7489
	_api_register( 'page()', function ( action ) {
7490
		if ( action === undefined ) {
7491
			return this.page.info().page; // not an expensive call
7492
		}
7493
	
7494
		// else, have an action to take on all tables
7495
		return this.iterator( 'table', function ( settings ) {
7496
			_fnPageChange( settings, action );
7497
		} );
7498
	} );
7499
	
7500
	
7501
	/**
7502
	 * Paging information for the first table in the current context.
7503
	 *
7504
	 * If you require paging information for another table, use the `table()` method
7505
	 * with a suitable selector.
7506
	 *
7507
	 * @return {object} Object with the following properties set:
7508
	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7509
	 *  * `pages` - Total number of pages
7510
	 *  * `start` - Display index for the first record shown on the current page
7511
	 *  * `end` - Display index for the last record shown on the current page
7512
	 *  * `length` - Display length (number of records). Note that generally `start
7513
	 *    + length = end`, but this is not always true, for example if there are
7514
	 *    only 2 records to show on the final page, with a length of 10.
7515
	 *  * `recordsTotal` - Full data set length
7516
	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7517
	 *    are applied.
7518
	 */
7519
	_api_register( 'page.info()', function ( action ) {
7520
		if ( this.context.length === 0 ) {
7521
			return undefined;
7522
		}
7523
	
7524
		var
7525
			settings   = this.context[0],
7526
			start      = settings._iDisplayStart,
7527
			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7528
			visRecords = settings.fnRecordsDisplay(),
7529
			all        = len === -1;
7530
	
7531
		return {
7532
			"page":           all ? 0 : Math.floor( start / len ),
7533
			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7534
			"start":          start,
7535
			"end":            settings.fnDisplayEnd(),
7536
			"length":         len,
7537
			"recordsTotal":   settings.fnRecordsTotal(),
7538
			"recordsDisplay": visRecords,
7539
			"serverSide":     _fnDataSource( settings ) === 'ssp'
7540
		};
7541
	} );
7542
	
7543
	
7544
	/**
7545
	 * Get the current page length.
7546
	 *
7547
	 * @return {integer} Current page length. Note `-1` indicates that all records
7548
	 *   are to be shown.
7549
	 *//**
7550
	 * Set the current page length.
7551
	 *
7552
	 * @param {integer} Page length to set. Use `-1` to show all records.
7553
	 * @returns {DataTables.Api} this
7554
	 */
7555
	_api_register( 'page.len()', function ( len ) {
7556
		// Note that we can't call this function 'length()' because `length`
7557
		// is a Javascript property of functions which defines how many arguments
7558
		// the function expects.
7559
		if ( len === undefined ) {
7560
			return this.context.length !== 0 ?
7561
				this.context[0]._iDisplayLength :
7562
				undefined;
7563
		}
7564
	
7565
		// else, set the page length
7566
		return this.iterator( 'table', function ( settings ) {
7567
			_fnLengthChange( settings, len );
7568
		} );
7569
	} );
7570
	
7571
	
7572
	
7573
	var __reload = function ( settings, holdPosition, callback ) {
7574
		// Use the draw event to trigger a callback
7575
		if ( callback ) {
7576
			var api = new _Api( settings );
7577
	
7578
			api.one( 'draw', function () {
7579
				callback( api.ajax.json() );
7580
			} );
7581
		}
7582
	
7583
		if ( _fnDataSource( settings ) == 'ssp' ) {
7584
			_fnReDraw( settings, holdPosition );
7585
		}
7586
		else {
7587
			_fnProcessingDisplay( settings, true );
7588
	
7589
			// Cancel an existing request
7590
			var xhr = settings.jqXHR;
7591
			if ( xhr && xhr.readyState !== 4 ) {
7592
				xhr.abort();
7593
			}
7594
	
7595
			// Trigger xhr
7596
			_fnBuildAjax( settings, [], function( json ) {
7597
				_fnClearTable( settings );
7598
	
7599
				var data = _fnAjaxDataSrc( settings, json );
7600
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7601
					_fnAddData( settings, data[i] );
7602
				}
7603
	
7604
				_fnReDraw( settings, holdPosition );
7605
				_fnProcessingDisplay( settings, false );
7606
			} );
7607
		}
7608
	};
7609
	
7610
	
7611
	/**
7612
	 * Get the JSON response from the last Ajax request that DataTables made to the
7613
	 * server. Note that this returns the JSON from the first table in the current
7614
	 * context.
7615
	 *
7616
	 * @return {object} JSON received from the server.
7617
	 */
7618
	_api_register( 'ajax.json()', function () {
7619
		var ctx = this.context;
7620
	
7621
		if ( ctx.length > 0 ) {
7622
			return ctx[0].json;
7623
		}
7624
	
7625
		// else return undefined;
7626
	} );
7627
	
7628
	
7629
	/**
7630
	 * Get the data submitted in the last Ajax request
7631
	 */
7632
	_api_register( 'ajax.params()', function () {
7633
		var ctx = this.context;
7634
	
7635
		if ( ctx.length > 0 ) {
7636
			return ctx[0].oAjaxData;
7637
		}
7638
	
7639
		// else return undefined;
7640
	} );
7641
	
7642
	
7643
	/**
7644
	 * Reload tables from the Ajax data source. Note that this function will
7645
	 * automatically re-draw the table when the remote data has been loaded.
7646
	 *
7647
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7648
	 *   position. A full re-sort and re-filter is performed when this method is
7649
	 *   called, which is why the pagination reset is the default action.
7650
	 * @returns {DataTables.Api} this
7651
	 */
7652
	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7653
		return this.iterator( 'table', function (settings) {
7654
			__reload( settings, resetPaging===false, callback );
7655
		} );
7656
	} );
7657
	
7658
	
7659
	/**
7660
	 * Get the current Ajax URL. Note that this returns the URL from the first
7661
	 * table in the current context.
7662
	 *
7663
	 * @return {string} Current Ajax source URL
7664
	 *//**
7665
	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7666
	 * current context.
7667
	 *
7668
	 * @param {string} url URL to set.
7669
	 * @returns {DataTables.Api} this
7670
	 */
7671
	_api_register( 'ajax.url()', function ( url ) {
7672
		var ctx = this.context;
7673
	
7674
		if ( url === undefined ) {
7675
			// get
7676
			if ( ctx.length === 0 ) {
7677
				return undefined;
7678
			}
7679
			ctx = ctx[0];
7680
	
7681
			return ctx.ajax ?
7682
				$.isPlainObject( ctx.ajax ) ?
7683
					ctx.ajax.url :
7684
					ctx.ajax :
7685
				ctx.sAjaxSource;
7686
		}
7687
	
7688
		// set
7689
		return this.iterator( 'table', function ( settings ) {
7690
			if ( $.isPlainObject( settings.ajax ) ) {
7691
				settings.ajax.url = url;
7692
			}
7693
			else {
7694
				settings.ajax = url;
7695
			}
7696
			// No need to consider sAjaxSource here since DataTables gives priority
7697
			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7698
			// value of `sAjaxSource` redundant.
7699
		} );
7700
	} );
7701
	
7702
	
7703
	/**
7704
	 * Load data from the newly set Ajax URL. Note that this method is only
7705
	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7706
	 * has the same effect as calling `ajax.reload()` but is provided for
7707
	 * convenience when setting a new URL. Like `ajax.reload()` it will
7708
	 * automatically redraw the table once the remote data has been loaded.
7709
	 *
7710
	 * @returns {DataTables.Api} this
7711
	 */
7712
	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7713
		// Same as a reload, but makes sense to present it for easy access after a
7714
		// url change
7715
		return this.iterator( 'table', function ( ctx ) {
7716
			__reload( ctx, resetPaging===false, callback );
7717
		} );
7718
	} );
7719
	
7720
	
7721
	
7722
	
7723
	var _selector_run = function ( type, selector, selectFn, settings, opts )
7724
	{
7725
		var
7726
			out = [], res,
7727
			a, i, ien, j, jen,
7728
			selectorType = typeof selector;
7729
	
7730
		// Can't just check for isArray here, as an API or jQuery instance might be
7731
		// given with their array like look
7732
		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7733
			selector = [ selector ];
7734
		}
7735
	
7736
		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7737
			// Only split on simple strings - complex expressions will be jQuery selectors
7738
			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7739
				selector[i].split(',') :
7740
				[ selector[i] ];
7741
	
7742
			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7743
				res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7744
	
7745
				if ( res && res.length ) {
7746
					out = out.concat( res );
7747
				}
7748
			}
7749
		}
7750
	
7751
		// selector extensions
7752
		var ext = _ext.selector[ type ];
7753
		if ( ext.length ) {
7754
			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7755
				out = ext[i]( settings, opts, out );
7756
			}
7757
		}
7758
	
7759
		return _unique( out );
7760
	};
7761
	
7762
	
7763
	var _selector_opts = function ( opts )
7764
	{
7765
		if ( ! opts ) {
7766
			opts = {};
7767
		}
7768
	
7769
		// Backwards compatibility for 1.9- which used the terminology filter rather
7770
		// than search
7771
		if ( opts.filter && opts.search === undefined ) {
7772
			opts.search = opts.filter;
7773
		}
7774
	
7775
		return $.extend( {
7776
			search: 'none',
7777
			order: 'current',
7778
			page: 'all'
7779
		}, opts );
7780
	};
7781
	
7782
	
7783
	var _selector_first = function ( inst )
7784
	{
7785
		// Reduce the API instance to the first item found
7786
		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7787
			if ( inst[i].length > 0 ) {
7788
				// Assign the first element to the first item in the instance
7789
				// and truncate the instance and context
7790
				inst[0] = inst[i];
7791
				inst[0].length = 1;
7792
				inst.length = 1;
7793
				inst.context = [ inst.context[i] ];
7794
	
7795
				return inst;
7796
			}
7797
		}
7798
	
7799
		// Not found - return an empty instance
7800
		inst.length = 0;
7801
		return inst;
7802
	};
7803
	
7804
	
7805
	var _selector_row_indexes = function ( settings, opts )
7806
	{
7807
		var
7808
			i, ien, tmp, a=[],
7809
			displayFiltered = settings.aiDisplay,
7810
			displayMaster = settings.aiDisplayMaster;
7811
	
7812
		var
7813
			search = opts.search,  // none, applied, removed
7814
			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7815
			page   = opts.page;    // all, current
7816
	
7817
		if ( _fnDataSource( settings ) == 'ssp' ) {
7818
			// In server-side processing mode, most options are irrelevant since
7819
			// rows not shown don't exist and the index order is the applied order
7820
			// Removed is a special case - for consistency just return an empty
7821
			// array
7822
			return search === 'removed' ?
7823
				[] :
7824
				_range( 0, displayMaster.length );
7825
		}
7826
		else if ( page == 'current' ) {
7827
			// Current page implies that order=current and fitler=applied, since it is
7828
			// fairly senseless otherwise, regardless of what order and search actually
7829
			// are
7830
			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7831
				a.push( displayFiltered[i] );
7832
			}
7833
		}
7834
		else if ( order == 'current' || order == 'applied' ) {
7835
			if ( search == 'none') {
7836
				a = displayMaster.slice();
7837
			}
7838
			else if ( search == 'applied' ) {
7839
				a = displayFiltered.slice();
7840
			}
7841
			else if ( search == 'removed' ) {
7842
				// O(n+m) solution by creating a hash map
7843
				var displayFilteredMap = {};
7844
	
7845
				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
7846
					displayFilteredMap[displayFiltered[i]] = null;
7847
				}
7848
	
7849
				a = $.map( displayMaster, function (el) {
7850
					return ! displayFilteredMap.hasOwnProperty(el) ?
7851
						el :
7852
						null;
7853
				} );
7854
			}
7855
		}
7856
		else if ( order == 'index' || order == 'original' ) {
7857
			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7858
				if ( search == 'none' ) {
7859
					a.push( i );
7860
				}
7861
				else { // applied | removed
7862
					tmp = $.inArray( i, displayFiltered );
7863
	
7864
					if ((tmp === -1 && search == 'removed') ||
7865
						(tmp >= 0   && search == 'applied') )
7866
					{
7867
						a.push( i );
7868
					}
7869
				}
7870
			}
7871
		}
7872
	
7873
		return a;
7874
	};
7875
	
7876
	
7877
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7878
	 * Rows
7879
	 *
7880
	 * {}          - no selector - use all available rows
7881
	 * {integer}   - row aoData index
7882
	 * {node}      - TR node
7883
	 * {string}    - jQuery selector to apply to the TR elements
7884
	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7885
	 *
7886
	 */
7887
	var __row_selector = function ( settings, selector, opts )
7888
	{
7889
		var rows;
7890
		var run = function ( sel ) {
7891
			var selInt = _intVal( sel );
7892
			var i, ien;
7893
			var aoData = settings.aoData;
7894
	
7895
			// Short cut - selector is a number and no options provided (default is
7896
			// all records, so no need to check if the index is in there, since it
7897
			// must be - dev error if the index doesn't exist).
7898
			if ( selInt !== null && ! opts ) {
7899
				return [ selInt ];
7900
			}
7901
	
7902
			if ( ! rows ) {
7903
				rows = _selector_row_indexes( settings, opts );
7904
			}
7905
	
7906
			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7907
				// Selector - integer
7908
				return [ selInt ];
7909
			}
7910
			else if ( sel === null || sel === undefined || sel === '' ) {
7911
				// Selector - none
7912
				return rows;
7913
			}
7914
	
7915
			// Selector - function
7916
			if ( typeof sel === 'function' ) {
7917
				return $.map( rows, function (idx) {
7918
					var row = aoData[ idx ];
7919
					return sel( idx, row._aData, row.nTr ) ? idx : null;
7920
				} );
7921
			}
7922
	
7923
			// Selector - node
7924
			if ( sel.nodeName ) {
7925
				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
7926
				var cellIdx = sel._DT_CellIndex;
7927
	
7928
				if ( rowIdx !== undefined ) {
7929
					// Make sure that the row is actually still present in the table
7930
					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
7931
						[ rowIdx ] :
7932
						[];
7933
				}
7934
				else if ( cellIdx ) {
7935
					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel ?
7936
						[ cellIdx.row ] :
7937
						[];
7938
				}
7939
				else {
7940
					var host = $(sel).closest('*[data-dt-row]');
7941
					return host.length ?
7942
						[ host.data('dt-row') ] :
7943
						[];
7944
				}
7945
			}
7946
	
7947
			// ID selector. Want to always be able to select rows by id, regardless
7948
			// of if the tr element has been created or not, so can't rely upon
7949
			// jQuery here - hence a custom implementation. This does not match
7950
			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7951
			// but to select it using a CSS selector engine (like Sizzle or
7952
			// querySelect) it would need to need to be escaped for some characters.
7953
			// DataTables simplifies this for row selectors since you can select
7954
			// only a row. A # indicates an id any anything that follows is the id -
7955
			// unescaped.
7956
			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7957
				// get row index from id
7958
				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7959
				if ( rowObj !== undefined ) {
7960
					return [ rowObj.idx ];
7961
				}
7962
	
7963
				// need to fall through to jQuery in case there is DOM id that
7964
				// matches
7965
			}
7966
			
7967
			// Get nodes in the order from the `rows` array with null values removed
7968
			var nodes = _removeEmpty(
7969
				_pluck_order( settings.aoData, rows, 'nTr' )
7970
			);
7971
	
7972
			// Selector - jQuery selector string, array of nodes or jQuery object/
7973
			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7974
			// it also allows arrays, so this will cope with all three options
7975
			return $(nodes)
7976
				.filter( sel )
7977
				.map( function () {
7978
					return this._DT_RowIndex;
7979
				} )
7980
				.toArray();
7981
		};
7982
	
7983
		return _selector_run( 'row', selector, run, settings, opts );
7984
	};
7985
	
7986
	
7987
	_api_register( 'rows()', function ( selector, opts ) {
7988
		// argument shifting
7989
		if ( selector === undefined ) {
7990
			selector = '';
7991
		}
7992
		else if ( $.isPlainObject( selector ) ) {
7993
			opts = selector;
7994
			selector = '';
7995
		}
7996
	
7997
		opts = _selector_opts( opts );
7998
	
7999
		var inst = this.iterator( 'table', function ( settings ) {
8000
			return __row_selector( settings, selector, opts );
8001
		}, 1 );
8002
	
8003
		// Want argument shifting here and in __row_selector?
8004
		inst.selector.rows = selector;
8005
		inst.selector.opts = opts;
8006
	
8007
		return inst;
8008
	} );
8009
	
8010
	_api_register( 'rows().nodes()', function () {
8011
		return this.iterator( 'row', function ( settings, row ) {
8012
			return settings.aoData[ row ].nTr || undefined;
8013
		}, 1 );
8014
	} );
8015
	
8016
	_api_register( 'rows().data()', function () {
8017
		return this.iterator( true, 'rows', function ( settings, rows ) {
8018
			return _pluck_order( settings.aoData, rows, '_aData' );
8019
		}, 1 );
8020
	} );
8021
	
8022
	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8023
		return this.iterator( 'row', function ( settings, row ) {
8024
			var r = settings.aoData[ row ];
8025
			return type === 'search' ? r._aFilterData : r._aSortData;
8026
		}, 1 );
8027
	} );
8028
	
8029
	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8030
		return this.iterator( 'row', function ( settings, row ) {
8031
			_fnInvalidate( settings, row, src );
8032
		} );
8033
	} );
8034
	
8035
	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8036
		return this.iterator( 'row', function ( settings, row ) {
8037
			return row;
8038
		}, 1 );
8039
	} );
8040
	
8041
	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8042
		var a = [];
8043
		var context = this.context;
8044
	
8045
		// `iterator` will drop undefined values, but in this case we want them
8046
		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8047
			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8048
				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8049
				a.push( (hash === true ? '#' : '' )+ id );
8050
			}
8051
		}
8052
	
8053
		return new _Api( context, a );
8054
	} );
8055
	
8056
	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8057
		var that = this;
8058
	
8059
		this.iterator( 'row', function ( settings, row, thatIdx ) {
8060
			var data = settings.aoData;
8061
			var rowData = data[ row ];
8062
			var i, ien, j, jen;
8063
			var loopRow, loopCells;
8064
	
8065
			data.splice( row, 1 );
8066
	
8067
			// Update the cached indexes
8068
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8069
				loopRow = data[i];
8070
				loopCells = loopRow.anCells;
8071
	
8072
				// Rows
8073
				if ( loopRow.nTr !== null ) {
8074
					loopRow.nTr._DT_RowIndex = i;
8075
				}
8076
	
8077
				// Cells
8078
				if ( loopCells !== null ) {
8079
					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8080
						loopCells[j]._DT_CellIndex.row = i;
8081
					}
8082
				}
8083
			}
8084
	
8085
			// Delete from the display arrays
8086
			_fnDeleteIndex( settings.aiDisplayMaster, row );
8087
			_fnDeleteIndex( settings.aiDisplay, row );
8088
			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8089
	
8090
			// For server-side processing tables - subtract the deleted row from the count
8091
			if ( settings._iRecordsDisplay > 0 ) {
8092
				settings._iRecordsDisplay--;
8093
			}
8094
	
8095
			// Check for an 'overflow' they case for displaying the table
8096
			_fnLengthOverflow( settings );
8097
	
8098
			// Remove the row's ID reference if there is one
8099
			var id = settings.rowIdFn( rowData._aData );
8100
			if ( id !== undefined ) {
8101
				delete settings.aIds[ id ];
8102
			}
8103
		} );
8104
	
8105
		this.iterator( 'table', function ( settings ) {
8106
			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8107
				settings.aoData[i].idx = i;
8108
			}
8109
		} );
8110
	
8111
		return this;
8112
	} );
8113
	
8114
	
8115
	_api_register( 'rows.add()', function ( rows ) {
8116
		var newRows = this.iterator( 'table', function ( settings ) {
8117
				var row, i, ien;
8118
				var out = [];
8119
	
8120
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8121
					row = rows[i];
8122
	
8123
					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8124
						out.push( _fnAddTr( settings, row )[0] );
8125
					}
8126
					else {
8127
						out.push( _fnAddData( settings, row ) );
8128
					}
8129
				}
8130
	
8131
				return out;
8132
			}, 1 );
8133
	
8134
		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8135
		var modRows = this.rows( -1 );
8136
		modRows.pop();
8137
		$.merge( modRows, newRows );
8138
	
8139
		return modRows;
8140
	} );
8141
	
8142
	
8143
	
8144
	
8145
	
8146
	/**
8147
	 *
8148
	 */
8149
	_api_register( 'row()', function ( selector, opts ) {
8150
		return _selector_first( this.rows( selector, opts ) );
8151
	} );
8152
	
8153
	
8154
	_api_register( 'row().data()', function ( data ) {
8155
		var ctx = this.context;
8156
	
8157
		if ( data === undefined ) {
8158
			// Get
8159
			return ctx.length && this.length ?
8160
				ctx[0].aoData[ this[0] ]._aData :
8161
				undefined;
8162
		}
8163
	
8164
		// Set
8165
		var row = ctx[0].aoData[ this[0] ];
8166
		row._aData = data;
8167
	
8168
		// If the DOM has an id, and the data source is an array
8169
		if ( $.isArray( data ) && row.nTr.id ) {
8170
			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8171
		}
8172
	
8173
		// Automatically invalidate
8174
		_fnInvalidate( ctx[0], this[0], 'data' );
8175
	
8176
		return this;
8177
	} );
8178
	
8179
	
8180
	_api_register( 'row().node()', function () {
8181
		var ctx = this.context;
8182
	
8183
		return ctx.length && this.length ?
8184
			ctx[0].aoData[ this[0] ].nTr || null :
8185
			null;
8186
	} );
8187
	
8188
	
8189
	_api_register( 'row.add()', function ( row ) {
8190
		// Allow a jQuery object to be passed in - only a single row is added from
8191
		// it though - the first element in the set
8192
		if ( row instanceof $ && row.length ) {
8193
			row = row[0];
8194
		}
8195
	
8196
		var rows = this.iterator( 'table', function ( settings ) {
8197
			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8198
				return _fnAddTr( settings, row )[0];
8199
			}
8200
			return _fnAddData( settings, row );
8201
		} );
8202
	
8203
		// Return an Api.rows() extended instance, with the newly added row selected
8204
		return this.row( rows[0] );
8205
	} );
8206
	
8207
	
8208
	
8209
	var __details_add = function ( ctx, row, data, klass )
8210
	{
8211
		// Convert to array of TR elements
8212
		var rows = [];
8213
		var addRow = function ( r, k ) {
8214
			// Recursion to allow for arrays of jQuery objects
8215
			if ( $.isArray( r ) || r instanceof $ ) {
8216
				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8217
					addRow( r[i], k );
8218
				}
8219
				return;
8220
			}
8221
	
8222
			// If we get a TR element, then just add it directly - up to the dev
8223
			// to add the correct number of columns etc
8224
			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8225
				rows.push( r );
8226
			}
8227
			else {
8228
				// Otherwise create a row with a wrapper
8229
				var created = $('<tr><td/></tr>').addClass( k );
8230
				$('td', created)
8231
					.addClass( k )
8232
					.html( r )
8233
					[0].colSpan = _fnVisbleColumns( ctx );
8234
	
8235
				rows.push( created[0] );
8236
			}
8237
		};
8238
	
8239
		addRow( data, klass );
8240
	
8241
		if ( row._details ) {
8242
			row._details.detach();
8243
		}
8244
	
8245
		row._details = $(rows);
8246
	
8247
		// If the children were already shown, that state should be retained
8248
		if ( row._detailsShow ) {
8249
			row._details.insertAfter( row.nTr );
8250
		}
8251
	};
8252
	
8253
	
8254
	var __details_remove = function ( api, idx )
8255
	{
8256
		var ctx = api.context;
8257
	
8258
		if ( ctx.length ) {
8259
			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8260
	
8261
			if ( row && row._details ) {
8262
				row._details.remove();
8263
	
8264
				row._detailsShow = undefined;
8265
				row._details = undefined;
8266
			}
8267
		}
8268
	};
8269
	
8270
	
8271
	var __details_display = function ( api, show ) {
8272
		var ctx = api.context;
8273
	
8274
		if ( ctx.length && api.length ) {
8275
			var row = ctx[0].aoData[ api[0] ];
8276
	
8277
			if ( row._details ) {
8278
				row._detailsShow = show;
8279
	
8280
				if ( show ) {
8281
					row._details.insertAfter( row.nTr );
8282
				}
8283
				else {
8284
					row._details.detach();
8285
				}
8286
	
8287
				__details_events( ctx[0] );
8288
			}
8289
		}
8290
	};
8291
	
8292
	
8293
	var __details_events = function ( settings )
8294
	{
8295
		var api = new _Api( settings );
8296
		var namespace = '.dt.DT_details';
8297
		var drawEvent = 'draw'+namespace;
8298
		var colvisEvent = 'column-visibility'+namespace;
8299
		var destroyEvent = 'destroy'+namespace;
8300
		var data = settings.aoData;
8301
	
8302
		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8303
	
8304
		if ( _pluck( data, '_details' ).length > 0 ) {
8305
			// On each draw, insert the required elements into the document
8306
			api.on( drawEvent, function ( e, ctx ) {
8307
				if ( settings !== ctx ) {
8308
					return;
8309
				}
8310
	
8311
				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8312
					// Internal data grab
8313
					var row = data[ idx ];
8314
	
8315
					if ( row._detailsShow ) {
8316
						row._details.insertAfter( row.nTr );
8317
					}
8318
				} );
8319
			} );
8320
	
8321
			// Column visibility change - update the colspan
8322
			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8323
				if ( settings !== ctx ) {
8324
					return;
8325
				}
8326
	
8327
				// Update the colspan for the details rows (note, only if it already has
8328
				// a colspan)
8329
				var row, visible = _fnVisbleColumns( ctx );
8330
	
8331
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8332
					row = data[i];
8333
	
8334
					if ( row._details ) {
8335
						row._details.children('td[colspan]').attr('colspan', visible );
8336
					}
8337
				}
8338
			} );
8339
	
8340
			// Table destroyed - nuke any child rows
8341
			api.on( destroyEvent, function ( e, ctx ) {
8342
				if ( settings !== ctx ) {
8343
					return;
8344
				}
8345
	
8346
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8347
					if ( data[i]._details ) {
8348
						__details_remove( api, i );
8349
					}
8350
				}
8351
			} );
8352
		}
8353
	};
8354
	
8355
	// Strings for the method names to help minification
8356
	var _emp = '';
8357
	var _child_obj = _emp+'row().child';
8358
	var _child_mth = _child_obj+'()';
8359
	
8360
	// data can be:
8361
	//  tr
8362
	//  string
8363
	//  jQuery or array of any of the above
8364
	_api_register( _child_mth, function ( data, klass ) {
8365
		var ctx = this.context;
8366
	
8367
		if ( data === undefined ) {
8368
			// get
8369
			return ctx.length && this.length ?
8370
				ctx[0].aoData[ this[0] ]._details :
8371
				undefined;
8372
		}
8373
		else if ( data === true ) {
8374
			// show
8375
			this.child.show();
8376
		}
8377
		else if ( data === false ) {
8378
			// remove
8379
			__details_remove( this );
8380
		}
8381
		else if ( ctx.length && this.length ) {
8382
			// set
8383
			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8384
		}
8385
	
8386
		return this;
8387
	} );
8388
	
8389
	
8390
	_api_register( [
8391
		_child_obj+'.show()',
8392
		_child_mth+'.show()' // only when `child()` was called with parameters (without
8393
	], function ( show ) {   // it returns an object and this method is not executed)
8394
		__details_display( this, true );
8395
		return this;
8396
	} );
8397
	
8398
	
8399
	_api_register( [
8400
		_child_obj+'.hide()',
8401
		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8402
	], function () {         // it returns an object and this method is not executed)
8403
		__details_display( this, false );
8404
		return this;
8405
	} );
8406
	
8407
	
8408
	_api_register( [
8409
		_child_obj+'.remove()',
8410
		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8411
	], function () {           // it returns an object and this method is not executed)
8412
		__details_remove( this );
8413
		return this;
8414
	} );
8415
	
8416
	
8417
	_api_register( _child_obj+'.isShown()', function () {
8418
		var ctx = this.context;
8419
	
8420
		if ( ctx.length && this.length ) {
8421
			// _detailsShown as false or undefined will fall through to return false
8422
			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8423
		}
8424
		return false;
8425
	} );
8426
	
8427
	
8428
	
8429
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8430
	 * Columns
8431
	 *
8432
	 * {integer}           - column index (>=0 count from left, <0 count from right)
8433
	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8434
	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8435
	 * "{string}:name"     - column name
8436
	 * "{string}"          - jQuery selector on column header nodes
8437
	 *
8438
	 */
8439
	
8440
	// can be an array of these items, comma separated list, or an array of comma
8441
	// separated lists
8442
	
8443
	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8444
	
8445
	
8446
	// r1 and r2 are redundant - but it means that the parameters match for the
8447
	// iterator callback in columns().data()
8448
	var __columnData = function ( settings, column, r1, r2, rows ) {
8449
		var a = [];
8450
		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8451
			a.push( _fnGetCellData( settings, rows[row], column ) );
8452
		}
8453
		return a;
8454
	};
8455
	
8456
	
8457
	var __column_selector = function ( settings, selector, opts )
8458
	{
8459
		var
8460
			columns = settings.aoColumns,
8461
			names = _pluck( columns, 'sName' ),
8462
			nodes = _pluck( columns, 'nTh' );
8463
	
8464
		var run = function ( s ) {
8465
			var selInt = _intVal( s );
8466
	
8467
			// Selector - all
8468
			if ( s === '' ) {
8469
				return _range( columns.length );
8470
			}
8471
	
8472
			// Selector - index
8473
			if ( selInt !== null ) {
8474
				return [ selInt >= 0 ?
8475
					selInt : // Count from left
8476
					columns.length + selInt // Count from right (+ because its a negative value)
8477
				];
8478
			}
8479
	
8480
			// Selector = function
8481
			if ( typeof s === 'function' ) {
8482
				var rows = _selector_row_indexes( settings, opts );
8483
	
8484
				return $.map( columns, function (col, idx) {
8485
					return s(
8486
							idx,
8487
							__columnData( settings, idx, 0, 0, rows ),
8488
							nodes[ idx ]
8489
						) ? idx : null;
8490
				} );
8491
			}
8492
	
8493
			// jQuery or string selector
8494
			var match = typeof s === 'string' ?
8495
				s.match( __re_column_selector ) :
8496
				'';
8497
	
8498
			if ( match ) {
8499
				switch( match[2] ) {
8500
					case 'visIdx':
8501
					case 'visible':
8502
						var idx = parseInt( match[1], 10 );
8503
						// Visible index given, convert to column index
8504
						if ( idx < 0 ) {
8505
							// Counting from the right
8506
							var visColumns = $.map( columns, function (col,i) {
8507
								return col.bVisible ? i : null;
8508
							} );
8509
							return [ visColumns[ visColumns.length + idx ] ];
8510
						}
8511
						// Counting from the left
8512
						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8513
	
8514
					case 'name':
8515
						// match by name. `names` is column index complete and in order
8516
						return $.map( names, function (name, i) {
8517
							return name === match[1] ? i : null;
8518
						} );
8519
	
8520
					default:
8521
						return [];
8522
				}
8523
			}
8524
	
8525
			// Cell in the table body
8526
			if ( s.nodeName && s._DT_CellIndex ) {
8527
				return [ s._DT_CellIndex.column ];
8528
			}
8529
	
8530
			// jQuery selector on the TH elements for the columns
8531
			var jqResult = $( nodes )
8532
				.filter( s )
8533
				.map( function () {
8534
					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8535
				} )
8536
				.toArray();
8537
	
8538
			if ( jqResult.length || ! s.nodeName ) {
8539
				return jqResult;
8540
			}
8541
	
8542
			// Otherwise a node which might have a `dt-column` data attribute, or be
8543
			// a child or such an element
8544
			var host = $(s).closest('*[data-dt-column]');
8545
			return host.length ?
8546
				[ host.data('dt-column') ] :
8547
				[];
8548
		};
8549
	
8550
		return _selector_run( 'column', selector, run, settings, opts );
8551
	};
8552
	
8553
	
8554
	var __setColumnVis = function ( settings, column, vis ) {
8555
		var
8556
			cols = settings.aoColumns,
8557
			col  = cols[ column ],
8558
			data = settings.aoData,
8559
			row, cells, i, ien, tr;
8560
	
8561
		// Get
8562
		if ( vis === undefined ) {
8563
			return col.bVisible;
8564
		}
8565
	
8566
		// Set
8567
		// No change
8568
		if ( col.bVisible === vis ) {
8569
			return;
8570
		}
8571
	
8572
		if ( vis ) {
8573
			// Insert column
8574
			// Need to decide if we should use appendChild or insertBefore
8575
			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8576
	
8577
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8578
				tr = data[i].nTr;
8579
				cells = data[i].anCells;
8580
	
8581
				if ( tr ) {
8582
					// insertBefore can act like appendChild if 2nd arg is null
8583
					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8584
				}
8585
			}
8586
		}
8587
		else {
8588
			// Remove column
8589
			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8590
		}
8591
	
8592
		// Common actions
8593
		col.bVisible = vis;
8594
		_fnDrawHead( settings, settings.aoHeader );
8595
		_fnDrawHead( settings, settings.aoFooter );
8596
	
8597
		// Update colspan for no records display. Child rows and extensions will use their own
8598
		// listeners to do this - only need to update the empty table item here
8599
		if ( ! settings.aiDisplay.length ) {
8600
			$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8601
		}
8602
	
8603
		_fnSaveState( settings );
8604
	};
8605
	
8606
	
8607
	_api_register( 'columns()', function ( selector, opts ) {
8608
		// argument shifting
8609
		if ( selector === undefined ) {
8610
			selector = '';
8611
		}
8612
		else if ( $.isPlainObject( selector ) ) {
8613
			opts = selector;
8614
			selector = '';
8615
		}
8616
	
8617
		opts = _selector_opts( opts );
8618
	
8619
		var inst = this.iterator( 'table', function ( settings ) {
8620
			return __column_selector( settings, selector, opts );
8621
		}, 1 );
8622
	
8623
		// Want argument shifting here and in _row_selector?
8624
		inst.selector.cols = selector;
8625
		inst.selector.opts = opts;
8626
	
8627
		return inst;
8628
	} );
8629
	
8630
	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8631
		return this.iterator( 'column', function ( settings, column ) {
8632
			return settings.aoColumns[column].nTh;
8633
		}, 1 );
8634
	} );
8635
	
8636
	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8637
		return this.iterator( 'column', function ( settings, column ) {
8638
			return settings.aoColumns[column].nTf;
8639
		}, 1 );
8640
	} );
8641
	
8642
	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8643
		return this.iterator( 'column-rows', __columnData, 1 );
8644
	} );
8645
	
8646
	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8647
		return this.iterator( 'column', function ( settings, column ) {
8648
			return settings.aoColumns[column].mData;
8649
		}, 1 );
8650
	} );
8651
	
8652
	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8653
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8654
			return _pluck_order( settings.aoData, rows,
8655
				type === 'search' ? '_aFilterData' : '_aSortData', column
8656
			);
8657
		}, 1 );
8658
	} );
8659
	
8660
	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8661
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8662
			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8663
		}, 1 );
8664
	} );
8665
	
8666
	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8667
		var ret = this.iterator( 'column', function ( settings, column ) {
8668
			if ( vis === undefined ) {
8669
				return settings.aoColumns[ column ].bVisible;
8670
			} // else
8671
			__setColumnVis( settings, column, vis );
8672
		} );
8673
	
8674
		// Group the column visibility changes
8675
		if ( vis !== undefined ) {
8676
			// Second loop once the first is done for events
8677
			this.iterator( 'column', function ( settings, column ) {
8678
				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8679
			} );
8680
	
8681
			if ( calc === undefined || calc ) {
8682
				this.columns.adjust();
8683
			}
8684
		}
8685
	
8686
		return ret;
8687
	} );
8688
	
8689
	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8690
		return this.iterator( 'column', function ( settings, column ) {
8691
			return type === 'visible' ?
8692
				_fnColumnIndexToVisible( settings, column ) :
8693
				column;
8694
		}, 1 );
8695
	} );
8696
	
8697
	_api_register( 'columns.adjust()', function () {
8698
		return this.iterator( 'table', function ( settings ) {
8699
			_fnAdjustColumnSizing( settings );
8700
		}, 1 );
8701
	} );
8702
	
8703
	_api_register( 'column.index()', function ( type, idx ) {
8704
		if ( this.context.length !== 0 ) {
8705
			var ctx = this.context[0];
8706
	
8707
			if ( type === 'fromVisible' || type === 'toData' ) {
8708
				return _fnVisibleToColumnIndex( ctx, idx );
8709
			}
8710
			else if ( type === 'fromData' || type === 'toVisible' ) {
8711
				return _fnColumnIndexToVisible( ctx, idx );
8712
			}
8713
		}
8714
	} );
8715
	
8716
	_api_register( 'column()', function ( selector, opts ) {
8717
		return _selector_first( this.columns( selector, opts ) );
8718
	} );
8719
	
8720
	
8721
	
8722
	var __cell_selector = function ( settings, selector, opts )
8723
	{
8724
		var data = settings.aoData;
8725
		var rows = _selector_row_indexes( settings, opts );
8726
		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8727
		var allCells = $( [].concat.apply([], cells) );
8728
		var row;
8729
		var columns = settings.aoColumns.length;
8730
		var a, i, ien, j, o, host;
8731
	
8732
		var run = function ( s ) {
8733
			var fnSelector = typeof s === 'function';
8734
	
8735
			if ( s === null || s === undefined || fnSelector ) {
8736
				// All cells and function selectors
8737
				a = [];
8738
	
8739
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8740
					row = rows[i];
8741
	
8742
					for ( j=0 ; j<columns ; j++ ) {
8743
						o = {
8744
							row: row,
8745
							column: j
8746
						};
8747
	
8748
						if ( fnSelector ) {
8749
							// Selector - function
8750
							host = data[ row ];
8751
	
8752
							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8753
								a.push( o );
8754
							}
8755
						}
8756
						else {
8757
							// Selector - all
8758
							a.push( o );
8759
						}
8760
					}
8761
				}
8762
	
8763
				return a;
8764
			}
8765
			
8766
			// Selector - index
8767
			if ( $.isPlainObject( s ) ) {
8768
				// Valid cell index and its in the array of selectable rows
8769
				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8770
					[s] :
8771
					[];
8772
			}
8773
	
8774
			// Selector - jQuery filtered cells
8775
			var jqResult = allCells
8776
				.filter( s )
8777
				.map( function (i, el) {
8778
					return { // use a new object, in case someone changes the values
8779
						row:    el._DT_CellIndex.row,
8780
						column: el._DT_CellIndex.column
8781
	 				};
8782
				} )
8783
				.toArray();
8784
	
8785
			if ( jqResult.length || ! s.nodeName ) {
8786
				return jqResult;
8787
			}
8788
	
8789
			// Otherwise the selector is a node, and there is one last option - the
8790
			// element might be a child of an element which has dt-row and dt-column
8791
			// data attributes
8792
			host = $(s).closest('*[data-dt-row]');
8793
			return host.length ?
8794
				[ {
8795
					row: host.data('dt-row'),
8796
					column: host.data('dt-column')
8797
				} ] :
8798
				[];
8799
		};
8800
	
8801
		return _selector_run( 'cell', selector, run, settings, opts );
8802
	};
8803
	
8804
	
8805
	
8806
	
8807
	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8808
		// Argument shifting
8809
		if ( $.isPlainObject( rowSelector ) ) {
8810
			// Indexes
8811
			if ( rowSelector.row === undefined ) {
8812
				// Selector options in first parameter
8813
				opts = rowSelector;
8814
				rowSelector = null;
8815
			}
8816
			else {
8817
				// Cell index objects in first parameter
8818
				opts = columnSelector;
8819
				columnSelector = null;
8820
			}
8821
		}
8822
		if ( $.isPlainObject( columnSelector ) ) {
8823
			opts = columnSelector;
8824
			columnSelector = null;
8825
		}
8826
	
8827
		// Cell selector
8828
		if ( columnSelector === null || columnSelector === undefined ) {
8829
			return this.iterator( 'table', function ( settings ) {
8830
				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8831
			} );
8832
		}
8833
	
8834
		// Row + column selector
8835
		var columns = this.columns( columnSelector );
8836
		var rows = this.rows( rowSelector );
8837
		var a, i, ien, j, jen;
8838
	
8839
		this.iterator( 'table', function ( settings, idx ) {
8840
			a = [];
8841
	
8842
			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8843
				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8844
					a.push( {
8845
						row:    rows[idx][i],
8846
						column: columns[idx][j]
8847
					} );
8848
				}
8849
			}
8850
		}, 1 );
8851
	
8852
	    // Now pass through the cell selector for options
8853
	    var cells = this.cells( a, opts );
8854
	
8855
		$.extend( cells.selector, {
8856
			cols: columnSelector,
8857
			rows: rowSelector,
8858
			opts: opts
8859
		} );
8860
	
8861
		return cells;
8862
	} );
8863
	
8864
	
8865
	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8866
		return this.iterator( 'cell', function ( settings, row, column ) {
8867
			var data = settings.aoData[ row ];
8868
	
8869
			return data && data.anCells ?
8870
				data.anCells[ column ] :
8871
				undefined;
8872
		}, 1 );
8873
	} );
8874
	
8875
	
8876
	_api_register( 'cells().data()', function () {
8877
		return this.iterator( 'cell', function ( settings, row, column ) {
8878
			return _fnGetCellData( settings, row, column );
8879
		}, 1 );
8880
	} );
8881
	
8882
	
8883
	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8884
		type = type === 'search' ? '_aFilterData' : '_aSortData';
8885
	
8886
		return this.iterator( 'cell', function ( settings, row, column ) {
8887
			return settings.aoData[ row ][ type ][ column ];
8888
		}, 1 );
8889
	} );
8890
	
8891
	
8892
	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8893
		return this.iterator( 'cell', function ( settings, row, column ) {
8894
			return _fnGetCellData( settings, row, column, type );
8895
		}, 1 );
8896
	} );
8897
	
8898
	
8899
	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8900
		return this.iterator( 'cell', function ( settings, row, column ) {
8901
			return {
8902
				row: row,
8903
				column: column,
8904
				columnVisible: _fnColumnIndexToVisible( settings, column )
8905
			};
8906
		}, 1 );
8907
	} );
8908
	
8909
	
8910
	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8911
		return this.iterator( 'cell', function ( settings, row, column ) {
8912
			_fnInvalidate( settings, row, src, column );
8913
		} );
8914
	} );
8915
	
8916
	
8917
	
8918
	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8919
		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8920
	} );
8921
	
8922
	
8923
	_api_register( 'cell().data()', function ( data ) {
8924
		var ctx = this.context;
8925
		var cell = this[0];
8926
	
8927
		if ( data === undefined ) {
8928
			// Get
8929
			return ctx.length && cell.length ?
8930
				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8931
				undefined;
8932
		}
8933
	
8934
		// Set
8935
		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8936
		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8937
	
8938
		return this;
8939
	} );
8940
	
8941
	
8942
	
8943
	/**
8944
	 * Get current ordering (sorting) that has been applied to the table.
8945
	 *
8946
	 * @returns {array} 2D array containing the sorting information for the first
8947
	 *   table in the current context. Each element in the parent array represents
8948
	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8949
	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8950
	 *   the column index that the sorting condition applies to, the second is the
8951
	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8952
	 *   index of the sorting order from the `column.sorting` initialisation array.
8953
	 *//**
8954
	 * Set the ordering for the table.
8955
	 *
8956
	 * @param {integer} order Column index to sort upon.
8957
	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8958
	 * @returns {DataTables.Api} this
8959
	 *//**
8960
	 * Set the ordering for the table.
8961
	 *
8962
	 * @param {array} order 1D array of sorting information to be applied.
8963
	 * @param {array} [...] Optional additional sorting conditions
8964
	 * @returns {DataTables.Api} this
8965
	 *//**
8966
	 * Set the ordering for the table.
8967
	 *
8968
	 * @param {array} order 2D array of sorting information to be applied.
8969
	 * @returns {DataTables.Api} this
8970
	 */
8971
	_api_register( 'order()', function ( order, dir ) {
8972
		var ctx = this.context;
8973
	
8974
		if ( order === undefined ) {
8975
			// get
8976
			return ctx.length !== 0 ?
8977
				ctx[0].aaSorting :
8978
				undefined;
8979
		}
8980
	
8981
		// set
8982
		if ( typeof order === 'number' ) {
8983
			// Simple column / direction passed in
8984
			order = [ [ order, dir ] ];
8985
		}
8986
		else if ( order.length && ! $.isArray( order[0] ) ) {
8987
			// Arguments passed in (list of 1D arrays)
8988
			order = Array.prototype.slice.call( arguments );
8989
		}
8990
		// otherwise a 2D array was passed in
8991
	
8992
		return this.iterator( 'table', function ( settings ) {
8993
			settings.aaSorting = order.slice();
8994
		} );
8995
	} );
8996
	
8997
	
8998
	/**
8999
	 * Attach a sort listener to an element for a given column
9000
	 *
9001
	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9002
	 *   listener to. This can take the form of a single DOM node, a jQuery
9003
	 *   collection of nodes or a jQuery selector which will identify the node(s).
9004
	 * @param {integer} column the column that a click on this node will sort on
9005
	 * @param {function} [callback] callback function when sort is run
9006
	 * @returns {DataTables.Api} this
9007
	 */
9008
	_api_register( 'order.listener()', function ( node, column, callback ) {
9009
		return this.iterator( 'table', function ( settings ) {
9010
			_fnSortAttachListener( settings, node, column, callback );
9011
		} );
9012
	} );
9013
	
9014
	
9015
	_api_register( 'order.fixed()', function ( set ) {
9016
		if ( ! set ) {
9017
			var ctx = this.context;
9018
			var fixed = ctx.length ?
9019
				ctx[0].aaSortingFixed :
9020
				undefined;
9021
	
9022
			return $.isArray( fixed ) ?
9023
				{ pre: fixed } :
9024
				fixed;
9025
		}
9026
	
9027
		return this.iterator( 'table', function ( settings ) {
9028
			settings.aaSortingFixed = $.extend( true, {}, set );
9029
		} );
9030
	} );
9031
	
9032
	
9033
	// Order by the selected column(s)
9034
	_api_register( [
9035
		'columns().order()',
9036
		'column().order()'
9037
	], function ( dir ) {
9038
		var that = this;
9039
	
9040
		return this.iterator( 'table', function ( settings, i ) {
9041
			var sort = [];
9042
	
9043
			$.each( that[i], function (j, col) {
9044
				sort.push( [ col, dir ] );
9045
			} );
9046
	
9047
			settings.aaSorting = sort;
9048
		} );
9049
	} );
9050
	
9051
	
9052
	
9053
	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9054
		var ctx = this.context;
9055
	
9056
		if ( input === undefined ) {
9057
			// get
9058
			return ctx.length !== 0 ?
9059
				ctx[0].oPreviousSearch.sSearch :
9060
				undefined;
9061
		}
9062
	
9063
		// set
9064
		return this.iterator( 'table', function ( settings ) {
9065
			if ( ! settings.oFeatures.bFilter ) {
9066
				return;
9067
			}
9068
	
9069
			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9070
				"sSearch": input+"",
9071
				"bRegex":  regex === null ? false : regex,
9072
				"bSmart":  smart === null ? true  : smart,
9073
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9074
			} ), 1 );
9075
		} );
9076
	} );
9077
	
9078
	
9079
	_api_registerPlural(
9080
		'columns().search()',
9081
		'column().search()',
9082
		function ( input, regex, smart, caseInsen ) {
9083
			return this.iterator( 'column', function ( settings, column ) {
9084
				var preSearch = settings.aoPreSearchCols;
9085
	
9086
				if ( input === undefined ) {
9087
					// get
9088
					return preSearch[ column ].sSearch;
9089
				}
9090
	
9091
				// set
9092
				if ( ! settings.oFeatures.bFilter ) {
9093
					return;
9094
				}
9095
	
9096
				$.extend( preSearch[ column ], {
9097
					"sSearch": input+"",
9098
					"bRegex":  regex === null ? false : regex,
9099
					"bSmart":  smart === null ? true  : smart,
9100
					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9101
				} );
9102
	
9103
				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9104
			} );
9105
		}
9106
	);
9107
	
9108
	/*
9109
	 * State API methods
9110
	 */
9111
	
9112
	_api_register( 'state()', function () {
9113
		return this.context.length ?
9114
			this.context[0].oSavedState :
9115
			null;
9116
	} );
9117
	
9118
	
9119
	_api_register( 'state.clear()', function () {
9120
		return this.iterator( 'table', function ( settings ) {
9121
			// Save an empty object
9122
			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9123
		} );
9124
	} );
9125
	
9126
	
9127
	_api_register( 'state.loaded()', function () {
9128
		return this.context.length ?
9129
			this.context[0].oLoadedState :
9130
			null;
9131
	} );
9132
	
9133
	
9134
	_api_register( 'state.save()', function () {
9135
		return this.iterator( 'table', function ( settings ) {
9136
			_fnSaveState( settings );
9137
		} );
9138
	} );
9139
	
9140
	
9141
	
9142
	/**
9143
	 * Provide a common method for plug-ins to check the version of DataTables being
9144
	 * used, in order to ensure compatibility.
9145
	 *
9146
	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9147
	 *    Note that the formats "X" and "X.Y" are also acceptable.
9148
	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9149
	 *    the required version, or false if this version of DataTales is not
9150
	 *    suitable
9151
	 *  @static
9152
	 *  @dtopt API-Static
9153
	 *
9154
	 *  @example
9155
	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9156
	 */
9157
	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9158
	{
9159
		var aThis = DataTable.version.split('.');
9160
		var aThat = version.split('.');
9161
		var iThis, iThat;
9162
	
9163
		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9164
			iThis = parseInt( aThis[i], 10 ) || 0;
9165
			iThat = parseInt( aThat[i], 10 ) || 0;
9166
	
9167
			// Parts are the same, keep comparing
9168
			if (iThis === iThat) {
9169
				continue;
9170
			}
9171
	
9172
			// Parts are different, return immediately
9173
			return iThis > iThat;
9174
		}
9175
	
9176
		return true;
9177
	};
9178
	
9179
	
9180
	/**
9181
	 * Check if a `<table>` node is a DataTable table already or not.
9182
	 *
9183
	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9184
	 *      selector for the table to test. Note that if more than more than one
9185
	 *      table is passed on, only the first will be checked
9186
	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9187
	 *  @static
9188
	 *  @dtopt API-Static
9189
	 *
9190
	 *  @example
9191
	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9192
	 *      $('#example').dataTable();
9193
	 *    }
9194
	 */
9195
	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9196
	{
9197
		var t = $(table).get(0);
9198
		var is = false;
9199
	
9200
		if ( table instanceof DataTable.Api ) {
9201
			return true;
9202
		}
9203
	
9204
		$.each( DataTable.settings, function (i, o) {
9205
			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9206
			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9207
	
9208
			if ( o.nTable === t || head === t || foot === t ) {
9209
				is = true;
9210
			}
9211
		} );
9212
	
9213
		return is;
9214
	};
9215
	
9216
	
9217
	/**
9218
	 * Get all DataTable tables that have been initialised - optionally you can
9219
	 * select to get only currently visible tables.
9220
	 *
9221
	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9222
	 *    or visible tables only.
9223
	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9224
	 *    DataTables
9225
	 *  @static
9226
	 *  @dtopt API-Static
9227
	 *
9228
	 *  @example
9229
	 *    $.each( $.fn.dataTable.tables(true), function () {
9230
	 *      $(table).DataTable().columns.adjust();
9231
	 *    } );
9232
	 */
9233
	DataTable.tables = DataTable.fnTables = function ( visible )
9234
	{
9235
		var api = false;
9236
	
9237
		if ( $.isPlainObject( visible ) ) {
9238
			api = visible.api;
9239
			visible = visible.visible;
9240
		}
9241
	
9242
		var a = $.map( DataTable.settings, function (o) {
9243
			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9244
				return o.nTable;
9245
			}
9246
		} );
9247
	
9248
		return api ?
9249
			new _Api( a ) :
9250
			a;
9251
	};
9252
	
9253
	
9254
	/**
9255
	 * Convert from camel case parameters to Hungarian notation. This is made public
9256
	 * for the extensions to provide the same ability as DataTables core to accept
9257
	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9258
	 * parameters.
9259
	 *
9260
	 *  @param {object} src The model object which holds all parameters that can be
9261
	 *    mapped.
9262
	 *  @param {object} user The object to convert from camel case to Hungarian.
9263
	 *  @param {boolean} force When set to `true`, properties which already have a
9264
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9265
	 *    won't be.
9266
	 */
9267
	DataTable.camelToHungarian = _fnCamelToHungarian;
9268
	
9269
	
9270
	
9271
	/**
9272
	 *
9273
	 */
9274
	_api_register( '$()', function ( selector, opts ) {
9275
		var
9276
			rows   = this.rows( opts ).nodes(), // Get all rows
9277
			jqRows = $(rows);
9278
	
9279
		return $( [].concat(
9280
			jqRows.filter( selector ).toArray(),
9281
			jqRows.find( selector ).toArray()
9282
		) );
9283
	} );
9284
	
9285
	
9286
	// jQuery functions to operate on the tables
9287
	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9288
		_api_register( key+'()', function ( /* event, handler */ ) {
9289
			var args = Array.prototype.slice.call(arguments);
9290
	
9291
			// Add the `dt` namespace automatically if it isn't already present
9292
			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9293
				return ! e.match(/\.dt\b/) ?
9294
					e+'.dt' :
9295
					e;
9296
				} ).join( ' ' );
9297
	
9298
			var inst = $( this.tables().nodes() );
9299
			inst[key].apply( inst, args );
9300
			return this;
9301
		} );
9302
	} );
9303
	
9304
	
9305
	_api_register( 'clear()', function () {
9306
		return this.iterator( 'table', function ( settings ) {
9307
			_fnClearTable( settings );
9308
		} );
9309
	} );
9310
	
9311
	
9312
	_api_register( 'settings()', function () {
9313
		return new _Api( this.context, this.context );
9314
	} );
9315
	
9316
	
9317
	_api_register( 'init()', function () {
9318
		var ctx = this.context;
9319
		return ctx.length ? ctx[0].oInit : null;
9320
	} );
9321
	
9322
	
9323
	_api_register( 'data()', function () {
9324
		return this.iterator( 'table', function ( settings ) {
9325
			return _pluck( settings.aoData, '_aData' );
9326
		} ).flatten();
9327
	} );
9328
	
9329
	
9330
	_api_register( 'destroy()', function ( remove ) {
9331
		remove = remove || false;
9332
	
9333
		return this.iterator( 'table', function ( settings ) {
9334
			var orig      = settings.nTableWrapper.parentNode;
9335
			var classes   = settings.oClasses;
9336
			var table     = settings.nTable;
9337
			var tbody     = settings.nTBody;
9338
			var thead     = settings.nTHead;
9339
			var tfoot     = settings.nTFoot;
9340
			var jqTable   = $(table);
9341
			var jqTbody   = $(tbody);
9342
			var jqWrapper = $(settings.nTableWrapper);
9343
			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9344
			var i, ien;
9345
	
9346
			// Flag to note that the table is currently being destroyed - no action
9347
			// should be taken
9348
			settings.bDestroying = true;
9349
	
9350
			// Fire off the destroy callbacks for plug-ins etc
9351
			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9352
	
9353
			// If not being removed from the document, make all columns visible
9354
			if ( ! remove ) {
9355
				new _Api( settings ).columns().visible( true );
9356
			}
9357
	
9358
			// Blitz all `DT` namespaced events (these are internal events, the
9359
			// lowercase, `dt` events are user subscribed and they are responsible
9360
			// for removing them
9361
			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9362
			$(window).off('.DT-'+settings.sInstance);
9363
	
9364
			// When scrolling we had to break the table up - restore it
9365
			if ( table != thead.parentNode ) {
9366
				jqTable.children('thead').detach();
9367
				jqTable.append( thead );
9368
			}
9369
	
9370
			if ( tfoot && table != tfoot.parentNode ) {
9371
				jqTable.children('tfoot').detach();
9372
				jqTable.append( tfoot );
9373
			}
9374
	
9375
			settings.aaSorting = [];
9376
			settings.aaSortingFixed = [];
9377
			_fnSortingClasses( settings );
9378
	
9379
			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9380
	
9381
			$('th, td', thead).removeClass( classes.sSortable+' '+
9382
				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9383
			);
9384
	
9385
			// Add the TR elements back into the table in their original order
9386
			jqTbody.children().detach();
9387
			jqTbody.append( rows );
9388
	
9389
			// Remove the DataTables generated nodes, events and classes
9390
			var removedMethod = remove ? 'remove' : 'detach';
9391
			jqTable[ removedMethod ]();
9392
			jqWrapper[ removedMethod ]();
9393
	
9394
			// If we need to reattach the table to the document
9395
			if ( ! remove && orig ) {
9396
				// insertBefore acts like appendChild if !arg[1]
9397
				orig.insertBefore( table, settings.nTableReinsertBefore );
9398
	
9399
				// Restore the width of the original table - was read from the style property,
9400
				// so we can restore directly to that
9401
				jqTable
9402
					.css( 'width', settings.sDestroyWidth )
9403
					.removeClass( classes.sTable );
9404
	
9405
				// If the were originally stripe classes - then we add them back here.
9406
				// Note this is not fool proof (for example if not all rows had stripe
9407
				// classes - but it's a good effort without getting carried away
9408
				ien = settings.asDestroyStripes.length;
9409
	
9410
				if ( ien ) {
9411
					jqTbody.children().each( function (i) {
9412
						$(this).addClass( settings.asDestroyStripes[i % ien] );
9413
					} );
9414
				}
9415
			}
9416
	
9417
			/* Remove the settings object from the settings array */
9418
			var idx = $.inArray( settings, DataTable.settings );
9419
			if ( idx !== -1 ) {
9420
				DataTable.settings.splice( idx, 1 );
9421
			}
9422
		} );
9423
	} );
9424
	
9425
	
9426
	// Add the `every()` method for rows, columns and cells in a compact form
9427
	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9428
		_api_register( type+'s().every()', function ( fn ) {
9429
			var opts = this.selector.opts;
9430
			var api = this;
9431
	
9432
			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9433
				// Rows and columns:
9434
				//  arg1 - index
9435
				//  arg2 - table counter
9436
				//  arg3 - loop counter
9437
				//  arg4 - undefined
9438
				// Cells:
9439
				//  arg1 - row index
9440
				//  arg2 - column index
9441
				//  arg3 - table counter
9442
				//  arg4 - loop counter
9443
				fn.call(
9444
					api[ type ](
9445
						arg1,
9446
						type==='cell' ? arg2 : opts,
9447
						type==='cell' ? opts : undefined
9448
					),
9449
					arg1, arg2, arg3, arg4
9450
				);
9451
			} );
9452
		} );
9453
	} );
9454
	
9455
	
9456
	// i18n method for extensions to be able to use the language object from the
9457
	// DataTable
9458
	_api_register( 'i18n()', function ( token, def, plural ) {
9459
		var ctx = this.context[0];
9460
		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9461
	
9462
		if ( resolved === undefined ) {
9463
			resolved = def;
9464
		}
9465
	
9466
		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9467
			resolved = resolved[ plural ] !== undefined ?
9468
				resolved[ plural ] :
9469
				resolved._;
9470
		}
9471
	
9472
		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9473
	} );
9474
9475
	/**
9476
	 * Version string for plug-ins to check compatibility. Allowed format is
9477
	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9478
	 * only for non-release builds. See http://semver.org/ for more information.
9479
	 *  @member
9480
	 *  @type string
9481
	 *  @default Version number
9482
	 */
9483
	DataTable.version = "1.10.18";
9484
9485
	/**
9486
	 * Private data store, containing all of the settings objects that are
9487
	 * created for the tables on a given page.
9488
	 *
9489
	 * Note that the `DataTable.settings` object is aliased to
9490
	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9491
	 * manipulated, or `jQuery.fn.dataTable.settings`.
9492
	 *  @member
9493
	 *  @type array
9494
	 *  @default []
9495
	 *  @private
9496
	 */
9497
	DataTable.settings = [];
9498
9499
	/**
9500
	 * Object models container, for the various models that DataTables has
9501
	 * available to it. These models define the objects that are used to hold
9502
	 * the active state and configuration of the table.
9503
	 *  @namespace
9504
	 */
9505
	DataTable.models = {};
9506
	
9507
	
9508
	
9509
	/**
9510
	 * Template object for the way in which DataTables holds information about
9511
	 * search information for the global filter and individual column filters.
9512
	 *  @namespace
9513
	 */
9514
	DataTable.models.oSearch = {
9515
		/**
9516
		 * Flag to indicate if the filtering should be case insensitive or not
9517
		 *  @type boolean
9518
		 *  @default true
9519
		 */
9520
		"bCaseInsensitive": true,
9521
	
9522
		/**
9523
		 * Applied search term
9524
		 *  @type string
9525
		 *  @default <i>Empty string</i>
9526
		 */
9527
		"sSearch": "",
9528
	
9529
		/**
9530
		 * Flag to indicate if the search term should be interpreted as a
9531
		 * regular expression (true) or not (false) and therefore and special
9532
		 * regex characters escaped.
9533
		 *  @type boolean
9534
		 *  @default false
9535
		 */
9536
		"bRegex": false,
9537
	
9538
		/**
9539
		 * Flag to indicate if DataTables is to use its smart filtering or not.
9540
		 *  @type boolean
9541
		 *  @default true
9542
		 */
9543
		"bSmart": true
9544
	};
9545
	
9546
	
9547
	
9548
	
9549
	/**
9550
	 * Template object for the way in which DataTables holds information about
9551
	 * each individual row. This is the object format used for the settings
9552
	 * aoData array.
9553
	 *  @namespace
9554
	 */
9555
	DataTable.models.oRow = {
9556
		/**
9557
		 * TR element for the row
9558
		 *  @type node
9559
		 *  @default null
9560
		 */
9561
		"nTr": null,
9562
	
9563
		/**
9564
		 * Array of TD elements for each row. This is null until the row has been
9565
		 * created.
9566
		 *  @type array nodes
9567
		 *  @default []
9568
		 */
9569
		"anCells": null,
9570
	
9571
		/**
9572
		 * Data object from the original data source for the row. This is either
9573
		 * an array if using the traditional form of DataTables, or an object if
9574
		 * using mData options. The exact type will depend on the passed in
9575
		 * data from the data source, or will be an array if using DOM a data
9576
		 * source.
9577
		 *  @type array|object
9578
		 *  @default []
9579
		 */
9580
		"_aData": [],
9581
	
9582
		/**
9583
		 * Sorting data cache - this array is ostensibly the same length as the
9584
		 * number of columns (although each index is generated only as it is
9585
		 * needed), and holds the data that is used for sorting each column in the
9586
		 * row. We do this cache generation at the start of the sort in order that
9587
		 * the formatting of the sort data need be done only once for each cell
9588
		 * per sort. This array should not be read from or written to by anything
9589
		 * other than the master sorting methods.
9590
		 *  @type array
9591
		 *  @default null
9592
		 *  @private
9593
		 */
9594
		"_aSortData": null,
9595
	
9596
		/**
9597
		 * Per cell filtering data cache. As per the sort data cache, used to
9598
		 * increase the performance of the filtering in DataTables
9599
		 *  @type array
9600
		 *  @default null
9601
		 *  @private
9602
		 */
9603
		"_aFilterData": null,
9604
	
9605
		/**
9606
		 * Filtering data cache. This is the same as the cell filtering cache, but
9607
		 * in this case a string rather than an array. This is easily computed with
9608
		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9609
		 * needed on every search (memory traded for performance)
9610
		 *  @type array
9611
		 *  @default null
9612
		 *  @private
9613
		 */
9614
		"_sFilterRow": null,
9615
	
9616
		/**
9617
		 * Cache of the class name that DataTables has applied to the row, so we
9618
		 * can quickly look at this variable rather than needing to do a DOM check
9619
		 * on className for the nTr property.
9620
		 *  @type string
9621
		 *  @default <i>Empty string</i>
9622
		 *  @private
9623
		 */
9624
		"_sRowStripe": "",
9625
	
9626
		/**
9627
		 * Denote if the original data source was from the DOM, or the data source
9628
		 * object. This is used for invalidating data, so DataTables can
9629
		 * automatically read data from the original source, unless uninstructed
9630
		 * otherwise.
9631
		 *  @type string
9632
		 *  @default null
9633
		 *  @private
9634
		 */
9635
		"src": null,
9636
	
9637
		/**
9638
		 * Index in the aoData array. This saves an indexOf lookup when we have the
9639
		 * object, but want to know the index
9640
		 *  @type integer
9641
		 *  @default -1
9642
		 *  @private
9643
		 */
9644
		"idx": -1
9645
	};
9646
	
9647
	
9648
	/**
9649
	 * Template object for the column information object in DataTables. This object
9650
	 * is held in the settings aoColumns array and contains all the information that
9651
	 * DataTables needs about each individual column.
9652
	 *
9653
	 * Note that this object is related to {@link DataTable.defaults.column}
9654
	 * but this one is the internal data store for DataTables's cache of columns.
9655
	 * It should NOT be manipulated outside of DataTables. Any configuration should
9656
	 * be done through the initialisation options.
9657
	 *  @namespace
9658
	 */
9659
	DataTable.models.oColumn = {
9660
		/**
9661
		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9662
		 * is faster to just hold it as a variable
9663
		 *  @type integer
9664
		 *  @default null
9665
		 */
9666
		"idx": null,
9667
	
9668
		/**
9669
		 * A list of the columns that sorting should occur on when this column
9670
		 * is sorted. That this property is an array allows multi-column sorting
9671
		 * to be defined for a column (for example first name / last name columns
9672
		 * would benefit from this). The values are integers pointing to the
9673
		 * columns to be sorted on (typically it will be a single integer pointing
9674
		 * at itself, but that doesn't need to be the case).
9675
		 *  @type array
9676
		 */
9677
		"aDataSort": null,
9678
	
9679
		/**
9680
		 * Define the sorting directions that are applied to the column, in sequence
9681
		 * as the column is repeatedly sorted upon - i.e. the first value is used
9682
		 * as the sorting direction when the column if first sorted (clicked on).
9683
		 * Sort it again (click again) and it will move on to the next index.
9684
		 * Repeat until loop.
9685
		 *  @type array
9686
		 */
9687
		"asSorting": null,
9688
	
9689
		/**
9690
		 * Flag to indicate if the column is searchable, and thus should be included
9691
		 * in the filtering or not.
9692
		 *  @type boolean
9693
		 */
9694
		"bSearchable": null,
9695
	
9696
		/**
9697
		 * Flag to indicate if the column is sortable or not.
9698
		 *  @type boolean
9699
		 */
9700
		"bSortable": null,
9701
	
9702
		/**
9703
		 * Flag to indicate if the column is currently visible in the table or not
9704
		 *  @type boolean
9705
		 */
9706
		"bVisible": null,
9707
	
9708
		/**
9709
		 * Store for manual type assignment using the `column.type` option. This
9710
		 * is held in store so we can manipulate the column's `sType` property.
9711
		 *  @type string
9712
		 *  @default null
9713
		 *  @private
9714
		 */
9715
		"_sManualType": null,
9716
	
9717
		/**
9718
		 * Flag to indicate if HTML5 data attributes should be used as the data
9719
		 * source for filtering or sorting. True is either are.
9720
		 *  @type boolean
9721
		 *  @default false
9722
		 *  @private
9723
		 */
9724
		"_bAttrSrc": false,
9725
	
9726
		/**
9727
		 * Developer definable function that is called whenever a cell is created (Ajax source,
9728
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9729
		 * allowing you to modify the DOM element (add background colour for example) when the
9730
		 * element is available.
9731
		 *  @type function
9732
		 *  @param {element} nTd The TD node that has been created
9733
		 *  @param {*} sData The Data for the cell
9734
		 *  @param {array|object} oData The data for the whole row
9735
		 *  @param {int} iRow The row index for the aoData data store
9736
		 *  @default null
9737
		 */
9738
		"fnCreatedCell": null,
9739
	
9740
		/**
9741
		 * Function to get data from a cell in a column. You should <b>never</b>
9742
		 * access data directly through _aData internally in DataTables - always use
9743
		 * the method attached to this property. It allows mData to function as
9744
		 * required. This function is automatically assigned by the column
9745
		 * initialisation method
9746
		 *  @type function
9747
		 *  @param {array|object} oData The data array/object for the array
9748
		 *    (i.e. aoData[]._aData)
9749
		 *  @param {string} sSpecific The specific data type you want to get -
9750
		 *    'display', 'type' 'filter' 'sort'
9751
		 *  @returns {*} The data for the cell from the given row's data
9752
		 *  @default null
9753
		 */
9754
		"fnGetData": null,
9755
	
9756
		/**
9757
		 * Function to set data for a cell in the column. You should <b>never</b>
9758
		 * set the data directly to _aData internally in DataTables - always use
9759
		 * this method. It allows mData to function as required. This function
9760
		 * is automatically assigned by the column initialisation method
9761
		 *  @type function
9762
		 *  @param {array|object} oData The data array/object for the array
9763
		 *    (i.e. aoData[]._aData)
9764
		 *  @param {*} sValue Value to set
9765
		 *  @default null
9766
		 */
9767
		"fnSetData": null,
9768
	
9769
		/**
9770
		 * Property to read the value for the cells in the column from the data
9771
		 * source array / object. If null, then the default content is used, if a
9772
		 * function is given then the return from the function is used.
9773
		 *  @type function|int|string|null
9774
		 *  @default null
9775
		 */
9776
		"mData": null,
9777
	
9778
		/**
9779
		 * Partner property to mData which is used (only when defined) to get
9780
		 * the data - i.e. it is basically the same as mData, but without the
9781
		 * 'set' option, and also the data fed to it is the result from mData.
9782
		 * This is the rendering method to match the data method of mData.
9783
		 *  @type function|int|string|null
9784
		 *  @default null
9785
		 */
9786
		"mRender": null,
9787
	
9788
		/**
9789
		 * Unique header TH/TD element for this column - this is what the sorting
9790
		 * listener is attached to (if sorting is enabled.)
9791
		 *  @type node
9792
		 *  @default null
9793
		 */
9794
		"nTh": null,
9795
	
9796
		/**
9797
		 * Unique footer TH/TD element for this column (if there is one). Not used
9798
		 * in DataTables as such, but can be used for plug-ins to reference the
9799
		 * footer for each column.
9800
		 *  @type node
9801
		 *  @default null
9802
		 */
9803
		"nTf": null,
9804
	
9805
		/**
9806
		 * The class to apply to all TD elements in the table's TBODY for the column
9807
		 *  @type string
9808
		 *  @default null
9809
		 */
9810
		"sClass": null,
9811
	
9812
		/**
9813
		 * When DataTables calculates the column widths to assign to each column,
9814
		 * it finds the longest string in each column and then constructs a
9815
		 * temporary table and reads the widths from that. The problem with this
9816
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9817
		 * string - thus the calculation can go wrong (doing it properly and putting
9818
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9819
		 * a "work around" we provide this option. It will append its value to the
9820
		 * text that is found to be the longest string for the column - i.e. padding.
9821
		 *  @type string
9822
		 */
9823
		"sContentPadding": null,
9824
	
9825
		/**
9826
		 * Allows a default value to be given for a column's data, and will be used
9827
		 * whenever a null data source is encountered (this can be because mData
9828
		 * is set to null, or because the data source itself is null).
9829
		 *  @type string
9830
		 *  @default null
9831
		 */
9832
		"sDefaultContent": null,
9833
	
9834
		/**
9835
		 * Name for the column, allowing reference to the column by name as well as
9836
		 * by index (needs a lookup to work by name).
9837
		 *  @type string
9838
		 */
9839
		"sName": null,
9840
	
9841
		/**
9842
		 * Custom sorting data type - defines which of the available plug-ins in
9843
		 * afnSortData the custom sorting will use - if any is defined.
9844
		 *  @type string
9845
		 *  @default std
9846
		 */
9847
		"sSortDataType": 'std',
9848
	
9849
		/**
9850
		 * Class to be applied to the header element when sorting on this column
9851
		 *  @type string
9852
		 *  @default null
9853
		 */
9854
		"sSortingClass": null,
9855
	
9856
		/**
9857
		 * Class to be applied to the header element when sorting on this column -
9858
		 * when jQuery UI theming is used.
9859
		 *  @type string
9860
		 *  @default null
9861
		 */
9862
		"sSortingClassJUI": null,
9863
	
9864
		/**
9865
		 * Title of the column - what is seen in the TH element (nTh).
9866
		 *  @type string
9867
		 */
9868
		"sTitle": null,
9869
	
9870
		/**
9871
		 * Column sorting and filtering type
9872
		 *  @type string
9873
		 *  @default null
9874
		 */
9875
		"sType": null,
9876
	
9877
		/**
9878
		 * Width of the column
9879
		 *  @type string
9880
		 *  @default null
9881
		 */
9882
		"sWidth": null,
9883
	
9884
		/**
9885
		 * Width of the column when it was first "encountered"
9886
		 *  @type string
9887
		 *  @default null
9888
		 */
9889
		"sWidthOrig": null
9890
	};
9891
	
9892
	
9893
	/*
9894
	 * Developer note: The properties of the object below are given in Hungarian
9895
	 * notation, that was used as the interface for DataTables prior to v1.10, however
9896
	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9897
	 * breaking backwards compatibility utterly with this change, the Hungarian
9898
	 * version is still, internally the primary interface, but is is not documented
9899
	 * - hence the @name tags in each doc comment. This allows a Javascript function
9900
	 * to create a map from Hungarian notation to camel case (going the other direction
9901
	 * would require each property to be listed, which would at around 3K to the size
9902
	 * of DataTables, while this method is about a 0.5K hit.
9903
	 *
9904
	 * Ultimately this does pave the way for Hungarian notation to be dropped
9905
	 * completely, but that is a massive amount of work and will break current
9906
	 * installs (therefore is on-hold until v2).
9907
	 */
9908
	
9909
	/**
9910
	 * Initialisation options that can be given to DataTables at initialisation
9911
	 * time.
9912
	 *  @namespace
9913
	 */
9914
	DataTable.defaults = {
9915
		/**
9916
		 * An array of data to use for the table, passed in at initialisation which
9917
		 * will be used in preference to any data which is already in the DOM. This is
9918
		 * particularly useful for constructing tables purely in Javascript, for
9919
		 * example with a custom Ajax call.
9920
		 *  @type array
9921
		 *  @default null
9922
		 *
9923
		 *  @dtopt Option
9924
		 *  @name DataTable.defaults.data
9925
		 *
9926
		 *  @example
9927
		 *    // Using a 2D array data source
9928
		 *    $(document).ready( function () {
9929
		 *      $('#example').dataTable( {
9930
		 *        "data": [
9931
		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9932
		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9933
		 *        ],
9934
		 *        "columns": [
9935
		 *          { "title": "Engine" },
9936
		 *          { "title": "Browser" },
9937
		 *          { "title": "Platform" },
9938
		 *          { "title": "Version" },
9939
		 *          { "title": "Grade" }
9940
		 *        ]
9941
		 *      } );
9942
		 *    } );
9943
		 *
9944
		 *  @example
9945
		 *    // Using an array of objects as a data source (`data`)
9946
		 *    $(document).ready( function () {
9947
		 *      $('#example').dataTable( {
9948
		 *        "data": [
9949
		 *          {
9950
		 *            "engine":   "Trident",
9951
		 *            "browser":  "Internet Explorer 4.0",
9952
		 *            "platform": "Win 95+",
9953
		 *            "version":  4,
9954
		 *            "grade":    "X"
9955
		 *          },
9956
		 *          {
9957
		 *            "engine":   "Trident",
9958
		 *            "browser":  "Internet Explorer 5.0",
9959
		 *            "platform": "Win 95+",
9960
		 *            "version":  5,
9961
		 *            "grade":    "C"
9962
		 *          }
9963
		 *        ],
9964
		 *        "columns": [
9965
		 *          { "title": "Engine",   "data": "engine" },
9966
		 *          { "title": "Browser",  "data": "browser" },
9967
		 *          { "title": "Platform", "data": "platform" },
9968
		 *          { "title": "Version",  "data": "version" },
9969
		 *          { "title": "Grade",    "data": "grade" }
9970
		 *        ]
9971
		 *      } );
9972
		 *    } );
9973
		 */
9974
		"aaData": null,
9975
	
9976
	
9977
		/**
9978
		 * If ordering is enabled, then DataTables will perform a first pass sort on
9979
		 * initialisation. You can define which column(s) the sort is performed
9980
		 * upon, and the sorting direction, with this variable. The `sorting` array
9981
		 * should contain an array for each column to be sorted initially containing
9982
		 * the column's index and a direction string ('asc' or 'desc').
9983
		 *  @type array
9984
		 *  @default [[0,'asc']]
9985
		 *
9986
		 *  @dtopt Option
9987
		 *  @name DataTable.defaults.order
9988
		 *
9989
		 *  @example
9990
		 *    // Sort by 3rd column first, and then 4th column
9991
		 *    $(document).ready( function() {
9992
		 *      $('#example').dataTable( {
9993
		 *        "order": [[2,'asc'], [3,'desc']]
9994
		 *      } );
9995
		 *    } );
9996
		 *
9997
		 *    // No initial sorting
9998
		 *    $(document).ready( function() {
9999
		 *      $('#example').dataTable( {
10000
		 *        "order": []
10001
		 *      } );
10002
		 *    } );
10003
		 */
10004
		"aaSorting": [[0,'asc']],
10005
	
10006
	
10007
		/**
10008
		 * This parameter is basically identical to the `sorting` parameter, but
10009
		 * cannot be overridden by user interaction with the table. What this means
10010
		 * is that you could have a column (visible or hidden) which the sorting
10011
		 * will always be forced on first - any sorting after that (from the user)
10012
		 * will then be performed as required. This can be useful for grouping rows
10013
		 * together.
10014
		 *  @type array
10015
		 *  @default null
10016
		 *
10017
		 *  @dtopt Option
10018
		 *  @name DataTable.defaults.orderFixed
10019
		 *
10020
		 *  @example
10021
		 *    $(document).ready( function() {
10022
		 *      $('#example').dataTable( {
10023
		 *        "orderFixed": [[0,'asc']]
10024
		 *      } );
10025
		 *    } )
10026
		 */
10027
		"aaSortingFixed": [],
10028
	
10029
	
10030
		/**
10031
		 * DataTables can be instructed to load data to display in the table from a
10032
		 * Ajax source. This option defines how that Ajax call is made and where to.
10033
		 *
10034
		 * The `ajax` property has three different modes of operation, depending on
10035
		 * how it is defined. These are:
10036
		 *
10037
		 * * `string` - Set the URL from where the data should be loaded from.
10038
		 * * `object` - Define properties for `jQuery.ajax`.
10039
		 * * `function` - Custom data get function
10040
		 *
10041
		 * `string`
10042
		 * --------
10043
		 *
10044
		 * As a string, the `ajax` property simply defines the URL from which
10045
		 * DataTables will load data.
10046
		 *
10047
		 * `object`
10048
		 * --------
10049
		 *
10050
		 * As an object, the parameters in the object are passed to
10051
		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10052
		 * of the Ajax request. DataTables has a number of default parameters which
10053
		 * you can override using this option. Please refer to the jQuery
10054
		 * documentation for a full description of the options available, although
10055
		 * the following parameters provide additional options in DataTables or
10056
		 * require special consideration:
10057
		 *
10058
		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10059
		 *   can also be used as a function to manipulate the data DataTables sends
10060
		 *   to the server. The function takes a single parameter, an object of
10061
		 *   parameters with the values that DataTables has readied for sending. An
10062
		 *   object may be returned which will be merged into the DataTables
10063
		 *   defaults, or you can add the items to the object that was passed in and
10064
		 *   not return anything from the function. This supersedes `fnServerParams`
10065
		 *   from DataTables 1.9-.
10066
		 *
10067
		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10068
		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10069
		 *   from an Ajax source or for server-side processing - this parameter
10070
		 *   allows that property to be changed. You can use Javascript dotted
10071
		 *   object notation to get a data source for multiple levels of nesting, or
10072
		 *   it my be used as a function. As a function it takes a single parameter,
10073
		 *   the JSON returned from the server, which can be manipulated as
10074
		 *   required, with the returned value being that used by DataTables as the
10075
		 *   data source for the table. This supersedes `sAjaxDataProp` from
10076
		 *   DataTables 1.9-.
10077
		 *
10078
		 * * `success` - Should not be overridden it is used internally in
10079
		 *   DataTables. To manipulate / transform the data returned by the server
10080
		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10081
		 *
10082
		 * `function`
10083
		 * ----------
10084
		 *
10085
		 * As a function, making the Ajax call is left up to yourself allowing
10086
		 * complete control of the Ajax request. Indeed, if desired, a method other
10087
		 * than Ajax could be used to obtain the required data, such as Web storage
10088
		 * or an AIR database.
10089
		 *
10090
		 * The function is given four parameters and no return is required. The
10091
		 * parameters are:
10092
		 *
10093
		 * 1. _object_ - Data to send to the server
10094
		 * 2. _function_ - Callback function that must be executed when the required
10095
		 *    data has been obtained. That data should be passed into the callback
10096
		 *    as the only parameter
10097
		 * 3. _object_ - DataTables settings object for the table
10098
		 *
10099
		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10100
		 *
10101
		 *  @type string|object|function
10102
		 *  @default null
10103
		 *
10104
		 *  @dtopt Option
10105
		 *  @name DataTable.defaults.ajax
10106
		 *  @since 1.10.0
10107
		 *
10108
		 * @example
10109
		 *   // Get JSON data from a file via Ajax.
10110
		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10111
		 *   $('#example').dataTable( {
10112
		 *     "ajax": "data.json"
10113
		 *   } );
10114
		 *
10115
		 * @example
10116
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10117
		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10118
		 *   $('#example').dataTable( {
10119
		 *     "ajax": {
10120
		 *       "url": "data.json",
10121
		 *       "dataSrc": "tableData"
10122
		 *     }
10123
		 *   } );
10124
		 *
10125
		 * @example
10126
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10127
		 *   // from a plain array rather than an array in an object
10128
		 *   $('#example').dataTable( {
10129
		 *     "ajax": {
10130
		 *       "url": "data.json",
10131
		 *       "dataSrc": ""
10132
		 *     }
10133
		 *   } );
10134
		 *
10135
		 * @example
10136
		 *   // Manipulate the data returned from the server - add a link to data
10137
		 *   // (note this can, should, be done using `render` for the column - this
10138
		 *   // is just a simple example of how the data can be manipulated).
10139
		 *   $('#example').dataTable( {
10140
		 *     "ajax": {
10141
		 *       "url": "data.json",
10142
		 *       "dataSrc": function ( json ) {
10143
		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10144
		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10145
		 *         }
10146
		 *         return json;
10147
		 *       }
10148
		 *     }
10149
		 *   } );
10150
		 *
10151
		 * @example
10152
		 *   // Add data to the request
10153
		 *   $('#example').dataTable( {
10154
		 *     "ajax": {
10155
		 *       "url": "data.json",
10156
		 *       "data": function ( d ) {
10157
		 *         return {
10158
		 *           "extra_search": $('#extra').val()
10159
		 *         };
10160
		 *       }
10161
		 *     }
10162
		 *   } );
10163
		 *
10164
		 * @example
10165
		 *   // Send request as POST
10166
		 *   $('#example').dataTable( {
10167
		 *     "ajax": {
10168
		 *       "url": "data.json",
10169
		 *       "type": "POST"
10170
		 *     }
10171
		 *   } );
10172
		 *
10173
		 * @example
10174
		 *   // Get the data from localStorage (could interface with a form for
10175
		 *   // adding, editing and removing rows).
10176
		 *   $('#example').dataTable( {
10177
		 *     "ajax": function (data, callback, settings) {
10178
		 *       callback(
10179
		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10180
		 *       );
10181
		 *     }
10182
		 *   } );
10183
		 */
10184
		"ajax": null,
10185
	
10186
	
10187
		/**
10188
		 * This parameter allows you to readily specify the entries in the length drop
10189
		 * down menu that DataTables shows when pagination is enabled. It can be
10190
		 * either a 1D array of options which will be used for both the displayed
10191
		 * option and the value, or a 2D array which will use the array in the first
10192
		 * position as the value, and the array in the second position as the
10193
		 * displayed options (useful for language strings such as 'All').
10194
		 *
10195
		 * Note that the `pageLength` property will be automatically set to the
10196
		 * first value given in this array, unless `pageLength` is also provided.
10197
		 *  @type array
10198
		 *  @default [ 10, 25, 50, 100 ]
10199
		 *
10200
		 *  @dtopt Option
10201
		 *  @name DataTable.defaults.lengthMenu
10202
		 *
10203
		 *  @example
10204
		 *    $(document).ready( function() {
10205
		 *      $('#example').dataTable( {
10206
		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10207
		 *      } );
10208
		 *    } );
10209
		 */
10210
		"aLengthMenu": [ 10, 25, 50, 100 ],
10211
	
10212
	
10213
		/**
10214
		 * The `columns` option in the initialisation parameter allows you to define
10215
		 * details about the way individual columns behave. For a full list of
10216
		 * column options that can be set, please see
10217
		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10218
		 * define your columns, you must have an entry in the array for every single
10219
		 * column that you have in your table (these can be null if you don't which
10220
		 * to specify any options).
10221
		 *  @member
10222
		 *
10223
		 *  @name DataTable.defaults.column
10224
		 */
10225
		"aoColumns": null,
10226
	
10227
		/**
10228
		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10229
		 * column, multiple columns, or all columns, using the `targets` property of
10230
		 * each object in the array. This allows great flexibility when creating
10231
		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10232
		 * columns you specifically want. `columnDefs` may use any of the column
10233
		 * options available: {@link DataTable.defaults.column}, but it _must_
10234
		 * have `targets` defined in each object in the array. Values in the `targets`
10235
		 * array may be:
10236
		 *   <ul>
10237
		 *     <li>a string - class name will be matched on the TH for the column</li>
10238
		 *     <li>0 or a positive integer - column index counting from the left</li>
10239
		 *     <li>a negative integer - column index counting from the right</li>
10240
		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10241
		 *   </ul>
10242
		 *  @member
10243
		 *
10244
		 *  @name DataTable.defaults.columnDefs
10245
		 */
10246
		"aoColumnDefs": null,
10247
	
10248
	
10249
		/**
10250
		 * Basically the same as `search`, this parameter defines the individual column
10251
		 * filtering state at initialisation time. The array must be of the same size
10252
		 * as the number of columns, and each element be an object with the parameters
10253
		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10254
		 * accepted and the default will be used.
10255
		 *  @type array
10256
		 *  @default []
10257
		 *
10258
		 *  @dtopt Option
10259
		 *  @name DataTable.defaults.searchCols
10260
		 *
10261
		 *  @example
10262
		 *    $(document).ready( function() {
10263
		 *      $('#example').dataTable( {
10264
		 *        "searchCols": [
10265
		 *          null,
10266
		 *          { "search": "My filter" },
10267
		 *          null,
10268
		 *          { "search": "^[0-9]", "escapeRegex": false }
10269
		 *        ]
10270
		 *      } );
10271
		 *    } )
10272
		 */
10273
		"aoSearchCols": [],
10274
	
10275
	
10276
		/**
10277
		 * An array of CSS classes that should be applied to displayed rows. This
10278
		 * array may be of any length, and DataTables will apply each class
10279
		 * sequentially, looping when required.
10280
		 *  @type array
10281
		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10282
		 *    options</i>
10283
		 *
10284
		 *  @dtopt Option
10285
		 *  @name DataTable.defaults.stripeClasses
10286
		 *
10287
		 *  @example
10288
		 *    $(document).ready( function() {
10289
		 *      $('#example').dataTable( {
10290
		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10291
		 *      } );
10292
		 *    } )
10293
		 */
10294
		"asStripeClasses": null,
10295
	
10296
	
10297
		/**
10298
		 * Enable or disable automatic column width calculation. This can be disabled
10299
		 * as an optimisation (it takes some time to calculate the widths) if the
10300
		 * tables widths are passed in using `columns`.
10301
		 *  @type boolean
10302
		 *  @default true
10303
		 *
10304
		 *  @dtopt Features
10305
		 *  @name DataTable.defaults.autoWidth
10306
		 *
10307
		 *  @example
10308
		 *    $(document).ready( function () {
10309
		 *      $('#example').dataTable( {
10310
		 *        "autoWidth": false
10311
		 *      } );
10312
		 *    } );
10313
		 */
10314
		"bAutoWidth": true,
10315
	
10316
	
10317
		/**
10318
		 * Deferred rendering can provide DataTables with a huge speed boost when you
10319
		 * are using an Ajax or JS data source for the table. This option, when set to
10320
		 * true, will cause DataTables to defer the creation of the table elements for
10321
		 * each row until they are needed for a draw - saving a significant amount of
10322
		 * time.
10323
		 *  @type boolean
10324
		 *  @default false
10325
		 *
10326
		 *  @dtopt Features
10327
		 *  @name DataTable.defaults.deferRender
10328
		 *
10329
		 *  @example
10330
		 *    $(document).ready( function() {
10331
		 *      $('#example').dataTable( {
10332
		 *        "ajax": "sources/arrays.txt",
10333
		 *        "deferRender": true
10334
		 *      } );
10335
		 *    } );
10336
		 */
10337
		"bDeferRender": false,
10338
	
10339
	
10340
		/**
10341
		 * Replace a DataTable which matches the given selector and replace it with
10342
		 * one which has the properties of the new initialisation object passed. If no
10343
		 * table matches the selector, then the new DataTable will be constructed as
10344
		 * per normal.
10345
		 *  @type boolean
10346
		 *  @default false
10347
		 *
10348
		 *  @dtopt Options
10349
		 *  @name DataTable.defaults.destroy
10350
		 *
10351
		 *  @example
10352
		 *    $(document).ready( function() {
10353
		 *      $('#example').dataTable( {
10354
		 *        "srollY": "200px",
10355
		 *        "paginate": false
10356
		 *      } );
10357
		 *
10358
		 *      // Some time later....
10359
		 *      $('#example').dataTable( {
10360
		 *        "filter": false,
10361
		 *        "destroy": true
10362
		 *      } );
10363
		 *    } );
10364
		 */
10365
		"bDestroy": false,
10366
	
10367
	
10368
		/**
10369
		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10370
		 * that it allows the end user to input multiple words (space separated) and
10371
		 * will match a row containing those words, even if not in the order that was
10372
		 * specified (this allow matching across multiple columns). Note that if you
10373
		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10374
		 * default filtering input box and retain filtering abilities, please use
10375
		 * {@link DataTable.defaults.dom}.
10376
		 *  @type boolean
10377
		 *  @default true
10378
		 *
10379
		 *  @dtopt Features
10380
		 *  @name DataTable.defaults.searching
10381
		 *
10382
		 *  @example
10383
		 *    $(document).ready( function () {
10384
		 *      $('#example').dataTable( {
10385
		 *        "searching": false
10386
		 *      } );
10387
		 *    } );
10388
		 */
10389
		"bFilter": true,
10390
	
10391
	
10392
		/**
10393
		 * Enable or disable the table information display. This shows information
10394
		 * about the data that is currently visible on the page, including information
10395
		 * about filtered data if that action is being performed.
10396
		 *  @type boolean
10397
		 *  @default true
10398
		 *
10399
		 *  @dtopt Features
10400
		 *  @name DataTable.defaults.info
10401
		 *
10402
		 *  @example
10403
		 *    $(document).ready( function () {
10404
		 *      $('#example').dataTable( {
10405
		 *        "info": false
10406
		 *      } );
10407
		 *    } );
10408
		 */
10409
		"bInfo": true,
10410
	
10411
	
10412
		/**
10413
		 * Allows the end user to select the size of a formatted page from a select
10414
		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10415
		 *  @type boolean
10416
		 *  @default true
10417
		 *
10418
		 *  @dtopt Features
10419
		 *  @name DataTable.defaults.lengthChange
10420
		 *
10421
		 *  @example
10422
		 *    $(document).ready( function () {
10423
		 *      $('#example').dataTable( {
10424
		 *        "lengthChange": false
10425
		 *      } );
10426
		 *    } );
10427
		 */
10428
		"bLengthChange": true,
10429
	
10430
	
10431
		/**
10432
		 * Enable or disable pagination.
10433
		 *  @type boolean
10434
		 *  @default true
10435
		 *
10436
		 *  @dtopt Features
10437
		 *  @name DataTable.defaults.paging
10438
		 *
10439
		 *  @example
10440
		 *    $(document).ready( function () {
10441
		 *      $('#example').dataTable( {
10442
		 *        "paging": false
10443
		 *      } );
10444
		 *    } );
10445
		 */
10446
		"bPaginate": true,
10447
	
10448
	
10449
		/**
10450
		 * Enable or disable the display of a 'processing' indicator when the table is
10451
		 * being processed (e.g. a sort). This is particularly useful for tables with
10452
		 * large amounts of data where it can take a noticeable amount of time to sort
10453
		 * the entries.
10454
		 *  @type boolean
10455
		 *  @default false
10456
		 *
10457
		 *  @dtopt Features
10458
		 *  @name DataTable.defaults.processing
10459
		 *
10460
		 *  @example
10461
		 *    $(document).ready( function () {
10462
		 *      $('#example').dataTable( {
10463
		 *        "processing": true
10464
		 *      } );
10465
		 *    } );
10466
		 */
10467
		"bProcessing": false,
10468
	
10469
	
10470
		/**
10471
		 * Retrieve the DataTables object for the given selector. Note that if the
10472
		 * table has already been initialised, this parameter will cause DataTables
10473
		 * to simply return the object that has already been set up - it will not take
10474
		 * account of any changes you might have made to the initialisation object
10475
		 * passed to DataTables (setting this parameter to true is an acknowledgement
10476
		 * that you understand this). `destroy` can be used to reinitialise a table if
10477
		 * you need.
10478
		 *  @type boolean
10479
		 *  @default false
10480
		 *
10481
		 *  @dtopt Options
10482
		 *  @name DataTable.defaults.retrieve
10483
		 *
10484
		 *  @example
10485
		 *    $(document).ready( function() {
10486
		 *      initTable();
10487
		 *      tableActions();
10488
		 *    } );
10489
		 *
10490
		 *    function initTable ()
10491
		 *    {
10492
		 *      return $('#example').dataTable( {
10493
		 *        "scrollY": "200px",
10494
		 *        "paginate": false,
10495
		 *        "retrieve": true
10496
		 *      } );
10497
		 *    }
10498
		 *
10499
		 *    function tableActions ()
10500
		 *    {
10501
		 *      var table = initTable();
10502
		 *      // perform API operations with oTable
10503
		 *    }
10504
		 */
10505
		"bRetrieve": false,
10506
	
10507
	
10508
		/**
10509
		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10510
		 * the table's viewport to the given height at all times (useful for layout).
10511
		 * However, this can look odd when filtering data down to a small data set,
10512
		 * and the footer is left "floating" further down. This parameter (when
10513
		 * enabled) will cause DataTables to collapse the table's viewport down when
10514
		 * the result set will fit within the given Y height.
10515
		 *  @type boolean
10516
		 *  @default false
10517
		 *
10518
		 *  @dtopt Options
10519
		 *  @name DataTable.defaults.scrollCollapse
10520
		 *
10521
		 *  @example
10522
		 *    $(document).ready( function() {
10523
		 *      $('#example').dataTable( {
10524
		 *        "scrollY": "200",
10525
		 *        "scrollCollapse": true
10526
		 *      } );
10527
		 *    } );
10528
		 */
10529
		"bScrollCollapse": false,
10530
	
10531
	
10532
		/**
10533
		 * Configure DataTables to use server-side processing. Note that the
10534
		 * `ajax` parameter must also be given in order to give DataTables a
10535
		 * source to obtain the required data for each draw.
10536
		 *  @type boolean
10537
		 *  @default false
10538
		 *
10539
		 *  @dtopt Features
10540
		 *  @dtopt Server-side
10541
		 *  @name DataTable.defaults.serverSide
10542
		 *
10543
		 *  @example
10544
		 *    $(document).ready( function () {
10545
		 *      $('#example').dataTable( {
10546
		 *        "serverSide": true,
10547
		 *        "ajax": "xhr.php"
10548
		 *      } );
10549
		 *    } );
10550
		 */
10551
		"bServerSide": false,
10552
	
10553
	
10554
		/**
10555
		 * Enable or disable sorting of columns. Sorting of individual columns can be
10556
		 * disabled by the `sortable` option for each column.
10557
		 *  @type boolean
10558
		 *  @default true
10559
		 *
10560
		 *  @dtopt Features
10561
		 *  @name DataTable.defaults.ordering
10562
		 *
10563
		 *  @example
10564
		 *    $(document).ready( function () {
10565
		 *      $('#example').dataTable( {
10566
		 *        "ordering": false
10567
		 *      } );
10568
		 *    } );
10569
		 */
10570
		"bSort": true,
10571
	
10572
	
10573
		/**
10574
		 * Enable or display DataTables' ability to sort multiple columns at the
10575
		 * same time (activated by shift-click by the user).
10576
		 *  @type boolean
10577
		 *  @default true
10578
		 *
10579
		 *  @dtopt Options
10580
		 *  @name DataTable.defaults.orderMulti
10581
		 *
10582
		 *  @example
10583
		 *    // Disable multiple column sorting ability
10584
		 *    $(document).ready( function () {
10585
		 *      $('#example').dataTable( {
10586
		 *        "orderMulti": false
10587
		 *      } );
10588
		 *    } );
10589
		 */
10590
		"bSortMulti": true,
10591
	
10592
	
10593
		/**
10594
		 * Allows control over whether DataTables should use the top (true) unique
10595
		 * cell that is found for a single column, or the bottom (false - default).
10596
		 * This is useful when using complex headers.
10597
		 *  @type boolean
10598
		 *  @default false
10599
		 *
10600
		 *  @dtopt Options
10601
		 *  @name DataTable.defaults.orderCellsTop
10602
		 *
10603
		 *  @example
10604
		 *    $(document).ready( function() {
10605
		 *      $('#example').dataTable( {
10606
		 *        "orderCellsTop": true
10607
		 *      } );
10608
		 *    } );
10609
		 */
10610
		"bSortCellsTop": false,
10611
	
10612
	
10613
		/**
10614
		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10615
		 * `sorting\_3` to the columns which are currently being sorted on. This is
10616
		 * presented as a feature switch as it can increase processing time (while
10617
		 * classes are removed and added) so for large data sets you might want to
10618
		 * turn this off.
10619
		 *  @type boolean
10620
		 *  @default true
10621
		 *
10622
		 *  @dtopt Features
10623
		 *  @name DataTable.defaults.orderClasses
10624
		 *
10625
		 *  @example
10626
		 *    $(document).ready( function () {
10627
		 *      $('#example').dataTable( {
10628
		 *        "orderClasses": false
10629
		 *      } );
10630
		 *    } );
10631
		 */
10632
		"bSortClasses": true,
10633
	
10634
	
10635
		/**
10636
		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10637
		 * used to save table display information such as pagination information,
10638
		 * display length, filtering and sorting. As such when the end user reloads
10639
		 * the page the display display will match what thy had previously set up.
10640
		 *
10641
		 * Due to the use of `localStorage` the default state saving is not supported
10642
		 * in IE6 or 7. If state saving is required in those browsers, use
10643
		 * `stateSaveCallback` to provide a storage solution such as cookies.
10644
		 *  @type boolean
10645
		 *  @default false
10646
		 *
10647
		 *  @dtopt Features
10648
		 *  @name DataTable.defaults.stateSave
10649
		 *
10650
		 *  @example
10651
		 *    $(document).ready( function () {
10652
		 *      $('#example').dataTable( {
10653
		 *        "stateSave": true
10654
		 *      } );
10655
		 *    } );
10656
		 */
10657
		"bStateSave": false,
10658
	
10659
	
10660
		/**
10661
		 * This function is called when a TR element is created (and all TD child
10662
		 * elements have been inserted), or registered if using a DOM source, allowing
10663
		 * manipulation of the TR element (adding classes etc).
10664
		 *  @type function
10665
		 *  @param {node} row "TR" element for the current row
10666
		 *  @param {array} data Raw data array for this row
10667
		 *  @param {int} dataIndex The index of this row in the internal aoData array
10668
		 *
10669
		 *  @dtopt Callbacks
10670
		 *  @name DataTable.defaults.createdRow
10671
		 *
10672
		 *  @example
10673
		 *    $(document).ready( function() {
10674
		 *      $('#example').dataTable( {
10675
		 *        "createdRow": function( row, data, dataIndex ) {
10676
		 *          // Bold the grade for all 'A' grade browsers
10677
		 *          if ( data[4] == "A" )
10678
		 *          {
10679
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10680
		 *          }
10681
		 *        }
10682
		 *      } );
10683
		 *    } );
10684
		 */
10685
		"fnCreatedRow": null,
10686
	
10687
	
10688
		/**
10689
		 * This function is called on every 'draw' event, and allows you to
10690
		 * dynamically modify any aspect you want about the created DOM.
10691
		 *  @type function
10692
		 *  @param {object} settings DataTables settings object
10693
		 *
10694
		 *  @dtopt Callbacks
10695
		 *  @name DataTable.defaults.drawCallback
10696
		 *
10697
		 *  @example
10698
		 *    $(document).ready( function() {
10699
		 *      $('#example').dataTable( {
10700
		 *        "drawCallback": function( settings ) {
10701
		 *          alert( 'DataTables has redrawn the table' );
10702
		 *        }
10703
		 *      } );
10704
		 *    } );
10705
		 */
10706
		"fnDrawCallback": null,
10707
	
10708
	
10709
		/**
10710
		 * Identical to fnHeaderCallback() but for the table footer this function
10711
		 * allows you to modify the table footer on every 'draw' event.
10712
		 *  @type function
10713
		 *  @param {node} foot "TR" element for the footer
10714
		 *  @param {array} data Full table data (as derived from the original HTML)
10715
		 *  @param {int} start Index for the current display starting point in the
10716
		 *    display array
10717
		 *  @param {int} end Index for the current display ending point in the
10718
		 *    display array
10719
		 *  @param {array int} display Index array to translate the visual position
10720
		 *    to the full data array
10721
		 *
10722
		 *  @dtopt Callbacks
10723
		 *  @name DataTable.defaults.footerCallback
10724
		 *
10725
		 *  @example
10726
		 *    $(document).ready( function() {
10727
		 *      $('#example').dataTable( {
10728
		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10729
		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10730
		 *        }
10731
		 *      } );
10732
		 *    } )
10733
		 */
10734
		"fnFooterCallback": null,
10735
	
10736
	
10737
		/**
10738
		 * When rendering large numbers in the information element for the table
10739
		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10740
		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10741
		 * rendered as "1,000,000") to help readability for the end user. This
10742
		 * function will override the default method DataTables uses.
10743
		 *  @type function
10744
		 *  @member
10745
		 *  @param {int} toFormat number to be formatted
10746
		 *  @returns {string} formatted string for DataTables to show the number
10747
		 *
10748
		 *  @dtopt Callbacks
10749
		 *  @name DataTable.defaults.formatNumber
10750
		 *
10751
		 *  @example
10752
		 *    // Format a number using a single quote for the separator (note that
10753
		 *    // this can also be done with the language.thousands option)
10754
		 *    $(document).ready( function() {
10755
		 *      $('#example').dataTable( {
10756
		 *        "formatNumber": function ( toFormat ) {
10757
		 *          return toFormat.toString().replace(
10758
		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10759
		 *          );
10760
		 *        };
10761
		 *      } );
10762
		 *    } );
10763
		 */
10764
		"fnFormatNumber": function ( toFormat ) {
10765
			return toFormat.toString().replace(
10766
				/\B(?=(\d{3})+(?!\d))/g,
10767
				this.oLanguage.sThousands
10768
			);
10769
		},
10770
	
10771
	
10772
		/**
10773
		 * This function is called on every 'draw' event, and allows you to
10774
		 * dynamically modify the header row. This can be used to calculate and
10775
		 * display useful information about the table.
10776
		 *  @type function
10777
		 *  @param {node} head "TR" element for the header
10778
		 *  @param {array} data Full table data (as derived from the original HTML)
10779
		 *  @param {int} start Index for the current display starting point in the
10780
		 *    display array
10781
		 *  @param {int} end Index for the current display ending point in the
10782
		 *    display array
10783
		 *  @param {array int} display Index array to translate the visual position
10784
		 *    to the full data array
10785
		 *
10786
		 *  @dtopt Callbacks
10787
		 *  @name DataTable.defaults.headerCallback
10788
		 *
10789
		 *  @example
10790
		 *    $(document).ready( function() {
10791
		 *      $('#example').dataTable( {
10792
		 *        "fheaderCallback": function( head, data, start, end, display ) {
10793
		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10794
		 *        }
10795
		 *      } );
10796
		 *    } )
10797
		 */
10798
		"fnHeaderCallback": null,
10799
	
10800
	
10801
		/**
10802
		 * The information element can be used to convey information about the current
10803
		 * state of the table. Although the internationalisation options presented by
10804
		 * DataTables are quite capable of dealing with most customisations, there may
10805
		 * be times where you wish to customise the string further. This callback
10806
		 * allows you to do exactly that.
10807
		 *  @type function
10808
		 *  @param {object} oSettings DataTables settings object
10809
		 *  @param {int} start Starting position in data for the draw
10810
		 *  @param {int} end End position in data for the draw
10811
		 *  @param {int} max Total number of rows in the table (regardless of
10812
		 *    filtering)
10813
		 *  @param {int} total Total number of rows in the data set, after filtering
10814
		 *  @param {string} pre The string that DataTables has formatted using it's
10815
		 *    own rules
10816
		 *  @returns {string} The string to be displayed in the information element.
10817
		 *
10818
		 *  @dtopt Callbacks
10819
		 *  @name DataTable.defaults.infoCallback
10820
		 *
10821
		 *  @example
10822
		 *    $('#example').dataTable( {
10823
		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10824
		 *        return start +" to "+ end;
10825
		 *      }
10826
		 *    } );
10827
		 */
10828
		"fnInfoCallback": null,
10829
	
10830
	
10831
		/**
10832
		 * Called when the table has been initialised. Normally DataTables will
10833
		 * initialise sequentially and there will be no need for this function,
10834
		 * however, this does not hold true when using external language information
10835
		 * since that is obtained using an async XHR call.
10836
		 *  @type function
10837
		 *  @param {object} settings DataTables settings object
10838
		 *  @param {object} json The JSON object request from the server - only
10839
		 *    present if client-side Ajax sourced data is used
10840
		 *
10841
		 *  @dtopt Callbacks
10842
		 *  @name DataTable.defaults.initComplete
10843
		 *
10844
		 *  @example
10845
		 *    $(document).ready( function() {
10846
		 *      $('#example').dataTable( {
10847
		 *        "initComplete": function(settings, json) {
10848
		 *          alert( 'DataTables has finished its initialisation.' );
10849
		 *        }
10850
		 *      } );
10851
		 *    } )
10852
		 */
10853
		"fnInitComplete": null,
10854
	
10855
	
10856
		/**
10857
		 * Called at the very start of each table draw and can be used to cancel the
10858
		 * draw by returning false, any other return (including undefined) results in
10859
		 * the full draw occurring).
10860
		 *  @type function
10861
		 *  @param {object} settings DataTables settings object
10862
		 *  @returns {boolean} False will cancel the draw, anything else (including no
10863
		 *    return) will allow it to complete.
10864
		 *
10865
		 *  @dtopt Callbacks
10866
		 *  @name DataTable.defaults.preDrawCallback
10867
		 *
10868
		 *  @example
10869
		 *    $(document).ready( function() {
10870
		 *      $('#example').dataTable( {
10871
		 *        "preDrawCallback": function( settings ) {
10872
		 *          if ( $('#test').val() == 1 ) {
10873
		 *            return false;
10874
		 *          }
10875
		 *        }
10876
		 *      } );
10877
		 *    } );
10878
		 */
10879
		"fnPreDrawCallback": null,
10880
	
10881
	
10882
		/**
10883
		 * This function allows you to 'post process' each row after it have been
10884
		 * generated for each table draw, but before it is rendered on screen. This
10885
		 * function might be used for setting the row class name etc.
10886
		 *  @type function
10887
		 *  @param {node} row "TR" element for the current row
10888
		 *  @param {array} data Raw data array for this row
10889
		 *  @param {int} displayIndex The display index for the current table draw
10890
		 *  @param {int} displayIndexFull The index of the data in the full list of
10891
		 *    rows (after filtering)
10892
		 *
10893
		 *  @dtopt Callbacks
10894
		 *  @name DataTable.defaults.rowCallback
10895
		 *
10896
		 *  @example
10897
		 *    $(document).ready( function() {
10898
		 *      $('#example').dataTable( {
10899
		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10900
		 *          // Bold the grade for all 'A' grade browsers
10901
		 *          if ( data[4] == "A" ) {
10902
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10903
		 *          }
10904
		 *        }
10905
		 *      } );
10906
		 *    } );
10907
		 */
10908
		"fnRowCallback": null,
10909
	
10910
	
10911
		/**
10912
		 * __Deprecated__ The functionality provided by this parameter has now been
10913
		 * superseded by that provided through `ajax`, which should be used instead.
10914
		 *
10915
		 * This parameter allows you to override the default function which obtains
10916
		 * the data from the server so something more suitable for your application.
10917
		 * For example you could use POST data, or pull information from a Gears or
10918
		 * AIR database.
10919
		 *  @type function
10920
		 *  @member
10921
		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10922
		 *  @param {array} data A key/value pair object containing the data to send
10923
		 *    to the server
10924
		 *  @param {function} callback to be called on completion of the data get
10925
		 *    process that will draw the data on the page.
10926
		 *  @param {object} settings DataTables settings object
10927
		 *
10928
		 *  @dtopt Callbacks
10929
		 *  @dtopt Server-side
10930
		 *  @name DataTable.defaults.serverData
10931
		 *
10932
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10933
		 */
10934
		"fnServerData": null,
10935
	
10936
	
10937
		/**
10938
		 * __Deprecated__ The functionality provided by this parameter has now been
10939
		 * superseded by that provided through `ajax`, which should be used instead.
10940
		 *
10941
		 *  It is often useful to send extra data to the server when making an Ajax
10942
		 * request - for example custom filtering information, and this callback
10943
		 * function makes it trivial to send extra information to the server. The
10944
		 * passed in parameter is the data set that has been constructed by
10945
		 * DataTables, and you can add to this or modify it as you require.
10946
		 *  @type function
10947
		 *  @param {array} data Data array (array of objects which are name/value
10948
		 *    pairs) that has been constructed by DataTables and will be sent to the
10949
		 *    server. In the case of Ajax sourced data with server-side processing
10950
		 *    this will be an empty array, for server-side processing there will be a
10951
		 *    significant number of parameters!
10952
		 *  @returns {undefined} Ensure that you modify the data array passed in,
10953
		 *    as this is passed by reference.
10954
		 *
10955
		 *  @dtopt Callbacks
10956
		 *  @dtopt Server-side
10957
		 *  @name DataTable.defaults.serverParams
10958
		 *
10959
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10960
		 */
10961
		"fnServerParams": null,
10962
	
10963
	
10964
		/**
10965
		 * Load the table state. With this function you can define from where, and how, the
10966
		 * state of a table is loaded. By default DataTables will load from `localStorage`
10967
		 * but you might wish to use a server-side database or cookies.
10968
		 *  @type function
10969
		 *  @member
10970
		 *  @param {object} settings DataTables settings object
10971
		 *  @param {object} callback Callback that can be executed when done. It
10972
		 *    should be passed the loaded state object.
10973
		 *  @return {object} The DataTables state object to be loaded
10974
		 *
10975
		 *  @dtopt Callbacks
10976
		 *  @name DataTable.defaults.stateLoadCallback
10977
		 *
10978
		 *  @example
10979
		 *    $(document).ready( function() {
10980
		 *      $('#example').dataTable( {
10981
		 *        "stateSave": true,
10982
		 *        "stateLoadCallback": function (settings, callback) {
10983
		 *          $.ajax( {
10984
		 *            "url": "/state_load",
10985
		 *            "dataType": "json",
10986
		 *            "success": function (json) {
10987
		 *              callback( json );
10988
		 *            }
10989
		 *          } );
10990
		 *        }
10991
		 *      } );
10992
		 *    } );
10993
		 */
10994
		"fnStateLoadCallback": function ( settings ) {
10995
			try {
10996
				return JSON.parse(
10997
					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10998
						'DataTables_'+settings.sInstance+'_'+location.pathname
10999
					)
11000
				);
11001
			} catch (e) {}
11002
		},
11003
	
11004
	
11005
		/**
11006
		 * Callback which allows modification of the saved state prior to loading that state.
11007
		 * This callback is called when the table is loading state from the stored data, but
11008
		 * prior to the settings object being modified by the saved state. Note that for
11009
		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11010
		 * a plug-in.
11011
		 *  @type function
11012
		 *  @param {object} settings DataTables settings object
11013
		 *  @param {object} data The state object that is to be loaded
11014
		 *
11015
		 *  @dtopt Callbacks
11016
		 *  @name DataTable.defaults.stateLoadParams
11017
		 *
11018
		 *  @example
11019
		 *    // Remove a saved filter, so filtering is never loaded
11020
		 *    $(document).ready( function() {
11021
		 *      $('#example').dataTable( {
11022
		 *        "stateSave": true,
11023
		 *        "stateLoadParams": function (settings, data) {
11024
		 *          data.oSearch.sSearch = "";
11025
		 *        }
11026
		 *      } );
11027
		 *    } );
11028
		 *
11029
		 *  @example
11030
		 *    // Disallow state loading by returning false
11031
		 *    $(document).ready( function() {
11032
		 *      $('#example').dataTable( {
11033
		 *        "stateSave": true,
11034
		 *        "stateLoadParams": function (settings, data) {
11035
		 *          return false;
11036
		 *        }
11037
		 *      } );
11038
		 *    } );
11039
		 */
11040
		"fnStateLoadParams": null,
11041
	
11042
	
11043
		/**
11044
		 * Callback that is called when the state has been loaded from the state saving method
11045
		 * and the DataTables settings object has been modified as a result of the loaded state.
11046
		 *  @type function
11047
		 *  @param {object} settings DataTables settings object
11048
		 *  @param {object} data The state object that was loaded
11049
		 *
11050
		 *  @dtopt Callbacks
11051
		 *  @name DataTable.defaults.stateLoaded
11052
		 *
11053
		 *  @example
11054
		 *    // Show an alert with the filtering value that was saved
11055
		 *    $(document).ready( function() {
11056
		 *      $('#example').dataTable( {
11057
		 *        "stateSave": true,
11058
		 *        "stateLoaded": function (settings, data) {
11059
		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11060
		 *        }
11061
		 *      } );
11062
		 *    } );
11063
		 */
11064
		"fnStateLoaded": null,
11065
	
11066
	
11067
		/**
11068
		 * Save the table state. This function allows you to define where and how the state
11069
		 * information for the table is stored By default DataTables will use `localStorage`
11070
		 * but you might wish to use a server-side database or cookies.
11071
		 *  @type function
11072
		 *  @member
11073
		 *  @param {object} settings DataTables settings object
11074
		 *  @param {object} data The state object to be saved
11075
		 *
11076
		 *  @dtopt Callbacks
11077
		 *  @name DataTable.defaults.stateSaveCallback
11078
		 *
11079
		 *  @example
11080
		 *    $(document).ready( function() {
11081
		 *      $('#example').dataTable( {
11082
		 *        "stateSave": true,
11083
		 *        "stateSaveCallback": function (settings, data) {
11084
		 *          // Send an Ajax request to the server with the state object
11085
		 *          $.ajax( {
11086
		 *            "url": "/state_save",
11087
		 *            "data": data,
11088
		 *            "dataType": "json",
11089
		 *            "method": "POST"
11090
		 *            "success": function () {}
11091
		 *          } );
11092
		 *        }
11093
		 *      } );
11094
		 *    } );
11095
		 */
11096
		"fnStateSaveCallback": function ( settings, data ) {
11097
			try {
11098
				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11099
					'DataTables_'+settings.sInstance+'_'+location.pathname,
11100
					JSON.stringify( data )
11101
				);
11102
			} catch (e) {}
11103
		},
11104
	
11105
	
11106
		/**
11107
		 * Callback which allows modification of the state to be saved. Called when the table
11108
		 * has changed state a new state save is required. This method allows modification of
11109
		 * the state saving object prior to actually doing the save, including addition or
11110
		 * other state properties or modification. Note that for plug-in authors, you should
11111
		 * use the `stateSaveParams` event to save parameters for a plug-in.
11112
		 *  @type function
11113
		 *  @param {object} settings DataTables settings object
11114
		 *  @param {object} data The state object to be saved
11115
		 *
11116
		 *  @dtopt Callbacks
11117
		 *  @name DataTable.defaults.stateSaveParams
11118
		 *
11119
		 *  @example
11120
		 *    // Remove a saved filter, so filtering is never saved
11121
		 *    $(document).ready( function() {
11122
		 *      $('#example').dataTable( {
11123
		 *        "stateSave": true,
11124
		 *        "stateSaveParams": function (settings, data) {
11125
		 *          data.oSearch.sSearch = "";
11126
		 *        }
11127
		 *      } );
11128
		 *    } );
11129
		 */
11130
		"fnStateSaveParams": null,
11131
	
11132
	
11133
		/**
11134
		 * Duration for which the saved state information is considered valid. After this period
11135
		 * has elapsed the state will be returned to the default.
11136
		 * Value is given in seconds.
11137
		 *  @type int
11138
		 *  @default 7200 <i>(2 hours)</i>
11139
		 *
11140
		 *  @dtopt Options
11141
		 *  @name DataTable.defaults.stateDuration
11142
		 *
11143
		 *  @example
11144
		 *    $(document).ready( function() {
11145
		 *      $('#example').dataTable( {
11146
		 *        "stateDuration": 60*60*24; // 1 day
11147
		 *      } );
11148
		 *    } )
11149
		 */
11150
		"iStateDuration": 7200,
11151
	
11152
	
11153
		/**
11154
		 * When enabled DataTables will not make a request to the server for the first
11155
		 * page draw - rather it will use the data already on the page (no sorting etc
11156
		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11157
		 * is used to indicate that deferred loading is required, but it is also used
11158
		 * to tell DataTables how many records there are in the full table (allowing
11159
		 * the information element and pagination to be displayed correctly). In the case
11160
		 * where a filtering is applied to the table on initial load, this can be
11161
		 * indicated by giving the parameter as an array, where the first element is
11162
		 * the number of records available after filtering and the second element is the
11163
		 * number of records without filtering (allowing the table information element
11164
		 * to be shown correctly).
11165
		 *  @type int | array
11166
		 *  @default null
11167
		 *
11168
		 *  @dtopt Options
11169
		 *  @name DataTable.defaults.deferLoading
11170
		 *
11171
		 *  @example
11172
		 *    // 57 records available in the table, no filtering applied
11173
		 *    $(document).ready( function() {
11174
		 *      $('#example').dataTable( {
11175
		 *        "serverSide": true,
11176
		 *        "ajax": "scripts/server_processing.php",
11177
		 *        "deferLoading": 57
11178
		 *      } );
11179
		 *    } );
11180
		 *
11181
		 *  @example
11182
		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11183
		 *    $(document).ready( function() {
11184
		 *      $('#example').dataTable( {
11185
		 *        "serverSide": true,
11186
		 *        "ajax": "scripts/server_processing.php",
11187
		 *        "deferLoading": [ 57, 100 ],
11188
		 *        "search": {
11189
		 *          "search": "my_filter"
11190
		 *        }
11191
		 *      } );
11192
		 *    } );
11193
		 */
11194
		"iDeferLoading": null,
11195
	
11196
	
11197
		/**
11198
		 * Number of rows to display on a single page when using pagination. If
11199
		 * feature enabled (`lengthChange`) then the end user will be able to override
11200
		 * this to a custom setting using a pop-up menu.
11201
		 *  @type int
11202
		 *  @default 10
11203
		 *
11204
		 *  @dtopt Options
11205
		 *  @name DataTable.defaults.pageLength
11206
		 *
11207
		 *  @example
11208
		 *    $(document).ready( function() {
11209
		 *      $('#example').dataTable( {
11210
		 *        "pageLength": 50
11211
		 *      } );
11212
		 *    } )
11213
		 */
11214
		"iDisplayLength": 10,
11215
	
11216
	
11217
		/**
11218
		 * Define the starting point for data display when using DataTables with
11219
		 * pagination. Note that this parameter is the number of records, rather than
11220
		 * the page number, so if you have 10 records per page and want to start on
11221
		 * the third page, it should be "20".
11222
		 *  @type int
11223
		 *  @default 0
11224
		 *
11225
		 *  @dtopt Options
11226
		 *  @name DataTable.defaults.displayStart
11227
		 *
11228
		 *  @example
11229
		 *    $(document).ready( function() {
11230
		 *      $('#example').dataTable( {
11231
		 *        "displayStart": 20
11232
		 *      } );
11233
		 *    } )
11234
		 */
11235
		"iDisplayStart": 0,
11236
	
11237
	
11238
		/**
11239
		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11240
		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11241
		 * allows you to tab through the controls and press the enter key to activate them.
11242
		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11243
		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11244
		 * disable built-in keyboard navigation.
11245
		 *  @type int
11246
		 *  @default 0
11247
		 *
11248
		 *  @dtopt Options
11249
		 *  @name DataTable.defaults.tabIndex
11250
		 *
11251
		 *  @example
11252
		 *    $(document).ready( function() {
11253
		 *      $('#example').dataTable( {
11254
		 *        "tabIndex": 1
11255
		 *      } );
11256
		 *    } );
11257
		 */
11258
		"iTabIndex": 0,
11259
	
11260
	
11261
		/**
11262
		 * Classes that DataTables assigns to the various components and features
11263
		 * that it adds to the HTML table. This allows classes to be configured
11264
		 * during initialisation in addition to through the static
11265
		 * {@link DataTable.ext.oStdClasses} object).
11266
		 *  @namespace
11267
		 *  @name DataTable.defaults.classes
11268
		 */
11269
		"oClasses": {},
11270
	
11271
	
11272
		/**
11273
		 * All strings that DataTables uses in the user interface that it creates
11274
		 * are defined in this object, allowing you to modified them individually or
11275
		 * completely replace them all as required.
11276
		 *  @namespace
11277
		 *  @name DataTable.defaults.language
11278
		 */
11279
		"oLanguage": {
11280
			/**
11281
			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11282
			 * actually visible on the page, but will be read by screenreaders, and thus
11283
			 * must be internationalised as well).
11284
			 *  @namespace
11285
			 *  @name DataTable.defaults.language.aria
11286
			 */
11287
			"oAria": {
11288
				/**
11289
				 * ARIA label that is added to the table headers when the column may be
11290
				 * sorted ascending by activing the column (click or return when focused).
11291
				 * Note that the column header is prefixed to this string.
11292
				 *  @type string
11293
				 *  @default : activate to sort column ascending
11294
				 *
11295
				 *  @dtopt Language
11296
				 *  @name DataTable.defaults.language.aria.sortAscending
11297
				 *
11298
				 *  @example
11299
				 *    $(document).ready( function() {
11300
				 *      $('#example').dataTable( {
11301
				 *        "language": {
11302
				 *          "aria": {
11303
				 *            "sortAscending": " - click/return to sort ascending"
11304
				 *          }
11305
				 *        }
11306
				 *      } );
11307
				 *    } );
11308
				 */
11309
				"sSortAscending": ": activate to sort column ascending",
11310
	
11311
				/**
11312
				 * ARIA label that is added to the table headers when the column may be
11313
				 * sorted descending by activing the column (click or return when focused).
11314
				 * Note that the column header is prefixed to this string.
11315
				 *  @type string
11316
				 *  @default : activate to sort column ascending
11317
				 *
11318
				 *  @dtopt Language
11319
				 *  @name DataTable.defaults.language.aria.sortDescending
11320
				 *
11321
				 *  @example
11322
				 *    $(document).ready( function() {
11323
				 *      $('#example').dataTable( {
11324
				 *        "language": {
11325
				 *          "aria": {
11326
				 *            "sortDescending": " - click/return to sort descending"
11327
				 *          }
11328
				 *        }
11329
				 *      } );
11330
				 *    } );
11331
				 */
11332
				"sSortDescending": ": activate to sort column descending"
11333
			},
11334
	
11335
			/**
11336
			 * Pagination string used by DataTables for the built-in pagination
11337
			 * control types.
11338
			 *  @namespace
11339
			 *  @name DataTable.defaults.language.paginate
11340
			 */
11341
			"oPaginate": {
11342
				/**
11343
				 * Text to use when using the 'full_numbers' type of pagination for the
11344
				 * button to take the user to the first page.
11345
				 *  @type string
11346
				 *  @default First
11347
				 *
11348
				 *  @dtopt Language
11349
				 *  @name DataTable.defaults.language.paginate.first
11350
				 *
11351
				 *  @example
11352
				 *    $(document).ready( function() {
11353
				 *      $('#example').dataTable( {
11354
				 *        "language": {
11355
				 *          "paginate": {
11356
				 *            "first": "First page"
11357
				 *          }
11358
				 *        }
11359
				 *      } );
11360
				 *    } );
11361
				 */
11362
				"sFirst": "First",
11363
	
11364
	
11365
				/**
11366
				 * Text to use when using the 'full_numbers' type of pagination for the
11367
				 * button to take the user to the last page.
11368
				 *  @type string
11369
				 *  @default Last
11370
				 *
11371
				 *  @dtopt Language
11372
				 *  @name DataTable.defaults.language.paginate.last
11373
				 *
11374
				 *  @example
11375
				 *    $(document).ready( function() {
11376
				 *      $('#example').dataTable( {
11377
				 *        "language": {
11378
				 *          "paginate": {
11379
				 *            "last": "Last page"
11380
				 *          }
11381
				 *        }
11382
				 *      } );
11383
				 *    } );
11384
				 */
11385
				"sLast": "Last",
11386
	
11387
	
11388
				/**
11389
				 * Text to use for the 'next' pagination button (to take the user to the
11390
				 * next page).
11391
				 *  @type string
11392
				 *  @default Next
11393
				 *
11394
				 *  @dtopt Language
11395
				 *  @name DataTable.defaults.language.paginate.next
11396
				 *
11397
				 *  @example
11398
				 *    $(document).ready( function() {
11399
				 *      $('#example').dataTable( {
11400
				 *        "language": {
11401
				 *          "paginate": {
11402
				 *            "next": "Next page"
11403
				 *          }
11404
				 *        }
11405
				 *      } );
11406
				 *    } );
11407
				 */
11408
				"sNext": "Next",
11409
	
11410
	
11411
				/**
11412
				 * Text to use for the 'previous' pagination button (to take the user to
11413
				 * the previous page).
11414
				 *  @type string
11415
				 *  @default Previous
11416
				 *
11417
				 *  @dtopt Language
11418
				 *  @name DataTable.defaults.language.paginate.previous
11419
				 *
11420
				 *  @example
11421
				 *    $(document).ready( function() {
11422
				 *      $('#example').dataTable( {
11423
				 *        "language": {
11424
				 *          "paginate": {
11425
				 *            "previous": "Previous page"
11426
				 *          }
11427
				 *        }
11428
				 *      } );
11429
				 *    } );
11430
				 */
11431
				"sPrevious": "Previous"
11432
			},
11433
	
11434
			/**
11435
			 * This string is shown in preference to `zeroRecords` when the table is
11436
			 * empty of data (regardless of filtering). Note that this is an optional
11437
			 * parameter - if it is not given, the value of `zeroRecords` will be used
11438
			 * instead (either the default or given value).
11439
			 *  @type string
11440
			 *  @default No data available in table
11441
			 *
11442
			 *  @dtopt Language
11443
			 *  @name DataTable.defaults.language.emptyTable
11444
			 *
11445
			 *  @example
11446
			 *    $(document).ready( function() {
11447
			 *      $('#example').dataTable( {
11448
			 *        "language": {
11449
			 *          "emptyTable": "No data available in table"
11450
			 *        }
11451
			 *      } );
11452
			 *    } );
11453
			 */
11454
			"sEmptyTable": "No data available in table",
11455
	
11456
	
11457
			/**
11458
			 * This string gives information to the end user about the information
11459
			 * that is current on display on the page. The following tokens can be
11460
			 * used in the string and will be dynamically replaced as the table
11461
			 * display updates. This tokens can be placed anywhere in the string, or
11462
			 * removed as needed by the language requires:
11463
			 *
11464
			 * * `\_START\_` - Display index of the first record on the current page
11465
			 * * `\_END\_` - Display index of the last record on the current page
11466
			 * * `\_TOTAL\_` - Number of records in the table after filtering
11467
			 * * `\_MAX\_` - Number of records in the table without filtering
11468
			 * * `\_PAGE\_` - Current page number
11469
			 * * `\_PAGES\_` - Total number of pages of data in the table
11470
			 *
11471
			 *  @type string
11472
			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11473
			 *
11474
			 *  @dtopt Language
11475
			 *  @name DataTable.defaults.language.info
11476
			 *
11477
			 *  @example
11478
			 *    $(document).ready( function() {
11479
			 *      $('#example').dataTable( {
11480
			 *        "language": {
11481
			 *          "info": "Showing page _PAGE_ of _PAGES_"
11482
			 *        }
11483
			 *      } );
11484
			 *    } );
11485
			 */
11486
			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11487
	
11488
	
11489
			/**
11490
			 * Display information string for when the table is empty. Typically the
11491
			 * format of this string should match `info`.
11492
			 *  @type string
11493
			 *  @default Showing 0 to 0 of 0 entries
11494
			 *
11495
			 *  @dtopt Language
11496
			 *  @name DataTable.defaults.language.infoEmpty
11497
			 *
11498
			 *  @example
11499
			 *    $(document).ready( function() {
11500
			 *      $('#example').dataTable( {
11501
			 *        "language": {
11502
			 *          "infoEmpty": "No entries to show"
11503
			 *        }
11504
			 *      } );
11505
			 *    } );
11506
			 */
11507
			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11508
	
11509
	
11510
			/**
11511
			 * When a user filters the information in a table, this string is appended
11512
			 * to the information (`info`) to give an idea of how strong the filtering
11513
			 * is. The variable _MAX_ is dynamically updated.
11514
			 *  @type string
11515
			 *  @default (filtered from _MAX_ total entries)
11516
			 *
11517
			 *  @dtopt Language
11518
			 *  @name DataTable.defaults.language.infoFiltered
11519
			 *
11520
			 *  @example
11521
			 *    $(document).ready( function() {
11522
			 *      $('#example').dataTable( {
11523
			 *        "language": {
11524
			 *          "infoFiltered": " - filtering from _MAX_ records"
11525
			 *        }
11526
			 *      } );
11527
			 *    } );
11528
			 */
11529
			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11530
	
11531
	
11532
			/**
11533
			 * If can be useful to append extra information to the info string at times,
11534
			 * and this variable does exactly that. This information will be appended to
11535
			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11536
			 * being used) at all times.
11537
			 *  @type string
11538
			 *  @default <i>Empty string</i>
11539
			 *
11540
			 *  @dtopt Language
11541
			 *  @name DataTable.defaults.language.infoPostFix
11542
			 *
11543
			 *  @example
11544
			 *    $(document).ready( function() {
11545
			 *      $('#example').dataTable( {
11546
			 *        "language": {
11547
			 *          "infoPostFix": "All records shown are derived from real information."
11548
			 *        }
11549
			 *      } );
11550
			 *    } );
11551
			 */
11552
			"sInfoPostFix": "",
11553
	
11554
	
11555
			/**
11556
			 * This decimal place operator is a little different from the other
11557
			 * language options since DataTables doesn't output floating point
11558
			 * numbers, so it won't ever use this for display of a number. Rather,
11559
			 * what this parameter does is modify the sort methods of the table so
11560
			 * that numbers which are in a format which has a character other than
11561
			 * a period (`.`) as a decimal place will be sorted numerically.
11562
			 *
11563
			 * Note that numbers with different decimal places cannot be shown in
11564
			 * the same table and still be sortable, the table must be consistent.
11565
			 * However, multiple different tables on the page can use different
11566
			 * decimal place characters.
11567
			 *  @type string
11568
			 *  @default 
11569
			 *
11570
			 *  @dtopt Language
11571
			 *  @name DataTable.defaults.language.decimal
11572
			 *
11573
			 *  @example
11574
			 *    $(document).ready( function() {
11575
			 *      $('#example').dataTable( {
11576
			 *        "language": {
11577
			 *          "decimal": ","
11578
			 *          "thousands": "."
11579
			 *        }
11580
			 *      } );
11581
			 *    } );
11582
			 */
11583
			"sDecimal": "",
11584
	
11585
	
11586
			/**
11587
			 * DataTables has a build in number formatter (`formatNumber`) which is
11588
			 * used to format large numbers that are used in the table information.
11589
			 * By default a comma is used, but this can be trivially changed to any
11590
			 * character you wish with this parameter.
11591
			 *  @type string
11592
			 *  @default ,
11593
			 *
11594
			 *  @dtopt Language
11595
			 *  @name DataTable.defaults.language.thousands
11596
			 *
11597
			 *  @example
11598
			 *    $(document).ready( function() {
11599
			 *      $('#example').dataTable( {
11600
			 *        "language": {
11601
			 *          "thousands": "'"
11602
			 *        }
11603
			 *      } );
11604
			 *    } );
11605
			 */
11606
			"sThousands": ",",
11607
	
11608
	
11609
			/**
11610
			 * Detail the action that will be taken when the drop down menu for the
11611
			 * pagination length option is changed. The '_MENU_' variable is replaced
11612
			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11613
			 * with a custom select box if required.
11614
			 *  @type string
11615
			 *  @default Show _MENU_ entries
11616
			 *
11617
			 *  @dtopt Language
11618
			 *  @name DataTable.defaults.language.lengthMenu
11619
			 *
11620
			 *  @example
11621
			 *    // Language change only
11622
			 *    $(document).ready( function() {
11623
			 *      $('#example').dataTable( {
11624
			 *        "language": {
11625
			 *          "lengthMenu": "Display _MENU_ records"
11626
			 *        }
11627
			 *      } );
11628
			 *    } );
11629
			 *
11630
			 *  @example
11631
			 *    // Language and options change
11632
			 *    $(document).ready( function() {
11633
			 *      $('#example').dataTable( {
11634
			 *        "language": {
11635
			 *          "lengthMenu": 'Display <select>'+
11636
			 *            '<option value="10">10</option>'+
11637
			 *            '<option value="20">20</option>'+
11638
			 *            '<option value="30">30</option>'+
11639
			 *            '<option value="40">40</option>'+
11640
			 *            '<option value="50">50</option>'+
11641
			 *            '<option value="-1">All</option>'+
11642
			 *            '</select> records'
11643
			 *        }
11644
			 *      } );
11645
			 *    } );
11646
			 */
11647
			"sLengthMenu": "Show _MENU_ entries",
11648
	
11649
	
11650
			/**
11651
			 * When using Ajax sourced data and during the first draw when DataTables is
11652
			 * gathering the data, this message is shown in an empty row in the table to
11653
			 * indicate to the end user the the data is being loaded. Note that this
11654
			 * parameter is not used when loading data by server-side processing, just
11655
			 * Ajax sourced data with client-side processing.
11656
			 *  @type string
11657
			 *  @default Loading...
11658
			 *
11659
			 *  @dtopt Language
11660
			 *  @name DataTable.defaults.language.loadingRecords
11661
			 *
11662
			 *  @example
11663
			 *    $(document).ready( function() {
11664
			 *      $('#example').dataTable( {
11665
			 *        "language": {
11666
			 *          "loadingRecords": "Please wait - loading..."
11667
			 *        }
11668
			 *      } );
11669
			 *    } );
11670
			 */
11671
			"sLoadingRecords": "Loading...",
11672
	
11673
	
11674
			/**
11675
			 * Text which is displayed when the table is processing a user action
11676
			 * (usually a sort command or similar).
11677
			 *  @type string
11678
			 *  @default Processing...
11679
			 *
11680
			 *  @dtopt Language
11681
			 *  @name DataTable.defaults.language.processing
11682
			 *
11683
			 *  @example
11684
			 *    $(document).ready( function() {
11685
			 *      $('#example').dataTable( {
11686
			 *        "language": {
11687
			 *          "processing": "DataTables is currently busy"
11688
			 *        }
11689
			 *      } );
11690
			 *    } );
11691
			 */
11692
			"sProcessing": "Processing...",
11693
	
11694
	
11695
			/**
11696
			 * Details the actions that will be taken when the user types into the
11697
			 * filtering input text box. The variable "_INPUT_", if used in the string,
11698
			 * is replaced with the HTML text box for the filtering input allowing
11699
			 * control over where it appears in the string. If "_INPUT_" is not given
11700
			 * then the input box is appended to the string automatically.
11701
			 *  @type string
11702
			 *  @default Search:
11703
			 *
11704
			 *  @dtopt Language
11705
			 *  @name DataTable.defaults.language.search
11706
			 *
11707
			 *  @example
11708
			 *    // Input text box will be appended at the end automatically
11709
			 *    $(document).ready( function() {
11710
			 *      $('#example').dataTable( {
11711
			 *        "language": {
11712
			 *          "search": "Filter records:"
11713
			 *        }
11714
			 *      } );
11715
			 *    } );
11716
			 *
11717
			 *  @example
11718
			 *    // Specify where the filter should appear
11719
			 *    $(document).ready( function() {
11720
			 *      $('#example').dataTable( {
11721
			 *        "language": {
11722
			 *          "search": "Apply filter _INPUT_ to table"
11723
			 *        }
11724
			 *      } );
11725
			 *    } );
11726
			 */
11727
			"sSearch": "Search:",
11728
	
11729
	
11730
			/**
11731
			 * Assign a `placeholder` attribute to the search `input` element
11732
			 *  @type string
11733
			 *  @default 
11734
			 *
11735
			 *  @dtopt Language
11736
			 *  @name DataTable.defaults.language.searchPlaceholder
11737
			 */
11738
			"sSearchPlaceholder": "",
11739
	
11740
	
11741
			/**
11742
			 * All of the language information can be stored in a file on the
11743
			 * server-side, which DataTables will look up if this parameter is passed.
11744
			 * It must store the URL of the language file, which is in a JSON format,
11745
			 * and the object has the same properties as the oLanguage object in the
11746
			 * initialiser object (i.e. the above parameters). Please refer to one of
11747
			 * the example language files to see how this works in action.
11748
			 *  @type string
11749
			 *  @default <i>Empty string - i.e. disabled</i>
11750
			 *
11751
			 *  @dtopt Language
11752
			 *  @name DataTable.defaults.language.url
11753
			 *
11754
			 *  @example
11755
			 *    $(document).ready( function() {
11756
			 *      $('#example').dataTable( {
11757
			 *        "language": {
11758
			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11759
			 *        }
11760
			 *      } );
11761
			 *    } );
11762
			 */
11763
			"sUrl": "",
11764
	
11765
	
11766
			/**
11767
			 * Text shown inside the table records when the is no information to be
11768
			 * displayed after filtering. `emptyTable` is shown when there is simply no
11769
			 * information in the table at all (regardless of filtering).
11770
			 *  @type string
11771
			 *  @default No matching records found
11772
			 *
11773
			 *  @dtopt Language
11774
			 *  @name DataTable.defaults.language.zeroRecords
11775
			 *
11776
			 *  @example
11777
			 *    $(document).ready( function() {
11778
			 *      $('#example').dataTable( {
11779
			 *        "language": {
11780
			 *          "zeroRecords": "No records to display"
11781
			 *        }
11782
			 *      } );
11783
			 *    } );
11784
			 */
11785
			"sZeroRecords": "No matching records found"
11786
		},
11787
	
11788
	
11789
		/**
11790
		 * This parameter allows you to have define the global filtering state at
11791
		 * initialisation time. As an object the `search` parameter must be
11792
		 * defined, but all other parameters are optional. When `regex` is true,
11793
		 * the search string will be treated as a regular expression, when false
11794
		 * (default) it will be treated as a straight string. When `smart`
11795
		 * DataTables will use it's smart filtering methods (to word match at
11796
		 * any point in the data), when false this will not be done.
11797
		 *  @namespace
11798
		 *  @extends DataTable.models.oSearch
11799
		 *
11800
		 *  @dtopt Options
11801
		 *  @name DataTable.defaults.search
11802
		 *
11803
		 *  @example
11804
		 *    $(document).ready( function() {
11805
		 *      $('#example').dataTable( {
11806
		 *        "search": {"search": "Initial search"}
11807
		 *      } );
11808
		 *    } )
11809
		 */
11810
		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11811
	
11812
	
11813
		/**
11814
		 * __Deprecated__ The functionality provided by this parameter has now been
11815
		 * superseded by that provided through `ajax`, which should be used instead.
11816
		 *
11817
		 * By default DataTables will look for the property `data` (or `aaData` for
11818
		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11819
		 * source or for server-side processing - this parameter allows that
11820
		 * property to be changed. You can use Javascript dotted object notation to
11821
		 * get a data source for multiple levels of nesting.
11822
		 *  @type string
11823
		 *  @default data
11824
		 *
11825
		 *  @dtopt Options
11826
		 *  @dtopt Server-side
11827
		 *  @name DataTable.defaults.ajaxDataProp
11828
		 *
11829
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11830
		 */
11831
		"sAjaxDataProp": "data",
11832
	
11833
	
11834
		/**
11835
		 * __Deprecated__ The functionality provided by this parameter has now been
11836
		 * superseded by that provided through `ajax`, which should be used instead.
11837
		 *
11838
		 * You can instruct DataTables to load data from an external
11839
		 * source using this parameter (use aData if you want to pass data in you
11840
		 * already have). Simply provide a url a JSON object can be obtained from.
11841
		 *  @type string
11842
		 *  @default null
11843
		 *
11844
		 *  @dtopt Options
11845
		 *  @dtopt Server-side
11846
		 *  @name DataTable.defaults.ajaxSource
11847
		 *
11848
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11849
		 */
11850
		"sAjaxSource": null,
11851
	
11852
	
11853
		/**
11854
		 * This initialisation variable allows you to specify exactly where in the
11855
		 * DOM you want DataTables to inject the various controls it adds to the page
11856
		 * (for example you might want the pagination controls at the top of the
11857
		 * table). DIV elements (with or without a custom class) can also be added to
11858
		 * aid styling. The follow syntax is used:
11859
		 *   <ul>
11860
		 *     <li>The following options are allowed:
11861
		 *       <ul>
11862
		 *         <li>'l' - Length changing</li>
11863
		 *         <li>'f' - Filtering input</li>
11864
		 *         <li>'t' - The table!</li>
11865
		 *         <li>'i' - Information</li>
11866
		 *         <li>'p' - Pagination</li>
11867
		 *         <li>'r' - pRocessing</li>
11868
		 *       </ul>
11869
		 *     </li>
11870
		 *     <li>The following constants are allowed:
11871
		 *       <ul>
11872
		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11873
		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11874
		 *       </ul>
11875
		 *     </li>
11876
		 *     <li>The following syntax is expected:
11877
		 *       <ul>
11878
		 *         <li>'&lt;' and '&gt;' - div elements</li>
11879
		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11880
		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11881
		 *       </ul>
11882
		 *     </li>
11883
		 *     <li>Examples:
11884
		 *       <ul>
11885
		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11886
		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11887
		 *       </ul>
11888
		 *     </li>
11889
		 *   </ul>
11890
		 *  @type string
11891
		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11892
		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11893
		 *
11894
		 *  @dtopt Options
11895
		 *  @name DataTable.defaults.dom
11896
		 *
11897
		 *  @example
11898
		 *    $(document).ready( function() {
11899
		 *      $('#example').dataTable( {
11900
		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11901
		 *      } );
11902
		 *    } );
11903
		 */
11904
		"sDom": "lfrtip",
11905
	
11906
	
11907
		/**
11908
		 * Search delay option. This will throttle full table searches that use the
11909
		 * DataTables provided search input element (it does not effect calls to
11910
		 * `dt-api search()`, providing a delay before the search is made.
11911
		 *  @type integer
11912
		 *  @default 0
11913
		 *
11914
		 *  @dtopt Options
11915
		 *  @name DataTable.defaults.searchDelay
11916
		 *
11917
		 *  @example
11918
		 *    $(document).ready( function() {
11919
		 *      $('#example').dataTable( {
11920
		 *        "searchDelay": 200
11921
		 *      } );
11922
		 *    } )
11923
		 */
11924
		"searchDelay": null,
11925
	
11926
	
11927
		/**
11928
		 * DataTables features six different built-in options for the buttons to
11929
		 * display for pagination control:
11930
		 *
11931
		 * * `numbers` - Page number buttons only
11932
		 * * `simple` - 'Previous' and 'Next' buttons only
11933
		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11934
		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11935
		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11936
		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11937
		 *  
11938
		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11939
		 *  @type string
11940
		 *  @default simple_numbers
11941
		 *
11942
		 *  @dtopt Options
11943
		 *  @name DataTable.defaults.pagingType
11944
		 *
11945
		 *  @example
11946
		 *    $(document).ready( function() {
11947
		 *      $('#example').dataTable( {
11948
		 *        "pagingType": "full_numbers"
11949
		 *      } );
11950
		 *    } )
11951
		 */
11952
		"sPaginationType": "simple_numbers",
11953
	
11954
	
11955
		/**
11956
		 * Enable horizontal scrolling. When a table is too wide to fit into a
11957
		 * certain layout, or you have a large number of columns in the table, you
11958
		 * can enable x-scrolling to show the table in a viewport, which can be
11959
		 * scrolled. This property can be `true` which will allow the table to
11960
		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11961
		 * case it will be treated as a pixel measurement). Setting as simply `true`
11962
		 * is recommended.
11963
		 *  @type boolean|string
11964
		 *  @default <i>blank string - i.e. disabled</i>
11965
		 *
11966
		 *  @dtopt Features
11967
		 *  @name DataTable.defaults.scrollX
11968
		 *
11969
		 *  @example
11970
		 *    $(document).ready( function() {
11971
		 *      $('#example').dataTable( {
11972
		 *        "scrollX": true,
11973
		 *        "scrollCollapse": true
11974
		 *      } );
11975
		 *    } );
11976
		 */
11977
		"sScrollX": "",
11978
	
11979
	
11980
		/**
11981
		 * This property can be used to force a DataTable to use more width than it
11982
		 * might otherwise do when x-scrolling is enabled. For example if you have a
11983
		 * table which requires to be well spaced, this parameter is useful for
11984
		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11985
		 * any CSS unit, or a number (in which case it will be treated as a pixel
11986
		 * measurement).
11987
		 *  @type string
11988
		 *  @default <i>blank string - i.e. disabled</i>
11989
		 *
11990
		 *  @dtopt Options
11991
		 *  @name DataTable.defaults.scrollXInner
11992
		 *
11993
		 *  @example
11994
		 *    $(document).ready( function() {
11995
		 *      $('#example').dataTable( {
11996
		 *        "scrollX": "100%",
11997
		 *        "scrollXInner": "110%"
11998
		 *      } );
11999
		 *    } );
12000
		 */
12001
		"sScrollXInner": "",
12002
	
12003
	
12004
		/**
12005
		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12006
		 * to the given height, and enable scrolling for any data which overflows the
12007
		 * current viewport. This can be used as an alternative to paging to display
12008
		 * a lot of data in a small area (although paging and scrolling can both be
12009
		 * enabled at the same time). This property can be any CSS unit, or a number
12010
		 * (in which case it will be treated as a pixel measurement).
12011
		 *  @type string
12012
		 *  @default <i>blank string - i.e. disabled</i>
12013
		 *
12014
		 *  @dtopt Features
12015
		 *  @name DataTable.defaults.scrollY
12016
		 *
12017
		 *  @example
12018
		 *    $(document).ready( function() {
12019
		 *      $('#example').dataTable( {
12020
		 *        "scrollY": "200px",
12021
		 *        "paginate": false
12022
		 *      } );
12023
		 *    } );
12024
		 */
12025
		"sScrollY": "",
12026
	
12027
	
12028
		/**
12029
		 * __Deprecated__ The functionality provided by this parameter has now been
12030
		 * superseded by that provided through `ajax`, which should be used instead.
12031
		 *
12032
		 * Set the HTTP method that is used to make the Ajax call for server-side
12033
		 * processing or Ajax sourced data.
12034
		 *  @type string
12035
		 *  @default GET
12036
		 *
12037
		 *  @dtopt Options
12038
		 *  @dtopt Server-side
12039
		 *  @name DataTable.defaults.serverMethod
12040
		 *
12041
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12042
		 */
12043
		"sServerMethod": "GET",
12044
	
12045
	
12046
		/**
12047
		 * DataTables makes use of renderers when displaying HTML elements for
12048
		 * a table. These renderers can be added or modified by plug-ins to
12049
		 * generate suitable mark-up for a site. For example the Bootstrap
12050
		 * integration plug-in for DataTables uses a paging button renderer to
12051
		 * display pagination buttons in the mark-up required by Bootstrap.
12052
		 *
12053
		 * For further information about the renderers available see
12054
		 * DataTable.ext.renderer
12055
		 *  @type string|object
12056
		 *  @default null
12057
		 *
12058
		 *  @name DataTable.defaults.renderer
12059
		 *
12060
		 */
12061
		"renderer": null,
12062
	
12063
	
12064
		/**
12065
		 * Set the data property name that DataTables should use to get a row's id
12066
		 * to set as the `id` property in the node.
12067
		 *  @type string
12068
		 *  @default DT_RowId
12069
		 *
12070
		 *  @name DataTable.defaults.rowId
12071
		 */
12072
		"rowId": "DT_RowId"
12073
	};
12074
	
12075
	_fnHungarianMap( DataTable.defaults );
12076
	
12077
	
12078
	
12079
	/*
12080
	 * Developer note - See note in model.defaults.js about the use of Hungarian
12081
	 * notation and camel case.
12082
	 */
12083
	
12084
	/**
12085
	 * Column options that can be given to DataTables at initialisation time.
12086
	 *  @namespace
12087
	 */
12088
	DataTable.defaults.column = {
12089
		/**
12090
		 * Define which column(s) an order will occur on for this column. This
12091
		 * allows a column's ordering to take multiple columns into account when
12092
		 * doing a sort or use the data from a different column. For example first
12093
		 * name / last name columns make sense to do a multi-column sort over the
12094
		 * two columns.
12095
		 *  @type array|int
12096
		 *  @default null <i>Takes the value of the column index automatically</i>
12097
		 *
12098
		 *  @name DataTable.defaults.column.orderData
12099
		 *  @dtopt Columns
12100
		 *
12101
		 *  @example
12102
		 *    // Using `columnDefs`
12103
		 *    $(document).ready( function() {
12104
		 *      $('#example').dataTable( {
12105
		 *        "columnDefs": [
12106
		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12107
		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12108
		 *          { "orderData": 2, "targets": [ 2 ] }
12109
		 *        ]
12110
		 *      } );
12111
		 *    } );
12112
		 *
12113
		 *  @example
12114
		 *    // Using `columns`
12115
		 *    $(document).ready( function() {
12116
		 *      $('#example').dataTable( {
12117
		 *        "columns": [
12118
		 *          { "orderData": [ 0, 1 ] },
12119
		 *          { "orderData": [ 1, 0 ] },
12120
		 *          { "orderData": 2 },
12121
		 *          null,
12122
		 *          null
12123
		 *        ]
12124
		 *      } );
12125
		 *    } );
12126
		 */
12127
		"aDataSort": null,
12128
		"iDataSort": -1,
12129
	
12130
	
12131
		/**
12132
		 * You can control the default ordering direction, and even alter the
12133
		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12134
		 * using this parameter.
12135
		 *  @type array
12136
		 *  @default [ 'asc', 'desc' ]
12137
		 *
12138
		 *  @name DataTable.defaults.column.orderSequence
12139
		 *  @dtopt Columns
12140
		 *
12141
		 *  @example
12142
		 *    // Using `columnDefs`
12143
		 *    $(document).ready( function() {
12144
		 *      $('#example').dataTable( {
12145
		 *        "columnDefs": [
12146
		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12147
		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12148
		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12149
		 *        ]
12150
		 *      } );
12151
		 *    } );
12152
		 *
12153
		 *  @example
12154
		 *    // Using `columns`
12155
		 *    $(document).ready( function() {
12156
		 *      $('#example').dataTable( {
12157
		 *        "columns": [
12158
		 *          null,
12159
		 *          { "orderSequence": [ "asc" ] },
12160
		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12161
		 *          { "orderSequence": [ "desc" ] },
12162
		 *          null
12163
		 *        ]
12164
		 *      } );
12165
		 *    } );
12166
		 */
12167
		"asSorting": [ 'asc', 'desc' ],
12168
	
12169
	
12170
		/**
12171
		 * Enable or disable filtering on the data in this column.
12172
		 *  @type boolean
12173
		 *  @default true
12174
		 *
12175
		 *  @name DataTable.defaults.column.searchable
12176
		 *  @dtopt Columns
12177
		 *
12178
		 *  @example
12179
		 *    // Using `columnDefs`
12180
		 *    $(document).ready( function() {
12181
		 *      $('#example').dataTable( {
12182
		 *        "columnDefs": [
12183
		 *          { "searchable": false, "targets": [ 0 ] }
12184
		 *        ] } );
12185
		 *    } );
12186
		 *
12187
		 *  @example
12188
		 *    // Using `columns`
12189
		 *    $(document).ready( function() {
12190
		 *      $('#example').dataTable( {
12191
		 *        "columns": [
12192
		 *          { "searchable": false },
12193
		 *          null,
12194
		 *          null,
12195
		 *          null,
12196
		 *          null
12197
		 *        ] } );
12198
		 *    } );
12199
		 */
12200
		"bSearchable": true,
12201
	
12202
	
12203
		/**
12204
		 * Enable or disable ordering on this column.
12205
		 *  @type boolean
12206
		 *  @default true
12207
		 *
12208
		 *  @name DataTable.defaults.column.orderable
12209
		 *  @dtopt Columns
12210
		 *
12211
		 *  @example
12212
		 *    // Using `columnDefs`
12213
		 *    $(document).ready( function() {
12214
		 *      $('#example').dataTable( {
12215
		 *        "columnDefs": [
12216
		 *          { "orderable": false, "targets": [ 0 ] }
12217
		 *        ] } );
12218
		 *    } );
12219
		 *
12220
		 *  @example
12221
		 *    // Using `columns`
12222
		 *    $(document).ready( function() {
12223
		 *      $('#example').dataTable( {
12224
		 *        "columns": [
12225
		 *          { "orderable": false },
12226
		 *          null,
12227
		 *          null,
12228
		 *          null,
12229
		 *          null
12230
		 *        ] } );
12231
		 *    } );
12232
		 */
12233
		"bSortable": true,
12234
	
12235
	
12236
		/**
12237
		 * Enable or disable the display of this column.
12238
		 *  @type boolean
12239
		 *  @default true
12240
		 *
12241
		 *  @name DataTable.defaults.column.visible
12242
		 *  @dtopt Columns
12243
		 *
12244
		 *  @example
12245
		 *    // Using `columnDefs`
12246
		 *    $(document).ready( function() {
12247
		 *      $('#example').dataTable( {
12248
		 *        "columnDefs": [
12249
		 *          { "visible": false, "targets": [ 0 ] }
12250
		 *        ] } );
12251
		 *    } );
12252
		 *
12253
		 *  @example
12254
		 *    // Using `columns`
12255
		 *    $(document).ready( function() {
12256
		 *      $('#example').dataTable( {
12257
		 *        "columns": [
12258
		 *          { "visible": false },
12259
		 *          null,
12260
		 *          null,
12261
		 *          null,
12262
		 *          null
12263
		 *        ] } );
12264
		 *    } );
12265
		 */
12266
		"bVisible": true,
12267
	
12268
	
12269
		/**
12270
		 * Developer definable function that is called whenever a cell is created (Ajax source,
12271
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12272
		 * allowing you to modify the DOM element (add background colour for example) when the
12273
		 * element is available.
12274
		 *  @type function
12275
		 *  @param {element} td The TD node that has been created
12276
		 *  @param {*} cellData The Data for the cell
12277
		 *  @param {array|object} rowData The data for the whole row
12278
		 *  @param {int} row The row index for the aoData data store
12279
		 *  @param {int} col The column index for aoColumns
12280
		 *
12281
		 *  @name DataTable.defaults.column.createdCell
12282
		 *  @dtopt Columns
12283
		 *
12284
		 *  @example
12285
		 *    $(document).ready( function() {
12286
		 *      $('#example').dataTable( {
12287
		 *        "columnDefs": [ {
12288
		 *          "targets": [3],
12289
		 *          "createdCell": function (td, cellData, rowData, row, col) {
12290
		 *            if ( cellData == "1.7" ) {
12291
		 *              $(td).css('color', 'blue')
12292
		 *            }
12293
		 *          }
12294
		 *        } ]
12295
		 *      });
12296
		 *    } );
12297
		 */
12298
		"fnCreatedCell": null,
12299
	
12300
	
12301
		/**
12302
		 * This parameter has been replaced by `data` in DataTables to ensure naming
12303
		 * consistency. `dataProp` can still be used, as there is backwards
12304
		 * compatibility in DataTables for this option, but it is strongly
12305
		 * recommended that you use `data` in preference to `dataProp`.
12306
		 *  @name DataTable.defaults.column.dataProp
12307
		 */
12308
	
12309
	
12310
		/**
12311
		 * This property can be used to read data from any data source property,
12312
		 * including deeply nested objects / properties. `data` can be given in a
12313
		 * number of different ways which effect its behaviour:
12314
		 *
12315
		 * * `integer` - treated as an array index for the data source. This is the
12316
		 *   default that DataTables uses (incrementally increased for each column).
12317
		 * * `string` - read an object property from the data source. There are
12318
		 *   three 'special' options that can be used in the string to alter how
12319
		 *   DataTables reads the data from the source object:
12320
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12321
		 *      Javascript to read from nested objects, so to can the options
12322
		 *      specified in `data`. For example: `browser.version` or
12323
		 *      `browser.name`. If your object parameter name contains a period, use
12324
		 *      `\\` to escape it - i.e. `first\\.name`.
12325
		 *    * `[]` - Array notation. DataTables can automatically combine data
12326
		 *      from and array source, joining the data with the characters provided
12327
		 *      between the two brackets. For example: `name[, ]` would provide a
12328
		 *      comma-space separated list from the source array. If no characters
12329
		 *      are provided between the brackets, the original array source is
12330
		 *      returned.
12331
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12332
		 *      execute a function of the name given. For example: `browser()` for a
12333
		 *      simple function on the data source, `browser.version()` for a
12334
		 *      function in a nested property or even `browser().version` to get an
12335
		 *      object property if the function called returns an object. Note that
12336
		 *      function notation is recommended for use in `render` rather than
12337
		 *      `data` as it is much simpler to use as a renderer.
12338
		 * * `null` - use the original data source for the row rather than plucking
12339
		 *   data directly from it. This action has effects on two other
12340
		 *   initialisation options:
12341
		 *    * `defaultContent` - When null is given as the `data` option and
12342
		 *      `defaultContent` is specified for the column, the value defined by
12343
		 *      `defaultContent` will be used for the cell.
12344
		 *    * `render` - When null is used for the `data` option and the `render`
12345
		 *      option is specified for the column, the whole data source for the
12346
		 *      row is used for the renderer.
12347
		 * * `function` - the function given will be executed whenever DataTables
12348
		 *   needs to set or get the data for a cell in the column. The function
12349
		 *   takes three parameters:
12350
		 *    * Parameters:
12351
		 *      * `{array|object}` The data source for the row
12352
		 *      * `{string}` The type call data requested - this will be 'set' when
12353
		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12354
		 *        when gathering data. Note that when `undefined` is given for the
12355
		 *        type DataTables expects to get the raw data for the object back<
12356
		 *      * `{*}` Data to set when the second parameter is 'set'.
12357
		 *    * Return:
12358
		 *      * The return value from the function is not required when 'set' is
12359
		 *        the type of call, but otherwise the return is what will be used
12360
		 *        for the data requested.
12361
		 *
12362
		 * Note that `data` is a getter and setter option. If you just require
12363
		 * formatting of data for output, you will likely want to use `render` which
12364
		 * is simply a getter and thus simpler to use.
12365
		 *
12366
		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12367
		 * name change reflects the flexibility of this property and is consistent
12368
		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12369
		 * be used by DataTables, as it automatically maps the old name to the new
12370
		 * if required.
12371
		 *
12372
		 *  @type string|int|function|null
12373
		 *  @default null <i>Use automatically calculated column index</i>
12374
		 *
12375
		 *  @name DataTable.defaults.column.data
12376
		 *  @dtopt Columns
12377
		 *
12378
		 *  @example
12379
		 *    // Read table data from objects
12380
		 *    // JSON structure for each row:
12381
		 *    //   {
12382
		 *    //      "engine": {value},
12383
		 *    //      "browser": {value},
12384
		 *    //      "platform": {value},
12385
		 *    //      "version": {value},
12386
		 *    //      "grade": {value}
12387
		 *    //   }
12388
		 *    $(document).ready( function() {
12389
		 *      $('#example').dataTable( {
12390
		 *        "ajaxSource": "sources/objects.txt",
12391
		 *        "columns": [
12392
		 *          { "data": "engine" },
12393
		 *          { "data": "browser" },
12394
		 *          { "data": "platform" },
12395
		 *          { "data": "version" },
12396
		 *          { "data": "grade" }
12397
		 *        ]
12398
		 *      } );
12399
		 *    } );
12400
		 *
12401
		 *  @example
12402
		 *    // Read information from deeply nested objects
12403
		 *    // JSON structure for each row:
12404
		 *    //   {
12405
		 *    //      "engine": {value},
12406
		 *    //      "browser": {value},
12407
		 *    //      "platform": {
12408
		 *    //         "inner": {value}
12409
		 *    //      },
12410
		 *    //      "details": [
12411
		 *    //         {value}, {value}
12412
		 *    //      ]
12413
		 *    //   }
12414
		 *    $(document).ready( function() {
12415
		 *      $('#example').dataTable( {
12416
		 *        "ajaxSource": "sources/deep.txt",
12417
		 *        "columns": [
12418
		 *          { "data": "engine" },
12419
		 *          { "data": "browser" },
12420
		 *          { "data": "platform.inner" },
12421
		 *          { "data": "details.0" },
12422
		 *          { "data": "details.1" }
12423
		 *        ]
12424
		 *      } );
12425
		 *    } );
12426
		 *
12427
		 *  @example
12428
		 *    // Using `data` as a function to provide different information for
12429
		 *    // sorting, filtering and display. In this case, currency (price)
12430
		 *    $(document).ready( function() {
12431
		 *      $('#example').dataTable( {
12432
		 *        "columnDefs": [ {
12433
		 *          "targets": [ 0 ],
12434
		 *          "data": function ( source, type, val ) {
12435
		 *            if (type === 'set') {
12436
		 *              source.price = val;
12437
		 *              // Store the computed dislay and filter values for efficiency
12438
		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12439
		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12440
		 *              return;
12441
		 *            }
12442
		 *            else if (type === 'display') {
12443
		 *              return source.price_display;
12444
		 *            }
12445
		 *            else if (type === 'filter') {
12446
		 *              return source.price_filter;
12447
		 *            }
12448
		 *            // 'sort', 'type' and undefined all just use the integer
12449
		 *            return source.price;
12450
		 *          }
12451
		 *        } ]
12452
		 *      } );
12453
		 *    } );
12454
		 *
12455
		 *  @example
12456
		 *    // Using default content
12457
		 *    $(document).ready( function() {
12458
		 *      $('#example').dataTable( {
12459
		 *        "columnDefs": [ {
12460
		 *          "targets": [ 0 ],
12461
		 *          "data": null,
12462
		 *          "defaultContent": "Click to edit"
12463
		 *        } ]
12464
		 *      } );
12465
		 *    } );
12466
		 *
12467
		 *  @example
12468
		 *    // Using array notation - outputting a list from an array
12469
		 *    $(document).ready( function() {
12470
		 *      $('#example').dataTable( {
12471
		 *        "columnDefs": [ {
12472
		 *          "targets": [ 0 ],
12473
		 *          "data": "name[, ]"
12474
		 *        } ]
12475
		 *      } );
12476
		 *    } );
12477
		 *
12478
		 */
12479
		"mData": null,
12480
	
12481
	
12482
		/**
12483
		 * This property is the rendering partner to `data` and it is suggested that
12484
		 * when you want to manipulate data for display (including filtering,
12485
		 * sorting etc) without altering the underlying data for the table, use this
12486
		 * property. `render` can be considered to be the the read only companion to
12487
		 * `data` which is read / write (then as such more complex). Like `data`
12488
		 * this option can be given in a number of different ways to effect its
12489
		 * behaviour:
12490
		 *
12491
		 * * `integer` - treated as an array index for the data source. This is the
12492
		 *   default that DataTables uses (incrementally increased for each column).
12493
		 * * `string` - read an object property from the data source. There are
12494
		 *   three 'special' options that can be used in the string to alter how
12495
		 *   DataTables reads the data from the source object:
12496
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12497
		 *      Javascript to read from nested objects, so to can the options
12498
		 *      specified in `data`. For example: `browser.version` or
12499
		 *      `browser.name`. If your object parameter name contains a period, use
12500
		 *      `\\` to escape it - i.e. `first\\.name`.
12501
		 *    * `[]` - Array notation. DataTables can automatically combine data
12502
		 *      from and array source, joining the data with the characters provided
12503
		 *      between the two brackets. For example: `name[, ]` would provide a
12504
		 *      comma-space separated list from the source array. If no characters
12505
		 *      are provided between the brackets, the original array source is
12506
		 *      returned.
12507
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12508
		 *      execute a function of the name given. For example: `browser()` for a
12509
		 *      simple function on the data source, `browser.version()` for a
12510
		 *      function in a nested property or even `browser().version` to get an
12511
		 *      object property if the function called returns an object.
12512
		 * * `object` - use different data for the different data types requested by
12513
		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12514
		 *   of the object is the data type the property refers to and the value can
12515
		 *   defined using an integer, string or function using the same rules as
12516
		 *   `render` normally does. Note that an `_` option _must_ be specified.
12517
		 *   This is the default value to use if you haven't specified a value for
12518
		 *   the data type requested by DataTables.
12519
		 * * `function` - the function given will be executed whenever DataTables
12520
		 *   needs to set or get the data for a cell in the column. The function
12521
		 *   takes three parameters:
12522
		 *    * Parameters:
12523
		 *      * {array|object} The data source for the row (based on `data`)
12524
		 *      * {string} The type call data requested - this will be 'filter',
12525
		 *        'display', 'type' or 'sort'.
12526
		 *      * {array|object} The full data source for the row (not based on
12527
		 *        `data`)
12528
		 *    * Return:
12529
		 *      * The return value from the function is what will be used for the
12530
		 *        data requested.
12531
		 *
12532
		 *  @type string|int|function|object|null
12533
		 *  @default null Use the data source value.
12534
		 *
12535
		 *  @name DataTable.defaults.column.render
12536
		 *  @dtopt Columns
12537
		 *
12538
		 *  @example
12539
		 *    // Create a comma separated list from an array of objects
12540
		 *    $(document).ready( function() {
12541
		 *      $('#example').dataTable( {
12542
		 *        "ajaxSource": "sources/deep.txt",
12543
		 *        "columns": [
12544
		 *          { "data": "engine" },
12545
		 *          { "data": "browser" },
12546
		 *          {
12547
		 *            "data": "platform",
12548
		 *            "render": "[, ].name"
12549
		 *          }
12550
		 *        ]
12551
		 *      } );
12552
		 *    } );
12553
		 *
12554
		 *  @example
12555
		 *    // Execute a function to obtain data
12556
		 *    $(document).ready( function() {
12557
		 *      $('#example').dataTable( {
12558
		 *        "columnDefs": [ {
12559
		 *          "targets": [ 0 ],
12560
		 *          "data": null, // Use the full data source object for the renderer's source
12561
		 *          "render": "browserName()"
12562
		 *        } ]
12563
		 *      } );
12564
		 *    } );
12565
		 *
12566
		 *  @example
12567
		 *    // As an object, extracting different data for the different types
12568
		 *    // This would be used with a data source such as:
12569
		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12570
		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12571
		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12572
		 *    // the formatted phone number is the one that is shown in the table.
12573
		 *    $(document).ready( function() {
12574
		 *      $('#example').dataTable( {
12575
		 *        "columnDefs": [ {
12576
		 *          "targets": [ 0 ],
12577
		 *          "data": null, // Use the full data source object for the renderer's source
12578
		 *          "render": {
12579
		 *            "_": "phone",
12580
		 *            "filter": "phone_filter",
12581
		 *            "display": "phone_display"
12582
		 *          }
12583
		 *        } ]
12584
		 *      } );
12585
		 *    } );
12586
		 *
12587
		 *  @example
12588
		 *    // Use as a function to create a link from the data source
12589
		 *    $(document).ready( function() {
12590
		 *      $('#example').dataTable( {
12591
		 *        "columnDefs": [ {
12592
		 *          "targets": [ 0 ],
12593
		 *          "data": "download_link",
12594
		 *          "render": function ( data, type, full ) {
12595
		 *            return '<a href="'+data+'">Download</a>';
12596
		 *          }
12597
		 *        } ]
12598
		 *      } );
12599
		 *    } );
12600
		 */
12601
		"mRender": null,
12602
	
12603
	
12604
		/**
12605
		 * Change the cell type created for the column - either TD cells or TH cells. This
12606
		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12607
		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12608
		 *  @type string
12609
		 *  @default td
12610
		 *
12611
		 *  @name DataTable.defaults.column.cellType
12612
		 *  @dtopt Columns
12613
		 *
12614
		 *  @example
12615
		 *    // Make the first column use TH cells
12616
		 *    $(document).ready( function() {
12617
		 *      $('#example').dataTable( {
12618
		 *        "columnDefs": [ {
12619
		 *          "targets": [ 0 ],
12620
		 *          "cellType": "th"
12621
		 *        } ]
12622
		 *      } );
12623
		 *    } );
12624
		 */
12625
		"sCellType": "td",
12626
	
12627
	
12628
		/**
12629
		 * Class to give to each cell in this column.
12630
		 *  @type string
12631
		 *  @default <i>Empty string</i>
12632
		 *
12633
		 *  @name DataTable.defaults.column.class
12634
		 *  @dtopt Columns
12635
		 *
12636
		 *  @example
12637
		 *    // Using `columnDefs`
12638
		 *    $(document).ready( function() {
12639
		 *      $('#example').dataTable( {
12640
		 *        "columnDefs": [
12641
		 *          { "class": "my_class", "targets": [ 0 ] }
12642
		 *        ]
12643
		 *      } );
12644
		 *    } );
12645
		 *
12646
		 *  @example
12647
		 *    // Using `columns`
12648
		 *    $(document).ready( function() {
12649
		 *      $('#example').dataTable( {
12650
		 *        "columns": [
12651
		 *          { "class": "my_class" },
12652
		 *          null,
12653
		 *          null,
12654
		 *          null,
12655
		 *          null
12656
		 *        ]
12657
		 *      } );
12658
		 *    } );
12659
		 */
12660
		"sClass": "",
12661
	
12662
		/**
12663
		 * When DataTables calculates the column widths to assign to each column,
12664
		 * it finds the longest string in each column and then constructs a
12665
		 * temporary table and reads the widths from that. The problem with this
12666
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12667
		 * string - thus the calculation can go wrong (doing it properly and putting
12668
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12669
		 * a "work around" we provide this option. It will append its value to the
12670
		 * text that is found to be the longest string for the column - i.e. padding.
12671
		 * Generally you shouldn't need this!
12672
		 *  @type string
12673
		 *  @default <i>Empty string<i>
12674
		 *
12675
		 *  @name DataTable.defaults.column.contentPadding
12676
		 *  @dtopt Columns
12677
		 *
12678
		 *  @example
12679
		 *    // Using `columns`
12680
		 *    $(document).ready( function() {
12681
		 *      $('#example').dataTable( {
12682
		 *        "columns": [
12683
		 *          null,
12684
		 *          null,
12685
		 *          null,
12686
		 *          {
12687
		 *            "contentPadding": "mmm"
12688
		 *          }
12689
		 *        ]
12690
		 *      } );
12691
		 *    } );
12692
		 */
12693
		"sContentPadding": "",
12694
	
12695
	
12696
		/**
12697
		 * Allows a default value to be given for a column's data, and will be used
12698
		 * whenever a null data source is encountered (this can be because `data`
12699
		 * is set to null, or because the data source itself is null).
12700
		 *  @type string
12701
		 *  @default null
12702
		 *
12703
		 *  @name DataTable.defaults.column.defaultContent
12704
		 *  @dtopt Columns
12705
		 *
12706
		 *  @example
12707
		 *    // Using `columnDefs`
12708
		 *    $(document).ready( function() {
12709
		 *      $('#example').dataTable( {
12710
		 *        "columnDefs": [
12711
		 *          {
12712
		 *            "data": null,
12713
		 *            "defaultContent": "Edit",
12714
		 *            "targets": [ -1 ]
12715
		 *          }
12716
		 *        ]
12717
		 *      } );
12718
		 *    } );
12719
		 *
12720
		 *  @example
12721
		 *    // Using `columns`
12722
		 *    $(document).ready( function() {
12723
		 *      $('#example').dataTable( {
12724
		 *        "columns": [
12725
		 *          null,
12726
		 *          null,
12727
		 *          null,
12728
		 *          {
12729
		 *            "data": null,
12730
		 *            "defaultContent": "Edit"
12731
		 *          }
12732
		 *        ]
12733
		 *      } );
12734
		 *    } );
12735
		 */
12736
		"sDefaultContent": null,
12737
	
12738
	
12739
		/**
12740
		 * This parameter is only used in DataTables' server-side processing. It can
12741
		 * be exceptionally useful to know what columns are being displayed on the
12742
		 * client side, and to map these to database fields. When defined, the names
12743
		 * also allow DataTables to reorder information from the server if it comes
12744
		 * back in an unexpected order (i.e. if you switch your columns around on the
12745
		 * client-side, your server-side code does not also need updating).
12746
		 *  @type string
12747
		 *  @default <i>Empty string</i>
12748
		 *
12749
		 *  @name DataTable.defaults.column.name
12750
		 *  @dtopt Columns
12751
		 *
12752
		 *  @example
12753
		 *    // Using `columnDefs`
12754
		 *    $(document).ready( function() {
12755
		 *      $('#example').dataTable( {
12756
		 *        "columnDefs": [
12757
		 *          { "name": "engine", "targets": [ 0 ] },
12758
		 *          { "name": "browser", "targets": [ 1 ] },
12759
		 *          { "name": "platform", "targets": [ 2 ] },
12760
		 *          { "name": "version", "targets": [ 3 ] },
12761
		 *          { "name": "grade", "targets": [ 4 ] }
12762
		 *        ]
12763
		 *      } );
12764
		 *    } );
12765
		 *
12766
		 *  @example
12767
		 *    // Using `columns`
12768
		 *    $(document).ready( function() {
12769
		 *      $('#example').dataTable( {
12770
		 *        "columns": [
12771
		 *          { "name": "engine" },
12772
		 *          { "name": "browser" },
12773
		 *          { "name": "platform" },
12774
		 *          { "name": "version" },
12775
		 *          { "name": "grade" }
12776
		 *        ]
12777
		 *      } );
12778
		 *    } );
12779
		 */
12780
		"sName": "",
12781
	
12782
	
12783
		/**
12784
		 * Defines a data source type for the ordering which can be used to read
12785
		 * real-time information from the table (updating the internally cached
12786
		 * version) prior to ordering. This allows ordering to occur on user
12787
		 * editable elements such as form inputs.
12788
		 *  @type string
12789
		 *  @default std
12790
		 *
12791
		 *  @name DataTable.defaults.column.orderDataType
12792
		 *  @dtopt Columns
12793
		 *
12794
		 *  @example
12795
		 *    // Using `columnDefs`
12796
		 *    $(document).ready( function() {
12797
		 *      $('#example').dataTable( {
12798
		 *        "columnDefs": [
12799
		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12800
		 *          { "type": "numeric", "targets": [ 3 ] },
12801
		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12802
		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12803
		 *        ]
12804
		 *      } );
12805
		 *    } );
12806
		 *
12807
		 *  @example
12808
		 *    // Using `columns`
12809
		 *    $(document).ready( function() {
12810
		 *      $('#example').dataTable( {
12811
		 *        "columns": [
12812
		 *          null,
12813
		 *          null,
12814
		 *          { "orderDataType": "dom-text" },
12815
		 *          { "orderDataType": "dom-text", "type": "numeric" },
12816
		 *          { "orderDataType": "dom-select" },
12817
		 *          { "orderDataType": "dom-checkbox" }
12818
		 *        ]
12819
		 *      } );
12820
		 *    } );
12821
		 */
12822
		"sSortDataType": "std",
12823
	
12824
	
12825
		/**
12826
		 * The title of this column.
12827
		 *  @type string
12828
		 *  @default null <i>Derived from the 'TH' value for this column in the
12829
		 *    original HTML table.</i>
12830
		 *
12831
		 *  @name DataTable.defaults.column.title
12832
		 *  @dtopt Columns
12833
		 *
12834
		 *  @example
12835
		 *    // Using `columnDefs`
12836
		 *    $(document).ready( function() {
12837
		 *      $('#example').dataTable( {
12838
		 *        "columnDefs": [
12839
		 *          { "title": "My column title", "targets": [ 0 ] }
12840
		 *        ]
12841
		 *      } );
12842
		 *    } );
12843
		 *
12844
		 *  @example
12845
		 *    // Using `columns`
12846
		 *    $(document).ready( function() {
12847
		 *      $('#example').dataTable( {
12848
		 *        "columns": [
12849
		 *          { "title": "My column title" },
12850
		 *          null,
12851
		 *          null,
12852
		 *          null,
12853
		 *          null
12854
		 *        ]
12855
		 *      } );
12856
		 *    } );
12857
		 */
12858
		"sTitle": null,
12859
	
12860
	
12861
		/**
12862
		 * The type allows you to specify how the data for this column will be
12863
		 * ordered. Four types (string, numeric, date and html (which will strip
12864
		 * HTML tags before ordering)) are currently available. Note that only date
12865
		 * formats understood by Javascript's Date() object will be accepted as type
12866
		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12867
		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12868
		 * through plug-ins.
12869
		 *  @type string
12870
		 *  @default null <i>Auto-detected from raw data</i>
12871
		 *
12872
		 *  @name DataTable.defaults.column.type
12873
		 *  @dtopt Columns
12874
		 *
12875
		 *  @example
12876
		 *    // Using `columnDefs`
12877
		 *    $(document).ready( function() {
12878
		 *      $('#example').dataTable( {
12879
		 *        "columnDefs": [
12880
		 *          { "type": "html", "targets": [ 0 ] }
12881
		 *        ]
12882
		 *      } );
12883
		 *    } );
12884
		 *
12885
		 *  @example
12886
		 *    // Using `columns`
12887
		 *    $(document).ready( function() {
12888
		 *      $('#example').dataTable( {
12889
		 *        "columns": [
12890
		 *          { "type": "html" },
12891
		 *          null,
12892
		 *          null,
12893
		 *          null,
12894
		 *          null
12895
		 *        ]
12896
		 *      } );
12897
		 *    } );
12898
		 */
12899
		"sType": null,
12900
	
12901
	
12902
		/**
12903
		 * Defining the width of the column, this parameter may take any CSS value
12904
		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12905
		 * been given a specific width through this interface ensuring that the table
12906
		 * remains readable.
12907
		 *  @type string
12908
		 *  @default null <i>Automatic</i>
12909
		 *
12910
		 *  @name DataTable.defaults.column.width
12911
		 *  @dtopt Columns
12912
		 *
12913
		 *  @example
12914
		 *    // Using `columnDefs`
12915
		 *    $(document).ready( function() {
12916
		 *      $('#example').dataTable( {
12917
		 *        "columnDefs": [
12918
		 *          { "width": "20%", "targets": [ 0 ] }
12919
		 *        ]
12920
		 *      } );
12921
		 *    } );
12922
		 *
12923
		 *  @example
12924
		 *    // Using `columns`
12925
		 *    $(document).ready( function() {
12926
		 *      $('#example').dataTable( {
12927
		 *        "columns": [
12928
		 *          { "width": "20%" },
12929
		 *          null,
12930
		 *          null,
12931
		 *          null,
12932
		 *          null
12933
		 *        ]
12934
		 *      } );
12935
		 *    } );
12936
		 */
12937
		"sWidth": null
12938
	};
12939
	
12940
	_fnHungarianMap( DataTable.defaults.column );
12941
	
12942
	
12943
	
12944
	/**
12945
	 * DataTables settings object - this holds all the information needed for a
12946
	 * given table, including configuration, data and current application of the
12947
	 * table options. DataTables does not have a single instance for each DataTable
12948
	 * with the settings attached to that instance, but rather instances of the
12949
	 * DataTable "class" are created on-the-fly as needed (typically by a
12950
	 * $().dataTable() call) and the settings object is then applied to that
12951
	 * instance.
12952
	 *
12953
	 * Note that this object is related to {@link DataTable.defaults} but this
12954
	 * one is the internal data store for DataTables's cache of columns. It should
12955
	 * NOT be manipulated outside of DataTables. Any configuration should be done
12956
	 * through the initialisation options.
12957
	 *  @namespace
12958
	 *  @todo Really should attach the settings object to individual instances so we
12959
	 *    don't need to create new instances on each $().dataTable() call (if the
12960
	 *    table already exists). It would also save passing oSettings around and
12961
	 *    into every single function. However, this is a very significant
12962
	 *    architecture change for DataTables and will almost certainly break
12963
	 *    backwards compatibility with older installations. This is something that
12964
	 *    will be done in 2.0.
12965
	 */
12966
	DataTable.models.oSettings = {
12967
		/**
12968
		 * Primary features of DataTables and their enablement state.
12969
		 *  @namespace
12970
		 */
12971
		"oFeatures": {
12972
	
12973
			/**
12974
			 * Flag to say if DataTables should automatically try to calculate the
12975
			 * optimum table and columns widths (true) or not (false).
12976
			 * Note that this parameter will be set by the initialisation routine. To
12977
			 * set a default use {@link DataTable.defaults}.
12978
			 *  @type boolean
12979
			 */
12980
			"bAutoWidth": null,
12981
	
12982
			/**
12983
			 * Delay the creation of TR and TD elements until they are actually
12984
			 * needed by a driven page draw. This can give a significant speed
12985
			 * increase for Ajax source and Javascript source data, but makes no
12986
			 * difference at all fro DOM and server-side processing tables.
12987
			 * Note that this parameter will be set by the initialisation routine. To
12988
			 * set a default use {@link DataTable.defaults}.
12989
			 *  @type boolean
12990
			 */
12991
			"bDeferRender": null,
12992
	
12993
			/**
12994
			 * Enable filtering on the table or not. Note that if this is disabled
12995
			 * then there is no filtering at all on the table, including fnFilter.
12996
			 * To just remove the filtering input use sDom and remove the 'f' option.
12997
			 * Note that this parameter will be set by the initialisation routine. To
12998
			 * set a default use {@link DataTable.defaults}.
12999
			 *  @type boolean
13000
			 */
13001
			"bFilter": null,
13002
	
13003
			/**
13004
			 * Table information element (the 'Showing x of y records' div) enable
13005
			 * flag.
13006
			 * Note that this parameter will be set by the initialisation routine. To
13007
			 * set a default use {@link DataTable.defaults}.
13008
			 *  @type boolean
13009
			 */
13010
			"bInfo": null,
13011
	
13012
			/**
13013
			 * Present a user control allowing the end user to change the page size
13014
			 * when pagination is enabled.
13015
			 * Note that this parameter will be set by the initialisation routine. To
13016
			 * set a default use {@link DataTable.defaults}.
13017
			 *  @type boolean
13018
			 */
13019
			"bLengthChange": null,
13020
	
13021
			/**
13022
			 * Pagination enabled or not. Note that if this is disabled then length
13023
			 * changing must also be disabled.
13024
			 * Note that this parameter will be set by the initialisation routine. To
13025
			 * set a default use {@link DataTable.defaults}.
13026
			 *  @type boolean
13027
			 */
13028
			"bPaginate": null,
13029
	
13030
			/**
13031
			 * Processing indicator enable flag whenever DataTables is enacting a
13032
			 * user request - typically an Ajax request for server-side processing.
13033
			 * Note that this parameter will be set by the initialisation routine. To
13034
			 * set a default use {@link DataTable.defaults}.
13035
			 *  @type boolean
13036
			 */
13037
			"bProcessing": null,
13038
	
13039
			/**
13040
			 * Server-side processing enabled flag - when enabled DataTables will
13041
			 * get all data from the server for every draw - there is no filtering,
13042
			 * sorting or paging done on the client-side.
13043
			 * Note that this parameter will be set by the initialisation routine. To
13044
			 * set a default use {@link DataTable.defaults}.
13045
			 *  @type boolean
13046
			 */
13047
			"bServerSide": null,
13048
	
13049
			/**
13050
			 * Sorting enablement flag.
13051
			 * Note that this parameter will be set by the initialisation routine. To
13052
			 * set a default use {@link DataTable.defaults}.
13053
			 *  @type boolean
13054
			 */
13055
			"bSort": null,
13056
	
13057
			/**
13058
			 * Multi-column sorting
13059
			 * Note that this parameter will be set by the initialisation routine. To
13060
			 * set a default use {@link DataTable.defaults}.
13061
			 *  @type boolean
13062
			 */
13063
			"bSortMulti": null,
13064
	
13065
			/**
13066
			 * Apply a class to the columns which are being sorted to provide a
13067
			 * visual highlight or not. This can slow things down when enabled since
13068
			 * there is a lot of DOM interaction.
13069
			 * Note that this parameter will be set by the initialisation routine. To
13070
			 * set a default use {@link DataTable.defaults}.
13071
			 *  @type boolean
13072
			 */
13073
			"bSortClasses": null,
13074
	
13075
			/**
13076
			 * State saving enablement flag.
13077
			 * Note that this parameter will be set by the initialisation routine. To
13078
			 * set a default use {@link DataTable.defaults}.
13079
			 *  @type boolean
13080
			 */
13081
			"bStateSave": null
13082
		},
13083
	
13084
	
13085
		/**
13086
		 * Scrolling settings for a table.
13087
		 *  @namespace
13088
		 */
13089
		"oScroll": {
13090
			/**
13091
			 * When the table is shorter in height than sScrollY, collapse the
13092
			 * table container down to the height of the table (when true).
13093
			 * Note that this parameter will be set by the initialisation routine. To
13094
			 * set a default use {@link DataTable.defaults}.
13095
			 *  @type boolean
13096
			 */
13097
			"bCollapse": null,
13098
	
13099
			/**
13100
			 * Width of the scrollbar for the web-browser's platform. Calculated
13101
			 * during table initialisation.
13102
			 *  @type int
13103
			 *  @default 0
13104
			 */
13105
			"iBarWidth": 0,
13106
	
13107
			/**
13108
			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13109
			 * disabled if an empty string.
13110
			 * Note that this parameter will be set by the initialisation routine. To
13111
			 * set a default use {@link DataTable.defaults}.
13112
			 *  @type string
13113
			 */
13114
			"sX": null,
13115
	
13116
			/**
13117
			 * Width to expand the table to when using x-scrolling. Typically you
13118
			 * should not need to use this.
13119
			 * Note that this parameter will be set by the initialisation routine. To
13120
			 * set a default use {@link DataTable.defaults}.
13121
			 *  @type string
13122
			 *  @deprecated
13123
			 */
13124
			"sXInner": null,
13125
	
13126
			/**
13127
			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13128
			 * if an empty string.
13129
			 * Note that this parameter will be set by the initialisation routine. To
13130
			 * set a default use {@link DataTable.defaults}.
13131
			 *  @type string
13132
			 */
13133
			"sY": null
13134
		},
13135
	
13136
		/**
13137
		 * Language information for the table.
13138
		 *  @namespace
13139
		 *  @extends DataTable.defaults.oLanguage
13140
		 */
13141
		"oLanguage": {
13142
			/**
13143
			 * Information callback function. See
13144
			 * {@link DataTable.defaults.fnInfoCallback}
13145
			 *  @type function
13146
			 *  @default null
13147
			 */
13148
			"fnInfoCallback": null
13149
		},
13150
	
13151
		/**
13152
		 * Browser support parameters
13153
		 *  @namespace
13154
		 */
13155
		"oBrowser": {
13156
			/**
13157
			 * Indicate if the browser incorrectly calculates width:100% inside a
13158
			 * scrolling element (IE6/7)
13159
			 *  @type boolean
13160
			 *  @default false
13161
			 */
13162
			"bScrollOversize": false,
13163
	
13164
			/**
13165
			 * Determine if the vertical scrollbar is on the right or left of the
13166
			 * scrolling container - needed for rtl language layout, although not
13167
			 * all browsers move the scrollbar (Safari).
13168
			 *  @type boolean
13169
			 *  @default false
13170
			 */
13171
			"bScrollbarLeft": false,
13172
	
13173
			/**
13174
			 * Flag for if `getBoundingClientRect` is fully supported or not
13175
			 *  @type boolean
13176
			 *  @default false
13177
			 */
13178
			"bBounding": false,
13179
	
13180
			/**
13181
			 * Browser scrollbar width
13182
			 *  @type integer
13183
			 *  @default 0
13184
			 */
13185
			"barWidth": 0
13186
		},
13187
	
13188
	
13189
		"ajax": null,
13190
	
13191
	
13192
		/**
13193
		 * Array referencing the nodes which are used for the features. The
13194
		 * parameters of this object match what is allowed by sDom - i.e.
13195
		 *   <ul>
13196
		 *     <li>'l' - Length changing</li>
13197
		 *     <li>'f' - Filtering input</li>
13198
		 *     <li>'t' - The table!</li>
13199
		 *     <li>'i' - Information</li>
13200
		 *     <li>'p' - Pagination</li>
13201
		 *     <li>'r' - pRocessing</li>
13202
		 *   </ul>
13203
		 *  @type array
13204
		 *  @default []
13205
		 */
13206
		"aanFeatures": [],
13207
	
13208
		/**
13209
		 * Store data information - see {@link DataTable.models.oRow} for detailed
13210
		 * information.
13211
		 *  @type array
13212
		 *  @default []
13213
		 */
13214
		"aoData": [],
13215
	
13216
		/**
13217
		 * Array of indexes which are in the current display (after filtering etc)
13218
		 *  @type array
13219
		 *  @default []
13220
		 */
13221
		"aiDisplay": [],
13222
	
13223
		/**
13224
		 * Array of indexes for display - no filtering
13225
		 *  @type array
13226
		 *  @default []
13227
		 */
13228
		"aiDisplayMaster": [],
13229
	
13230
		/**
13231
		 * Map of row ids to data indexes
13232
		 *  @type object
13233
		 *  @default {}
13234
		 */
13235
		"aIds": {},
13236
	
13237
		/**
13238
		 * Store information about each column that is in use
13239
		 *  @type array
13240
		 *  @default []
13241
		 */
13242
		"aoColumns": [],
13243
	
13244
		/**
13245
		 * Store information about the table's header
13246
		 *  @type array
13247
		 *  @default []
13248
		 */
13249
		"aoHeader": [],
13250
	
13251
		/**
13252
		 * Store information about the table's footer
13253
		 *  @type array
13254
		 *  @default []
13255
		 */
13256
		"aoFooter": [],
13257
	
13258
		/**
13259
		 * Store the applied global search information in case we want to force a
13260
		 * research or compare the old search to a new one.
13261
		 * Note that this parameter will be set by the initialisation routine. To
13262
		 * set a default use {@link DataTable.defaults}.
13263
		 *  @namespace
13264
		 *  @extends DataTable.models.oSearch
13265
		 */
13266
		"oPreviousSearch": {},
13267
	
13268
		/**
13269
		 * Store the applied search for each column - see
13270
		 * {@link DataTable.models.oSearch} for the format that is used for the
13271
		 * filtering information for each column.
13272
		 *  @type array
13273
		 *  @default []
13274
		 */
13275
		"aoPreSearchCols": [],
13276
	
13277
		/**
13278
		 * Sorting that is applied to the table. Note that the inner arrays are
13279
		 * used in the following manner:
13280
		 * <ul>
13281
		 *   <li>Index 0 - column number</li>
13282
		 *   <li>Index 1 - current sorting direction</li>
13283
		 * </ul>
13284
		 * Note that this parameter will be set by the initialisation routine. To
13285
		 * set a default use {@link DataTable.defaults}.
13286
		 *  @type array
13287
		 *  @todo These inner arrays should really be objects
13288
		 */
13289
		"aaSorting": null,
13290
	
13291
		/**
13292
		 * Sorting that is always applied to the table (i.e. prefixed in front of
13293
		 * aaSorting).
13294
		 * Note that this parameter will be set by the initialisation routine. To
13295
		 * set a default use {@link DataTable.defaults}.
13296
		 *  @type array
13297
		 *  @default []
13298
		 */
13299
		"aaSortingFixed": [],
13300
	
13301
		/**
13302
		 * Classes to use for the striping of a table.
13303
		 * Note that this parameter will be set by the initialisation routine. To
13304
		 * set a default use {@link DataTable.defaults}.
13305
		 *  @type array
13306
		 *  @default []
13307
		 */
13308
		"asStripeClasses": null,
13309
	
13310
		/**
13311
		 * If restoring a table - we should restore its striping classes as well
13312
		 *  @type array
13313
		 *  @default []
13314
		 */
13315
		"asDestroyStripes": [],
13316
	
13317
		/**
13318
		 * If restoring a table - we should restore its width
13319
		 *  @type int
13320
		 *  @default 0
13321
		 */
13322
		"sDestroyWidth": 0,
13323
	
13324
		/**
13325
		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13326
		 *  @type array
13327
		 *  @default []
13328
		 */
13329
		"aoRowCallback": [],
13330
	
13331
		/**
13332
		 * Callback functions for the header on each draw.
13333
		 *  @type array
13334
		 *  @default []
13335
		 */
13336
		"aoHeaderCallback": [],
13337
	
13338
		/**
13339
		 * Callback function for the footer on each draw.
13340
		 *  @type array
13341
		 *  @default []
13342
		 */
13343
		"aoFooterCallback": [],
13344
	
13345
		/**
13346
		 * Array of callback functions for draw callback functions
13347
		 *  @type array
13348
		 *  @default []
13349
		 */
13350
		"aoDrawCallback": [],
13351
	
13352
		/**
13353
		 * Array of callback functions for row created function
13354
		 *  @type array
13355
		 *  @default []
13356
		 */
13357
		"aoRowCreatedCallback": [],
13358
	
13359
		/**
13360
		 * Callback functions for just before the table is redrawn. A return of
13361
		 * false will be used to cancel the draw.
13362
		 *  @type array
13363
		 *  @default []
13364
		 */
13365
		"aoPreDrawCallback": [],
13366
	
13367
		/**
13368
		 * Callback functions for when the table has been initialised.
13369
		 *  @type array
13370
		 *  @default []
13371
		 */
13372
		"aoInitComplete": [],
13373
	
13374
	
13375
		/**
13376
		 * Callbacks for modifying the settings to be stored for state saving, prior to
13377
		 * saving state.
13378
		 *  @type array
13379
		 *  @default []
13380
		 */
13381
		"aoStateSaveParams": [],
13382
	
13383
		/**
13384
		 * Callbacks for modifying the settings that have been stored for state saving
13385
		 * prior to using the stored values to restore the state.
13386
		 *  @type array
13387
		 *  @default []
13388
		 */
13389
		"aoStateLoadParams": [],
13390
	
13391
		/**
13392
		 * Callbacks for operating on the settings object once the saved state has been
13393
		 * loaded
13394
		 *  @type array
13395
		 *  @default []
13396
		 */
13397
		"aoStateLoaded": [],
13398
	
13399
		/**
13400
		 * Cache the table ID for quick access
13401
		 *  @type string
13402
		 *  @default <i>Empty string</i>
13403
		 */
13404
		"sTableId": "",
13405
	
13406
		/**
13407
		 * The TABLE node for the main table
13408
		 *  @type node
13409
		 *  @default null
13410
		 */
13411
		"nTable": null,
13412
	
13413
		/**
13414
		 * Permanent ref to the thead element
13415
		 *  @type node
13416
		 *  @default null
13417
		 */
13418
		"nTHead": null,
13419
	
13420
		/**
13421
		 * Permanent ref to the tfoot element - if it exists
13422
		 *  @type node
13423
		 *  @default null
13424
		 */
13425
		"nTFoot": null,
13426
	
13427
		/**
13428
		 * Permanent ref to the tbody element
13429
		 *  @type node
13430
		 *  @default null
13431
		 */
13432
		"nTBody": null,
13433
	
13434
		/**
13435
		 * Cache the wrapper node (contains all DataTables controlled elements)
13436
		 *  @type node
13437
		 *  @default null
13438
		 */
13439
		"nTableWrapper": null,
13440
	
13441
		/**
13442
		 * Indicate if when using server-side processing the loading of data
13443
		 * should be deferred until the second draw.
13444
		 * Note that this parameter will be set by the initialisation routine. To
13445
		 * set a default use {@link DataTable.defaults}.
13446
		 *  @type boolean
13447
		 *  @default false
13448
		 */
13449
		"bDeferLoading": false,
13450
	
13451
		/**
13452
		 * Indicate if all required information has been read in
13453
		 *  @type boolean
13454
		 *  @default false
13455
		 */
13456
		"bInitialised": false,
13457
	
13458
		/**
13459
		 * Information about open rows. Each object in the array has the parameters
13460
		 * 'nTr' and 'nParent'
13461
		 *  @type array
13462
		 *  @default []
13463
		 */
13464
		"aoOpenRows": [],
13465
	
13466
		/**
13467
		 * Dictate the positioning of DataTables' control elements - see
13468
		 * {@link DataTable.model.oInit.sDom}.
13469
		 * Note that this parameter will be set by the initialisation routine. To
13470
		 * set a default use {@link DataTable.defaults}.
13471
		 *  @type string
13472
		 *  @default null
13473
		 */
13474
		"sDom": null,
13475
	
13476
		/**
13477
		 * Search delay (in mS)
13478
		 *  @type integer
13479
		 *  @default null
13480
		 */
13481
		"searchDelay": null,
13482
	
13483
		/**
13484
		 * Which type of pagination should be used.
13485
		 * Note that this parameter will be set by the initialisation routine. To
13486
		 * set a default use {@link DataTable.defaults}.
13487
		 *  @type string
13488
		 *  @default two_button
13489
		 */
13490
		"sPaginationType": "two_button",
13491
	
13492
		/**
13493
		 * The state duration (for `stateSave`) in seconds.
13494
		 * Note that this parameter will be set by the initialisation routine. To
13495
		 * set a default use {@link DataTable.defaults}.
13496
		 *  @type int
13497
		 *  @default 0
13498
		 */
13499
		"iStateDuration": 0,
13500
	
13501
		/**
13502
		 * Array of callback functions for state saving. Each array element is an
13503
		 * object with the following parameters:
13504
		 *   <ul>
13505
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13506
		 *       and the JSON string to save that has been thus far created. Returns
13507
		 *       a JSON string to be inserted into a json object
13508
		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13509
		 *     <li>string:sName - name of callback</li>
13510
		 *   </ul>
13511
		 *  @type array
13512
		 *  @default []
13513
		 */
13514
		"aoStateSave": [],
13515
	
13516
		/**
13517
		 * Array of callback functions for state loading. Each array element is an
13518
		 * object with the following parameters:
13519
		 *   <ul>
13520
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13521
		 *       and the object stored. May return false to cancel state loading</li>
13522
		 *     <li>string:sName - name of callback</li>
13523
		 *   </ul>
13524
		 *  @type array
13525
		 *  @default []
13526
		 */
13527
		"aoStateLoad": [],
13528
	
13529
		/**
13530
		 * State that was saved. Useful for back reference
13531
		 *  @type object
13532
		 *  @default null
13533
		 */
13534
		"oSavedState": null,
13535
	
13536
		/**
13537
		 * State that was loaded. Useful for back reference
13538
		 *  @type object
13539
		 *  @default null
13540
		 */
13541
		"oLoadedState": null,
13542
	
13543
		/**
13544
		 * Source url for AJAX data for the table.
13545
		 * Note that this parameter will be set by the initialisation routine. To
13546
		 * set a default use {@link DataTable.defaults}.
13547
		 *  @type string
13548
		 *  @default null
13549
		 */
13550
		"sAjaxSource": null,
13551
	
13552
		/**
13553
		 * Property from a given object from which to read the table data from. This
13554
		 * can be an empty string (when not server-side processing), in which case
13555
		 * it is  assumed an an array is given directly.
13556
		 * Note that this parameter will be set by the initialisation routine. To
13557
		 * set a default use {@link DataTable.defaults}.
13558
		 *  @type string
13559
		 */
13560
		"sAjaxDataProp": null,
13561
	
13562
		/**
13563
		 * Note if draw should be blocked while getting data
13564
		 *  @type boolean
13565
		 *  @default true
13566
		 */
13567
		"bAjaxDataGet": true,
13568
	
13569
		/**
13570
		 * The last jQuery XHR object that was used for server-side data gathering.
13571
		 * This can be used for working with the XHR information in one of the
13572
		 * callbacks
13573
		 *  @type object
13574
		 *  @default null
13575
		 */
13576
		"jqXHR": null,
13577
	
13578
		/**
13579
		 * JSON returned from the server in the last Ajax request
13580
		 *  @type object
13581
		 *  @default undefined
13582
		 */
13583
		"json": undefined,
13584
	
13585
		/**
13586
		 * Data submitted as part of the last Ajax request
13587
		 *  @type object
13588
		 *  @default undefined
13589
		 */
13590
		"oAjaxData": undefined,
13591
	
13592
		/**
13593
		 * Function to get the server-side data.
13594
		 * Note that this parameter will be set by the initialisation routine. To
13595
		 * set a default use {@link DataTable.defaults}.
13596
		 *  @type function
13597
		 */
13598
		"fnServerData": null,
13599
	
13600
		/**
13601
		 * Functions which are called prior to sending an Ajax request so extra
13602
		 * parameters can easily be sent to the server
13603
		 *  @type array
13604
		 *  @default []
13605
		 */
13606
		"aoServerParams": [],
13607
	
13608
		/**
13609
		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13610
		 * required).
13611
		 * Note that this parameter will be set by the initialisation routine. To
13612
		 * set a default use {@link DataTable.defaults}.
13613
		 *  @type string
13614
		 */
13615
		"sServerMethod": null,
13616
	
13617
		/**
13618
		 * Format numbers for display.
13619
		 * Note that this parameter will be set by the initialisation routine. To
13620
		 * set a default use {@link DataTable.defaults}.
13621
		 *  @type function
13622
		 */
13623
		"fnFormatNumber": null,
13624
	
13625
		/**
13626
		 * List of options that can be used for the user selectable length menu.
13627
		 * Note that this parameter will be set by the initialisation routine. To
13628
		 * set a default use {@link DataTable.defaults}.
13629
		 *  @type array
13630
		 *  @default []
13631
		 */
13632
		"aLengthMenu": null,
13633
	
13634
		/**
13635
		 * Counter for the draws that the table does. Also used as a tracker for
13636
		 * server-side processing
13637
		 *  @type int
13638
		 *  @default 0
13639
		 */
13640
		"iDraw": 0,
13641
	
13642
		/**
13643
		 * Indicate if a redraw is being done - useful for Ajax
13644
		 *  @type boolean
13645
		 *  @default false
13646
		 */
13647
		"bDrawing": false,
13648
	
13649
		/**
13650
		 * Draw index (iDraw) of the last error when parsing the returned data
13651
		 *  @type int
13652
		 *  @default -1
13653
		 */
13654
		"iDrawError": -1,
13655
	
13656
		/**
13657
		 * Paging display length
13658
		 *  @type int
13659
		 *  @default 10
13660
		 */
13661
		"_iDisplayLength": 10,
13662
	
13663
		/**
13664
		 * Paging start point - aiDisplay index
13665
		 *  @type int
13666
		 *  @default 0
13667
		 */
13668
		"_iDisplayStart": 0,
13669
	
13670
		/**
13671
		 * Server-side processing - number of records in the result set
13672
		 * (i.e. before filtering), Use fnRecordsTotal rather than
13673
		 * this property to get the value of the number of records, regardless of
13674
		 * the server-side processing setting.
13675
		 *  @type int
13676
		 *  @default 0
13677
		 *  @private
13678
		 */
13679
		"_iRecordsTotal": 0,
13680
	
13681
		/**
13682
		 * Server-side processing - number of records in the current display set
13683
		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13684
		 * this property to get the value of the number of records, regardless of
13685
		 * the server-side processing setting.
13686
		 *  @type boolean
13687
		 *  @default 0
13688
		 *  @private
13689
		 */
13690
		"_iRecordsDisplay": 0,
13691
	
13692
		/**
13693
		 * The classes to use for the table
13694
		 *  @type object
13695
		 *  @default {}
13696
		 */
13697
		"oClasses": {},
13698
	
13699
		/**
13700
		 * Flag attached to the settings object so you can check in the draw
13701
		 * callback if filtering has been done in the draw. Deprecated in favour of
13702
		 * events.
13703
		 *  @type boolean
13704
		 *  @default false
13705
		 *  @deprecated
13706
		 */
13707
		"bFiltered": false,
13708
	
13709
		/**
13710
		 * Flag attached to the settings object so you can check in the draw
13711
		 * callback if sorting has been done in the draw. Deprecated in favour of
13712
		 * events.
13713
		 *  @type boolean
13714
		 *  @default false
13715
		 *  @deprecated
13716
		 */
13717
		"bSorted": false,
13718
	
13719
		/**
13720
		 * Indicate that if multiple rows are in the header and there is more than
13721
		 * one unique cell per column, if the top one (true) or bottom one (false)
13722
		 * should be used for sorting / title by DataTables.
13723
		 * Note that this parameter will be set by the initialisation routine. To
13724
		 * set a default use {@link DataTable.defaults}.
13725
		 *  @type boolean
13726
		 */
13727
		"bSortCellsTop": null,
13728
	
13729
		/**
13730
		 * Initialisation object that is used for the table
13731
		 *  @type object
13732
		 *  @default null
13733
		 */
13734
		"oInit": null,
13735
	
13736
		/**
13737
		 * Destroy callback functions - for plug-ins to attach themselves to the
13738
		 * destroy so they can clean up markup and events.
13739
		 *  @type array
13740
		 *  @default []
13741
		 */
13742
		"aoDestroyCallback": [],
13743
	
13744
	
13745
		/**
13746
		 * Get the number of records in the current record set, before filtering
13747
		 *  @type function
13748
		 */
13749
		"fnRecordsTotal": function ()
13750
		{
13751
			return _fnDataSource( this ) == 'ssp' ?
13752
				this._iRecordsTotal * 1 :
13753
				this.aiDisplayMaster.length;
13754
		},
13755
	
13756
		/**
13757
		 * Get the number of records in the current record set, after filtering
13758
		 *  @type function
13759
		 */
13760
		"fnRecordsDisplay": function ()
13761
		{
13762
			return _fnDataSource( this ) == 'ssp' ?
13763
				this._iRecordsDisplay * 1 :
13764
				this.aiDisplay.length;
13765
		},
13766
	
13767
		/**
13768
		 * Get the display end point - aiDisplay index
13769
		 *  @type function
13770
		 */
13771
		"fnDisplayEnd": function ()
13772
		{
13773
			var
13774
				len      = this._iDisplayLength,
13775
				start    = this._iDisplayStart,
13776
				calc     = start + len,
13777
				records  = this.aiDisplay.length,
13778
				features = this.oFeatures,
13779
				paginate = features.bPaginate;
13780
	
13781
			if ( features.bServerSide ) {
13782
				return paginate === false || len === -1 ?
13783
					start + records :
13784
					Math.min( start+len, this._iRecordsDisplay );
13785
			}
13786
			else {
13787
				return ! paginate || calc>records || len===-1 ?
13788
					records :
13789
					calc;
13790
			}
13791
		},
13792
	
13793
		/**
13794
		 * The DataTables object for this table
13795
		 *  @type object
13796
		 *  @default null
13797
		 */
13798
		"oInstance": null,
13799
	
13800
		/**
13801
		 * Unique identifier for each instance of the DataTables object. If there
13802
		 * is an ID on the table node, then it takes that value, otherwise an
13803
		 * incrementing internal counter is used.
13804
		 *  @type string
13805
		 *  @default null
13806
		 */
13807
		"sInstance": null,
13808
	
13809
		/**
13810
		 * tabindex attribute value that is added to DataTables control elements, allowing
13811
		 * keyboard navigation of the table and its controls.
13812
		 */
13813
		"iTabIndex": 0,
13814
	
13815
		/**
13816
		 * DIV container for the footer scrolling table if scrolling
13817
		 */
13818
		"nScrollHead": null,
13819
	
13820
		/**
13821
		 * DIV container for the footer scrolling table if scrolling
13822
		 */
13823
		"nScrollFoot": null,
13824
	
13825
		/**
13826
		 * Last applied sort
13827
		 *  @type array
13828
		 *  @default []
13829
		 */
13830
		"aLastSort": [],
13831
	
13832
		/**
13833
		 * Stored plug-in instances
13834
		 *  @type object
13835
		 *  @default {}
13836
		 */
13837
		"oPlugins": {},
13838
	
13839
		/**
13840
		 * Function used to get a row's id from the row's data
13841
		 *  @type function
13842
		 *  @default null
13843
		 */
13844
		"rowIdFn": null,
13845
	
13846
		/**
13847
		 * Data location where to store a row's id
13848
		 *  @type string
13849
		 *  @default null
13850
		 */
13851
		"rowId": null
13852
	};
13853
13854
	/**
13855
	 * Extension object for DataTables that is used to provide all extension
13856
	 * options.
13857
	 *
13858
	 * Note that the `DataTable.ext` object is available through
13859
	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13860
	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13861
	 *  @namespace
13862
	 *  @extends DataTable.models.ext
13863
	 */
13864
	
13865
	
13866
	/**
13867
	 * DataTables extensions
13868
	 * 
13869
	 * This namespace acts as a collection area for plug-ins that can be used to
13870
	 * extend DataTables capabilities. Indeed many of the build in methods
13871
	 * use this method to provide their own capabilities (sorting methods for
13872
	 * example).
13873
	 *
13874
	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13875
	 * reasons
13876
	 *
13877
	 *  @namespace
13878
	 */
13879
	DataTable.ext = _ext = {
13880
		/**
13881
		 * Buttons. For use with the Buttons extension for DataTables. This is
13882
		 * defined here so other extensions can define buttons regardless of load
13883
		 * order. It is _not_ used by DataTables core.
13884
		 *
13885
		 *  @type object
13886
		 *  @default {}
13887
		 */
13888
		buttons: {},
13889
	
13890
	
13891
		/**
13892
		 * Element class names
13893
		 *
13894
		 *  @type object
13895
		 *  @default {}
13896
		 */
13897
		classes: {},
13898
	
13899
	
13900
		/**
13901
		 * DataTables build type (expanded by the download builder)
13902
		 *
13903
		 *  @type string
13904
		 */
13905
		build:"bs4/dt-1.10.18",
13906
	
13907
	
13908
		/**
13909
		 * Error reporting.
13910
		 * 
13911
		 * How should DataTables report an error. Can take the value 'alert',
13912
		 * 'throw', 'none' or a function.
13913
		 *
13914
		 *  @type string|function
13915
		 *  @default alert
13916
		 */
13917
		errMode: "alert",
13918
	
13919
	
13920
		/**
13921
		 * Feature plug-ins.
13922
		 * 
13923
		 * This is an array of objects which describe the feature plug-ins that are
13924
		 * available to DataTables. These feature plug-ins are then available for
13925
		 * use through the `dom` initialisation option.
13926
		 * 
13927
		 * Each feature plug-in is described by an object which must have the
13928
		 * following properties:
13929
		 * 
13930
		 * * `fnInit` - function that is used to initialise the plug-in,
13931
		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13932
		 *   instillation option. This is case sensitive.
13933
		 *
13934
		 * The `fnInit` function has the following input parameters:
13935
		 *
13936
		 * 1. `{object}` DataTables settings object: see
13937
		 *    {@link DataTable.models.oSettings}
13938
		 *
13939
		 * And the following return is expected:
13940
		 * 
13941
		 * * {node|null} The element which contains your feature. Note that the
13942
		 *   return may also be void if your plug-in does not require to inject any
13943
		 *   DOM elements into DataTables control (`dom`) - for example this might
13944
		 *   be useful when developing a plug-in which allows table control via
13945
		 *   keyboard entry
13946
		 *
13947
		 *  @type array
13948
		 *
13949
		 *  @example
13950
		 *    $.fn.dataTable.ext.features.push( {
13951
		 *      "fnInit": function( oSettings ) {
13952
		 *        return new TableTools( { "oDTSettings": oSettings } );
13953
		 *      },
13954
		 *      "cFeature": "T"
13955
		 *    } );
13956
		 */
13957
		feature: [],
13958
	
13959
	
13960
		/**
13961
		 * Row searching.
13962
		 * 
13963
		 * This method of searching is complimentary to the default type based
13964
		 * searching, and a lot more comprehensive as it allows you complete control
13965
		 * over the searching logic. Each element in this array is a function
13966
		 * (parameters described below) that is called for every row in the table,
13967
		 * and your logic decides if it should be included in the searching data set
13968
		 * or not.
13969
		 *
13970
		 * Searching functions have the following input parameters:
13971
		 *
13972
		 * 1. `{object}` DataTables settings object: see
13973
		 *    {@link DataTable.models.oSettings}
13974
		 * 2. `{array|object}` Data for the row to be processed (same as the
13975
		 *    original format that was passed in as the data source, or an array
13976
		 *    from a DOM data source
13977
		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13978
		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13979
		 *
13980
		 * And the following return is expected:
13981
		 *
13982
		 * * {boolean} Include the row in the searched result set (true) or not
13983
		 *   (false)
13984
		 *
13985
		 * Note that as with the main search ability in DataTables, technically this
13986
		 * is "filtering", since it is subtractive. However, for consistency in
13987
		 * naming we call it searching here.
13988
		 *
13989
		 *  @type array
13990
		 *  @default []
13991
		 *
13992
		 *  @example
13993
		 *    // The following example shows custom search being applied to the
13994
		 *    // fourth column (i.e. the data[3] index) based on two input values
13995
		 *    // from the end-user, matching the data in a certain range.
13996
		 *    $.fn.dataTable.ext.search.push(
13997
		 *      function( settings, data, dataIndex ) {
13998
		 *        var min = document.getElementById('min').value * 1;
13999
		 *        var max = document.getElementById('max').value * 1;
14000
		 *        var version = data[3] == "-" ? 0 : data[3]*1;
14001
		 *
14002
		 *        if ( min == "" && max == "" ) {
14003
		 *          return true;
14004
		 *        }
14005
		 *        else if ( min == "" && version < max ) {
14006
		 *          return true;
14007
		 *        }
14008
		 *        else if ( min < version && "" == max ) {
14009
		 *          return true;
14010
		 *        }
14011
		 *        else if ( min < version && version < max ) {
14012
		 *          return true;
14013
		 *        }
14014
		 *        return false;
14015
		 *      }
14016
		 *    );
14017
		 */
14018
		search: [],
14019
	
14020
	
14021
		/**
14022
		 * Selector extensions
14023
		 *
14024
		 * The `selector` option can be used to extend the options available for the
14025
		 * selector modifier options (`selector-modifier` object data type) that
14026
		 * each of the three built in selector types offer (row, column and cell +
14027
		 * their plural counterparts). For example the Select extension uses this
14028
		 * mechanism to provide an option to select only rows, columns and cells
14029
		 * that have been marked as selected by the end user (`{selected: true}`),
14030
		 * which can be used in conjunction with the existing built in selector
14031
		 * options.
14032
		 *
14033
		 * Each property is an array to which functions can be pushed. The functions
14034
		 * take three attributes:
14035
		 *
14036
		 * * Settings object for the host table
14037
		 * * Options object (`selector-modifier` object type)
14038
		 * * Array of selected item indexes
14039
		 *
14040
		 * The return is an array of the resulting item indexes after the custom
14041
		 * selector has been applied.
14042
		 *
14043
		 *  @type object
14044
		 */
14045
		selector: {
14046
			cell: [],
14047
			column: [],
14048
			row: []
14049
		},
14050
	
14051
	
14052
		/**
14053
		 * Internal functions, exposed for used in plug-ins.
14054
		 * 
14055
		 * Please note that you should not need to use the internal methods for
14056
		 * anything other than a plug-in (and even then, try to avoid if possible).
14057
		 * The internal function may change between releases.
14058
		 *
14059
		 *  @type object
14060
		 *  @default {}
14061
		 */
14062
		internal: {},
14063
	
14064
	
14065
		/**
14066
		 * Legacy configuration options. Enable and disable legacy options that
14067
		 * are available in DataTables.
14068
		 *
14069
		 *  @type object
14070
		 */
14071
		legacy: {
14072
			/**
14073
			 * Enable / disable DataTables 1.9 compatible server-side processing
14074
			 * requests
14075
			 *
14076
			 *  @type boolean
14077
			 *  @default null
14078
			 */
14079
			ajax: null
14080
		},
14081
	
14082
	
14083
		/**
14084
		 * Pagination plug-in methods.
14085
		 * 
14086
		 * Each entry in this object is a function and defines which buttons should
14087
		 * be shown by the pagination rendering method that is used for the table:
14088
		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14089
		 * buttons are displayed in the document, while the functions here tell it
14090
		 * what buttons to display. This is done by returning an array of button
14091
		 * descriptions (what each button will do).
14092
		 *
14093
		 * Pagination types (the four built in options and any additional plug-in
14094
		 * options defined here) can be used through the `paginationType`
14095
		 * initialisation parameter.
14096
		 *
14097
		 * The functions defined take two parameters:
14098
		 *
14099
		 * 1. `{int} page` The current page index
14100
		 * 2. `{int} pages` The number of pages in the table
14101
		 *
14102
		 * Each function is expected to return an array where each element of the
14103
		 * array can be one of:
14104
		 *
14105
		 * * `first` - Jump to first page when activated
14106
		 * * `last` - Jump to last page when activated
14107
		 * * `previous` - Show previous page when activated
14108
		 * * `next` - Show next page when activated
14109
		 * * `{int}` - Show page of the index given
14110
		 * * `{array}` - A nested array containing the above elements to add a
14111
		 *   containing 'DIV' element (might be useful for styling).
14112
		 *
14113
		 * Note that DataTables v1.9- used this object slightly differently whereby
14114
		 * an object with two functions would be defined for each plug-in. That
14115
		 * ability is still supported by DataTables 1.10+ to provide backwards
14116
		 * compatibility, but this option of use is now decremented and no longer
14117
		 * documented in DataTables 1.10+.
14118
		 *
14119
		 *  @type object
14120
		 *  @default {}
14121
		 *
14122
		 *  @example
14123
		 *    // Show previous, next and current page buttons only
14124
		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14125
		 *      return [ 'previous', page, 'next' ];
14126
		 *    };
14127
		 */
14128
		pager: {},
14129
	
14130
	
14131
		renderer: {
14132
			pageButton: {},
14133
			header: {}
14134
		},
14135
	
14136
	
14137
		/**
14138
		 * Ordering plug-ins - custom data source
14139
		 * 
14140
		 * The extension options for ordering of data available here is complimentary
14141
		 * to the default type based ordering that DataTables typically uses. It
14142
		 * allows much greater control over the the data that is being used to
14143
		 * order a column, but is necessarily therefore more complex.
14144
		 * 
14145
		 * This type of ordering is useful if you want to do ordering based on data
14146
		 * live from the DOM (for example the contents of an 'input' element) rather
14147
		 * than just the static string that DataTables knows of.
14148
		 * 
14149
		 * The way these plug-ins work is that you create an array of the values you
14150
		 * wish to be ordering for the column in question and then return that
14151
		 * array. The data in the array much be in the index order of the rows in
14152
		 * the table (not the currently ordering order!). Which order data gathering
14153
		 * function is run here depends on the `dt-init columns.orderDataType`
14154
		 * parameter that is used for the column (if any).
14155
		 *
14156
		 * The functions defined take two parameters:
14157
		 *
14158
		 * 1. `{object}` DataTables settings object: see
14159
		 *    {@link DataTable.models.oSettings}
14160
		 * 2. `{int}` Target column index
14161
		 *
14162
		 * Each function is expected to return an array:
14163
		 *
14164
		 * * `{array}` Data for the column to be ordering upon
14165
		 *
14166
		 *  @type array
14167
		 *
14168
		 *  @example
14169
		 *    // Ordering using `input` node values
14170
		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14171
		 *    {
14172
		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14173
		 *        return $('input', td).val();
14174
		 *      } );
14175
		 *    }
14176
		 */
14177
		order: {},
14178
	
14179
	
14180
		/**
14181
		 * Type based plug-ins.
14182
		 *
14183
		 * Each column in DataTables has a type assigned to it, either by automatic
14184
		 * detection or by direct assignment using the `type` option for the column.
14185
		 * The type of a column will effect how it is ordering and search (plug-ins
14186
		 * can also make use of the column type if required).
14187
		 *
14188
		 * @namespace
14189
		 */
14190
		type: {
14191
			/**
14192
			 * Type detection functions.
14193
			 *
14194
			 * The functions defined in this object are used to automatically detect
14195
			 * a column's type, making initialisation of DataTables super easy, even
14196
			 * when complex data is in the table.
14197
			 *
14198
			 * The functions defined take two parameters:
14199
			 *
14200
		     *  1. `{*}` Data from the column cell to be analysed
14201
		     *  2. `{settings}` DataTables settings object. This can be used to
14202
		     *     perform context specific type detection - for example detection
14203
		     *     based on language settings such as using a comma for a decimal
14204
		     *     place. Generally speaking the options from the settings will not
14205
		     *     be required
14206
			 *
14207
			 * Each function is expected to return:
14208
			 *
14209
			 * * `{string|null}` Data type detected, or null if unknown (and thus
14210
			 *   pass it on to the other type detection functions.
14211
			 *
14212
			 *  @type array
14213
			 *
14214
			 *  @example
14215
			 *    // Currency type detection plug-in:
14216
			 *    $.fn.dataTable.ext.type.detect.push(
14217
			 *      function ( data, settings ) {
14218
			 *        // Check the numeric part
14219
			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14220
			 *          return null;
14221
			 *        }
14222
			 *
14223
			 *        // Check prefixed by currency
14224
			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14225
			 *          return 'currency';
14226
			 *        }
14227
			 *        return null;
14228
			 *      }
14229
			 *    );
14230
			 */
14231
			detect: [],
14232
	
14233
	
14234
			/**
14235
			 * Type based search formatting.
14236
			 *
14237
			 * The type based searching functions can be used to pre-format the
14238
			 * data to be search on. For example, it can be used to strip HTML
14239
			 * tags or to de-format telephone numbers for numeric only searching.
14240
			 *
14241
			 * Note that is a search is not defined for a column of a given type,
14242
			 * no search formatting will be performed.
14243
			 * 
14244
			 * Pre-processing of searching data plug-ins - When you assign the sType
14245
			 * for a column (or have it automatically detected for you by DataTables
14246
			 * or a type detection plug-in), you will typically be using this for
14247
			 * custom sorting, but it can also be used to provide custom searching
14248
			 * by allowing you to pre-processing the data and returning the data in
14249
			 * the format that should be searched upon. This is done by adding
14250
			 * functions this object with a parameter name which matches the sType
14251
			 * for that target column. This is the corollary of <i>afnSortData</i>
14252
			 * for searching data.
14253
			 *
14254
			 * The functions defined take a single parameter:
14255
			 *
14256
		     *  1. `{*}` Data from the column cell to be prepared for searching
14257
			 *
14258
			 * Each function is expected to return:
14259
			 *
14260
			 * * `{string|null}` Formatted string that will be used for the searching.
14261
			 *
14262
			 *  @type object
14263
			 *  @default {}
14264
			 *
14265
			 *  @example
14266
			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14267
			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14268
			 *    }
14269
			 */
14270
			search: {},
14271
	
14272
	
14273
			/**
14274
			 * Type based ordering.
14275
			 *
14276
			 * The column type tells DataTables what ordering to apply to the table
14277
			 * when a column is sorted upon. The order for each type that is defined,
14278
			 * is defined by the functions available in this object.
14279
			 *
14280
			 * Each ordering option can be described by three properties added to
14281
			 * this object:
14282
			 *
14283
			 * * `{type}-pre` - Pre-formatting function
14284
			 * * `{type}-asc` - Ascending order function
14285
			 * * `{type}-desc` - Descending order function
14286
			 *
14287
			 * All three can be used together, only `{type}-pre` or only
14288
			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14289
			 * that only `{type}-pre` is used, as this provides the optimal
14290
			 * implementation in terms of speed, although the others are provided
14291
			 * for compatibility with existing Javascript sort functions.
14292
			 *
14293
			 * `{type}-pre`: Functions defined take a single parameter:
14294
			 *
14295
		     *  1. `{*}` Data from the column cell to be prepared for ordering
14296
			 *
14297
			 * And return:
14298
			 *
14299
			 * * `{*}` Data to be sorted upon
14300
			 *
14301
			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14302
			 * functions, taking two parameters:
14303
			 *
14304
		     *  1. `{*}` Data to compare to the second parameter
14305
		     *  2. `{*}` Data to compare to the first parameter
14306
			 *
14307
			 * And returning:
14308
			 *
14309
			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14310
			 *   than the second parameter, ===0 if the two parameters are equal and
14311
			 *   >0 if the first parameter should be sorted height than the second
14312
			 *   parameter.
14313
			 * 
14314
			 *  @type object
14315
			 *  @default {}
14316
			 *
14317
			 *  @example
14318
			 *    // Numeric ordering of formatted numbers with a pre-formatter
14319
			 *    $.extend( $.fn.dataTable.ext.type.order, {
14320
			 *      "string-pre": function(x) {
14321
			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14322
			 *        return parseFloat( a );
14323
			 *      }
14324
			 *    } );
14325
			 *
14326
			 *  @example
14327
			 *    // Case-sensitive string ordering, with no pre-formatting method
14328
			 *    $.extend( $.fn.dataTable.ext.order, {
14329
			 *      "string-case-asc": function(x,y) {
14330
			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14331
			 *      },
14332
			 *      "string-case-desc": function(x,y) {
14333
			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14334
			 *      }
14335
			 *    } );
14336
			 */
14337
			order: {}
14338
		},
14339
	
14340
		/**
14341
		 * Unique DataTables instance counter
14342
		 *
14343
		 * @type int
14344
		 * @private
14345
		 */
14346
		_unique: 0,
14347
	
14348
	
14349
		//
14350
		// Depreciated
14351
		// The following properties are retained for backwards compatiblity only.
14352
		// The should not be used in new projects and will be removed in a future
14353
		// version
14354
		//
14355
	
14356
		/**
14357
		 * Version check function.
14358
		 *  @type function
14359
		 *  @depreciated Since 1.10
14360
		 */
14361
		fnVersionCheck: DataTable.fnVersionCheck,
14362
	
14363
	
14364
		/**
14365
		 * Index for what 'this' index API functions should use
14366
		 *  @type int
14367
		 *  @deprecated Since v1.10
14368
		 */
14369
		iApiIndex: 0,
14370
	
14371
	
14372
		/**
14373
		 * jQuery UI class container
14374
		 *  @type object
14375
		 *  @deprecated Since v1.10
14376
		 */
14377
		oJUIClasses: {},
14378
	
14379
	
14380
		/**
14381
		 * Software version
14382
		 *  @type string
14383
		 *  @deprecated Since v1.10
14384
		 */
14385
		sVersion: DataTable.version
14386
	};
14387
	
14388
	
14389
	//
14390
	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14391
	//
14392
	$.extend( _ext, {
14393
		afnFiltering: _ext.search,
14394
		aTypes:       _ext.type.detect,
14395
		ofnSearch:    _ext.type.search,
14396
		oSort:        _ext.type.order,
14397
		afnSortData:  _ext.order,
14398
		aoFeatures:   _ext.feature,
14399
		oApi:         _ext.internal,
14400
		oStdClasses:  _ext.classes,
14401
		oPagination:  _ext.pager
14402
	} );
14403
	
14404
	
14405
	$.extend( DataTable.ext.classes, {
14406
		"sTable": "dataTable",
14407
		"sNoFooter": "no-footer",
14408
	
14409
		/* Paging buttons */
14410
		"sPageButton": "paginate_button",
14411
		"sPageButtonActive": "current",
14412
		"sPageButtonDisabled": "disabled",
14413
	
14414
		/* Striping classes */
14415
		"sStripeOdd": "odd",
14416
		"sStripeEven": "even",
14417
	
14418
		/* Empty row */
14419
		"sRowEmpty": "dataTables_empty",
14420
	
14421
		/* Features */
14422
		"sWrapper": "dataTables_wrapper",
14423
		"sFilter": "dataTables_filter",
14424
		"sInfo": "dataTables_info",
14425
		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14426
		"sLength": "dataTables_length",
14427
		"sProcessing": "dataTables_processing",
14428
	
14429
		/* Sorting */
14430
		"sSortAsc": "sorting_asc",
14431
		"sSortDesc": "sorting_desc",
14432
		"sSortable": "sorting", /* Sortable in both directions */
14433
		"sSortableAsc": "sorting_asc_disabled",
14434
		"sSortableDesc": "sorting_desc_disabled",
14435
		"sSortableNone": "sorting_disabled",
14436
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14437
	
14438
		/* Filtering */
14439
		"sFilterInput": "",
14440
	
14441
		/* Page length */
14442
		"sLengthSelect": "",
14443
	
14444
		/* Scrolling */
14445
		"sScrollWrapper": "dataTables_scroll",
14446
		"sScrollHead": "dataTables_scrollHead",
14447
		"sScrollHeadInner": "dataTables_scrollHeadInner",
14448
		"sScrollBody": "dataTables_scrollBody",
14449
		"sScrollFoot": "dataTables_scrollFoot",
14450
		"sScrollFootInner": "dataTables_scrollFootInner",
14451
	
14452
		/* Misc */
14453
		"sHeaderTH": "",
14454
		"sFooterTH": "",
14455
	
14456
		// Deprecated
14457
		"sSortJUIAsc": "",
14458
		"sSortJUIDesc": "",
14459
		"sSortJUI": "",
14460
		"sSortJUIAscAllowed": "",
14461
		"sSortJUIDescAllowed": "",
14462
		"sSortJUIWrapper": "",
14463
		"sSortIcon": "",
14464
		"sJUIHeader": "",
14465
		"sJUIFooter": ""
14466
	} );
14467
	
14468
	
14469
	var extPagination = DataTable.ext.pager;
14470
	
14471
	function _numbers ( page, pages ) {
14472
		var
14473
			numbers = [],
14474
			buttons = extPagination.numbers_length,
14475
			half = Math.floor( buttons / 2 ),
14476
			i = 1;
14477
	
14478
		if ( pages <= buttons ) {
14479
			numbers = _range( 0, pages );
14480
		}
14481
		else if ( page <= half ) {
14482
			numbers = _range( 0, buttons-2 );
14483
			numbers.push( 'ellipsis' );
14484
			numbers.push( pages-1 );
14485
		}
14486
		else if ( page >= pages - 1 - half ) {
14487
			numbers = _range( pages-(buttons-2), pages );
14488
			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14489
			numbers.splice( 0, 0, 0 );
14490
		}
14491
		else {
14492
			numbers = _range( page-half+2, page+half-1 );
14493
			numbers.push( 'ellipsis' );
14494
			numbers.push( pages-1 );
14495
			numbers.splice( 0, 0, 'ellipsis' );
14496
			numbers.splice( 0, 0, 0 );
14497
		}
14498
	
14499
		numbers.DT_el = 'span';
14500
		return numbers;
14501
	}
14502
	
14503
	
14504
	$.extend( extPagination, {
14505
		simple: function ( page, pages ) {
14506
			return [ 'previous', 'next' ];
14507
		},
14508
	
14509
		full: function ( page, pages ) {
14510
			return [  'first', 'previous', 'next', 'last' ];
14511
		},
14512
	
14513
		numbers: function ( page, pages ) {
14514
			return [ _numbers(page, pages) ];
14515
		},
14516
	
14517
		simple_numbers: function ( page, pages ) {
14518
			return [ 'previous', _numbers(page, pages), 'next' ];
14519
		},
14520
	
14521
		full_numbers: function ( page, pages ) {
14522
			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14523
		},
14524
		
14525
		first_last_numbers: function (page, pages) {
14526
	 		return ['first', _numbers(page, pages), 'last'];
14527
	 	},
14528
	
14529
		// For testing and plug-ins to use
14530
		_numbers: _numbers,
14531
	
14532
		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14533
		numbers_length: 7
14534
	} );
14535
	
14536
	
14537
	$.extend( true, DataTable.ext.renderer, {
14538
		pageButton: {
14539
			_: function ( settings, host, idx, buttons, page, pages ) {
14540
				var classes = settings.oClasses;
14541
				var lang = settings.oLanguage.oPaginate;
14542
				var aria = settings.oLanguage.oAria.paginate || {};
14543
				var btnDisplay, btnClass, counter=0;
14544
	
14545
				var attach = function( container, buttons ) {
14546
					var i, ien, node, button;
14547
					var clickHandler = function ( e ) {
14548
						_fnPageChange( settings, e.data.action, true );
14549
					};
14550
	
14551
					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14552
						button = buttons[i];
14553
	
14554
						if ( $.isArray( button ) ) {
14555
							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14556
								.appendTo( container );
14557
							attach( inner, button );
14558
						}
14559
						else {
14560
							btnDisplay = null;
14561
							btnClass = '';
14562
	
14563
							switch ( button ) {
14564
								case 'ellipsis':
14565
									container.append('<span class="ellipsis">&#x2026;</span>');
14566
									break;
14567
	
14568
								case 'first':
14569
									btnDisplay = lang.sFirst;
14570
									btnClass = button + (page > 0 ?
14571
										'' : ' '+classes.sPageButtonDisabled);
14572
									break;
14573
	
14574
								case 'previous':
14575
									btnDisplay = lang.sPrevious;
14576
									btnClass = button + (page > 0 ?
14577
										'' : ' '+classes.sPageButtonDisabled);
14578
									break;
14579
	
14580
								case 'next':
14581
									btnDisplay = lang.sNext;
14582
									btnClass = button + (page < pages-1 ?
14583
										'' : ' '+classes.sPageButtonDisabled);
14584
									break;
14585
	
14586
								case 'last':
14587
									btnDisplay = lang.sLast;
14588
									btnClass = button + (page < pages-1 ?
14589
										'' : ' '+classes.sPageButtonDisabled);
14590
									break;
14591
	
14592
								default:
14593
									btnDisplay = button + 1;
14594
									btnClass = page === button ?
14595
										classes.sPageButtonActive : '';
14596
									break;
14597
							}
14598
	
14599
							if ( btnDisplay !== null ) {
14600
								node = $('<a>', {
14601
										'class': classes.sPageButton+' '+btnClass,
14602
										'aria-controls': settings.sTableId,
14603
										'aria-label': aria[ button ],
14604
										'data-dt-idx': counter,
14605
										'tabindex': settings.iTabIndex,
14606
										'id': idx === 0 && typeof button === 'string' ?
14607
											settings.sTableId +'_'+ button :
14608
											null
14609
									} )
14610
									.html( btnDisplay )
14611
									.appendTo( container );
14612
	
14613
								_fnBindAction(
14614
									node, {action: button}, clickHandler
14615
								);
14616
	
14617
								counter++;
14618
							}
14619
						}
14620
					}
14621
				};
14622
	
14623
				// IE9 throws an 'unknown error' if document.activeElement is used
14624
				// inside an iframe or frame. Try / catch the error. Not good for
14625
				// accessibility, but neither are frames.
14626
				var activeEl;
14627
	
14628
				try {
14629
					// Because this approach is destroying and recreating the paging
14630
					// elements, focus is lost on the select button which is bad for
14631
					// accessibility. So we want to restore focus once the draw has
14632
					// completed
14633
					activeEl = $(host).find(document.activeElement).data('dt-idx');
14634
				}
14635
				catch (e) {}
14636
	
14637
				attach( $(host).empty(), buttons );
14638
	
14639
				if ( activeEl !== undefined ) {
14640
					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14641
				}
14642
			}
14643
		}
14644
	} );
14645
	
14646
	
14647
	
14648
	// Built in type detection. See model.ext.aTypes for information about
14649
	// what is required from this methods.
14650
	$.extend( DataTable.ext.type.detect, [
14651
		// Plain numbers - first since V8 detects some plain numbers as dates
14652
		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14653
		function ( d, settings )
14654
		{
14655
			var decimal = settings.oLanguage.sDecimal;
14656
			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14657
		},
14658
	
14659
		// Dates (only those recognised by the browser's Date.parse)
14660
		function ( d, settings )
14661
		{
14662
			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14663
			// valid, so we need to use a regex to restrict date formats. Use a
14664
			// plug-in for anything other than ISO8601 style strings
14665
			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14666
				return null;
14667
			}
14668
			var parsed = Date.parse(d);
14669
			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14670
		},
14671
	
14672
		// Formatted numbers
14673
		function ( d, settings )
14674
		{
14675
			var decimal = settings.oLanguage.sDecimal;
14676
			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14677
		},
14678
	
14679
		// HTML numeric
14680
		function ( d, settings )
14681
		{
14682
			var decimal = settings.oLanguage.sDecimal;
14683
			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14684
		},
14685
	
14686
		// HTML numeric, formatted
14687
		function ( d, settings )
14688
		{
14689
			var decimal = settings.oLanguage.sDecimal;
14690
			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14691
		},
14692
	
14693
		// HTML (this is strict checking - there must be html)
14694
		function ( d, settings )
14695
		{
14696
			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14697
				'html' : null;
14698
		}
14699
	] );
14700
	
14701
	
14702
	
14703
	// Filter formatting functions. See model.ext.ofnSearch for information about
14704
	// what is required from these methods.
14705
	// 
14706
	// Note that additional search methods are added for the html numbers and
14707
	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14708
	// place is
14709
	
14710
	
14711
	$.extend( DataTable.ext.type.search, {
14712
		html: function ( data ) {
14713
			return _empty(data) ?
14714
				data :
14715
				typeof data === 'string' ?
14716
					data
14717
						.replace( _re_new_lines, " " )
14718
						.replace( _re_html, "" ) :
14719
					'';
14720
		},
14721
	
14722
		string: function ( data ) {
14723
			return _empty(data) ?
14724
				data :
14725
				typeof data === 'string' ?
14726
					data.replace( _re_new_lines, " " ) :
14727
					data;
14728
		}
14729
	} );
14730
	
14731
	
14732
	
14733
	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14734
		if ( d !== 0 && (!d || d === '-') ) {
14735
			return -Infinity;
14736
		}
14737
	
14738
		// If a decimal place other than `.` is used, it needs to be given to the
14739
		// function so we can detect it and replace with a `.` which is the only
14740
		// decimal place Javascript recognises - it is not locale aware.
14741
		if ( decimalPlace ) {
14742
			d = _numToDecimal( d, decimalPlace );
14743
		}
14744
	
14745
		if ( d.replace ) {
14746
			if ( re1 ) {
14747
				d = d.replace( re1, '' );
14748
			}
14749
	
14750
			if ( re2 ) {
14751
				d = d.replace( re2, '' );
14752
			}
14753
		}
14754
	
14755
		return d * 1;
14756
	};
14757
	
14758
	
14759
	// Add the numeric 'deformatting' functions for sorting and search. This is done
14760
	// in a function to provide an easy ability for the language options to add
14761
	// additional methods if a non-period decimal place is used.
14762
	function _addNumericSort ( decimalPlace ) {
14763
		$.each(
14764
			{
14765
				// Plain numbers
14766
				"num": function ( d ) {
14767
					return __numericReplace( d, decimalPlace );
14768
				},
14769
	
14770
				// Formatted numbers
14771
				"num-fmt": function ( d ) {
14772
					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14773
				},
14774
	
14775
				// HTML numeric
14776
				"html-num": function ( d ) {
14777
					return __numericReplace( d, decimalPlace, _re_html );
14778
				},
14779
	
14780
				// HTML numeric, formatted
14781
				"html-num-fmt": function ( d ) {
14782
					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14783
				}
14784
			},
14785
			function ( key, fn ) {
14786
				// Add the ordering method
14787
				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14788
	
14789
				// For HTML types add a search formatter that will strip the HTML
14790
				if ( key.match(/^html\-/) ) {
14791
					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14792
				}
14793
			}
14794
		);
14795
	}
14796
	
14797
	
14798
	// Default sort methods
14799
	$.extend( _ext.type.order, {
14800
		// Dates
14801
		"date-pre": function ( d ) {
14802
			var ts = Date.parse( d );
14803
			return isNaN(ts) ? -Infinity : ts;
14804
		},
14805
	
14806
		// html
14807
		"html-pre": function ( a ) {
14808
			return _empty(a) ?
14809
				'' :
14810
				a.replace ?
14811
					a.replace( /<.*?>/g, "" ).toLowerCase() :
14812
					a+'';
14813
		},
14814
	
14815
		// string
14816
		"string-pre": function ( a ) {
14817
			// This is a little complex, but faster than always calling toString,
14818
			// http://jsperf.com/tostring-v-check
14819
			return _empty(a) ?
14820
				'' :
14821
				typeof a === 'string' ?
14822
					a.toLowerCase() :
14823
					! a.toString ?
14824
						'' :
14825
						a.toString();
14826
		},
14827
	
14828
		// string-asc and -desc are retained only for compatibility with the old
14829
		// sort methods
14830
		"string-asc": function ( x, y ) {
14831
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14832
		},
14833
	
14834
		"string-desc": function ( x, y ) {
14835
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14836
		}
14837
	} );
14838
	
14839
	
14840
	// Numeric sorting types - order doesn't matter here
14841
	_addNumericSort( '' );
14842
	
14843
	
14844
	$.extend( true, DataTable.ext.renderer, {
14845
		header: {
14846
			_: function ( settings, cell, column, classes ) {
14847
				// No additional mark-up required
14848
				// Attach a sort listener to update on sort - note that using the
14849
				// `DT` namespace will allow the event to be removed automatically
14850
				// on destroy, while the `dt` namespaced event is the one we are
14851
				// listening for
14852
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14853
					if ( settings !== ctx ) { // need to check this this is the host
14854
						return;               // table, not a nested one
14855
					}
14856
	
14857
					var colIdx = column.idx;
14858
	
14859
					cell
14860
						.removeClass(
14861
							column.sSortingClass +' '+
14862
							classes.sSortAsc +' '+
14863
							classes.sSortDesc
14864
						)
14865
						.addClass( columns[ colIdx ] == 'asc' ?
14866
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14867
								classes.sSortDesc :
14868
								column.sSortingClass
14869
						);
14870
				} );
14871
			},
14872
	
14873
			jqueryui: function ( settings, cell, column, classes ) {
14874
				$('<div/>')
14875
					.addClass( classes.sSortJUIWrapper )
14876
					.append( cell.contents() )
14877
					.append( $('<span/>')
14878
						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14879
					)
14880
					.appendTo( cell );
14881
	
14882
				// Attach a sort listener to update on sort
14883
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14884
					if ( settings !== ctx ) {
14885
						return;
14886
					}
14887
	
14888
					var colIdx = column.idx;
14889
	
14890
					cell
14891
						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14892
						.addClass( columns[ colIdx ] == 'asc' ?
14893
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14894
								classes.sSortDesc :
14895
								column.sSortingClass
14896
						);
14897
	
14898
					cell
14899
						.find( 'span.'+classes.sSortIcon )
14900
						.removeClass(
14901
							classes.sSortJUIAsc +" "+
14902
							classes.sSortJUIDesc +" "+
14903
							classes.sSortJUI +" "+
14904
							classes.sSortJUIAscAllowed +" "+
14905
							classes.sSortJUIDescAllowed
14906
						)
14907
						.addClass( columns[ colIdx ] == 'asc' ?
14908
							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14909
								classes.sSortJUIDesc :
14910
								column.sSortingClassJUI
14911
						);
14912
				} );
14913
			}
14914
		}
14915
	} );
14916
	
14917
	/*
14918
	 * Public helper functions. These aren't used internally by DataTables, or
14919
	 * called by any of the options passed into DataTables, but they can be used
14920
	 * externally by developers working with DataTables. They are helper functions
14921
	 * to make working with DataTables a little bit easier.
14922
	 */
14923
	
14924
	var __htmlEscapeEntities = function ( d ) {
14925
		return typeof d === 'string' ?
14926
			d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14927
			d;
14928
	};
14929
	
14930
	/**
14931
	 * Helpers for `columns.render`.
14932
	 *
14933
	 * The options defined here can be used with the `columns.render` initialisation
14934
	 * option to provide a display renderer. The following functions are defined:
14935
	 *
14936
	 * * `number` - Will format numeric data (defined by `columns.data`) for
14937
	 *   display, retaining the original unformatted data for sorting and filtering.
14938
	 *   It takes 5 parameters:
14939
	 *   * `string` - Thousands grouping separator
14940
	 *   * `string` - Decimal point indicator
14941
	 *   * `integer` - Number of decimal points to show
14942
	 *   * `string` (optional) - Prefix.
14943
	 *   * `string` (optional) - Postfix (/suffix).
14944
	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14945
	 *   parameters.
14946
	 *
14947
	 * @example
14948
	 *   // Column definition using the number renderer
14949
	 *   {
14950
	 *     data: "salary",
14951
	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14952
	 *   }
14953
	 *
14954
	 * @namespace
14955
	 */
14956
	DataTable.render = {
14957
		number: function ( thousands, decimal, precision, prefix, postfix ) {
14958
			return {
14959
				display: function ( d ) {
14960
					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14961
						return d;
14962
					}
14963
	
14964
					var negative = d < 0 ? '-' : '';
14965
					var flo = parseFloat( d );
14966
	
14967
					// If NaN then there isn't much formatting that we can do - just
14968
					// return immediately, escaping any HTML (this was supposed to
14969
					// be a number after all)
14970
					if ( isNaN( flo ) ) {
14971
						return __htmlEscapeEntities( d );
14972
					}
14973
	
14974
					flo = flo.toFixed( precision );
14975
					d = Math.abs( flo );
14976
	
14977
					var intPart = parseInt( d, 10 );
14978
					var floatPart = precision ?
14979
						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14980
						'';
14981
	
14982
					return negative + (prefix||'') +
14983
						intPart.toString().replace(
14984
							/\B(?=(\d{3})+(?!\d))/g, thousands
14985
						) +
14986
						floatPart +
14987
						(postfix||'');
14988
				}
14989
			};
14990
		},
14991
	
14992
		text: function () {
14993
			return {
14994
				display: __htmlEscapeEntities
14995
			};
14996
		}
14997
	};
14998
	
14999
	
15000
	/*
15001
	 * This is really a good bit rubbish this method of exposing the internal methods
15002
	 * publicly... - To be fixed in 2.0 using methods on the prototype
15003
	 */
15004
	
15005
	
15006
	/**
15007
	 * Create a wrapper function for exporting an internal functions to an external API.
15008
	 *  @param {string} fn API function name
15009
	 *  @returns {function} wrapped function
15010
	 *  @memberof DataTable#internal
15011
	 */
15012
	function _fnExternApiFunc (fn)
15013
	{
15014
		return function() {
15015
			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15016
				Array.prototype.slice.call(arguments)
15017
			);
15018
			return DataTable.ext.internal[fn].apply( this, args );
15019
		};
15020
	}
15021
	
15022
	
15023
	/**
15024
	 * Reference to internal functions for use by plug-in developers. Note that
15025
	 * these methods are references to internal functions and are considered to be
15026
	 * private. If you use these methods, be aware that they are liable to change
15027
	 * between versions.
15028
	 *  @namespace
15029
	 */
15030
	$.extend( DataTable.ext.internal, {
15031
		_fnExternApiFunc: _fnExternApiFunc,
15032
		_fnBuildAjax: _fnBuildAjax,
15033
		_fnAjaxUpdate: _fnAjaxUpdate,
15034
		_fnAjaxParameters: _fnAjaxParameters,
15035
		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15036
		_fnAjaxDataSrc: _fnAjaxDataSrc,
15037
		_fnAddColumn: _fnAddColumn,
15038
		_fnColumnOptions: _fnColumnOptions,
15039
		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15040
		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15041
		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15042
		_fnVisbleColumns: _fnVisbleColumns,
15043
		_fnGetColumns: _fnGetColumns,
15044
		_fnColumnTypes: _fnColumnTypes,
15045
		_fnApplyColumnDefs: _fnApplyColumnDefs,
15046
		_fnHungarianMap: _fnHungarianMap,
15047
		_fnCamelToHungarian: _fnCamelToHungarian,
15048
		_fnLanguageCompat: _fnLanguageCompat,
15049
		_fnBrowserDetect: _fnBrowserDetect,
15050
		_fnAddData: _fnAddData,
15051
		_fnAddTr: _fnAddTr,
15052
		_fnNodeToDataIndex: _fnNodeToDataIndex,
15053
		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15054
		_fnGetCellData: _fnGetCellData,
15055
		_fnSetCellData: _fnSetCellData,
15056
		_fnSplitObjNotation: _fnSplitObjNotation,
15057
		_fnGetObjectDataFn: _fnGetObjectDataFn,
15058
		_fnSetObjectDataFn: _fnSetObjectDataFn,
15059
		_fnGetDataMaster: _fnGetDataMaster,
15060
		_fnClearTable: _fnClearTable,
15061
		_fnDeleteIndex: _fnDeleteIndex,
15062
		_fnInvalidate: _fnInvalidate,
15063
		_fnGetRowElements: _fnGetRowElements,
15064
		_fnCreateTr: _fnCreateTr,
15065
		_fnBuildHead: _fnBuildHead,
15066
		_fnDrawHead: _fnDrawHead,
15067
		_fnDraw: _fnDraw,
15068
		_fnReDraw: _fnReDraw,
15069
		_fnAddOptionsHtml: _fnAddOptionsHtml,
15070
		_fnDetectHeader: _fnDetectHeader,
15071
		_fnGetUniqueThs: _fnGetUniqueThs,
15072
		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15073
		_fnFilterComplete: _fnFilterComplete,
15074
		_fnFilterCustom: _fnFilterCustom,
15075
		_fnFilterColumn: _fnFilterColumn,
15076
		_fnFilter: _fnFilter,
15077
		_fnFilterCreateSearch: _fnFilterCreateSearch,
15078
		_fnEscapeRegex: _fnEscapeRegex,
15079
		_fnFilterData: _fnFilterData,
15080
		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15081
		_fnUpdateInfo: _fnUpdateInfo,
15082
		_fnInfoMacros: _fnInfoMacros,
15083
		_fnInitialise: _fnInitialise,
15084
		_fnInitComplete: _fnInitComplete,
15085
		_fnLengthChange: _fnLengthChange,
15086
		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15087
		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15088
		_fnPageChange: _fnPageChange,
15089
		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15090
		_fnProcessingDisplay: _fnProcessingDisplay,
15091
		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15092
		_fnScrollDraw: _fnScrollDraw,
15093
		_fnApplyToChildren: _fnApplyToChildren,
15094
		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15095
		_fnThrottle: _fnThrottle,
15096
		_fnConvertToWidth: _fnConvertToWidth,
15097
		_fnGetWidestNode: _fnGetWidestNode,
15098
		_fnGetMaxLenString: _fnGetMaxLenString,
15099
		_fnStringToCss: _fnStringToCss,
15100
		_fnSortFlatten: _fnSortFlatten,
15101
		_fnSort: _fnSort,
15102
		_fnSortAria: _fnSortAria,
15103
		_fnSortListener: _fnSortListener,
15104
		_fnSortAttachListener: _fnSortAttachListener,
15105
		_fnSortingClasses: _fnSortingClasses,
15106
		_fnSortData: _fnSortData,
15107
		_fnSaveState: _fnSaveState,
15108
		_fnLoadState: _fnLoadState,
15109
		_fnSettingsFromNode: _fnSettingsFromNode,
15110
		_fnLog: _fnLog,
15111
		_fnMap: _fnMap,
15112
		_fnBindAction: _fnBindAction,
15113
		_fnCallbackReg: _fnCallbackReg,
15114
		_fnCallbackFire: _fnCallbackFire,
15115
		_fnLengthOverflow: _fnLengthOverflow,
15116
		_fnRenderer: _fnRenderer,
15117
		_fnDataSource: _fnDataSource,
15118
		_fnRowAttributes: _fnRowAttributes,
15119
		_fnExtend: _fnExtend,
15120
		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15121
		                                // in 1.10, so this dead-end function is
15122
		                                // added to prevent errors
15123
	} );
15124
	
15125
15126
	// jQuery access
15127
	$.fn.dataTable = DataTable;
15128
15129
	// Provide access to the host jQuery object (circular reference)
15130
	DataTable.$ = $;
15131
15132
	// Legacy aliases
15133
	$.fn.dataTableSettings = DataTable.settings;
15134
	$.fn.dataTableExt = DataTable.ext;
15135
15136
	// With a capital `D` we return a DataTables API instance rather than a
15137
	// jQuery object
15138
	$.fn.DataTable = function ( opts ) {
15139
		return $(this).dataTable( opts ).api();
15140
	};
15141
15142
	// All properties that are available to $.fn.dataTable should also be
15143
	// available on $.fn.DataTable
15144
	$.each( DataTable, function ( prop, val ) {
15145
		$.fn.DataTable[ prop ] = val;
15146
	} );
15147
15148
15149
	// Information about events fired by DataTables - for documentation.
15150
	/**
15151
	 * Draw event, fired whenever the table is redrawn on the page, at the same
15152
	 * point as fnDrawCallback. This may be useful for binding events or
15153
	 * performing calculations when the table is altered at all.
15154
	 *  @name DataTable#draw.dt
15155
	 *  @event
15156
	 *  @param {event} e jQuery event object
15157
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15158
	 */
15159
15160
	/**
15161
	 * Search event, fired when the searching applied to the table (using the
15162
	 * built-in global search, or column filters) is altered.
15163
	 *  @name DataTable#search.dt
15164
	 *  @event
15165
	 *  @param {event} e jQuery event object
15166
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15167
	 */
15168
15169
	/**
15170
	 * Page change event, fired when the paging of the table is altered.
15171
	 *  @name DataTable#page.dt
15172
	 *  @event
15173
	 *  @param {event} e jQuery event object
15174
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15175
	 */
15176
15177
	/**
15178
	 * Order event, fired when the ordering applied to the table is altered.
15179
	 *  @name DataTable#order.dt
15180
	 *  @event
15181
	 *  @param {event} e jQuery event object
15182
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15183
	 */
15184
15185
	/**
15186
	 * DataTables initialisation complete event, fired when the table is fully
15187
	 * drawn, including Ajax data loaded, if Ajax data is required.
15188
	 *  @name DataTable#init.dt
15189
	 *  @event
15190
	 *  @param {event} e jQuery event object
15191
	 *  @param {object} oSettings DataTables settings object
15192
	 *  @param {object} json The JSON object request from the server - only
15193
	 *    present if client-side Ajax sourced data is used</li></ol>
15194
	 */
15195
15196
	/**
15197
	 * State save event, fired when the table has changed state a new state save
15198
	 * is required. This event allows modification of the state saving object
15199
	 * prior to actually doing the save, including addition or other state
15200
	 * properties (for plug-ins) or modification of a DataTables core property.
15201
	 *  @name DataTable#stateSaveParams.dt
15202
	 *  @event
15203
	 *  @param {event} e jQuery event object
15204
	 *  @param {object} oSettings DataTables settings object
15205
	 *  @param {object} json The state information to be saved
15206
	 */
15207
15208
	/**
15209
	 * State load event, fired when the table is loading state from the stored
15210
	 * data, but prior to the settings object being modified by the saved state
15211
	 * - allowing modification of the saved state is required or loading of
15212
	 * state for a plug-in.
15213
	 *  @name DataTable#stateLoadParams.dt
15214
	 *  @event
15215
	 *  @param {event} e jQuery event object
15216
	 *  @param {object} oSettings DataTables settings object
15217
	 *  @param {object} json The saved state information
15218
	 */
15219
15220
	/**
15221
	 * State loaded event, fired when state has been loaded from stored data and
15222
	 * the settings object has been modified by the loaded data.
15223
	 *  @name DataTable#stateLoaded.dt
15224
	 *  @event
15225
	 *  @param {event} e jQuery event object
15226
	 *  @param {object} oSettings DataTables settings object
15227
	 *  @param {object} json The saved state information
15228
	 */
15229
15230
	/**
15231
	 * Processing event, fired when DataTables is doing some kind of processing
15232
	 * (be it, order, searcg or anything else). It can be used to indicate to
15233
	 * the end user that there is something happening, or that something has
15234
	 * finished.
15235
	 *  @name DataTable#processing.dt
15236
	 *  @event
15237
	 *  @param {event} e jQuery event object
15238
	 *  @param {object} oSettings DataTables settings object
15239
	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15240
	 */
15241
15242
	/**
15243
	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15244
	 * request to made to the server for new data. This event is called before
15245
	 * DataTables processed the returned data, so it can also be used to pre-
15246
	 * process the data returned from the server, if needed.
15247
	 *
15248
	 * Note that this trigger is called in `fnServerData`, if you override
15249
	 * `fnServerData` and which to use this event, you need to trigger it in you
15250
	 * success function.
15251
	 *  @name DataTable#xhr.dt
15252
	 *  @event
15253
	 *  @param {event} e jQuery event object
15254
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15255
	 *  @param {object} json JSON returned from the server
15256
	 *
15257
	 *  @example
15258
	 *     // Use a custom property returned from the server in another DOM element
15259
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15260
	 *       $('#status').html( json.status );
15261
	 *     } );
15262
	 *
15263
	 *  @example
15264
	 *     // Pre-process the data returned from the server
15265
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15266
	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15267
	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15268
	 *       }
15269
	 *       // Note no return - manipulate the data directly in the JSON object.
15270
	 *     } );
15271
	 */
15272
15273
	/**
15274
	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15275
	 * or passing the bDestroy:true parameter in the initialisation object. This
15276
	 * can be used to remove bound events, added DOM nodes, etc.
15277
	 *  @name DataTable#destroy.dt
15278
	 *  @event
15279
	 *  @param {event} e jQuery event object
15280
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15281
	 */
15282
15283
	/**
15284
	 * Page length change event, fired when number of records to show on each
15285
	 * page (the length) is changed.
15286
	 *  @name DataTable#length.dt
15287
	 *  @event
15288
	 *  @param {event} e jQuery event object
15289
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15290
	 *  @param {integer} len New length
15291
	 */
15292
15293
	/**
15294
	 * Column sizing has changed.
15295
	 *  @name DataTable#column-sizing.dt
15296
	 *  @event
15297
	 *  @param {event} e jQuery event object
15298
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15299
	 */
15300
15301
	/**
15302
	 * Column visibility has changed.
15303
	 *  @name DataTable#column-visibility.dt
15304
	 *  @event
15305
	 *  @param {event} e jQuery event object
15306
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15307
	 *  @param {int} column Column index
15308
	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15309
	 */
15310
15311
	return $.fn.dataTable;
15312
}));
15313
15314
15315
/*! DataTables Bootstrap 4 integration
15316
 * ©2011-2017 SpryMedia Ltd - datatables.net/license
15317
 */
15318
15319
/**
15320
 * DataTables integration for Bootstrap 4. This requires Bootstrap 4 and
15321
 * DataTables 1.10 or newer.
15322
 *
15323
 * This file sets the defaults and adds options to DataTables to style its
15324
 * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
15325
 * for further information.
15326
 */
15327
(function( factory ){
15328
	if ( typeof define === 'function' && define.amd ) {
15329
		// AMD
15330
		define( ['jquery', 'datatables.net'], function ( $ ) {
15331
			return factory( $, window, document );
15332
		} );
15333
	}
15334
	else if ( typeof exports === 'object' ) {
15335
		// CommonJS
15336
		module.exports = function (root, $) {
15337
			if ( ! root ) {
15338
				root = window;
15339
			}
15340
15341
			if ( ! $ || ! $.fn.dataTable ) {
15342
				// Require DataTables, which attaches to jQuery, including
15343
				// jQuery if needed and have a $ property so we can access the
15344
				// jQuery object that is used
15345
				$ = require('datatables.net')(root, $).$;
15346
			}
15347
15348
			return factory( $, root, root.document );
15349
		};
15350
	}
15351
	else {
15352
		// Browser
15353
		factory( jQuery, window, document );
15354
	}
15355
}(function( $, window, document, undefined ) {
15356
'use strict';
15357
var DataTable = $.fn.dataTable;
15358
15359
15360
/* Set the defaults for DataTables initialisation */
15361
$.extend( true, DataTable.defaults, {
15362
	dom:
15363
		"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" +
15364
		"<'row'<'col-sm-12'tr>>" +
15365
		"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
15366
	renderer: 'bootstrap'
15367
} );
15368
15369
15370
/* Default class modification */
15371
$.extend( DataTable.ext.classes, {
15372
	sWrapper:      "dataTables_wrapper dt-bootstrap4",
15373
	sFilterInput:  "form-control form-control-sm",
15374
	sLengthSelect: "custom-select custom-select-sm form-control form-control-sm",
15375
	sProcessing:   "dataTables_processing card",
15376
	sPageButton:   "paginate_button page-item"
15377
} );
15378
15379
15380
/* Bootstrap paging button renderer */
15381
DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
15382
	var api     = new DataTable.Api( settings );
15383
	var classes = settings.oClasses;
15384
	var lang    = settings.oLanguage.oPaginate;
15385
	var aria = settings.oLanguage.oAria.paginate || {};
15386
	var btnDisplay, btnClass, counter=0;
15387
15388
	var attach = function( container, buttons ) {
15389
		var i, ien, node, button;
15390
		var clickHandler = function ( e ) {
15391
			e.preventDefault();
15392
			if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
15393
				api.page( e.data.action ).draw( 'page' );
15394
			}
15395
		};
15396
15397
		for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
15398
			button = buttons[i];
15399
15400
			if ( $.isArray( button ) ) {
15401
				attach( container, button );
15402
			}
15403
			else {
15404
				btnDisplay = '';
15405
				btnClass = '';
15406
15407
				switch ( button ) {
15408
					case 'ellipsis':
15409
						btnDisplay = '&#x2026;';
15410
						btnClass = 'disabled';
15411
						break;
15412
15413
					case 'first':
15414
						btnDisplay = lang.sFirst;
15415
						btnClass = button + (page > 0 ?
15416
							'' : ' disabled');
15417
						break;
15418
15419
					case 'previous':
15420
						btnDisplay = lang.sPrevious;
15421
						btnClass = button + (page > 0 ?
15422
							'' : ' disabled');
15423
						break;
15424
15425
					case 'next':
15426
						btnDisplay = lang.sNext;
15427
						btnClass = button + (page < pages-1 ?
15428
							'' : ' disabled');
15429
						break;
15430
15431
					case 'last':
15432
						btnDisplay = lang.sLast;
15433
						btnClass = button + (page < pages-1 ?
15434
							'' : ' disabled');
15435
						break;
15436
15437
					default:
15438
						btnDisplay = button + 1;
15439
						btnClass = page === button ?
15440
							'active' : '';
15441
						break;
15442
				}
15443
15444
				if ( btnDisplay ) {
15445
					node = $('<li>', {
15446
							'class': classes.sPageButton+' '+btnClass,
15447
							'id': idx === 0 && typeof button === 'string' ?
15448
								settings.sTableId +'_'+ button :
15449
								null
15450
						} )
15451
						.append( $('<a>', {
15452
								'href': '#',
15453
								'aria-controls': settings.sTableId,
15454
								'aria-label': aria[ button ],
15455
								'data-dt-idx': counter,
15456
								'tabindex': settings.iTabIndex,
15457
								'class': 'page-link'
15458
							} )
15459
							.html( btnDisplay )
15460
						)
15461
						.appendTo( container );
15462
15463
					settings.oApi._fnBindAction(
15464
						node, {action: button}, clickHandler
15465
					);
15466
15467
					counter++;
15468
				}
15469
			}
15470
		}
15471
	};
15472
15473
	// IE9 throws an 'unknown error' if document.activeElement is used
15474
	// inside an iframe or frame. 
15475
	var activeEl;
15476
15477
	try {
15478
		// Because this approach is destroying and recreating the paging
15479
		// elements, focus is lost on the select button which is bad for
15480
		// accessibility. So we want to restore focus once the draw has
15481
		// completed
15482
		activeEl = $(host).find(document.activeElement).data('dt-idx');
15483
	}
15484
	catch (e) {}
15485
15486
	attach(
15487
		$(host).empty().html('<ul class="pagination"/>').children('ul'),
15488
		buttons
15489
	);
15490
15491
	if ( activeEl !== undefined ) {
15492
		$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
15493
	}
15494
};
15495
15496
15497
return DataTable;
15498
}));
15499
15500
15501