Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14491 manish.sha 1
/*! DataTables 1.10.3
2
 * ©2008-2014 SpryMedia Ltd - datatables.net/license
3
 */
4
 
5
/**
6
 * @summary     DataTables
7
 * @description Paginate, search and order HTML tables
8
 * @version     1.10.3
9
 * @file        jquery.dataTables.js
10
 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11
 * @contact     www.sprymedia.co.uk/contact
12
 * @copyright   Copyright 2008-2014 SpryMedia Ltd.
13
 *
14
 * This source file is free software, available under the following license:
15
 *   MIT license - http://datatables.net/license
16
 *
17
 * This source file is distributed in the hope that it will be useful, but
18
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20
 *
21
 * For details please refer to: http://www.datatables.net
22
 */
23
 
24
/*jslint evil: true, undef: true, browser: true */
25
/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidateRow,_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,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26
 
27
(/** @lends <global> */function( window, document, undefined ) {
28
 
29
(function( factory ) {
30
	"use strict";
31
 
32
	if ( typeof define === 'function' && define.amd ) {
33
		// Define as an AMD module if possible
34
		define( 'datatables', ['jquery'], factory );
35
	}
36
    else if ( typeof exports === 'object' ) {
37
        // Node/CommonJS
38
        factory( require( 'jquery' ) );
39
    }
40
	else if ( jQuery && !jQuery.fn.dataTable ) {
41
		// Define using browser globals otherwise
42
		// Prevent multiple instantiations if the script is loaded twice
43
		factory( jQuery );
44
	}
45
}
46
(/** @lends <global> */function( $ ) {
47
	"use strict";
48
 
49
	/**
50
	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
51
	 * flexible tool, based upon the foundations of progressive enhancement,
52
	 * which will add advanced interaction controls to any HTML table. For a
53
	 * full list of features please refer to
54
	 * [DataTables.net](href="http://datatables.net).
55
	 *
56
	 * Note that the `DataTable` object is not a global variable but is aliased
57
	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
58
	 * be  accessed.
59
	 *
60
	 *  @class
61
	 *  @param {object} [init={}] Configuration object for DataTables. Options
62
	 *    are defined by {@link DataTable.defaults}
63
	 *  @requires jQuery 1.7+
64
	 *
65
	 *  @example
66
	 *    // Basic initialisation
67
	 *    $(document).ready( function {
68
	 *      $('#example').dataTable();
69
	 *    } );
70
	 *
71
	 *  @example
72
	 *    // Initialisation with configuration options - in this case, disable
73
	 *    // pagination and sorting.
74
	 *    $(document).ready( function {
75
	 *      $('#example').dataTable( {
76
	 *        "paginate": false,
77
	 *        "sort": false
78
	 *      } );
79
	 *    } );
80
	 */
81
	var DataTable;
82
 
83
 
84
	/*
85
	 * It is useful to have variables which are scoped locally so only the
86
	 * DataTables functions can access them and they don't leak into global space.
87
	 * At the same time these functions are often useful over multiple files in the
88
	 * core and API, so we list, or at least document, all variables which are used
89
	 * by DataTables as private variables here. This also ensures that there is no
90
	 * clashing of variable names and that they can easily referenced for reuse.
91
	 */
92
 
93
 
94
	// Defined else where
95
	//  _selector_run
96
	//  _selector_opts
97
	//  _selector_first
98
	//  _selector_row_indexes
99
 
100
	var _ext; // DataTable.ext
101
	var _Api; // DataTable.Api
102
	var _api_register; // DataTable.Api.register
103
	var _api_registerPlural; // DataTable.Api.registerPlural
104
 
105
	var _re_dic = {};
106
	var _re_new_lines = /[\r\n]/g;
107
	var _re_html = /<.*?>/g;
108
	var _re_date_start = /^[\w\+\-]/;
109
	var _re_date_end = /[\w\+\-]$/;
110
 
111
	// Escape regular expression special characters
112
	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
113
 
114
	// U+2009 is thin space and U+202F is narrow no-break space, both used in many
115
	// standards as thousands separators
116
	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F]/g;
117
 
118
 
119
	var _empty = function ( d ) {
120
		return !d || d === true || d === '-' ? true : false;
121
	};
122
 
123
 
124
	var _intVal = function ( s ) {
125
		var integer = parseInt( s, 10 );
126
		return !isNaN(integer) && isFinite(s) ? integer : null;
127
	};
128
 
129
	// Convert from a formatted number with characters other than `.` as the
130
	// decimal place, to a Javascript number
131
	var _numToDecimal = function ( num, decimalPoint ) {
132
		// Cache created regular expressions for speed as this function is called often
133
		if ( ! _re_dic[ decimalPoint ] ) {
134
			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
135
		}
136
		return typeof num === 'string' && decimalPoint !== '.' ?
137
			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
138
			num;
139
	};
140
 
141
 
142
	var _isNumber = function ( d, decimalPoint, formatted ) {
143
		var strType = typeof d === 'string';
144
 
145
		if ( decimalPoint && strType ) {
146
			d = _numToDecimal( d, decimalPoint );
147
		}
148
 
149
		if ( formatted && strType ) {
150
			d = d.replace( _re_formatted_numeric, '' );
151
		}
152
 
153
		return _empty( d ) || (!isNaN( parseFloat(d) ) && isFinite( d ));
154
	};
155
 
156
 
157
	// A string without HTML in it can be considered to be HTML still
158
	var _isHtml = function ( d ) {
159
		return _empty( d ) || typeof d === 'string';
160
	};
161
 
162
 
163
	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
164
		if ( _empty( d ) ) {
165
			return true;
166
		}
167
 
168
		var html = _isHtml( d );
169
		return ! html ?
170
			null :
171
			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
172
				true :
173
				null;
174
	};
175
 
176
 
177
	var _pluck = function ( a, prop, prop2 ) {
178
		var out = [];
179
		var i=0, ien=a.length;
180
 
181
		// Could have the test in the loop for slightly smaller code, but speed
182
		// is essential here
183
		if ( prop2 !== undefined ) {
184
			for ( ; i<ien ; i++ ) {
185
				if ( a[i] && a[i][ prop ] ) {
186
					out.push( a[i][ prop ][ prop2 ] );
187
				}
188
			}
189
		}
190
		else {
191
			for ( ; i<ien ; i++ ) {
192
				if ( a[i] ) {
193
					out.push( a[i][ prop ] );
194
				}
195
			}
196
		}
197
 
198
		return out;
199
	};
200
 
201
 
202
	// Basically the same as _pluck, but rather than looping over `a` we use `order`
203
	// as the indexes to pick from `a`
204
	var _pluck_order = function ( a, order, prop, prop2 )
205
	{
206
		var out = [];
207
		var i=0, ien=order.length;
208
 
209
		// Could have the test in the loop for slightly smaller code, but speed
210
		// is essential here
211
		if ( prop2 !== undefined ) {
212
			for ( ; i<ien ; i++ ) {
213
				out.push( a[ order[i] ][ prop ][ prop2 ] );
214
			}
215
		}
216
		else {
217
			for ( ; i<ien ; i++ ) {
218
				out.push( a[ order[i] ][ prop ] );
219
			}
220
		}
221
 
222
		return out;
223
	};
224
 
225
 
226
	var _range = function ( len, start )
227
	{
228
		var out = [];
229
		var end;
230
 
231
		if ( start === undefined ) {
232
			start = 0;
233
			end = len;
234
		}
235
		else {
236
			end = start;
237
			start = len;
238
		}
239
 
240
		for ( var i=start ; i<end ; i++ ) {
241
			out.push( i );
242
		}
243
 
244
		return out;
245
	};
246
 
247
 
248
	var _stripHtml = function ( d ) {
249
		return d.replace( _re_html, '' );
250
	};
251
 
252
 
253
	/**
254
	 * Find the unique elements in a source array.
255
	 *
256
	 * @param  {array} src Source array
257
	 * @return {array} Array of unique items
258
	 * @ignore
259
	 */
260
	var _unique = function ( src )
261
	{
262
		// A faster unique method is to use object keys to identify used values,
263
		// but this doesn't work with arrays or objects, which we must also
264
		// consider. See jsperf.com/compare-array-unique-versions/4 for more
265
		// information.
266
		var
267
			out = [],
268
			val,
269
			i, ien=src.length,
270
			j, k=0;
271
 
272
		again: for ( i=0 ; i<ien ; i++ ) {
273
			val = src[i];
274
 
275
			for ( j=0 ; j<k ; j++ ) {
276
				if ( out[j] === val ) {
277
					continue again;
278
				}
279
			}
280
 
281
			out.push( val );
282
			k++;
283
		}
284
 
285
		return out;
286
	};
287
 
288
 
289
 
290
	/**
291
	 * Create a mapping object that allows camel case parameters to be looked up
292
	 * for their Hungarian counterparts. The mapping is stored in a private
293
	 * parameter called `_hungarianMap` which can be accessed on the source object.
294
	 *  @param {object} o
295
	 *  @memberof DataTable#oApi
296
	 */
297
	function _fnHungarianMap ( o )
298
	{
299
		var
300
			hungarian = 'a aa ai ao as b fn i m o s ',
301
			match,
302
			newKey,
303
			map = {};
304
 
305
		$.each( o, function (key, val) {
306
			match = key.match(/^([^A-Z]+?)([A-Z])/);
307
 
308
			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
309
			{
310
				newKey = key.replace( match[0], match[2].toLowerCase() );
311
				map[ newKey ] = key;
312
 
313
				if ( match[1] === 'o' )
314
				{
315
					_fnHungarianMap( o[key] );
316
				}
317
			}
318
		} );
319
 
320
		o._hungarianMap = map;
321
	}
322
 
323
 
324
	/**
325
	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
326
	 * created by _fnHungarianMap.
327
	 *  @param {object} src The model object which holds all parameters that can be
328
	 *    mapped.
329
	 *  @param {object} user The object to convert from camel case to Hungarian.
330
	 *  @param {boolean} force When set to `true`, properties which already have a
331
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
332
	 *    won't be.
333
	 *  @memberof DataTable#oApi
334
	 */
335
	function _fnCamelToHungarian ( src, user, force )
336
	{
337
		if ( ! src._hungarianMap ) {
338
			_fnHungarianMap( src );
339
		}
340
 
341
		var hungarianKey;
342
 
343
		$.each( user, function (key, val) {
344
			hungarianKey = src._hungarianMap[ key ];
345
 
346
			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
347
			{
348
				// For objects, we need to buzz down into the object to copy parameters
349
				if ( hungarianKey.charAt(0) === 'o' )
350
				{
351
					// Copy the camelCase options over to the hungarian
352
					if ( ! user[ hungarianKey ] ) {
353
						user[ hungarianKey ] = {};
354
					}
355
					$.extend( true, user[hungarianKey], user[key] );
356
 
357
					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
358
				}
359
				else {
360
					user[hungarianKey] = user[ key ];
361
				}
362
			}
363
		} );
364
	}
365
 
366
 
367
	/**
368
	 * Language compatibility - when certain options are given, and others aren't, we
369
	 * need to duplicate the values over, in order to provide backwards compatibility
370
	 * with older language files.
371
	 *  @param {object} oSettings dataTables settings object
372
	 *  @memberof DataTable#oApi
373
	 */
374
	function _fnLanguageCompat( lang )
375
	{
376
		var defaults = DataTable.defaults.oLanguage;
377
		var zeroRecords = lang.sZeroRecords;
378
 
379
		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
380
		 * sZeroRecords - assuming that is given.
381
		 */
382
		if ( ! lang.sEmptyTable && zeroRecords &&
383
			defaults.sEmptyTable === "No data available in table" )
384
		{
385
			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
386
		}
387
 
388
		/* Likewise with loading records */
389
		if ( ! lang.sLoadingRecords && zeroRecords &&
390
			defaults.sLoadingRecords === "Loading..." )
391
		{
392
			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
393
		}
394
 
395
		// Old parameter name of the thousands separator mapped onto the new
396
		if ( lang.sInfoThousands ) {
397
			lang.sThousands = lang.sInfoThousands;
398
		}
399
 
400
		var decimal = lang.sDecimal;
401
		if ( decimal ) {
402
			_addNumericSort( decimal );
403
		}
404
	}
405
 
406
 
407
	/**
408
	 * Map one parameter onto another
409
	 *  @param {object} o Object to map
410
	 *  @param {*} knew The new parameter name
411
	 *  @param {*} old The old parameter name
412
	 */
413
	var _fnCompatMap = function ( o, knew, old ) {
414
		if ( o[ knew ] !== undefined ) {
415
			o[ old ] = o[ knew ];
416
		}
417
	};
418
 
419
 
420
	/**
421
	 * Provide backwards compatibility for the main DT options. Note that the new
422
	 * options are mapped onto the old parameters, so this is an external interface
423
	 * change only.
424
	 *  @param {object} init Object to map
425
	 */
426
	function _fnCompatOpts ( init )
427
	{
428
		_fnCompatMap( init, 'ordering',      'bSort' );
429
		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
430
		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
431
		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
432
		_fnCompatMap( init, 'order',         'aaSorting' );
433
		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
434
		_fnCompatMap( init, 'paging',        'bPaginate' );
435
		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
436
		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
437
		_fnCompatMap( init, 'searching',     'bFilter' );
438
 
439
		// Column search objects are in an array, so it needs to be converted
440
		// element by element
441
		var searchCols = init.aoSearchCols;
442
 
443
		if ( searchCols ) {
444
			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
445
				if ( searchCols[i] ) {
446
					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
447
				}
448
			}
449
		}
450
	}
451
 
452
 
453
	/**
454
	 * Provide backwards compatibility for column options. Note that the new options
455
	 * are mapped onto the old parameters, so this is an external interface change
456
	 * only.
457
	 *  @param {object} init Object to map
458
	 */
459
	function _fnCompatCols ( init )
460
	{
461
		_fnCompatMap( init, 'orderable',     'bSortable' );
462
		_fnCompatMap( init, 'orderData',     'aDataSort' );
463
		_fnCompatMap( init, 'orderSequence', 'asSorting' );
464
		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
465
	}
466
 
467
 
468
	/**
469
	 * Browser feature detection for capabilities, quirks
470
	 *  @param {object} settings dataTables settings object
471
	 *  @memberof DataTable#oApi
472
	 */
473
	function _fnBrowserDetect( settings )
474
	{
475
		var browser = settings.oBrowser;
476
 
477
		// Scrolling feature / quirks detection
478
		var n = $('<div/>')
479
			.css( {
480
				position: 'absolute',
481
				top: 0,
482
				left: 0,
483
				height: 1,
484
				width: 1,
485
				overflow: 'hidden'
486
			} )
487
			.append(
488
				$('<div/>')
489
					.css( {
490
						position: 'absolute',
491
						top: 1,
492
						left: 1,
493
						width: 100,
494
						overflow: 'scroll'
495
					} )
496
					.append(
497
						$('<div class="test"/>')
498
							.css( {
499
								width: '100%',
500
								height: 10
501
							} )
502
					)
503
			)
504
			.appendTo( 'body' );
505
 
506
		var test = n.find('.test');
507
 
508
		// IE6/7 will oversize a width 100% element inside a scrolling element, to
509
		// include the width of the scrollbar, while other browsers ensure the inner
510
		// element is contained without forcing scrolling
511
		browser.bScrollOversize = test[0].offsetWidth === 100;
512
 
513
		// In rtl text layout, some browsers (most, but not all) will place the
514
		// scrollbar on the left, rather than the right.
515
		browser.bScrollbarLeft = test.offset().left !== 1;
516
 
517
		n.remove();
518
	}
519
 
520
 
521
	/**
522
	 * Array.prototype reduce[Right] method, used for browsers which don't support
523
	 * JS 1.6. Done this way to reduce code size, since we iterate either way
524
	 *  @param {object} settings dataTables settings object
525
	 *  @memberof DataTable#oApi
526
	 */
527
	function _fnReduce ( that, fn, init, start, end, inc )
528
	{
529
		var
530
			i = start,
531
			value,
532
			isSet = false;
533
 
534
		if ( init !== undefined ) {
535
			value = init;
536
			isSet = true;
537
		}
538
 
539
		while ( i !== end ) {
540
			if ( ! that.hasOwnProperty(i) ) {
541
				continue;
542
			}
543
 
544
			value = isSet ?
545
				fn( value, that[i], i, that ) :
546
				that[i];
547
 
548
			isSet = true;
549
			i += inc;
550
		}
551
 
552
		return value;
553
	}
554
 
555
	/**
556
	 * Add a column to the list used for the table with default values
557
	 *  @param {object} oSettings dataTables settings object
558
	 *  @param {node} nTh The th element for this column
559
	 *  @memberof DataTable#oApi
560
	 */
561
	function _fnAddColumn( oSettings, nTh )
562
	{
563
		// Add column to aoColumns array
564
		var oDefaults = DataTable.defaults.column;
565
		var iCol = oSettings.aoColumns.length;
566
		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
567
			"nTh": nTh ? nTh : document.createElement('th'),
568
			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
569
			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
570
			"mData": oDefaults.mData ? oDefaults.mData : iCol,
571
			idx: iCol
572
		} );
573
		oSettings.aoColumns.push( oCol );
574
 
575
		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
576
		// passed into extend can be undefined. This allows the user to give a default
577
		// with only some of the parameters defined, and also not give a default
578
		var searchCols = oSettings.aoPreSearchCols;
579
		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
580
 
581
		// Use the default column options function to initialise classes etc
582
		_fnColumnOptions( oSettings, iCol, null );
583
	}
584
 
585
 
586
	/**
587
	 * Apply options for a column
588
	 *  @param {object} oSettings dataTables settings object
589
	 *  @param {int} iCol column index to consider
590
	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
591
	 *  @memberof DataTable#oApi
592
	 */
593
	function _fnColumnOptions( oSettings, iCol, oOptions )
594
	{
595
		var oCol = oSettings.aoColumns[ iCol ];
596
		var oClasses = oSettings.oClasses;
597
		var th = $(oCol.nTh);
598
 
599
		// Try to get width information from the DOM. We can't get it from CSS
600
		// as we'd need to parse the CSS stylesheet. `width` option can override
601
		if ( ! oCol.sWidthOrig ) {
602
			// Width attribute
603
			oCol.sWidthOrig = th.attr('width') || null;
604
 
605
			// Style attribute
606
			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
607
			if ( t ) {
608
				oCol.sWidthOrig = t[1];
609
			}
610
		}
611
 
612
		/* User specified column options */
613
		if ( oOptions !== undefined && oOptions !== null )
614
		{
615
			// Backwards compatibility
616
			_fnCompatCols( oOptions );
617
 
618
			// Map camel case parameters to their Hungarian counterparts
619
			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
620
 
621
			/* Backwards compatibility for mDataProp */
622
			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
623
			{
624
				oOptions.mData = oOptions.mDataProp;
625
			}
626
 
627
			if ( oOptions.sType )
628
			{
629
				oCol._sManualType = oOptions.sType;
630
			}
631
 
632
			// `class` is a reserved word in Javascript, so we need to provide
633
			// the ability to use a valid name for the camel case input
634
			if ( oOptions.className && ! oOptions.sClass )
635
			{
636
				oOptions.sClass = oOptions.className;
637
			}
638
 
639
			$.extend( oCol, oOptions );
640
			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
641
 
642
			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
643
			 * priority if defined
644
			 */
645
			if ( typeof oOptions.iDataSort === 'number' )
646
			{
647
				oCol.aDataSort = [ oOptions.iDataSort ];
648
			}
649
			_fnMap( oCol, oOptions, "aDataSort" );
650
		}
651
 
652
		/* Cache the data get and set functions for speed */
653
		var mDataSrc = oCol.mData;
654
		var mData = _fnGetObjectDataFn( mDataSrc );
655
		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
656
 
657
		var attrTest = function( src ) {
658
			return typeof src === 'string' && src.indexOf('@') !== -1;
659
		};
660
		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
661
			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
662
		);
663
 
664
		oCol.fnGetData = function (rowData, type, meta) {
665
			var innerData = mData( rowData, type, undefined, meta );
666
 
667
			return mRender && type ?
668
				mRender( innerData, type, rowData, meta ) :
669
				innerData;
670
		};
671
		oCol.fnSetData = function ( rowData, val, meta ) {
672
			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
673
		};
674
 
675
		// Indicate if DataTables should read DOM data as an object or array
676
		// Used in _fnGetRowElements
677
		if ( typeof mDataSrc !== 'number' ) {
678
			oSettings._rowReadObject = true;
679
		}
680
 
681
		/* Feature sorting overrides column specific when off */
682
		if ( !oSettings.oFeatures.bSort )
683
		{
684
			oCol.bSortable = false;
685
			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
686
		}
687
 
688
		/* Check that the class assignment is correct for sorting */
689
		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
690
		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
691
		if ( !oCol.bSortable || (!bAsc && !bDesc) )
692
		{
693
			oCol.sSortingClass = oClasses.sSortableNone;
694
			oCol.sSortingClassJUI = "";
695
		}
696
		else if ( bAsc && !bDesc )
697
		{
698
			oCol.sSortingClass = oClasses.sSortableAsc;
699
			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
700
		}
701
		else if ( !bAsc && bDesc )
702
		{
703
			oCol.sSortingClass = oClasses.sSortableDesc;
704
			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
705
		}
706
		else
707
		{
708
			oCol.sSortingClass = oClasses.sSortable;
709
			oCol.sSortingClassJUI = oClasses.sSortJUI;
710
		}
711
	}
712
 
713
 
714
	/**
715
	 * Adjust the table column widths for new data. Note: you would probably want to
716
	 * do a redraw after calling this function!
717
	 *  @param {object} settings dataTables settings object
718
	 *  @memberof DataTable#oApi
719
	 */
720
	function _fnAdjustColumnSizing ( settings )
721
	{
722
		/* Not interested in doing column width calculation if auto-width is disabled */
723
		if ( settings.oFeatures.bAutoWidth !== false )
724
		{
725
			var columns = settings.aoColumns;
726
 
727
			_fnCalculateColumnWidths( settings );
728
			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
729
			{
730
				columns[i].nTh.style.width = columns[i].sWidth;
731
			}
732
		}
733
 
734
		var scroll = settings.oScroll;
735
		if ( scroll.sY !== '' || scroll.sX !== '')
736
		{
737
			_fnScrollDraw( settings );
738
		}
739
 
740
		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
741
	}
742
 
743
 
744
	/**
745
	 * Covert the index of a visible column to the index in the data array (take account
746
	 * of hidden columns)
747
	 *  @param {object} oSettings dataTables settings object
748
	 *  @param {int} iMatch Visible column index to lookup
749
	 *  @returns {int} i the data index
750
	 *  @memberof DataTable#oApi
751
	 */
752
	function _fnVisibleToColumnIndex( oSettings, iMatch )
753
	{
754
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
755
 
756
		return typeof aiVis[iMatch] === 'number' ?
757
			aiVis[iMatch] :
758
			null;
759
	}
760
 
761
 
762
	/**
763
	 * Covert the index of an index in the data array and convert it to the visible
764
	 *   column index (take account of hidden columns)
765
	 *  @param {int} iMatch Column index to lookup
766
	 *  @param {object} oSettings dataTables settings object
767
	 *  @returns {int} i the data index
768
	 *  @memberof DataTable#oApi
769
	 */
770
	function _fnColumnIndexToVisible( oSettings, iMatch )
771
	{
772
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
773
		var iPos = $.inArray( iMatch, aiVis );
774
 
775
		return iPos !== -1 ? iPos : null;
776
	}
777
 
778
 
779
	/**
780
	 * Get the number of visible columns
781
	 *  @param {object} oSettings dataTables settings object
782
	 *  @returns {int} i the number of visible columns
783
	 *  @memberof DataTable#oApi
784
	 */
785
	function _fnVisbleColumns( oSettings )
786
	{
787
		return _fnGetColumns( oSettings, 'bVisible' ).length;
788
	}
789
 
790
 
791
	/**
792
	 * Get an array of column indexes that match a given property
793
	 *  @param {object} oSettings dataTables settings object
794
	 *  @param {string} sParam Parameter in aoColumns to look for - typically
795
	 *    bVisible or bSearchable
796
	 *  @returns {array} Array of indexes with matched properties
797
	 *  @memberof DataTable#oApi
798
	 */
799
	function _fnGetColumns( oSettings, sParam )
800
	{
801
		var a = [];
802
 
803
		$.map( oSettings.aoColumns, function(val, i) {
804
			if ( val[sParam] ) {
805
				a.push( i );
806
			}
807
		} );
808
 
809
		return a;
810
	}
811
 
812
 
813
	/**
814
	 * Calculate the 'type' of a column
815
	 *  @param {object} settings dataTables settings object
816
	 *  @memberof DataTable#oApi
817
	 */
818
	function _fnColumnTypes ( settings )
819
	{
820
		var columns = settings.aoColumns;
821
		var data = settings.aoData;
822
		var types = DataTable.ext.type.detect;
823
		var i, ien, j, jen, k, ken;
824
		var col, cell, detectedType, cache;
825
 
826
		// For each column, spin over the 
827
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
828
			col = columns[i];
829
			cache = [];
830
 
831
			if ( ! col.sType && col._sManualType ) {
832
				col.sType = col._sManualType;
833
			}
834
			else if ( ! col.sType ) {
835
				for ( j=0, jen=types.length ; j<jen ; j++ ) {
836
					for ( k=0, ken=data.length ; k<ken ; k++ ) {
837
						// Use a cache array so we only need to get the type data
838
						// from the formatter once (when using multiple detectors)
839
						if ( cache[k] === undefined ) {
840
							cache[k] = _fnGetCellData( settings, k, i, 'type' );
841
						}
842
 
843
						detectedType = types[j]( cache[k], settings );
844
 
845
						// Doesn't match, so break early, since this type can't
846
						// apply to this column. Also, HTML is a special case since
847
						// it is so similar to `string`. Just a single match is
848
						// needed for a column to be html type
849
						if ( ! detectedType || detectedType === 'html' ) {
850
							break;
851
						}
852
					}
853
 
854
					// Type is valid for all data points in the column - use this
855
					// type
856
					if ( detectedType ) {
857
						col.sType = detectedType;
858
						break;
859
					}
860
				}
861
 
862
				// Fall back - if no type was detected, always use string
863
				if ( ! col.sType ) {
864
					col.sType = 'string';
865
				}
866
			}
867
		}
868
	}
869
 
870
 
871
	/**
872
	 * Take the column definitions and static columns arrays and calculate how
873
	 * they relate to column indexes. The callback function will then apply the
874
	 * definition found for a column to a suitable configuration object.
875
	 *  @param {object} oSettings dataTables settings object
876
	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
877
	 *  @param {array} aoCols The aoColumns array that defines columns individually
878
	 *  @param {function} fn Callback function - takes two parameters, the calculated
879
	 *    column index and the definition for that column.
880
	 *  @memberof DataTable#oApi
881
	 */
882
	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
883
	{
884
		var i, iLen, j, jLen, k, kLen, def;
885
		var columns = oSettings.aoColumns;
886
 
887
		// Column definitions with aTargets
888
		if ( aoColDefs )
889
		{
890
			/* Loop over the definitions array - loop in reverse so first instance has priority */
891
			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
892
			{
893
				def = aoColDefs[i];
894
 
895
				/* Each definition can target multiple columns, as it is an array */
896
				var aTargets = def.targets !== undefined ?
897
					def.targets :
898
					def.aTargets;
899
 
900
				if ( ! $.isArray( aTargets ) )
901
				{
902
					aTargets = [ aTargets ];
903
				}
904
 
905
				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
906
				{
907
					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
908
					{
909
						/* Add columns that we don't yet know about */
910
						while( columns.length <= aTargets[j] )
911
						{
912
							_fnAddColumn( oSettings );
913
						}
914
 
915
						/* Integer, basic index */
916
						fn( aTargets[j], def );
917
					}
918
					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
919
					{
920
						/* Negative integer, right to left column counting */
921
						fn( columns.length+aTargets[j], def );
922
					}
923
					else if ( typeof aTargets[j] === 'string' )
924
					{
925
						/* Class name matching on TH element */
926
						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
927
						{
928
							if ( aTargets[j] == "_all" ||
929
							     $(columns[k].nTh).hasClass( aTargets[j] ) )
930
							{
931
								fn( k, def );
932
							}
933
						}
934
					}
935
				}
936
			}
937
		}
938
 
939
		// Statically defined columns array
940
		if ( aoCols )
941
		{
942
			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
943
			{
944
				fn( i, aoCols[i] );
945
			}
946
		}
947
	}
948
 
949
	/**
950
	 * Add a data array to the table, creating DOM node etc. This is the parallel to
951
	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
952
	 * DOM source.
953
	 *  @param {object} oSettings dataTables settings object
954
	 *  @param {array} aData data array to be added
955
	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
956
	 *    DataTables will create a row automatically
957
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
958
	 *    if nTr is.
959
	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
960
	 *  @memberof DataTable#oApi
961
	 */
962
	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
963
	{
964
		/* Create the object for storing information about this new row */
965
		var iRow = oSettings.aoData.length;
966
		var oData = $.extend( true, {}, DataTable.models.oRow, {
967
			src: nTr ? 'dom' : 'data'
968
		} );
969
 
970
		oData._aData = aDataIn;
971
		oSettings.aoData.push( oData );
972
 
973
		/* Create the cells */
974
		var nTd, sThisType;
975
		var columns = oSettings.aoColumns;
976
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
977
		{
978
			// When working with a row, the data source object must be populated. In
979
			// all other cases, the data source object is already populated, so we
980
			// don't overwrite it, which might break bindings etc
981
			if ( nTr ) {
982
				_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
983
			}
984
			columns[i].sType = null;
985
		}
986
 
987
		/* Add to the display array */
988
		oSettings.aiDisplayMaster.push( iRow );
989
 
990
		/* Create the DOM information, or register it if already present */
991
		if ( nTr || ! oSettings.oFeatures.bDeferRender )
992
		{
993
			_fnCreateTr( oSettings, iRow, nTr, anTds );
994
		}
995
 
996
		return iRow;
997
	}
998
 
999
 
1000
	/**
1001
	 * Add one or more TR elements to the table. Generally we'd expect to
1002
	 * use this for reading data from a DOM sourced table, but it could be
1003
	 * used for an TR element. Note that if a TR is given, it is used (i.e.
1004
	 * it is not cloned).
1005
	 *  @param {object} settings dataTables settings object
1006
	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
1007
	 *  @returns {array} Array of indexes for the added rows
1008
	 *  @memberof DataTable#oApi
1009
	 */
1010
	function _fnAddTr( settings, trs )
1011
	{
1012
		var row;
1013
 
1014
		// Allow an individual node to be passed in
1015
		if ( ! (trs instanceof $) ) {
1016
			trs = $(trs);
1017
		}
1018
 
1019
		return trs.map( function (i, el) {
1020
			row = _fnGetRowElements( settings, el );
1021
			return _fnAddData( settings, row.data, el, row.cells );
1022
		} );
1023
	}
1024
 
1025
 
1026
	/**
1027
	 * Take a TR element and convert it to an index in aoData
1028
	 *  @param {object} oSettings dataTables settings object
1029
	 *  @param {node} n the TR element to find
1030
	 *  @returns {int} index if the node is found, null if not
1031
	 *  @memberof DataTable#oApi
1032
	 */
1033
	function _fnNodeToDataIndex( oSettings, n )
1034
	{
1035
		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
1036
	}
1037
 
1038
 
1039
	/**
1040
	 * Take a TD element and convert it into a column data index (not the visible index)
1041
	 *  @param {object} oSettings dataTables settings object
1042
	 *  @param {int} iRow The row number the TD/TH can be found in
1043
	 *  @param {node} n The TD/TH element to find
1044
	 *  @returns {int} index if the node is found, -1 if not
1045
	 *  @memberof DataTable#oApi
1046
	 */
1047
	function _fnNodeToColumnIndex( oSettings, iRow, n )
1048
	{
1049
		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
1050
	}
1051
 
1052
 
1053
	/**
1054
	 * Get the data for a given cell from the internal cache, taking into account data mapping
1055
	 *  @param {object} settings dataTables settings object
1056
	 *  @param {int} rowIdx aoData row id
1057
	 *  @param {int} colIdx Column index
1058
	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
1059
	 *  @returns {*} Cell data
1060
	 *  @memberof DataTable#oApi
1061
	 */
1062
	function _fnGetCellData( settings, rowIdx, colIdx, type )
1063
	{
1064
		var draw           = settings.iDraw;
1065
		var col            = settings.aoColumns[colIdx];
1066
		var rowData        = settings.aoData[rowIdx]._aData;
1067
		var defaultContent = col.sDefaultContent;
1068
		var cellData       = col.fnGetData( rowData, type, {
1069
			settings: settings,
1070
			row:      rowIdx,
1071
			col:      colIdx
1072
		} );
1073
 
1074
		if ( cellData === undefined ) {
1075
			if ( settings.iDrawError != draw && defaultContent === null ) {
1076
				_fnLog( settings, 0, "Requested unknown parameter "+
1077
					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
1078
					" for row "+rowIdx, 4 );
1079
				settings.iDrawError = draw;
1080
			}
1081
			return defaultContent;
1082
		}
1083
 
1084
		/* When the data source is null, we can use default column data */
1085
		if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
1086
			cellData = defaultContent;
1087
		}
1088
		else if ( typeof cellData === 'function' ) {
1089
			// If the data source is a function, then we run it and use the return,
1090
			// executing in the scope of the data object (for instances)
1091
			return cellData.call( rowData );
1092
		}
1093
 
1094
		if ( cellData === null && type == 'display' ) {
1095
			return '';
1096
		}
1097
		return cellData;
1098
	}
1099
 
1100
 
1101
	/**
1102
	 * Set the value for a specific cell, into the internal data cache
1103
	 *  @param {object} settings dataTables settings object
1104
	 *  @param {int} rowIdx aoData row id
1105
	 *  @param {int} colIdx Column index
1106
	 *  @param {*} val Value to set
1107
	 *  @memberof DataTable#oApi
1108
	 */
1109
	function _fnSetCellData( settings, rowIdx, colIdx, val )
1110
	{
1111
		var col     = settings.aoColumns[colIdx];
1112
		var rowData = settings.aoData[rowIdx]._aData;
1113
 
1114
		col.fnSetData( rowData, val, {
1115
			settings: settings,
1116
			row:      rowIdx,
1117
			col:      colIdx
1118
		}  );
1119
	}
1120
 
1121
 
1122
	// Private variable that is used to match action syntax in the data property object
1123
	var __reArray = /\[.*?\]$/;
1124
	var __reFn = /\(\)$/;
1125
 
1126
	/**
1127
	 * Split string on periods, taking into account escaped periods
1128
	 * @param  {string} str String to split
1129
	 * @return {array} Split string
1130
	 */
1131
	function _fnSplitObjNotation( str )
1132
	{
1133
		return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1134
			return s.replace(/\\./g, '.');
1135
		} );
1136
	}
1137
 
1138
 
1139
	/**
1140
	 * Return a function that can be used to get data from a source object, taking
1141
	 * into account the ability to use nested objects as a source
1142
	 *  @param {string|int|function} mSource The data source for the object
1143
	 *  @returns {function} Data get function
1144
	 *  @memberof DataTable#oApi
1145
	 */
1146
	function _fnGetObjectDataFn( mSource )
1147
	{
1148
		if ( $.isPlainObject( mSource ) )
1149
		{
1150
			/* Build an object of get functions, and wrap them in a single call */
1151
			var o = {};
1152
			$.each( mSource, function (key, val) {
1153
				if ( val ) {
1154
					o[key] = _fnGetObjectDataFn( val );
1155
				}
1156
			} );
1157
 
1158
			return function (data, type, row, meta) {
1159
				var t = o[type] || o._;
1160
				return t !== undefined ?
1161
					t(data, type, row, meta) :
1162
					data;
1163
			};
1164
		}
1165
		else if ( mSource === null )
1166
		{
1167
			/* Give an empty string for rendering / sorting etc */
1168
			return function (data) { // type, row and meta also passed, but not used
1169
				return data;
1170
			};
1171
		}
1172
		else if ( typeof mSource === 'function' )
1173
		{
1174
			return function (data, type, row, meta) {
1175
				return mSource( data, type, row, meta );
1176
			};
1177
		}
1178
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1179
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1180
		{
1181
			/* If there is a . in the source string then the data source is in a
1182
			 * nested object so we loop over the data for each level to get the next
1183
			 * level down. On each loop we test for undefined, and if found immediately
1184
			 * return. This allows entire objects to be missing and sDefaultContent to
1185
			 * be used if defined, rather than throwing an error
1186
			 */
1187
			var fetchData = function (data, type, src) {
1188
				var arrayNotation, funcNotation, out, innerSrc;
1189
 
1190
				if ( src !== "" )
1191
				{
1192
					var a = _fnSplitObjNotation( src );
1193
 
1194
					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1195
					{
1196
						// Check if we are dealing with special notation
1197
						arrayNotation = a[i].match(__reArray);
1198
						funcNotation = a[i].match(__reFn);
1199
 
1200
						if ( arrayNotation )
1201
						{
1202
							// Array notation
1203
							a[i] = a[i].replace(__reArray, '');
1204
 
1205
							// Condition allows simply [] to be passed in
1206
							if ( a[i] !== "" ) {
1207
								data = data[ a[i] ];
1208
							}
1209
							out = [];
1210
 
1211
							// Get the remainder of the nested object to get
1212
							a.splice( 0, i+1 );
1213
							innerSrc = a.join('.');
1214
 
1215
							// Traverse each entry in the array getting the properties requested
1216
							for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1217
								out.push( fetchData( data[j], type, innerSrc ) );
1218
							}
1219
 
1220
							// If a string is given in between the array notation indicators, that
1221
							// is used to join the strings together, otherwise an array is returned
1222
							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1223
							data = (join==="") ? out : out.join(join);
1224
 
1225
							// The inner call to fetchData has already traversed through the remainder
1226
							// of the source requested, so we exit from the loop
1227
							break;
1228
						}
1229
						else if ( funcNotation )
1230
						{
1231
							// Function call
1232
							a[i] = a[i].replace(__reFn, '');
1233
							data = data[ a[i] ]();
1234
							continue;
1235
						}
1236
 
1237
						if ( data === null || data[ a[i] ] === undefined )
1238
						{
1239
							return undefined;
1240
						}
1241
						data = data[ a[i] ];
1242
					}
1243
				}
1244
 
1245
				return data;
1246
			};
1247
 
1248
			return function (data, type) { // row and meta also passed, but not used
1249
				return fetchData( data, type, mSource );
1250
			};
1251
		}
1252
		else
1253
		{
1254
			/* Array or flat object mapping */
1255
			return function (data, type) { // row and meta also passed, but not used
1256
				return data[mSource];
1257
			};
1258
		}
1259
	}
1260
 
1261
 
1262
	/**
1263
	 * Return a function that can be used to set data from a source object, taking
1264
	 * into account the ability to use nested objects as a source
1265
	 *  @param {string|int|function} mSource The data source for the object
1266
	 *  @returns {function} Data set function
1267
	 *  @memberof DataTable#oApi
1268
	 */
1269
	function _fnSetObjectDataFn( mSource )
1270
	{
1271
		if ( $.isPlainObject( mSource ) )
1272
		{
1273
			/* Unlike get, only the underscore (global) option is used for for
1274
			 * setting data since we don't know the type here. This is why an object
1275
			 * option is not documented for `mData` (which is read/write), but it is
1276
			 * for `mRender` which is read only.
1277
			 */
1278
			return _fnSetObjectDataFn( mSource._ );
1279
		}
1280
		else if ( mSource === null )
1281
		{
1282
			/* Nothing to do when the data source is null */
1283
			return function () {};
1284
		}
1285
		else if ( typeof mSource === 'function' )
1286
		{
1287
			return function (data, val, meta) {
1288
				mSource( data, 'set', val, meta );
1289
			};
1290
		}
1291
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1292
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1293
		{
1294
			/* Like the get, we need to get data from a nested object */
1295
			var setData = function (data, val, src) {
1296
				var a = _fnSplitObjNotation( src ), b;
1297
				var aLast = a[a.length-1];
1298
				var arrayNotation, funcNotation, o, innerSrc;
1299
 
1300
				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
1301
				{
1302
					// Check if we are dealing with an array notation request
1303
					arrayNotation = a[i].match(__reArray);
1304
					funcNotation = a[i].match(__reFn);
1305
 
1306
					if ( arrayNotation )
1307
					{
1308
						a[i] = a[i].replace(__reArray, '');
1309
						data[ a[i] ] = [];
1310
 
1311
						// Get the remainder of the nested object to set so we can recurse
1312
						b = a.slice();
1313
						b.splice( 0, i+1 );
1314
						innerSrc = b.join('.');
1315
 
1316
						// Traverse each entry in the array setting the properties requested
1317
						for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1318
						{
1319
							o = {};
1320
							setData( o, val[j], innerSrc );
1321
							data[ a[i] ].push( o );
1322
						}
1323
 
1324
						// The inner call to setData has already traversed through the remainder
1325
						// of the source and has set the data, thus we can exit here
1326
						return;
1327
					}
1328
					else if ( funcNotation )
1329
					{
1330
						// Function call
1331
						a[i] = a[i].replace(__reFn, '');
1332
						data = data[ a[i] ]( val );
1333
					}
1334
 
1335
					// If the nested object doesn't currently exist - since we are
1336
					// trying to set the value - create it
1337
					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
1338
					{
1339
						data[ a[i] ] = {};
1340
					}
1341
					data = data[ a[i] ];
1342
				}
1343
 
1344
				// Last item in the input - i.e, the actual set
1345
				if ( aLast.match(__reFn ) )
1346
				{
1347
					// Function call
1348
					data = data[ aLast.replace(__reFn, '') ]( val );
1349
				}
1350
				else
1351
				{
1352
					// If array notation is used, we just want to strip it and use the property name
1353
					// and assign the value. If it isn't used, then we get the result we want anyway
1354
					data[ aLast.replace(__reArray, '') ] = val;
1355
				}
1356
			};
1357
 
1358
			return function (data, val) { // meta is also passed in, but not used
1359
				return setData( data, val, mSource );
1360
			};
1361
		}
1362
		else
1363
		{
1364
			/* Array or flat object mapping */
1365
			return function (data, val) { // meta is also passed in, but not used
1366
				data[mSource] = val;
1367
			};
1368
		}
1369
	}
1370
 
1371
 
1372
	/**
1373
	 * Return an array with the full table data
1374
	 *  @param {object} oSettings dataTables settings object
1375
	 *  @returns array {array} aData Master data array
1376
	 *  @memberof DataTable#oApi
1377
	 */
1378
	function _fnGetDataMaster ( settings )
1379
	{
1380
		return _pluck( settings.aoData, '_aData' );
1381
	}
1382
 
1383
 
1384
	/**
1385
	 * Nuke the table
1386
	 *  @param {object} oSettings dataTables settings object
1387
	 *  @memberof DataTable#oApi
1388
	 */
1389
	function _fnClearTable( settings )
1390
	{
1391
		settings.aoData.length = 0;
1392
		settings.aiDisplayMaster.length = 0;
1393
		settings.aiDisplay.length = 0;
1394
	}
1395
 
1396
 
1397
	 /**
1398
	 * Take an array of integers (index array) and remove a target integer (value - not
1399
	 * the key!)
1400
	 *  @param {array} a Index array to target
1401
	 *  @param {int} iTarget value to find
1402
	 *  @memberof DataTable#oApi
1403
	 */
1404
	function _fnDeleteIndex( a, iTarget, splice )
1405
	{
1406
		var iTargetIndex = -1;
1407
 
1408
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1409
		{
1410
			if ( a[i] == iTarget )
1411
			{
1412
				iTargetIndex = i;
1413
			}
1414
			else if ( a[i] > iTarget )
1415
			{
1416
				a[i]--;
1417
			}
1418
		}
1419
 
1420
		if ( iTargetIndex != -1 && splice === undefined )
1421
		{
1422
			a.splice( iTargetIndex, 1 );
1423
		}
1424
	}
1425
 
1426
 
1427
	/**
1428
	 * Mark cached data as invalid such that a re-read of the data will occur when
1429
	 * the cached data is next requested. Also update from the data source object.
1430
	 *
1431
	 * @param {object} settings DataTables settings object
1432
	 * @param  {int}    rowIdx   Row index to invalidate
1433
	 * @memberof DataTable#oApi
1434
	 *
1435
	 * @todo For the modularisation of v1.11 this will need to become a callback, so
1436
	 *   the sort and filter methods can subscribe to it. That will required
1437
	 *   initialisation options for sorting, which is why it is not already baked in
1438
	 */
1439
	function _fnInvalidateRow( settings, rowIdx, src, column )
1440
	{
1441
		var row = settings.aoData[ rowIdx ];
1442
		var i, ien;
1443
 
1444
		// Are we reading last data from DOM or the data object?
1445
		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1446
			// Read the data from the DOM
1447
			row._aData = _fnGetRowElements( settings, row ).data;
1448
		}
1449
		else {
1450
			// Reading from data object, update the DOM
1451
			var cells = row.anCells;
1452
			var cell;
1453
 
1454
			if ( cells ) {
1455
				for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1456
					cell = cells[i];
1457
 
1458
					// This is very frustrating, but in IE if you just write directly
1459
					// to innerHTML, and elements that are overwritten are GC'ed,
1460
					// even if there is a reference to them elsewhere
1461
					while ( cell.childNodes.length ) {
1462
						cell.removeChild( cell.firstChild );
1463
					}
1464
 
1465
					cells[i].innerHTML = _fnGetCellData( settings, rowIdx, i, 'display' );
1466
				}
1467
			}
1468
		}
1469
 
1470
		row._aSortData = null;
1471
		row._aFilterData = null;
1472
 
1473
		// Invalidate the type for a specific column (if given) or all columns since
1474
		// the data might have changed
1475
		var cols = settings.aoColumns;
1476
		if ( column !== undefined ) {
1477
			cols[ column ].sType = null;
1478
		}
1479
		else {
1480
			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1481
				cols[i].sType = null;
1482
			}
1483
		}
1484
 
1485
		// Update DataTables special `DT_*` attributes for the row
1486
		_fnRowAttributes( row );
1487
	}
1488
 
1489
 
1490
	/**
1491
	 * Build a data source object from an HTML row, reading the contents of the
1492
	 * cells that are in the row.
1493
	 *
1494
	 * @param {object} settings DataTables settings object
1495
	 * @param {node|object} TR element from which to read data or existing row
1496
	 *   object from which to re-read the data from the cells
1497
	 * @returns {object} Object with two parameters: `data` the data read, in
1498
	 *   document order, and `cells` and array of nodes (they can be useful to the
1499
	 *   caller, so rather than needing a second traversal to get them, just return
1500
	 *   them from here).
1501
	 * @memberof DataTable#oApi
1502
	 */
1503
	function _fnGetRowElements( settings, row )
1504
	{
1505
		var
1506
			tds = [],
1507
			td = row.firstChild,
1508
			name, col, o, i=0, contents,
1509
			columns = settings.aoColumns,
1510
			objectRead = settings._rowReadObject;
1511
 
1512
		var d = objectRead ? {} : [];
1513
 
1514
		var attr = function ( str, td  ) {
1515
			if ( typeof str === 'string' ) {
1516
				var idx = str.indexOf('@');
1517
 
1518
				if ( idx !== -1 ) {
1519
					var attr = str.substring( idx+1 );
1520
					var setter = _fnSetObjectDataFn( str );
1521
					setter( d, td.getAttribute( attr ) );
1522
				}
1523
			}
1524
		};
1525
 
1526
		var cellProcess = function ( cell ) {
1527
			col = columns[i];
1528
			contents = $.trim(cell.innerHTML);
1529
 
1530
			if ( col && col._bAttrSrc ) {
1531
				var setter = _fnSetObjectDataFn( col.mData._ );
1532
				setter( d, contents );
1533
 
1534
				attr( col.mData.sort, cell );
1535
				attr( col.mData.type, cell );
1536
				attr( col.mData.filter, cell );
1537
			}
1538
			else {
1539
				// Depending on the `data` option for the columns the data can be
1540
				// read to either an object or an array.
1541
				if ( objectRead ) {
1542
					if ( ! col._setter ) {
1543
						// Cache the setter function
1544
						col._setter = _fnSetObjectDataFn( col.mData );
1545
					}
1546
					col._setter( d, contents );
1547
				}
1548
				else {
1549
					d.push( contents );
1550
				}
1551
			}
1552
 
1553
			i++;
1554
		};
1555
 
1556
		if ( td ) {
1557
			// `tr` element passed in
1558
			while ( td ) {
1559
				name = td.nodeName.toUpperCase();
1560
 
1561
				if ( name == "TD" || name == "TH" ) {
1562
					cellProcess( td );
1563
					tds.push( td );
1564
				}
1565
 
1566
				td = td.nextSibling;
1567
			}
1568
		}
1569
		else {
1570
			// Existing row object passed in
1571
			tds = row.anCells;
1572
 
1573
			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1574
				cellProcess( tds[j] );
1575
			}
1576
		}
1577
 
1578
		return {
1579
			data: d,
1580
			cells: tds
1581
		};
1582
	}
1583
	/**
1584
	 * Create a new TR element (and it's TD children) for a row
1585
	 *  @param {object} oSettings dataTables settings object
1586
	 *  @param {int} iRow Row to consider
1587
	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1588
	 *    DataTables will create a row automatically
1589
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1590
	 *    if nTr is.
1591
	 *  @memberof DataTable#oApi
1592
	 */
1593
	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
1594
	{
1595
		var
1596
			row = oSettings.aoData[iRow],
1597
			rowData = row._aData,
1598
			cells = [],
1599
			nTr, nTd, oCol,
1600
			i, iLen;
1601
 
1602
		if ( row.nTr === null )
1603
		{
1604
			nTr = nTrIn || document.createElement('tr');
1605
 
1606
			row.nTr = nTr;
1607
			row.anCells = cells;
1608
 
1609
			/* Use a private property on the node to allow reserve mapping from the node
1610
			 * to the aoData array for fast look up
1611
			 */
1612
			nTr._DT_RowIndex = iRow;
1613
 
1614
			/* Special parameters can be given by the data source to be used on the row */
1615
			_fnRowAttributes( row );
1616
 
1617
			/* Process each column */
1618
			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1619
			{
1620
				oCol = oSettings.aoColumns[i];
1621
 
1622
				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1623
				cells.push( nTd );
1624
 
1625
				// Need to create the HTML if new, or if a rendering function is defined
1626
				if ( !nTrIn || oCol.mRender || oCol.mData !== i )
1627
				{
1628
					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
1629
				}
1630
 
1631
				/* Add user defined class */
1632
				if ( oCol.sClass )
1633
				{
1634
					nTd.className += ' '+oCol.sClass;
1635
				}
1636
 
1637
				// Visibility - add or remove as required
1638
				if ( oCol.bVisible && ! nTrIn )
1639
				{
1640
					nTr.appendChild( nTd );
1641
				}
1642
				else if ( ! oCol.bVisible && nTrIn )
1643
				{
1644
					nTd.parentNode.removeChild( nTd );
1645
				}
1646
 
1647
				if ( oCol.fnCreatedCell )
1648
				{
1649
					oCol.fnCreatedCell.call( oSettings.oInstance,
1650
						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
1651
					);
1652
				}
1653
			}
1654
 
1655
			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
1656
		}
1657
 
1658
		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1659
		// and deployed
1660
		row.nTr.setAttribute( 'role', 'row' );
1661
	}
1662
 
1663
 
1664
	/**
1665
	 * Add attributes to a row based on the special `DT_*` parameters in a data
1666
	 * source object.
1667
	 *  @param {object} DataTables row object for the row to be modified
1668
	 *  @memberof DataTable#oApi
1669
	 */
1670
	function _fnRowAttributes( row )
1671
	{
1672
		var tr = row.nTr;
1673
		var data = row._aData;
1674
 
1675
		if ( tr ) {
1676
			if ( data.DT_RowId ) {
1677
				tr.id = data.DT_RowId;
1678
			}
1679
 
1680
			if ( data.DT_RowClass ) {
1681
				// Remove any classes added by DT_RowClass before
1682
				var a = data.DT_RowClass.split(' ');
1683
				row.__rowc = row.__rowc ?
1684
					_unique( row.__rowc.concat( a ) ) :
1685
					a;
1686
 
1687
				$(tr)
1688
					.removeClass( row.__rowc.join(' ') )
1689
					.addClass( data.DT_RowClass );
1690
			}
1691
 
1692
			if ( data.DT_RowData ) {
1693
				$(tr).data( data.DT_RowData );
1694
			}
1695
		}
1696
	}
1697
 
1698
 
1699
	/**
1700
	 * Create the HTML header for the table
1701
	 *  @param {object} oSettings dataTables settings object
1702
	 *  @memberof DataTable#oApi
1703
	 */
1704
	function _fnBuildHead( oSettings )
1705
	{
1706
		var i, ien, cell, row, column;
1707
		var thead = oSettings.nTHead;
1708
		var tfoot = oSettings.nTFoot;
1709
		var createHeader = $('th, td', thead).length === 0;
1710
		var classes = oSettings.oClasses;
1711
		var columns = oSettings.aoColumns;
1712
 
1713
		if ( createHeader ) {
1714
			row = $('<tr/>').appendTo( thead );
1715
		}
1716
 
1717
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
1718
			column = columns[i];
1719
			cell = $( column.nTh ).addClass( column.sClass );
1720
 
1721
			if ( createHeader ) {
1722
				cell.appendTo( row );
1723
			}
1724
 
1725
			// 1.11 move into sorting
1726
			if ( oSettings.oFeatures.bSort ) {
1727
				cell.addClass( column.sSortingClass );
1728
 
1729
				if ( column.bSortable !== false ) {
1730
					cell
1731
						.attr( 'tabindex', oSettings.iTabIndex )
1732
						.attr( 'aria-controls', oSettings.sTableId );
1733
 
1734
					_fnSortAttachListener( oSettings, column.nTh, i );
1735
				}
1736
			}
1737
 
1738
			if ( column.sTitle != cell.html() ) {
1739
				cell.html( column.sTitle );
1740
			}
1741
 
1742
			_fnRenderer( oSettings, 'header' )(
1743
				oSettings, cell, column, classes
1744
			);
1745
		}
1746
 
1747
		if ( createHeader ) {
1748
			_fnDetectHeader( oSettings.aoHeader, thead );
1749
		}
1750
 
1751
		/* ARIA role for the rows */
1752
	 	$(thead).find('>tr').attr('role', 'row');
1753
 
1754
		/* Deal with the footer - add classes if required */
1755
		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
1756
		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
1757
 
1758
		// Cache the footer cells. Note that we only take the cells from the first
1759
		// row in the footer. If there is more than one row the user wants to
1760
		// interact with, they need to use the table().foot() method. Note also this
1761
		// allows cells to be used for multiple columns using colspan
1762
		if ( tfoot !== null ) {
1763
			var cells = oSettings.aoFooter[0];
1764
 
1765
			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1766
				column = columns[i];
1767
				column.nTf = cells[i].cell;
1768
 
1769
				if ( column.sClass ) {
1770
					$(column.nTf).addClass( column.sClass );
1771
				}
1772
			}
1773
		}
1774
	}
1775
 
1776
 
1777
	/**
1778
	 * Draw the header (or footer) element based on the column visibility states. The
1779
	 * methodology here is to use the layout array from _fnDetectHeader, modified for
1780
	 * the instantaneous column visibility, to construct the new layout. The grid is
1781
	 * traversed over cell at a time in a rows x columns grid fashion, although each
1782
	 * cell insert can cover multiple elements in the grid - which is tracks using the
1783
	 * aApplied array. Cell inserts in the grid will only occur where there isn't
1784
	 * already a cell in that position.
1785
	 *  @param {object} oSettings dataTables settings object
1786
	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
1787
	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1788
	 *  @memberof DataTable#oApi
1789
	 */
1790
	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1791
	{
1792
		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1793
		var aoLocal = [];
1794
		var aApplied = [];
1795
		var iColumns = oSettings.aoColumns.length;
1796
		var iRowspan, iColspan;
1797
 
1798
		if ( ! aoSource )
1799
		{
1800
			return;
1801
		}
1802
 
1803
		if (  bIncludeHidden === undefined )
1804
		{
1805
			bIncludeHidden = false;
1806
		}
1807
 
1808
		/* Make a copy of the master layout array, but without the visible columns in it */
1809
		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1810
		{
1811
			aoLocal[i] = aoSource[i].slice();
1812
			aoLocal[i].nTr = aoSource[i].nTr;
1813
 
1814
			/* Remove any columns which are currently hidden */
1815
			for ( j=iColumns-1 ; j>=0 ; j-- )
1816
			{
1817
				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1818
				{
1819
					aoLocal[i].splice( j, 1 );
1820
				}
1821
			}
1822
 
1823
			/* Prep the applied array - it needs an element for each row */
1824
			aApplied.push( [] );
1825
		}
1826
 
1827
		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1828
		{
1829
			nLocalTr = aoLocal[i].nTr;
1830
 
1831
			/* All cells are going to be replaced, so empty out the row */
1832
			if ( nLocalTr )
1833
			{
1834
				while( (n = nLocalTr.firstChild) )
1835
				{
1836
					nLocalTr.removeChild( n );
1837
				}
1838
			}
1839
 
1840
			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1841
			{
1842
				iRowspan = 1;
1843
				iColspan = 1;
1844
 
1845
				/* Check to see if there is already a cell (row/colspan) covering our target
1846
				 * insert point. If there is, then there is nothing to do.
1847
				 */
1848
				if ( aApplied[i][j] === undefined )
1849
				{
1850
					nLocalTr.appendChild( aoLocal[i][j].cell );
1851
					aApplied[i][j] = 1;
1852
 
1853
					/* Expand the cell to cover as many rows as needed */
1854
					while ( aoLocal[i+iRowspan] !== undefined &&
1855
					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1856
					{
1857
						aApplied[i+iRowspan][j] = 1;
1858
						iRowspan++;
1859
					}
1860
 
1861
					/* Expand the cell to cover as many columns as needed */
1862
					while ( aoLocal[i][j+iColspan] !== undefined &&
1863
					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1864
					{
1865
						/* Must update the applied array over the rows for the columns */
1866
						for ( k=0 ; k<iRowspan ; k++ )
1867
						{
1868
							aApplied[i+k][j+iColspan] = 1;
1869
						}
1870
						iColspan++;
1871
					}
1872
 
1873
					/* Do the actual expansion in the DOM */
1874
					$(aoLocal[i][j].cell)
1875
						.attr('rowspan', iRowspan)
1876
						.attr('colspan', iColspan);
1877
				}
1878
			}
1879
		}
1880
	}
1881
 
1882
 
1883
	/**
1884
	 * Insert the required TR nodes into the table for display
1885
	 *  @param {object} oSettings dataTables settings object
1886
	 *  @memberof DataTable#oApi
1887
	 */
1888
	function _fnDraw( oSettings )
1889
	{
1890
		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1891
		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
1892
		if ( $.inArray( false, aPreDraw ) !== -1 )
1893
		{
1894
			_fnProcessingDisplay( oSettings, false );
1895
			return;
1896
		}
1897
 
1898
		var i, iLen, n;
1899
		var anRows = [];
1900
		var iRowCount = 0;
1901
		var asStripeClasses = oSettings.asStripeClasses;
1902
		var iStripes = asStripeClasses.length;
1903
		var iOpenRows = oSettings.aoOpenRows.length;
1904
		var oLang = oSettings.oLanguage;
1905
		var iInitDisplayStart = oSettings.iInitDisplayStart;
1906
		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
1907
		var aiDisplay = oSettings.aiDisplay;
1908
 
1909
		oSettings.bDrawing = true;
1910
 
1911
		/* Check and see if we have an initial draw position from state saving */
1912
		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
1913
		{
1914
			oSettings._iDisplayStart = bServerSide ?
1915
				iInitDisplayStart :
1916
				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
1917
 
1918
					iInitDisplayStart;
1919
 
1920
			oSettings.iInitDisplayStart = -1;
1921
		}
1922
 
1923
		var iDisplayStart = oSettings._iDisplayStart;
1924
		var iDisplayEnd = oSettings.fnDisplayEnd();
1925
 
1926
		/* Server-side processing draw intercept */
1927
		if ( oSettings.bDeferLoading )
1928
		{
1929
			oSettings.bDeferLoading = false;
1930
			oSettings.iDraw++;
1931
			_fnProcessingDisplay( oSettings, false );
1932
		}
1933
		else if ( !bServerSide )
1934
		{
1935
			oSettings.iDraw++;
1936
		}
1937
		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
1938
		{
1939
			return;
1940
		}
1941
 
1942
		if ( aiDisplay.length !== 0 )
1943
		{
1944
			var iStart = bServerSide ? 0 : iDisplayStart;
1945
			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
1946
 
1947
			for ( var j=iStart ; j<iEnd ; j++ )
1948
			{
1949
				var iDataIndex = aiDisplay[j];
1950
				var aoData = oSettings.aoData[ iDataIndex ];
1951
				if ( aoData.nTr === null )
1952
				{
1953
					_fnCreateTr( oSettings, iDataIndex );
1954
				}
1955
 
1956
				var nRow = aoData.nTr;
1957
 
1958
				/* Remove the old striping classes and then add the new one */
1959
				if ( iStripes !== 0 )
1960
				{
1961
					var sStripe = asStripeClasses[ iRowCount % iStripes ];
1962
					if ( aoData._sRowStripe != sStripe )
1963
					{
1964
						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
1965
						aoData._sRowStripe = sStripe;
1966
					}
1967
				}
1968
 
1969
				// Row callback functions - might want to manipulate the row
1970
				// iRowCount and j are not currently documented. Are they at all
1971
				// useful?
1972
				_fnCallbackFire( oSettings, 'aoRowCallback', null,
1973
					[nRow, aoData._aData, iRowCount, j] );
1974
 
1975
				anRows.push( nRow );
1976
				iRowCount++;
1977
			}
1978
		}
1979
		else
1980
		{
1981
			/* Table is empty - create a row with an empty message in it */
1982
			var sZero = oLang.sZeroRecords;
1983
			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
1984
			{
1985
				sZero = oLang.sLoadingRecords;
1986
			}
1987
			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
1988
			{
1989
				sZero = oLang.sEmptyTable;
1990
			}
1991
 
1992
			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
1993
				.append( $('<td />', {
1994
					'valign':  'top',
1995
					'colSpan': _fnVisbleColumns( oSettings ),
1996
					'class':   oSettings.oClasses.sRowEmpty
1997
				} ).html( sZero ) )[0];
1998
		}
1999
 
2000
		/* Header and footer callbacks */
2001
		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
2002
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2003
 
2004
		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
2005
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2006
 
2007
		var body = $(oSettings.nTBody);
2008
 
2009
		body.children().detach();
2010
		body.append( $(anRows) );
2011
 
2012
		/* Call all required callback functions for the end of a draw */
2013
		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
2014
 
2015
		/* Draw is complete, sorting and filtering must be as well */
2016
		oSettings.bSorted = false;
2017
		oSettings.bFiltered = false;
2018
		oSettings.bDrawing = false;
2019
	}
2020
 
2021
 
2022
	/**
2023
	 * Redraw the table - taking account of the various features which are enabled
2024
	 *  @param {object} oSettings dataTables settings object
2025
	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
2026
	 *    the paging is reset to the first page
2027
	 *  @memberof DataTable#oApi
2028
	 */
2029
	function _fnReDraw( settings, holdPosition )
2030
	{
2031
		var
2032
			features = settings.oFeatures,
2033
			sort     = features.bSort,
2034
			filter   = features.bFilter;
2035
 
2036
		if ( sort ) {
2037
			_fnSort( settings );
2038
		}
2039
 
2040
		if ( filter ) {
2041
			_fnFilterComplete( settings, settings.oPreviousSearch );
2042
		}
2043
		else {
2044
			// No filtering, so we want to just use the display master
2045
			settings.aiDisplay = settings.aiDisplayMaster.slice();
2046
		}
2047
 
2048
		if ( holdPosition !== true ) {
2049
			settings._iDisplayStart = 0;
2050
		}
2051
 
2052
		// Let any modules know about the draw hold position state (used by
2053
		// scrolling internally)
2054
		settings._drawHold = holdPosition;
2055
 
2056
		_fnDraw( settings );
2057
 
2058
		settings._drawHold = false;
2059
	}
2060
 
2061
 
2062
	/**
2063
	 * Add the options to the page HTML for the table
2064
	 *  @param {object} oSettings dataTables settings object
2065
	 *  @memberof DataTable#oApi
2066
	 */
2067
	function _fnAddOptionsHtml ( oSettings )
2068
	{
2069
		var classes = oSettings.oClasses;
2070
		var table = $(oSettings.nTable);
2071
		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
2072
		var features = oSettings.oFeatures;
2073
 
2074
		// All DataTables are wrapped in a div
2075
		var insert = $('<div/>', {
2076
			id:      oSettings.sTableId+'_wrapper',
2077
			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
2078
		} );
2079
 
2080
		oSettings.nHolding = holding[0];
2081
		oSettings.nTableWrapper = insert[0];
2082
		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
2083
 
2084
		/* Loop over the user set positioning and place the elements as needed */
2085
		var aDom = oSettings.sDom.split('');
2086
		var featureNode, cOption, nNewNode, cNext, sAttr, j;
2087
		for ( var i=0 ; i<aDom.length ; i++ )
2088
		{
2089
			featureNode = null;
2090
			cOption = aDom[i];
2091
 
2092
			if ( cOption == '<' )
2093
			{
2094
				/* New container div */
2095
				nNewNode = $('<div/>')[0];
2096
 
2097
				/* Check to see if we should append an id and/or a class name to the container */
2098
				cNext = aDom[i+1];
2099
				if ( cNext == "'" || cNext == '"' )
2100
				{
2101
					sAttr = "";
2102
					j = 2;
2103
					while ( aDom[i+j] != cNext )
2104
					{
2105
						sAttr += aDom[i+j];
2106
						j++;
2107
					}
2108
 
2109
					/* Replace jQuery UI constants @todo depreciated */
2110
					if ( sAttr == "H" )
2111
					{
2112
						sAttr = classes.sJUIHeader;
2113
					}
2114
					else if ( sAttr == "F" )
2115
					{
2116
						sAttr = classes.sJUIFooter;
2117
					}
2118
 
2119
					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2120
					 * breaks the string into parts and applies them as needed
2121
					 */
2122
					if ( sAttr.indexOf('.') != -1 )
2123
					{
2124
						var aSplit = sAttr.split('.');
2125
						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
2126
						nNewNode.className = aSplit[1];
2127
					}
2128
					else if ( sAttr.charAt(0) == "#" )
2129
					{
2130
						nNewNode.id = sAttr.substr(1, sAttr.length-1);
2131
					}
2132
					else
2133
					{
2134
						nNewNode.className = sAttr;
2135
					}
2136
 
2137
					i += j; /* Move along the position array */
2138
				}
2139
 
2140
				insert.append( nNewNode );
2141
				insert = $(nNewNode);
2142
			}
2143
			else if ( cOption == '>' )
2144
			{
2145
				/* End container div */
2146
				insert = insert.parent();
2147
			}
2148
			// @todo Move options into their own plugins?
2149
			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
2150
			{
2151
				/* Length */
2152
				featureNode = _fnFeatureHtmlLength( oSettings );
2153
			}
2154
			else if ( cOption == 'f' && features.bFilter )
2155
			{
2156
				/* Filter */
2157
				featureNode = _fnFeatureHtmlFilter( oSettings );
2158
			}
2159
			else if ( cOption == 'r' && features.bProcessing )
2160
			{
2161
				/* pRocessing */
2162
				featureNode = _fnFeatureHtmlProcessing( oSettings );
2163
			}
2164
			else if ( cOption == 't' )
2165
			{
2166
				/* Table */
2167
				featureNode = _fnFeatureHtmlTable( oSettings );
2168
			}
2169
			else if ( cOption ==  'i' && features.bInfo )
2170
			{
2171
				/* Info */
2172
				featureNode = _fnFeatureHtmlInfo( oSettings );
2173
			}
2174
			else if ( cOption == 'p' && features.bPaginate )
2175
			{
2176
				/* Pagination */
2177
				featureNode = _fnFeatureHtmlPaginate( oSettings );
2178
			}
2179
			else if ( DataTable.ext.feature.length !== 0 )
2180
			{
2181
				/* Plug-in features */
2182
				var aoFeatures = DataTable.ext.feature;
2183
				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
2184
				{
2185
					if ( cOption == aoFeatures[k].cFeature )
2186
					{
2187
						featureNode = aoFeatures[k].fnInit( oSettings );
2188
						break;
2189
					}
2190
				}
2191
			}
2192
 
2193
			/* Add to the 2D features array */
2194
			if ( featureNode )
2195
			{
2196
				var aanFeatures = oSettings.aanFeatures;
2197
 
2198
				if ( ! aanFeatures[cOption] )
2199
				{
2200
					aanFeatures[cOption] = [];
2201
				}
2202
 
2203
				aanFeatures[cOption].push( featureNode );
2204
				insert.append( featureNode );
2205
			}
2206
		}
2207
 
2208
		/* Built our DOM structure - replace the holding div with what we want */
2209
		holding.replaceWith( insert );
2210
	}
2211
 
2212
 
2213
	/**
2214
	 * Use the DOM source to create up an array of header cells. The idea here is to
2215
	 * create a layout grid (array) of rows x columns, which contains a reference
2216
	 * to the cell that that point in the grid (regardless of col/rowspan), such that
2217
	 * any column / row could be removed and the new grid constructed
2218
	 *  @param array {object} aLayout Array to store the calculated layout in
2219
	 *  @param {node} nThead The header/footer element for the table
2220
	 *  @memberof DataTable#oApi
2221
	 */
2222
	function _fnDetectHeader ( aLayout, nThead )
2223
	{
2224
		var nTrs = $(nThead).children('tr');
2225
		var nTr, nCell;
2226
		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
2227
		var bUnique;
2228
		var fnShiftCol = function ( a, i, j ) {
2229
			var k = a[i];
2230
	                while ( k[j] ) {
2231
				j++;
2232
			}
2233
			return j;
2234
		};
2235
 
2236
		aLayout.splice( 0, aLayout.length );
2237
 
2238
		/* We know how many rows there are in the layout - so prep it */
2239
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2240
		{
2241
			aLayout.push( [] );
2242
		}
2243
 
2244
		/* Calculate a layout array */
2245
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2246
		{
2247
			nTr = nTrs[i];
2248
			iColumn = 0;
2249
 
2250
			/* For every cell in the row... */
2251
			nCell = nTr.firstChild;
2252
			while ( nCell ) {
2253
				if ( nCell.nodeName.toUpperCase() == "TD" ||
2254
				     nCell.nodeName.toUpperCase() == "TH" )
2255
				{
2256
					/* Get the col and rowspan attributes from the DOM and sanitise them */
2257
					iColspan = nCell.getAttribute('colspan') * 1;
2258
					iRowspan = nCell.getAttribute('rowspan') * 1;
2259
					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
2260
					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
2261
 
2262
					/* There might be colspan cells already in this row, so shift our target
2263
					 * accordingly
2264
					 */
2265
					iColShifted = fnShiftCol( aLayout, i, iColumn );
2266
 
2267
					/* Cache calculation for unique columns */
2268
					bUnique = iColspan === 1 ? true : false;
2269
 
2270
					/* If there is col / rowspan, copy the information into the layout grid */
2271
					for ( l=0 ; l<iColspan ; l++ )
2272
					{
2273
						for ( k=0 ; k<iRowspan ; k++ )
2274
						{
2275
							aLayout[i+k][iColShifted+l] = {
2276
								"cell": nCell,
2277
								"unique": bUnique
2278
							};
2279
							aLayout[i+k].nTr = nTr;
2280
						}
2281
					}
2282
				}
2283
				nCell = nCell.nextSibling;
2284
			}
2285
		}
2286
	}
2287
 
2288
 
2289
	/**
2290
	 * Get an array of unique th elements, one for each column
2291
	 *  @param {object} oSettings dataTables settings object
2292
	 *  @param {node} nHeader automatically detect the layout from this node - optional
2293
	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2294
	 *  @returns array {node} aReturn list of unique th's
2295
	 *  @memberof DataTable#oApi
2296
	 */
2297
	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
2298
	{
2299
		var aReturn = [];
2300
		if ( !aLayout )
2301
		{
2302
			aLayout = oSettings.aoHeader;
2303
			if ( nHeader )
2304
			{
2305
				aLayout = [];
2306
				_fnDetectHeader( aLayout, nHeader );
2307
			}
2308
		}
2309
 
2310
		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
2311
		{
2312
			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
2313
			{
2314
				if ( aLayout[i][j].unique &&
2315
					 (!aReturn[j] || !oSettings.bSortCellsTop) )
2316
				{
2317
					aReturn[j] = aLayout[i][j].cell;
2318
				}
2319
			}
2320
		}
2321
 
2322
		return aReturn;
2323
	}
2324
 
2325
 
2326
 
2327
	/**
2328
	 * Create an Ajax call based on the table's settings, taking into account that
2329
	 * parameters can have multiple forms, and backwards compatibility.
2330
	 *
2331
	 * @param {object} oSettings dataTables settings object
2332
	 * @param {array} data Data to send to the server, required by
2333
	 *     DataTables - may be augmented by developer callbacks
2334
	 * @param {function} fn Callback function to run when data is obtained
2335
	 */
2336
	function _fnBuildAjax( oSettings, data, fn )
2337
	{
2338
		// Compatibility with 1.9-, allow fnServerData and event to manipulate
2339
		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
2340
 
2341
		// Convert to object based for 1.10+ if using the old array scheme which can
2342
		// come from server-side processing or serverParams
2343
		if ( data && $.isArray(data) ) {
2344
			var tmp = {};
2345
			var rbracket = /(.*?)\[\]$/;
2346
 
2347
			$.each( data, function (key, val) {
2348
				var match = val.name.match(rbracket);
2349
 
2350
				if ( match ) {
2351
					// Support for arrays
2352
					var name = match[0];
2353
 
2354
					if ( ! tmp[ name ] ) {
2355
						tmp[ name ] = [];
2356
					}
2357
					tmp[ name ].push( val.value );
2358
				}
2359
				else {
2360
					tmp[val.name] = val.value;
2361
				}
2362
			} );
2363
			data = tmp;
2364
		}
2365
 
2366
		var ajaxData;
2367
		var ajax = oSettings.ajax;
2368
		var instance = oSettings.oInstance;
2369
 
2370
		if ( $.isPlainObject( ajax ) && ajax.data )
2371
		{
2372
			ajaxData = ajax.data;
2373
 
2374
			var newData = $.isFunction( ajaxData ) ?
2375
				ajaxData( data ) :  // fn can manipulate data or return an object
2376
				ajaxData;           // object or array to merge
2377
 
2378
			// If the function returned an object, use that alone
2379
			data = $.isFunction( ajaxData ) && newData ?
2380
				newData :
2381
				$.extend( true, data, newData );
2382
 
2383
			// Remove the data property as we've resolved it already and don't want
2384
			// jQuery to do it again (it is restored at the end of the function)
2385
			delete ajax.data;
2386
		}
2387
 
2388
		var baseAjax = {
2389
			"data": data,
2390
			"success": function (json) {
2391
				var error = json.error || json.sError;
2392
				if ( error ) {
2393
					oSettings.oApi._fnLog( oSettings, 0, error );
2394
				}
2395
 
2396
				oSettings.json = json;
2397
				_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2398
				fn( json );
2399
			},
2400
			"dataType": "json",
2401
			"cache": false,
2402
			"type": oSettings.sServerMethod,
2403
			"error": function (xhr, error, thrown) {
2404
				var log = oSettings.oApi._fnLog;
2405
 
2406
				if ( error == "parsererror" ) {
2407
					log( oSettings, 0, 'Invalid JSON response', 1 );
2408
				}
2409
				else if ( xhr.readyState === 4 ) {
2410
					log( oSettings, 0, 'Ajax error', 7 );
2411
				}
2412
 
2413
				_fnProcessingDisplay( oSettings, false );
2414
			}
2415
		};
2416
 
2417
		// Store the data submitted for the API
2418
		oSettings.oAjaxData = data;
2419
 
2420
		// Allow plug-ins and external processes to modify the data
2421
		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
2422
 
2423
		if ( oSettings.fnServerData )
2424
		{
2425
			// DataTables 1.9- compatibility
2426
			oSettings.fnServerData.call( instance,
2427
				oSettings.sAjaxSource,
2428
				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2429
					return { name: key, value: val };
2430
				} ),
2431
				fn,
2432
				oSettings
2433
			);
2434
		}
2435
		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
2436
		{
2437
			// DataTables 1.9- compatibility
2438
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
2439
				url: ajax || oSettings.sAjaxSource
2440
			} ) );
2441
		}
2442
		else if ( $.isFunction( ajax ) )
2443
		{
2444
			// Is a function - let the caller define what needs to be done
2445
			oSettings.jqXHR = ajax.call( instance, data, fn, oSettings );
2446
		}
2447
		else
2448
		{
2449
			// Object to extend the base settings
2450
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
2451
 
2452
			// Restore for next time around
2453
			ajax.data = ajaxData;
2454
		}
2455
	}
2456
 
2457
 
2458
	/**
2459
	 * Update the table using an Ajax call
2460
	 *  @param {object} settings dataTables settings object
2461
	 *  @returns {boolean} Block the table drawing or not
2462
	 *  @memberof DataTable#oApi
2463
	 */
2464
	function _fnAjaxUpdate( settings )
2465
	{
2466
		if ( settings.bAjaxDataGet ) {
2467
			settings.iDraw++;
2468
			_fnProcessingDisplay( settings, true );
2469
 
2470
			_fnBuildAjax(
2471
				settings,
2472
				_fnAjaxParameters( settings ),
2473
				function(json) {
2474
					_fnAjaxUpdateDraw( settings, json );
2475
				}
2476
			);
2477
 
2478
			return false;
2479
		}
2480
		return true;
2481
	}
2482
 
2483
 
2484
	/**
2485
	 * Build up the parameters in an object needed for a server-side processing
2486
	 * request. Note that this is basically done twice, is different ways - a modern
2487
	 * method which is used by default in DataTables 1.10 which uses objects and
2488
	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2489
	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
2490
	 * option is set.
2491
	 *  @param {object} oSettings dataTables settings object
2492
	 *  @returns {bool} block the table drawing or not
2493
	 *  @memberof DataTable#oApi
2494
	 */
2495
	function _fnAjaxParameters( settings )
2496
	{
2497
		var
2498
			columns = settings.aoColumns,
2499
			columnCount = columns.length,
2500
			features = settings.oFeatures,
2501
			preSearch = settings.oPreviousSearch,
2502
			preColSearch = settings.aoPreSearchCols,
2503
			i, data = [], dataProp, column, columnSearch,
2504
			sort = _fnSortFlatten( settings ),
2505
			displayStart = settings._iDisplayStart,
2506
			displayLength = features.bPaginate !== false ?
2507
				settings._iDisplayLength :
2508
				-1;
2509
 
2510
		var param = function ( name, value ) {
2511
			data.push( { 'name': name, 'value': value } );
2512
		};
2513
 
2514
		// DataTables 1.9- compatible method
2515
		param( 'sEcho',          settings.iDraw );
2516
		param( 'iColumns',       columnCount );
2517
		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
2518
		param( 'iDisplayStart',  displayStart );
2519
		param( 'iDisplayLength', displayLength );
2520
 
2521
		// DataTables 1.10+ method
2522
		var d = {
2523
			draw:    settings.iDraw,
2524
			columns: [],
2525
			order:   [],
2526
			start:   displayStart,
2527
			length:  displayLength,
2528
			search:  {
2529
				value: preSearch.sSearch,
2530
				regex: preSearch.bRegex
2531
			}
2532
		};
2533
 
2534
		for ( i=0 ; i<columnCount ; i++ ) {
2535
			column = columns[i];
2536
			columnSearch = preColSearch[i];
2537
			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
2538
 
2539
			d.columns.push( {
2540
				data:       dataProp,
2541
				name:       column.sName,
2542
				searchable: column.bSearchable,
2543
				orderable:  column.bSortable,
2544
				search:     {
2545
					value: columnSearch.sSearch,
2546
					regex: columnSearch.bRegex
2547
				}
2548
			} );
2549
 
2550
			param( "mDataProp_"+i, dataProp );
2551
 
2552
			if ( features.bFilter ) {
2553
				param( 'sSearch_'+i,     columnSearch.sSearch );
2554
				param( 'bRegex_'+i,      columnSearch.bRegex );
2555
				param( 'bSearchable_'+i, column.bSearchable );
2556
			}
2557
 
2558
			if ( features.bSort ) {
2559
				param( 'bSortable_'+i, column.bSortable );
2560
			}
2561
		}
2562
 
2563
		if ( features.bFilter ) {
2564
			param( 'sSearch', preSearch.sSearch );
2565
			param( 'bRegex', preSearch.bRegex );
2566
		}
2567
 
2568
		if ( features.bSort ) {
2569
			$.each( sort, function ( i, val ) {
2570
				d.order.push( { column: val.col, dir: val.dir } );
2571
 
2572
				param( 'iSortCol_'+i, val.col );
2573
				param( 'sSortDir_'+i, val.dir );
2574
			} );
2575
 
2576
			param( 'iSortingCols', sort.length );
2577
		}
2578
 
2579
		// If the legacy.ajax parameter is null, then we automatically decide which
2580
		// form to use, based on sAjaxSource
2581
		var legacy = DataTable.ext.legacy.ajax;
2582
		if ( legacy === null ) {
2583
			return settings.sAjaxSource ? data : d;
2584
		}
2585
 
2586
		// Otherwise, if legacy has been specified then we use that to decide on the
2587
		// form
2588
		return legacy ? data : d;
2589
	}
2590
 
2591
 
2592
	/**
2593
	 * Data the data from the server (nuking the old) and redraw the table
2594
	 *  @param {object} oSettings dataTables settings object
2595
	 *  @param {object} json json data return from the server.
2596
	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
2597
	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2598
	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2599
	 *  @param {array} json.aaData The data to display on this page
2600
	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
2601
	 *  @memberof DataTable#oApi
2602
	 */
2603
	function _fnAjaxUpdateDraw ( settings, json )
2604
	{
2605
		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2606
		// Support both
2607
		var compat = function ( old, modern ) {
2608
			return json[old] !== undefined ? json[old] : json[modern];
2609
		};
2610
 
2611
		var draw            = compat( 'sEcho',                'draw' );
2612
		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
2613
		var rocordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2614
 
2615
		if ( draw ) {
2616
			// Protect against out of sequence returns
2617
			if ( draw*1 < settings.iDraw ) {
2618
				return;
2619
			}
2620
			settings.iDraw = draw * 1;
2621
		}
2622
 
2623
		_fnClearTable( settings );
2624
		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
2625
		settings._iRecordsDisplay = parseInt(rocordsFiltered, 10);
2626
 
2627
		var data = _fnAjaxDataSrc( settings, json );
2628
		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2629
			_fnAddData( settings, data[i] );
2630
		}
2631
		settings.aiDisplay = settings.aiDisplayMaster.slice();
2632
 
2633
		settings.bAjaxDataGet = false;
2634
		_fnDraw( settings );
2635
 
2636
		if ( ! settings._bInitComplete ) {
2637
			_fnInitComplete( settings, json );
2638
		}
2639
 
2640
		settings.bAjaxDataGet = true;
2641
		_fnProcessingDisplay( settings, false );
2642
	}
2643
 
2644
 
2645
	/**
2646
	 * Get the data from the JSON data source to use for drawing a table. Using
2647
	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2648
	 * source object, or from a processing function.
2649
	 *  @param {object} oSettings dataTables settings object
2650
	 *  @param  {object} json Data source object / array from the server
2651
	 *  @return {array} Array of data to use
2652
	 */
2653
	function _fnAjaxDataSrc ( oSettings, json )
2654
	{
2655
		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
2656
			oSettings.ajax.dataSrc :
2657
			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
2658
 
2659
		// Compatibility with 1.9-. In order to read from aaData, check if the
2660
		// default has been changed, if not, check for aaData
2661
		if ( dataSrc === 'data' ) {
2662
			return json.aaData || json[dataSrc];
2663
		}
2664
 
2665
		return dataSrc !== "" ?
2666
			_fnGetObjectDataFn( dataSrc )( json ) :
2667
			json;
2668
	}
2669
 
2670
 
2671
	/**
2672
	 * Generate the node required for filtering text
2673
	 *  @returns {node} Filter control element
2674
	 *  @param {object} oSettings dataTables settings object
2675
	 *  @memberof DataTable#oApi
2676
	 */
2677
	function _fnFeatureHtmlFilter ( settings )
2678
	{
2679
		var classes = settings.oClasses;
2680
		var tableId = settings.sTableId;
2681
		var language = settings.oLanguage;
2682
		var previousSearch = settings.oPreviousSearch;
2683
		var features = settings.aanFeatures;
2684
		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
2685
 
2686
		var str = language.sSearch;
2687
		str = str.match(/_INPUT_/) ?
2688
			str.replace('_INPUT_', input) :
2689
			str+input;
2690
 
2691
		var filter = $('<div/>', {
2692
				'id': ! features.f ? tableId+'_filter' : null,
2693
				'class': classes.sFilter
2694
			} )
2695
			.append( $('<label/>' ).append( str ) );
2696
 
2697
		var searchFn = function() {
2698
			/* Update all other filter input elements for the new display */
2699
			var n = features.f;
2700
			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
2701
 
2702
			/* Now do the filter */
2703
			if ( val != previousSearch.sSearch ) {
2704
				_fnFilterComplete( settings, {
2705
					"sSearch": val,
2706
					"bRegex": previousSearch.bRegex,
2707
					"bSmart": previousSearch.bSmart ,
2708
					"bCaseInsensitive": previousSearch.bCaseInsensitive
2709
				} );
2710
 
2711
				// Need to redraw, without resorting
2712
				settings._iDisplayStart = 0;
2713
				_fnDraw( settings );
2714
			}
2715
		};
2716
 
2717
		var searchDelay = settings.searchDelay !== null ?
2718
			settings.searchDelay :
2719
			_fnDataSource( settings ) === 'ssp' ?
2720
				400 :
2721
				0;
2722
 
2723
		var jqFilter = $('input', filter)
2724
			.val( previousSearch.sSearch )
2725
			.attr( 'placeholder', language.sSearchPlaceholder )
2726
			.bind(
2727
				'keyup.DT search.DT input.DT paste.DT cut.DT',
2728
				searchDelay ?
2729
					_fnThrottle( searchFn, searchDelay ) :
2730
					searchFn
2731
			)
2732
			.bind( 'keypress.DT', function(e) {
2733
				/* Prevent form submission */
2734
				if ( e.keyCode == 13 ) {
2735
					return false;
2736
				}
2737
			} )
2738
			.attr('aria-controls', tableId);
2739
 
2740
		// Update the input elements whenever the table is filtered
2741
		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
2742
			if ( settings === s ) {
2743
				// IE9 throws an 'unknown error' if document.activeElement is used
2744
				// inside an iframe or frame...
2745
				try {
2746
					if ( jqFilter[0] !== document.activeElement ) {
2747
						jqFilter.val( previousSearch.sSearch );
2748
					}
2749
				}
2750
				catch ( e ) {}
2751
			}
2752
		} );
2753
 
2754
		return filter[0];
2755
	}
2756
 
2757
 
2758
	/**
2759
	 * Filter the table using both the global filter and column based filtering
2760
	 *  @param {object} oSettings dataTables settings object
2761
	 *  @param {object} oSearch search information
2762
	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2763
	 *  @memberof DataTable#oApi
2764
	 */
2765
	function _fnFilterComplete ( oSettings, oInput, iForce )
2766
	{
2767
		var oPrevSearch = oSettings.oPreviousSearch;
2768
		var aoPrevSearch = oSettings.aoPreSearchCols;
2769
		var fnSaveFilter = function ( oFilter ) {
2770
			/* Save the filtering values */
2771
			oPrevSearch.sSearch = oFilter.sSearch;
2772
			oPrevSearch.bRegex = oFilter.bRegex;
2773
			oPrevSearch.bSmart = oFilter.bSmart;
2774
			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
2775
		};
2776
		var fnRegex = function ( o ) {
2777
			// Backwards compatibility with the bEscapeRegex option
2778
			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
2779
		};
2780
 
2781
		// Resolve any column types that are unknown due to addition or invalidation
2782
		// @todo As per sort - can this be moved into an event handler?
2783
		_fnColumnTypes( oSettings );
2784
 
2785
		/* In server-side processing all filtering is done by the server, so no point hanging around here */
2786
		if ( _fnDataSource( oSettings ) != 'ssp' )
2787
		{
2788
			/* Global filter */
2789
			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
2790
			fnSaveFilter( oInput );
2791
 
2792
			/* Now do the individual column filter */
2793
			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
2794
			{
2795
				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
2796
					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
2797
			}
2798
 
2799
			/* Custom filtering */
2800
			_fnFilterCustom( oSettings );
2801
		}
2802
		else
2803
		{
2804
			fnSaveFilter( oInput );
2805
		}
2806
 
2807
		/* Tell the draw function we have been filtering */
2808
		oSettings.bFiltered = true;
2809
		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
2810
	}
2811
 
2812
 
2813
	/**
2814
	 * Apply custom filtering functions
2815
	 *  @param {object} oSettings dataTables settings object
2816
	 *  @memberof DataTable#oApi
2817
	 */
2818
	function _fnFilterCustom( settings )
2819
	{
2820
		var filters = DataTable.ext.search;
2821
		var displayRows = settings.aiDisplay;
2822
		var row, rowIdx;
2823
 
2824
		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
2825
			var rows = [];
2826
 
2827
			// Loop over each row and see if it should be included
2828
			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
2829
				rowIdx = displayRows[ j ];
2830
				row = settings.aoData[ rowIdx ];
2831
 
2832
				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
2833
					rows.push( rowIdx );
2834
				}
2835
			}
2836
 
2837
			// So the array reference doesn't break set the results into the
2838
			// existing array
2839
			displayRows.length = 0;
2840
			displayRows.push.apply( displayRows, rows );
2841
		}
2842
	}
2843
 
2844
 
2845
	/**
2846
	 * Filter the table on a per-column basis
2847
	 *  @param {object} oSettings dataTables settings object
2848
	 *  @param {string} sInput string to filter on
2849
	 *  @param {int} iColumn column to filter
2850
	 *  @param {bool} bRegex treat search string as a regular expression or not
2851
	 *  @param {bool} bSmart use smart filtering or not
2852
	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
2853
	 *  @memberof DataTable#oApi
2854
	 */
2855
	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
2856
	{
2857
		if ( searchStr === '' ) {
2858
			return;
2859
		}
2860
 
2861
		var data;
2862
		var display = settings.aiDisplay;
2863
		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
2864
 
2865
		for ( var i=display.length-1 ; i>=0 ; i-- ) {
2866
			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
2867
 
2868
			if ( ! rpSearch.test( data ) ) {
2869
				display.splice( i, 1 );
2870
			}
2871
		}
2872
	}
2873
 
2874
 
2875
	/**
2876
	 * Filter the data table based on user input and draw the table
2877
	 *  @param {object} settings dataTables settings object
2878
	 *  @param {string} input string to filter on
2879
	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
2880
	 *  @param {bool} regex treat as a regular expression or not
2881
	 *  @param {bool} smart perform smart filtering or not
2882
	 *  @param {bool} caseInsensitive Do case insenstive matching or not
2883
	 *  @memberof DataTable#oApi
2884
	 */
2885
	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
2886
	{
2887
		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
2888
		var prevSearch = settings.oPreviousSearch.sSearch;
2889
		var displayMaster = settings.aiDisplayMaster;
2890
		var display, invalidated, i;
2891
 
2892
		// Need to take account of custom filtering functions - always filter
2893
		if ( DataTable.ext.search.length !== 0 ) {
2894
			force = true;
2895
		}
2896
 
2897
		// Check if any of the rows were invalidated
2898
		invalidated = _fnFilterData( settings );
2899
 
2900
		// If the input is blank - we just want the full data set
2901
		if ( input.length <= 0 ) {
2902
			settings.aiDisplay = displayMaster.slice();
2903
		}
2904
		else {
2905
			// New search - start from the master array
2906
			if ( invalidated ||
2907
				 force ||
2908
				 prevSearch.length > input.length ||
2909
				 input.indexOf(prevSearch) !== 0 ||
2910
				 settings.bSorted // On resort, the display master needs to be
2911
				                  // re-filtered since indexes will have changed
2912
			) {
2913
				settings.aiDisplay = displayMaster.slice();
2914
			}
2915
 
2916
			// Search the display array
2917
			display = settings.aiDisplay;
2918
 
2919
			for ( i=display.length-1 ; i>=0 ; i-- ) {
2920
				if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
2921
					display.splice( i, 1 );
2922
				}
2923
			}
2924
		}
2925
	}
2926
 
2927
 
2928
	/**
2929
	 * Build a regular expression object suitable for searching a table
2930
	 *  @param {string} sSearch string to search for
2931
	 *  @param {bool} bRegex treat as a regular expression or not
2932
	 *  @param {bool} bSmart perform smart filtering or not
2933
	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
2934
	 *  @returns {RegExp} constructed object
2935
	 *  @memberof DataTable#oApi
2936
	 */
2937
	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
2938
	{
2939
		search = regex ?
2940
			search :
2941
			_fnEscapeRegex( search );
2942
 
2943
		if ( smart ) {
2944
			/* For smart filtering we want to allow the search to work regardless of
2945
			 * word order. We also want double quoted text to be preserved, so word
2946
			 * order is important - a la google. So this is what we want to
2947
			 * generate:
2948
			 * 
2949
			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
2950
			 */
2951
			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || '', function ( word ) {
2952
				if ( word.charAt(0) === '"' ) {
2953
					var m = word.match( /^"(.*)"$/ );
2954
					word = m ? m[1] : word;
2955
				}
2956
 
2957
				return word.replace('"', '');
2958
			} );
2959
 
2960
			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
2961
		}
2962
 
2963
		return new RegExp( search, caseInsensitive ? 'i' : '' );
2964
	}
2965
 
2966
 
2967
	/**
2968
	 * scape a string such that it can be used in a regular expression
2969
	 *  @param {string} sVal string to escape
2970
	 *  @returns {string} escaped string
2971
	 *  @memberof DataTable#oApi
2972
	 */
2973
	function _fnEscapeRegex ( sVal )
2974
	{
2975
		return sVal.replace( _re_escape_regex, '\\$1' );
2976
	}
2977
 
2978
 
2979
 
2980
	var __filter_div = $('<div>')[0];
2981
	var __filter_div_textContent = __filter_div.textContent !== undefined;
2982
 
2983
	// Update the filtering data for each row if needed (by invalidation or first run)
2984
	function _fnFilterData ( settings )
2985
	{
2986
		var columns = settings.aoColumns;
2987
		var column;
2988
		var i, j, ien, jen, filterData, cellData, row;
2989
		var fomatters = DataTable.ext.type.search;
2990
		var wasInvalidated = false;
2991
 
2992
		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
2993
			row = settings.aoData[i];
2994
 
2995
			if ( ! row._aFilterData ) {
2996
				filterData = [];
2997
 
2998
				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
2999
					column = columns[j];
3000
 
3001
					if ( column.bSearchable ) {
3002
						cellData = _fnGetCellData( settings, i, j, 'filter' );
3003
 
3004
						if ( fomatters[ column.sType ] ) {
3005
							cellData = fomatters[ column.sType ]( cellData );
3006
						}
3007
 
3008
						// Search in DataTables 1.10 is string based. In 1.11 this
3009
						// should be altered to also allow strict type checking.
3010
						if ( cellData === null ) {
3011
							cellData = '';
3012
						}
3013
 
3014
						if ( typeof cellData !== 'string' && cellData.toString ) {
3015
							cellData = cellData.toString();
3016
						}
3017
					}
3018
					else {
3019
						cellData = '';
3020
					}
3021
 
3022
					// If it looks like there is an HTML entity in the string,
3023
					// attempt to decode it so sorting works as expected. Note that
3024
					// we could use a single line of jQuery to do this, but the DOM
3025
					// method used here is much faster http://jsperf.com/html-decode
3026
					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
3027
						__filter_div.innerHTML = cellData;
3028
						cellData = __filter_div_textContent ?
3029
							__filter_div.textContent :
3030
							__filter_div.innerText;
3031
					}
3032
 
3033
					if ( cellData.replace ) {
3034
						cellData = cellData.replace(/[\r\n]/g, '');
3035
					}
3036
 
3037
					filterData.push( cellData );
3038
				}
3039
 
3040
				row._aFilterData = filterData;
3041
				row._sFilterRow = filterData.join('  ');
3042
				wasInvalidated = true;
3043
			}
3044
		}
3045
 
3046
		return wasInvalidated;
3047
	}
3048
 
3049
 
3050
	/**
3051
	 * Convert from the internal Hungarian notation to camelCase for external
3052
	 * interaction
3053
	 *  @param {object} obj Object to convert
3054
	 *  @returns {object} Inverted object
3055
	 *  @memberof DataTable#oApi
3056
	 */
3057
	function _fnSearchToCamel ( obj )
3058
	{
3059
		return {
3060
			search:          obj.sSearch,
3061
			smart:           obj.bSmart,
3062
			regex:           obj.bRegex,
3063
			caseInsensitive: obj.bCaseInsensitive
3064
		};
3065
	}
3066
 
3067
 
3068
 
3069
	/**
3070
	 * Convert from camelCase notation to the internal Hungarian. We could use the
3071
	 * Hungarian convert function here, but this is cleaner
3072
	 *  @param {object} obj Object to convert
3073
	 *  @returns {object} Inverted object
3074
	 *  @memberof DataTable#oApi
3075
	 */
3076
	function _fnSearchToHung ( obj )
3077
	{
3078
		return {
3079
			sSearch:          obj.search,
3080
			bSmart:           obj.smart,
3081
			bRegex:           obj.regex,
3082
			bCaseInsensitive: obj.caseInsensitive
3083
		};
3084
	}
3085
 
3086
	/**
3087
	 * Generate the node required for the info display
3088
	 *  @param {object} oSettings dataTables settings object
3089
	 *  @returns {node} Information element
3090
	 *  @memberof DataTable#oApi
3091
	 */
3092
	function _fnFeatureHtmlInfo ( settings )
3093
	{
3094
		var
3095
			tid = settings.sTableId,
3096
			nodes = settings.aanFeatures.i,
3097
			n = $('<div/>', {
3098
				'class': settings.oClasses.sInfo,
3099
				'id': ! nodes ? tid+'_info' : null
3100
			} );
3101
 
3102
		if ( ! nodes ) {
3103
			// Update display on each draw
3104
			settings.aoDrawCallback.push( {
3105
				"fn": _fnUpdateInfo,
3106
				"sName": "information"
3107
			} );
3108
 
3109
			n
3110
				.attr( 'role', 'status' )
3111
				.attr( 'aria-live', 'polite' );
3112
 
3113
			// Table is described by our info div
3114
			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
3115
		}
3116
 
3117
		return n[0];
3118
	}
3119
 
3120
 
3121
	/**
3122
	 * Update the information elements in the display
3123
	 *  @param {object} settings dataTables settings object
3124
	 *  @memberof DataTable#oApi
3125
	 */
3126
	function _fnUpdateInfo ( settings )
3127
	{
3128
		/* Show information about the table */
3129
		var nodes = settings.aanFeatures.i;
3130
		if ( nodes.length === 0 ) {
3131
			return;
3132
		}
3133
 
3134
		var
3135
			lang  = settings.oLanguage,
3136
			start = settings._iDisplayStart+1,
3137
			end   = settings.fnDisplayEnd(),
3138
			max   = settings.fnRecordsTotal(),
3139
			total = settings.fnRecordsDisplay(),
3140
			out   = total ?
3141
				lang.sInfo :
3142
				lang.sInfoEmpty;
3143
 
3144
		if ( total !== max ) {
3145
			/* Record set after filtering */
3146
			out += ' ' + lang.sInfoFiltered;
3147
		}
3148
 
3149
		// Convert the macros
3150
		out += lang.sInfoPostFix;
3151
		out = _fnInfoMacros( settings, out );
3152
 
3153
		var callback = lang.fnInfoCallback;
3154
		if ( callback !== null ) {
3155
			out = callback.call( settings.oInstance,
3156
				settings, start, end, max, total, out
3157
			);
3158
		}
3159
 
3160
		$(nodes).html( out );
3161
	}
3162
 
3163
 
3164
	function _fnInfoMacros ( settings, str )
3165
	{
3166
		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3167
		// internally
3168
		var
3169
			formatter  = settings.fnFormatNumber,
3170
			start      = settings._iDisplayStart+1,
3171
			len        = settings._iDisplayLength,
3172
			vis        = settings.fnRecordsDisplay(),
3173
			all        = len === -1;
3174
 
3175
		return str.
3176
			replace(/_START_/g, formatter.call( settings, start ) ).
3177
			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
3178
			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
3179
			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
3180
			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
3181
			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
3182
	}
3183
 
3184
 
3185
 
3186
	/**
3187
	 * Draw the table for the first time, adding all required features
3188
	 *  @param {object} settings dataTables settings object
3189
	 *  @memberof DataTable#oApi
3190
	 */
3191
	function _fnInitialise ( settings )
3192
	{
3193
		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3194
		var columns = settings.aoColumns, column;
3195
		var features = settings.oFeatures;
3196
 
3197
		/* Ensure that the table data is fully initialised */
3198
		if ( ! settings.bInitialised ) {
3199
			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
3200
			return;
3201
		}
3202
 
3203
		/* Show the display HTML options */
3204
		_fnAddOptionsHtml( settings );
3205
 
3206
		/* Build and draw the header / footer for the table */
3207
		_fnBuildHead( settings );
3208
		_fnDrawHead( settings, settings.aoHeader );
3209
		_fnDrawHead( settings, settings.aoFooter );
3210
 
3211
		/* Okay to show that something is going on now */
3212
		_fnProcessingDisplay( settings, true );
3213
 
3214
		/* Calculate sizes for columns */
3215
		if ( features.bAutoWidth ) {
3216
			_fnCalculateColumnWidths( settings );
3217
		}
3218
 
3219
		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
3220
			column = columns[i];
3221
 
3222
			if ( column.sWidth ) {
3223
				column.nTh.style.width = _fnStringToCss( column.sWidth );
3224
			}
3225
		}
3226
 
3227
		// If there is default sorting required - let's do it. The sort function
3228
		// will do the drawing for us. Otherwise we draw the table regardless of the
3229
		// Ajax source - this allows the table to look initialised for Ajax sourcing
3230
		// data (show 'loading' message possibly)
3231
		_fnReDraw( settings );
3232
 
3233
		// Server-side processing init complete is done by _fnAjaxUpdateDraw
3234
		var dataSrc = _fnDataSource( settings );
3235
		if ( dataSrc != 'ssp' ) {
3236
			// if there is an ajax source load the data
3237
			if ( dataSrc == 'ajax' ) {
3238
				_fnBuildAjax( settings, [], function(json) {
3239
					var aData = _fnAjaxDataSrc( settings, json );
3240
 
3241
					// Got the data - add it to the table
3242
					for ( i=0 ; i<aData.length ; i++ ) {
3243
						_fnAddData( settings, aData[i] );
3244
					}
3245
 
3246
					// Reset the init display for cookie saving. We've already done
3247
					// a filter, and therefore cleared it before. So we need to make
3248
					// it appear 'fresh'
3249
					settings.iInitDisplayStart = iAjaxStart;
3250
 
3251
					_fnReDraw( settings );
3252
 
3253
					_fnProcessingDisplay( settings, false );
3254
					_fnInitComplete( settings, json );
3255
				}, settings );
3256
			}
3257
			else {
3258
				_fnProcessingDisplay( settings, false );
3259
				_fnInitComplete( settings );
3260
			}
3261
		}
3262
	}
3263
 
3264
 
3265
	/**
3266
	 * Draw the table for the first time, adding all required features
3267
	 *  @param {object} oSettings dataTables settings object
3268
	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
3269
	 *    with client-side processing (optional)
3270
	 *  @memberof DataTable#oApi
3271
	 */
3272
	function _fnInitComplete ( settings, json )
3273
	{
3274
		settings._bInitComplete = true;
3275
 
3276
		// On an Ajax load we now have data and therefore want to apply the column
3277
		// sizing
3278
		if ( json ) {
3279
			_fnAdjustColumnSizing( settings );
3280
		}
3281
 
3282
		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3283
	}
3284
 
3285
 
3286
	function _fnLengthChange ( settings, val )
3287
	{
3288
		var len = parseInt( val, 10 );
3289
		settings._iDisplayLength = len;
3290
 
3291
		_fnLengthOverflow( settings );
3292
 
3293
		// Fire length change event
3294
		_fnCallbackFire( settings, null, 'length', [settings, len] );
3295
	}
3296
 
3297
 
3298
	/**
3299
	 * Generate the node required for user display length changing
3300
	 *  @param {object} settings dataTables settings object
3301
	 *  @returns {node} Display length feature node
3302
	 *  @memberof DataTable#oApi
3303
	 */
3304
	function _fnFeatureHtmlLength ( settings )
3305
	{
3306
		var
3307
			classes  = settings.oClasses,
3308
			tableId  = settings.sTableId,
3309
			menu     = settings.aLengthMenu,
3310
			d2       = $.isArray( menu[0] ),
3311
			lengths  = d2 ? menu[0] : menu,
3312
			language = d2 ? menu[1] : menu;
3313
 
3314
		var select = $('<select/>', {
3315
			'name':          tableId+'_length',
3316
			'aria-controls': tableId,
3317
			'class':         classes.sLengthSelect
3318
		} );
3319
 
3320
		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
3321
			select[0][ i ] = new Option( language[i], lengths[i] );
3322
		}
3323
 
3324
		var div = $('<div><label/></div>').addClass( classes.sLength );
3325
		if ( ! settings.aanFeatures.l ) {
3326
			div[0].id = tableId+'_length';
3327
		}
3328
 
3329
		div.children().append(
3330
			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
3331
		);
3332
 
3333
		// Can't use `select` variable as user might provide their own and the
3334
		// reference is broken by the use of outerHTML
3335
		$('select', div)
3336
			.val( settings._iDisplayLength )
3337
			.bind( 'change.DT', function(e) {
3338
				_fnLengthChange( settings, $(this).val() );
3339
				_fnDraw( settings );
3340
			} );
3341
 
3342
		// Update node value whenever anything changes the table's length
3343
		$(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
3344
			if ( settings === s ) {
3345
				$('select', div).val( len );
3346
			}
3347
		} );
3348
 
3349
		return div[0];
3350
	}
3351
 
3352
 
3353
 
3354
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3355
	 * Note that most of the paging logic is done in
3356
	 * DataTable.ext.pager
3357
	 */
3358
 
3359
	/**
3360
	 * Generate the node required for default pagination
3361
	 *  @param {object} oSettings dataTables settings object
3362
	 *  @returns {node} Pagination feature node
3363
	 *  @memberof DataTable#oApi
3364
	 */
3365
	function _fnFeatureHtmlPaginate ( settings )
3366
	{
3367
		var
3368
			type   = settings.sPaginationType,
3369
			plugin = DataTable.ext.pager[ type ],
3370
			modern = typeof plugin === 'function',
3371
			redraw = function( settings ) {
3372
				_fnDraw( settings );
3373
			},
3374
			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
3375
			features = settings.aanFeatures;
3376
 
3377
		if ( ! modern ) {
3378
			plugin.fnInit( settings, node, redraw );
3379
		}
3380
 
3381
		/* Add a draw callback for the pagination on first instance, to update the paging display */
3382
		if ( ! features.p )
3383
		{
3384
			node.id = settings.sTableId+'_paginate';
3385
 
3386
			settings.aoDrawCallback.push( {
3387
				"fn": function( settings ) {
3388
					if ( modern ) {
3389
						var
3390
							start      = settings._iDisplayStart,
3391
							len        = settings._iDisplayLength,
3392
							visRecords = settings.fnRecordsDisplay(),
3393
							all        = len === -1,
3394
							page = all ? 0 : Math.ceil( start / len ),
3395
							pages = all ? 1 : Math.ceil( visRecords / len ),
3396
							buttons = plugin(page, pages),
3397
							i, ien;
3398
 
3399
						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
3400
							_fnRenderer( settings, 'pageButton' )(
3401
								settings, features.p[i], i, buttons, page, pages
3402
							);
3403
						}
3404
					}
3405
					else {
3406
						plugin.fnUpdate( settings, redraw );
3407
					}
3408
				},
3409
				"sName": "pagination"
3410
			} );
3411
		}
3412
 
3413
		return node;
3414
	}
3415
 
3416
 
3417
	/**
3418
	 * Alter the display settings to change the page
3419
	 *  @param {object} settings DataTables settings object
3420
	 *  @param {string|int} action Paging action to take: "first", "previous",
3421
	 *    "next" or "last" or page number to jump to (integer)
3422
	 *  @param [bool] redraw Automatically draw the update or not
3423
	 *  @returns {bool} true page has changed, false - no change
3424
	 *  @memberof DataTable#oApi
3425
	 */
3426
	function _fnPageChange ( settings, action, redraw )
3427
	{
3428
		var
3429
			start     = settings._iDisplayStart,
3430
			len       = settings._iDisplayLength,
3431
			records   = settings.fnRecordsDisplay();
3432
 
3433
		if ( records === 0 || len === -1 )
3434
		{
3435
			start = 0;
3436
		}
3437
		else if ( typeof action === "number" )
3438
		{
3439
			start = action * len;
3440
 
3441
			if ( start > records )
3442
			{
3443
				start = 0;
3444
			}
3445
		}
3446
		else if ( action == "first" )
3447
		{
3448
			start = 0;
3449
		}
3450
		else if ( action == "previous" )
3451
		{
3452
			start = len >= 0 ?
3453
				start - len :
3454
				0;
3455
 
3456
			if ( start < 0 )
3457
			{
3458
			  start = 0;
3459
			}
3460
		}
3461
		else if ( action == "next" )
3462
		{
3463
			if ( start + len < records )
3464
			{
3465
				start += len;
3466
			}
3467
		}
3468
		else if ( action == "last" )
3469
		{
3470
			start = Math.floor( (records-1) / len) * len;
3471
		}
3472
		else
3473
		{
3474
			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
3475
		}
3476
 
3477
		var changed = settings._iDisplayStart !== start;
3478
		settings._iDisplayStart = start;
3479
 
3480
		if ( changed ) {
3481
			_fnCallbackFire( settings, null, 'page', [settings] );
3482
 
3483
			if ( redraw ) {
3484
				_fnDraw( settings );
3485
			}
3486
		}
3487
 
3488
		return changed;
3489
	}
3490
 
3491
 
3492
 
3493
	/**
3494
	 * Generate the node required for the processing node
3495
	 *  @param {object} settings dataTables settings object
3496
	 *  @returns {node} Processing element
3497
	 *  @memberof DataTable#oApi
3498
	 */
3499
	function _fnFeatureHtmlProcessing ( settings )
3500
	{
3501
		return $('<div/>', {
3502
				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
3503
				'class': settings.oClasses.sProcessing
3504
			} )
3505
			.html( settings.oLanguage.sProcessing )
3506
			.insertBefore( settings.nTable )[0];
3507
	}
3508
 
3509
 
3510
	/**
3511
	 * Display or hide the processing indicator
3512
	 *  @param {object} settings dataTables settings object
3513
	 *  @param {bool} show Show the processing indicator (true) or not (false)
3514
	 *  @memberof DataTable#oApi
3515
	 */
3516
	function _fnProcessingDisplay ( settings, show )
3517
	{
3518
		if ( settings.oFeatures.bProcessing ) {
3519
			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
3520
		}
3521
 
3522
		_fnCallbackFire( settings, null, 'processing', [settings, show] );
3523
	}
3524
 
3525
	/**
3526
	 * Add any control elements for the table - specifically scrolling
3527
	 *  @param {object} settings dataTables settings object
3528
	 *  @returns {node} Node to add to the DOM
3529
	 *  @memberof DataTable#oApi
3530
	 */
3531
	function _fnFeatureHtmlTable ( settings )
3532
	{
3533
		var table = $(settings.nTable);
3534
 
3535
		// Add the ARIA grid role to the table
3536
		table.attr( 'role', 'grid' );
3537
 
3538
		// Scrolling from here on in
3539
		var scroll = settings.oScroll;
3540
 
3541
		if ( scroll.sX === '' && scroll.sY === '' ) {
3542
			return settings.nTable;
3543
		}
3544
 
3545
		var scrollX = scroll.sX;
3546
		var scrollY = scroll.sY;
3547
		var classes = settings.oClasses;
3548
		var caption = table.children('caption');
3549
		var captionSide = caption.length ? caption[0]._captionSide : null;
3550
		var headerClone = $( table[0].cloneNode(false) );
3551
		var footerClone = $( table[0].cloneNode(false) );
3552
		var footer = table.children('tfoot');
3553
		var _div = '<div/>';
3554
		var size = function ( s ) {
3555
			return !s ? null : _fnStringToCss( s );
3556
		};
3557
 
3558
		// This is fairly messy, but with x scrolling enabled, if the table has a
3559
		// width attribute, regardless of any width applied using the column width
3560
		// options, the browser will shrink or grow the table as needed to fit into
3561
		// that 100%. That would make the width options useless. So we remove it.
3562
		// This is okay, under the assumption that width:100% is applied to the
3563
		// table in CSS (it is in the default stylesheet) which will set the table
3564
		// width as appropriate (the attribute and css behave differently...)
3565
		if ( scroll.sX && table.attr('width') === '100%' ) {
3566
			table.removeAttr('width');
3567
		}
3568
 
3569
		if ( ! footer.length ) {
3570
			footer = null;
3571
		}
3572
 
3573
		/*
3574
		 * The HTML structure that we want to generate in this function is:
3575
		 *  div - scroller
3576
		 *    div - scroll head
3577
		 *      div - scroll head inner
3578
		 *        table - scroll head table
3579
		 *          thead - thead
3580
		 *    div - scroll body
3581
		 *      table - table (master table)
3582
		 *        thead - thead clone for sizing
3583
		 *        tbody - tbody
3584
		 *    div - scroll foot
3585
		 *      div - scroll foot inner
3586
		 *        table - scroll foot table
3587
		 *          tfoot - tfoot
3588
		 */
3589
		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
3590
			.append(
3591
				$(_div, { 'class': classes.sScrollHead } )
3592
					.css( {
3593
						overflow: 'hidden',
3594
						position: 'relative',
3595
						border: 0,
3596
						width: scrollX ? size(scrollX) : '100%'
3597
					} )
3598
					.append(
3599
						$(_div, { 'class': classes.sScrollHeadInner } )
3600
							.css( {
3601
								'box-sizing': 'content-box',
3602
								width: scroll.sXInner || '100%'
3603
							} )
3604
							.append(
3605
								headerClone
3606
									.removeAttr('id')
3607
									.css( 'margin-left', 0 )
3608
									.append(
3609
										table.children('thead')
3610
									)
3611
							)
3612
					)
3613
					.append( captionSide === 'top' ? caption : null )
3614
			)
3615
			.append(
3616
				$(_div, { 'class': classes.sScrollBody } )
3617
					.css( {
3618
						overflow: 'auto',
3619
						height: size( scrollY ),
3620
						width: size( scrollX )
3621
					} )
3622
					.append( table )
3623
			);
3624
 
3625
		if ( footer ) {
3626
			scroller.append(
3627
				$(_div, { 'class': classes.sScrollFoot } )
3628
					.css( {
3629
						overflow: 'hidden',
3630
						border: 0,
3631
						width: scrollX ? size(scrollX) : '100%'
3632
					} )
3633
					.append(
3634
						$(_div, { 'class': classes.sScrollFootInner } )
3635
							.append(
3636
								footerClone
3637
									.removeAttr('id')
3638
									.css( 'margin-left', 0 )
3639
									.append(
3640
										table.children('tfoot')
3641
									)
3642
							)
3643
					)
3644
					.append( captionSide === 'bottom' ? caption : null )
3645
			);
3646
		}
3647
 
3648
		var children = scroller.children();
3649
		var scrollHead = children[0];
3650
		var scrollBody = children[1];
3651
		var scrollFoot = footer ? children[2] : null;
3652
 
3653
		// When the body is scrolled, then we also want to scroll the headers
3654
		if ( scrollX ) {
3655
			$(scrollBody).scroll( function (e) {
3656
				var scrollLeft = this.scrollLeft;
3657
 
3658
				scrollHead.scrollLeft = scrollLeft;
3659
 
3660
				if ( footer ) {
3661
					scrollFoot.scrollLeft = scrollLeft;
3662
				}
3663
			} );
3664
		}
3665
 
3666
		settings.nScrollHead = scrollHead;
3667
		settings.nScrollBody = scrollBody;
3668
		settings.nScrollFoot = scrollFoot;
3669
 
3670
		// On redraw - align columns
3671
		settings.aoDrawCallback.push( {
3672
			"fn": _fnScrollDraw,
3673
			"sName": "scrolling"
3674
		} );
3675
 
3676
		return scroller[0];
3677
	}
3678
 
3679
 
3680
 
3681
	/**
3682
	 * Update the header, footer and body tables for resizing - i.e. column
3683
	 * alignment.
3684
	 *
3685
	 * Welcome to the most horrible function DataTables. The process that this
3686
	 * function follows is basically:
3687
	 *   1. Re-create the table inside the scrolling div
3688
	 *   2. Take live measurements from the DOM
3689
	 *   3. Apply the measurements to align the columns
3690
	 *   4. Clean up
3691
	 *
3692
	 *  @param {object} settings dataTables settings object
3693
	 *  @memberof DataTable#oApi
3694
	 */
3695
	function _fnScrollDraw ( settings )
3696
	{
3697
		// Given that this is such a monster function, a lot of variables are use
3698
		// to try and keep the minimised size as small as possible
3699
		var
3700
			scroll         = settings.oScroll,
3701
			scrollX        = scroll.sX,
3702
			scrollXInner   = scroll.sXInner,
3703
			scrollY        = scroll.sY,
3704
			barWidth       = scroll.iBarWidth,
3705
			divHeader      = $(settings.nScrollHead),
3706
			divHeaderStyle = divHeader[0].style,
3707
			divHeaderInner = divHeader.children('div'),
3708
			divHeaderInnerStyle = divHeaderInner[0].style,
3709
			divHeaderTable = divHeaderInner.children('table'),
3710
			divBodyEl      = settings.nScrollBody,
3711
			divBody        = $(divBodyEl),
3712
			divBodyStyle   = divBodyEl.style,
3713
			divFooter      = $(settings.nScrollFoot),
3714
			divFooterInner = divFooter.children('div'),
3715
			divFooterTable = divFooterInner.children('table'),
3716
			header         = $(settings.nTHead),
3717
			table          = $(settings.nTable),
3718
			tableEl        = table[0],
3719
			tableStyle     = tableEl.style,
3720
			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
3721
			browser        = settings.oBrowser,
3722
			ie67           = browser.bScrollOversize,
3723
			headerTrgEls, footerTrgEls,
3724
			headerSrcEls, footerSrcEls,
3725
			headerCopy, footerCopy,
3726
			headerWidths=[], footerWidths=[],
3727
			headerContent=[],
3728
			idx, correction, sanityWidth,
3729
			zeroOut = function(nSizer) {
3730
				var style = nSizer.style;
3731
				style.paddingTop = "0";
3732
				style.paddingBottom = "0";
3733
				style.borderTopWidth = "0";
3734
				style.borderBottomWidth = "0";
3735
				style.height = 0;
3736
			};
3737
 
3738
		/*
3739
		 * 1. Re-create the table inside the scrolling div
3740
		 */
3741
 
3742
		// Remove the old minimised thead and tfoot elements in the inner table
3743
		table.children('thead, tfoot').remove();
3744
 
3745
		// Clone the current header and footer elements and then place it into the inner table
3746
		headerCopy = header.clone().prependTo( table );
3747
		headerTrgEls = header.find('tr'); // original header is in its own table
3748
		headerSrcEls = headerCopy.find('tr');
3749
		headerCopy.find('th, td').removeAttr('tabindex');
3750
 
3751
		if ( footer ) {
3752
			footerCopy = footer.clone().prependTo( table );
3753
			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
3754
			footerSrcEls = footerCopy.find('tr');
3755
		}
3756
 
3757
 
3758
		/*
3759
		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
3760
		 */
3761
 
3762
		// Remove old sizing and apply the calculated column widths
3763
		// Get the unique column headers in the newly created (cloned) header. We want to apply the
3764
		// calculated sizes to this header
3765
		if ( ! scrollX )
3766
		{
3767
			divBodyStyle.width = '100%';
3768
			divHeader[0].style.width = '100%';
3769
		}
3770
 
3771
		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
3772
			idx = _fnVisibleToColumnIndex( settings, i );
3773
			el.style.width = settings.aoColumns[idx].sWidth;
3774
		} );
3775
 
3776
		if ( footer ) {
3777
			_fnApplyToChildren( function(n) {
3778
				n.style.width = "";
3779
			}, footerSrcEls );
3780
		}
3781
 
3782
		// If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3783
		// will end up forcing the scrollbar to appear, making our measurements wrong for when we
3784
		// then hide it (end of this function), so add the header height to the body scroller.
3785
		if ( scroll.bCollapse && scrollY !== "" ) {
3786
			divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3787
		}
3788
 
3789
		// Size the table as a whole
3790
		sanityWidth = table.outerWidth();
3791
		if ( scrollX === "" ) {
3792
			// No x scrolling
3793
			tableStyle.width = "100%";
3794
 
3795
			// IE7 will make the width of the table when 100% include the scrollbar
3796
			// - which is shouldn't. When there is a scrollbar we need to take this
3797
			// into account.
3798
			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
3799
				divBody.css('overflow-y') == "scroll")
3800
			) {
3801
				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3802
			}
3803
		}
3804
		else
3805
		{
3806
			// x scrolling
3807
			if ( scrollXInner !== "" ) {
3808
				// x scroll inner has been given - use it
3809
				tableStyle.width = _fnStringToCss(scrollXInner);
3810
			}
3811
			else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3812
				// There is y-scrolling - try to take account of the y scroll bar
3813
				tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3814
				if ( table.outerWidth() > sanityWidth-barWidth ) {
3815
					// Not possible to take account of it
3816
					tableStyle.width = _fnStringToCss( sanityWidth );
3817
				}
3818
			}
3819
			else {
3820
				// When all else fails
3821
				tableStyle.width = _fnStringToCss( sanityWidth );
3822
			}
3823
		}
3824
 
3825
		// Recalculate the sanity width - now that we've applied the required width,
3826
		// before it was a temporary variable. This is required because the column
3827
		// width calculation is done before this table DOM is created.
3828
		sanityWidth = table.outerWidth();
3829
 
3830
		// Hidden header should have zero height, so remove padding and borders. Then
3831
		// set the width based on the real headers
3832
 
3833
		// Apply all styles in one pass
3834
		_fnApplyToChildren( zeroOut, headerSrcEls );
3835
 
3836
		// Read all widths in next pass
3837
		_fnApplyToChildren( function(nSizer) {
3838
			headerContent.push( nSizer.innerHTML );
3839
			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3840
		}, headerSrcEls );
3841
 
3842
		// Apply all widths in final pass
3843
		_fnApplyToChildren( function(nToSize, i) {
3844
			nToSize.style.width = headerWidths[i];
3845
		}, headerTrgEls );
3846
 
3847
		$(headerSrcEls).height(0);
3848
 
3849
		/* Same again with the footer if we have one */
3850
		if ( footer )
3851
		{
3852
			_fnApplyToChildren( zeroOut, footerSrcEls );
3853
 
3854
			_fnApplyToChildren( function(nSizer) {
3855
				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3856
			}, footerSrcEls );
3857
 
3858
			_fnApplyToChildren( function(nToSize, i) {
3859
				nToSize.style.width = footerWidths[i];
3860
			}, footerTrgEls );
3861
 
3862
			$(footerSrcEls).height(0);
3863
		}
3864
 
3865
 
3866
		/*
3867
		 * 3. Apply the measurements
3868
		 */
3869
 
3870
		// "Hide" the header and footer that we used for the sizing. We need to keep
3871
		// the content of the cell so that the width applied to the header and body
3872
		// both match, but we want to hide it completely. We want to also fix their
3873
		// width to what they currently are
3874
		_fnApplyToChildren( function(nSizer, i) {
3875
			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
3876
			nSizer.style.width = headerWidths[i];
3877
		}, headerSrcEls );
3878
 
3879
		if ( footer )
3880
		{
3881
			_fnApplyToChildren( function(nSizer, i) {
3882
				nSizer.innerHTML = "";
3883
				nSizer.style.width = footerWidths[i];
3884
			}, footerSrcEls );
3885
		}
3886
 
3887
		// Sanity check that the table is of a sensible width. If not then we are going to get
3888
		// misalignment - try to prevent this by not allowing the table to shrink below its min width
3889
		if ( table.outerWidth() < sanityWidth )
3890
		{
3891
			// The min width depends upon if we have a vertical scrollbar visible or not */
3892
			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
3893
				divBody.css('overflow-y') == "scroll")) ?
3894
					sanityWidth+barWidth :
3895
					sanityWidth;
3896
 
3897
			// IE6/7 are a law unto themselves...
3898
			if ( ie67 && (divBodyEl.scrollHeight >
3899
				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
3900
			) {
3901
				tableStyle.width = _fnStringToCss( correction-barWidth );
3902
			}
3903
 
3904
			// And give the user a warning that we've stopped the table getting too small
3905
			if ( scrollX === "" || scrollXInner !== "" ) {
3906
				_fnLog( settings, 1, 'Possible column misalignment', 6 );
3907
			}
3908
		}
3909
		else
3910
		{
3911
			correction = '100%';
3912
		}
3913
 
3914
		// Apply to the container elements
3915
		divBodyStyle.width = _fnStringToCss( correction );
3916
		divHeaderStyle.width = _fnStringToCss( correction );
3917
 
3918
		if ( footer ) {
3919
			settings.nScrollFoot.style.width = _fnStringToCss( correction );
3920
		}
3921
 
3922
 
3923
		/*
3924
		 * 4. Clean up
3925
		 */
3926
		if ( ! scrollY ) {
3927
			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
3928
			 * the scrollbar height from the visible display, rather than adding it on. We need to
3929
			 * set the height in order to sort this. Don't want to do it in any other browsers.
3930
			 */
3931
			if ( ie67 ) {
3932
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
3933
			}
3934
		}
3935
 
3936
		if ( scrollY && scroll.bCollapse ) {
3937
			divBodyStyle.height = _fnStringToCss( scrollY );
3938
 
3939
			var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
3940
				barWidth :
3941
				0;
3942
 
3943
			if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
3944
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
3945
			}
3946
		}
3947
 
3948
		/* Finally set the width's of the header and footer tables */
3949
		var iOuterWidth = table.outerWidth();
3950
		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
3951
		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
3952
 
3953
		// Figure out if there are scrollbar present - if so then we need a the header and footer to
3954
		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
3955
		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
3956
		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
3957
		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
3958
 
3959
		if ( footer ) {
3960
			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
3961
			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
3962
			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
3963
		}
3964
 
3965
		/* Adjust the position of the header in case we loose the y-scrollbar */
3966
		divBody.scroll();
3967
 
3968
		// If sorting or filtering has occurred, jump the scrolling back to the top
3969
		// only if we aren't holding the position
3970
		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
3971
			divBodyEl.scrollTop = 0;
3972
		}
3973
	}
3974
 
3975
 
3976
 
3977
	/**
3978
	 * Apply a given function to the display child nodes of an element array (typically
3979
	 * TD children of TR rows
3980
	 *  @param {function} fn Method to apply to the objects
3981
	 *  @param array {nodes} an1 List of elements to look through for display children
3982
	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
3983
	 *  @memberof DataTable#oApi
3984
	 */
3985
	function _fnApplyToChildren( fn, an1, an2 )
3986
	{
3987
		var index=0, i=0, iLen=an1.length;
3988
		var nNode1, nNode2;
3989
 
3990
		while ( i < iLen ) {
3991
			nNode1 = an1[i].firstChild;
3992
			nNode2 = an2 ? an2[i].firstChild : null;
3993
 
3994
			while ( nNode1 ) {
3995
				if ( nNode1.nodeType === 1 ) {
3996
					if ( an2 ) {
3997
						fn( nNode1, nNode2, index );
3998
					}
3999
					else {
4000
						fn( nNode1, index );
4001
					}
4002
 
4003
					index++;
4004
				}
4005
 
4006
				nNode1 = nNode1.nextSibling;
4007
				nNode2 = an2 ? nNode2.nextSibling : null;
4008
			}
4009
 
4010
			i++;
4011
		}
4012
	}
4013
 
4014
 
4015
 
4016
	var __re_html_remove = /<.*?>/g;
4017
 
4018
 
4019
	/**
4020
	 * Calculate the width of columns for the table
4021
	 *  @param {object} oSettings dataTables settings object
4022
	 *  @memberof DataTable#oApi
4023
	 */
4024
	function _fnCalculateColumnWidths ( oSettings )
4025
	{
4026
		var
4027
			table = oSettings.nTable,
4028
			columns = oSettings.aoColumns,
4029
			scroll = oSettings.oScroll,
4030
			scrollY = scroll.sY,
4031
			scrollX = scroll.sX,
4032
			scrollXInner = scroll.sXInner,
4033
			columnCount = columns.length,
4034
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
4035
			headerCells = $('th', oSettings.nTHead),
4036
			tableWidthAttr = table.getAttribute('width'),
4037
			tableContainer = table.parentNode,
4038
			userInputs = false,
4039
			i, column, columnIdx, width, outerWidth;
4040
 
4041
		/* Convert any user input sizes into pixel sizes */
4042
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
4043
			column = columns[ visibleColumns[i] ];
4044
 
4045
			if ( column.sWidth !== null ) {
4046
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
4047
 
4048
				userInputs = true;
4049
			}
4050
		}
4051
 
4052
		/* If the number of columns in the DOM equals the number that we have to
4053
		 * process in DataTables, then we can use the offsets that are created by
4054
		 * the web- browser. No custom sizes can be set in order for this to happen,
4055
		 * nor scrolling used
4056
		 */
4057
		if ( ! userInputs && ! scrollX && ! scrollY &&
4058
		    columnCount == _fnVisbleColumns( oSettings ) &&
4059
			columnCount == headerCells.length
4060
		) {
4061
			for ( i=0 ; i<columnCount ; i++ ) {
4062
				columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
4063
			}
4064
		}
4065
		else
4066
		{
4067
			// Otherwise construct a single row table with the widest node in the
4068
			// data, assign any user defined widths, then insert it into the DOM and
4069
			// allow the browser to do all the hard work of calculating table widths
4070
			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
4071
				.empty()
4072
				.css( 'visibility', 'hidden' )
4073
				.removeAttr( 'id' )
4074
				.append( $(oSettings.nTHead).clone( false ) )
4075
				.append( $(oSettings.nTFoot).clone( false ) )
4076
				.append( $('<tbody><tr/></tbody>') );
4077
 
4078
			// Remove any assigned widths from the footer (from scrolling)
4079
			tmpTable.find('tfoot th, tfoot td').css('width', '');
4080
 
4081
			var tr = tmpTable.find( 'tbody tr' );
4082
 
4083
			// Apply custom sizing to the cloned header
4084
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
4085
 
4086
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
4087
				column = columns[ visibleColumns[i] ];
4088
 
4089
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
4090
					_fnStringToCss( column.sWidthOrig ) :
4091
					'';
4092
			}
4093
 
4094
			// Find the widest cell for each column and put it into the table
4095
			if ( oSettings.aoData.length ) {
4096
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
4097
					columnIdx = visibleColumns[i];
4098
					column = columns[ columnIdx ];
4099
 
4100
					$( _fnGetWidestNode( oSettings, columnIdx ) )
4101
						.clone( false )
4102
						.append( column.sContentPadding )
4103
						.appendTo( tr );
4104
				}
4105
			}
4106
 
4107
			// Table has been built, attach to the document so we can work with it
4108
			tmpTable.appendTo( tableContainer );
4109
 
4110
			// When scrolling (X or Y) we want to set the width of the table as 
4111
			// appropriate. However, when not scrolling leave the table width as it
4112
			// is. This results in slightly different, but I think correct behaviour
4113
			if ( scrollX && scrollXInner ) {
4114
				tmpTable.width( scrollXInner );
4115
			}
4116
			else if ( scrollX ) {
4117
				tmpTable.css( 'width', 'auto' );
4118
 
4119
				if ( tmpTable.width() < tableContainer.offsetWidth ) {
4120
					tmpTable.width( tableContainer.offsetWidth );
4121
				}
4122
			}
4123
			else if ( scrollY ) {
4124
				tmpTable.width( tableContainer.offsetWidth );
4125
			}
4126
			else if ( tableWidthAttr ) {
4127
				tmpTable.width( tableWidthAttr );
4128
			}
4129
 
4130
			// Take into account the y scrollbar
4131
			_fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4132
 
4133
			// Browsers need a bit of a hand when a width is assigned to any columns
4134
			// when x-scrolling as they tend to collapse the table to the min-width,
4135
			// even if we sent the column widths. So we need to keep track of what
4136
			// the table width should be by summing the user given values, and the
4137
			// automatic values
4138
			if ( scrollX )
4139
			{
4140
				var total = 0;
4141
 
4142
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
4143
					column = columns[ visibleColumns[i] ];
4144
					outerWidth = $(headerCells[i]).outerWidth();
4145
 
4146
					total += column.sWidthOrig === null ?
4147
						outerWidth :
4148
						parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4149
				}
4150
 
4151
				tmpTable.width( _fnStringToCss( total ) );
4152
				table.style.width = _fnStringToCss( total );
4153
			}
4154
 
4155
			// Get the width of each column in the constructed table
4156
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
4157
				column = columns[ visibleColumns[i] ];
4158
				width = $(headerCells[i]).width();
4159
 
4160
				if ( width ) {
4161
					column.sWidth = _fnStringToCss( width );
4162
				}
4163
			}
4164
 
4165
			table.style.width = _fnStringToCss( tmpTable.css('width') );
4166
 
4167
			// Finished with the table - ditch it
4168
			tmpTable.remove();
4169
		}
4170
 
4171
		// If there is a width attr, we want to attach an event listener which
4172
		// allows the table sizing to automatically adjust when the window is
4173
		// resized. Use the width attr rather than CSS, since we can't know if the
4174
		// CSS is a relative value or absolute - DOM read is always px.
4175
		if ( tableWidthAttr ) {
4176
			table.style.width = _fnStringToCss( tableWidthAttr );
4177
		}
4178
 
4179
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4180
			$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4181
				_fnAdjustColumnSizing( oSettings );
4182
			} ) );
4183
 
4184
			oSettings._reszEvt = true;
4185
		}
4186
	}
4187
 
4188
 
4189
	/**
4190
	 * Throttle the calls to a function. Arguments and context are maintained for
4191
	 * the throttled function
4192
	 *  @param {function} fn Function to be called
4193
	 *  @param {int} [freq=200] call frequency in mS
4194
	 *  @returns {function} wrapped function
4195
	 *  @memberof DataTable#oApi
4196
	 */
4197
	function _fnThrottle( fn, freq ) {
4198
		var
4199
			frequency = freq !== undefined ? freq : 200,
4200
			last,
4201
			timer;
4202
 
4203
		return function () {
4204
			var
4205
				that = this,
4206
				now  = +new Date(),
4207
				args = arguments;
4208
 
4209
			if ( last && now < last + frequency ) {
4210
				clearTimeout( timer );
4211
 
4212
				timer = setTimeout( function () {
4213
					last = undefined;
4214
					fn.apply( that, args );
4215
				}, frequency );
4216
			}
4217
			else if ( last ) {
4218
				last = now;
4219
				fn.apply( that, args );
4220
			}
4221
			else {
4222
				last = now;
4223
			}
4224
		};
4225
	}
4226
 
4227
 
4228
	/**
4229
	 * Convert a CSS unit width to pixels (e.g. 2em)
4230
	 *  @param {string} width width to be converted
4231
	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
4232
	 *  @returns {int} width in pixels
4233
	 *  @memberof DataTable#oApi
4234
	 */
4235
	function _fnConvertToWidth ( width, parent )
4236
	{
4237
		if ( ! width ) {
4238
			return 0;
4239
		}
4240
 
4241
		var n = $('<div/>')
4242
			.css( 'width', _fnStringToCss( width ) )
4243
			.appendTo( parent || document.body );
4244
 
4245
		var val = n[0].offsetWidth;
4246
		n.remove();
4247
 
4248
		return val;
4249
	}
4250
 
4251
 
4252
	/**
4253
	 * Adjust a table's width to take account of vertical scroll bar
4254
	 *  @param {object} oSettings dataTables settings object
4255
	 *  @param {node} n table node
4256
	 *  @memberof DataTable#oApi
4257
	 */
4258
 
4259
	function _fnScrollingWidthAdjust ( settings, n )
4260
	{
4261
		var scroll = settings.oScroll;
4262
 
4263
		if ( scroll.sX || scroll.sY ) {
4264
			// When y-scrolling only, we want to remove the width of the scroll bar
4265
			// so the table + scroll bar will fit into the area available, otherwise
4266
			// we fix the table at its current size with no adjustment
4267
			var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4268
			n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4269
		}
4270
	}
4271
 
4272
 
4273
	/**
4274
	 * Get the widest node
4275
	 *  @param {object} settings dataTables settings object
4276
	 *  @param {int} colIdx column of interest
4277
	 *  @returns {node} widest table node
4278
	 *  @memberof DataTable#oApi
4279
	 */
4280
	function _fnGetWidestNode( settings, colIdx )
4281
	{
4282
		var idx = _fnGetMaxLenString( settings, colIdx );
4283
		if ( idx < 0 ) {
4284
			return null;
4285
		}
4286
 
4287
		var data = settings.aoData[ idx ];
4288
		return ! data.nTr ? // Might not have been created when deferred rendering
4289
			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
4290
			data.anCells[ colIdx ];
4291
	}
4292
 
4293
 
4294
	/**
4295
	 * Get the maximum strlen for each data column
4296
	 *  @param {object} settings dataTables settings object
4297
	 *  @param {int} colIdx column of interest
4298
	 *  @returns {string} max string length for each column
4299
	 *  @memberof DataTable#oApi
4300
	 */
4301
	function _fnGetMaxLenString( settings, colIdx )
4302
	{
4303
		var s, max=-1, maxIdx = -1;
4304
 
4305
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4306
			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4307
			s = s.replace( __re_html_remove, '' );
4308
 
4309
			if ( s.length > max ) {
4310
				max = s.length;
4311
				maxIdx = i;
4312
			}
4313
		}
4314
 
4315
		return maxIdx;
4316
	}
4317
 
4318
 
4319
	/**
4320
	 * Append a CSS unit (only if required) to a string
4321
	 *  @param {string} value to css-ify
4322
	 *  @returns {string} value with css unit
4323
	 *  @memberof DataTable#oApi
4324
	 */
4325
	function _fnStringToCss( s )
4326
	{
4327
		if ( s === null ) {
4328
			return '0px';
4329
		}
4330
 
4331
		if ( typeof s == 'number' ) {
4332
			return s < 0 ?
4333
				'0px' :
4334
				s+'px';
4335
		}
4336
 
4337
		// Check it has a unit character already
4338
		return s.match(/\d$/) ?
4339
			s+'px' :
4340
			s;
4341
	}
4342
 
4343
 
4344
	/**
4345
	 * Get the width of a scroll bar in this browser being used
4346
	 *  @returns {int} width in pixels
4347
	 *  @memberof DataTable#oApi
4348
	 */
4349
	function _fnScrollBarWidth ()
4350
	{
4351
		// On first run a static variable is set, since this is only needed once.
4352
		// Subsequent runs will just use the previously calculated value
4353
		if ( ! DataTable.__scrollbarWidth ) {
4354
			var inner = $('<p/>').css( {
4355
				width: '100%',
4356
				height: 200,
4357
				padding: 0
4358
			} )[0];
4359
 
4360
			var outer = $('<div/>')
4361
				.css( {
4362
					position: 'absolute',
4363
					top: 0,
4364
					left: 0,
4365
					width: 200,
4366
					height: 150,
4367
					padding: 0,
4368
					overflow: 'hidden',
4369
					visibility: 'hidden'
4370
				} )
4371
				.append( inner )
4372
				.appendTo( 'body' );
4373
 
4374
			var w1 = inner.offsetWidth;
4375
			outer.css( 'overflow', 'scroll' );
4376
			var w2 = inner.offsetWidth;
4377
 
4378
			if ( w1 === w2 ) {
4379
				w2 = outer[0].clientWidth;
4380
			}
4381
 
4382
			outer.remove();
4383
 
4384
			DataTable.__scrollbarWidth = w1 - w2;
4385
		}
4386
 
4387
		return DataTable.__scrollbarWidth;
4388
	}
4389
 
4390
 
4391
 
4392
	function _fnSortFlatten ( settings )
4393
	{
4394
		var
4395
			i, iLen, k, kLen,
4396
			aSort = [],
4397
			aiOrig = [],
4398
			aoColumns = settings.aoColumns,
4399
			aDataSort, iCol, sType, srcCol,
4400
			fixed = settings.aaSortingFixed,
4401
			fixedObj = $.isPlainObject( fixed ),
4402
			nestedSort = [],
4403
			add = function ( a ) {
4404
				if ( a.length && ! $.isArray( a[0] ) ) {
4405
					// 1D array
4406
					nestedSort.push( a );
4407
				}
4408
				else {
4409
					// 2D array
4410
					nestedSort.push.apply( nestedSort, a );
4411
				}
4412
			};
4413
 
4414
		// Build the sort array, with pre-fix and post-fix options if they have been
4415
		// specified
4416
		if ( $.isArray( fixed ) ) {
4417
			add( fixed );
4418
		}
4419
 
4420
		if ( fixedObj && fixed.pre ) {
4421
			add( fixed.pre );
4422
		}
4423
 
4424
		add( settings.aaSorting );
4425
 
4426
		if (fixedObj && fixed.post ) {
4427
			add( fixed.post );
4428
		}
4429
 
4430
		for ( i=0 ; i<nestedSort.length ; i++ )
4431
		{
4432
			srcCol = nestedSort[i][0];
4433
			aDataSort = aoColumns[ srcCol ].aDataSort;
4434
 
4435
			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
4436
			{
4437
				iCol = aDataSort[k];
4438
				sType = aoColumns[ iCol ].sType || 'string';
4439
 
4440
				if ( nestedSort[i]._idx === undefined ) {
4441
					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
4442
				}
4443
 
4444
				aSort.push( {
4445
					src:       srcCol,
4446
					col:       iCol,
4447
					dir:       nestedSort[i][1],
4448
					index:     nestedSort[i]._idx,
4449
					type:      sType,
4450
					formatter: DataTable.ext.type.order[ sType+"-pre" ]
4451
				} );
4452
			}
4453
		}
4454
 
4455
		return aSort;
4456
	}
4457
 
4458
	/**
4459
	 * Change the order of the table
4460
	 *  @param {object} oSettings dataTables settings object
4461
	 *  @memberof DataTable#oApi
4462
	 *  @todo This really needs split up!
4463
	 */
4464
	function _fnSort ( oSettings )
4465
	{
4466
		var
4467
			i, ien, iLen, j, jLen, k, kLen,
4468
			sDataType, nTh,
4469
			aiOrig = [],
4470
			oExtSort = DataTable.ext.type.order,
4471
			aoData = oSettings.aoData,
4472
			aoColumns = oSettings.aoColumns,
4473
			aDataSort, data, iCol, sType, oSort,
4474
			formatters = 0,
4475
			sortCol,
4476
			displayMaster = oSettings.aiDisplayMaster,
4477
			aSort;
4478
 
4479
		// Resolve any column types that are unknown due to addition or invalidation
4480
		// @todo Can this be moved into a 'data-ready' handler which is called when
4481
		//   data is going to be used in the table?
4482
		_fnColumnTypes( oSettings );
4483
 
4484
		aSort = _fnSortFlatten( oSettings );
4485
 
4486
		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
4487
			sortCol = aSort[i];
4488
 
4489
			// Track if we can use the fast sort algorithm
4490
			if ( sortCol.formatter ) {
4491
				formatters++;
4492
			}
4493
 
4494
			// Load the data needed for the sort, for each cell
4495
			_fnSortData( oSettings, sortCol.col );
4496
		}
4497
 
4498
		/* No sorting required if server-side or no sorting array */
4499
		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
4500
		{
4501
			// Create a value - key array of the current row positions such that we can use their
4502
			// current position during the sort, if values match, in order to perform stable sorting
4503
			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
4504
				aiOrig[ displayMaster[i] ] = i;
4505
			}
4506
 
4507
			/* Do the sort - here we want multi-column sorting based on a given data source (column)
4508
			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4509
			 * follow on it's own, but this is what we want (example two column sorting):
4510
			 *  fnLocalSorting = function(a,b){
4511
			 *    var iTest;
4512
			 *    iTest = oSort['string-asc']('data11', 'data12');
4513
			 *      if (iTest !== 0)
4514
			 *        return iTest;
4515
			 *    iTest = oSort['numeric-desc']('data21', 'data22');
4516
			 *    if (iTest !== 0)
4517
			 *      return iTest;
4518
			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4519
			 *  }
4520
			 * Basically we have a test for each sorting column, if the data in that column is equal,
4521
			 * test the next column. If all columns match, then we use a numeric sort on the row
4522
			 * positions in the original data array to provide a stable sort.
4523
			 *
4524
			 * Note - I know it seems excessive to have two sorting methods, but the first is around
4525
			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
4526
			 * methods which do not have a pre-sort formatting function.
4527
			 */
4528
			if ( formatters === aSort.length ) {
4529
				// All sort types have formatting functions
4530
				displayMaster.sort( function ( a, b ) {
4531
					var
4532
						x, y, k, test, sort,
4533
						len=aSort.length,
4534
						dataA = aoData[a]._aSortData,
4535
						dataB = aoData[b]._aSortData;
4536
 
4537
					for ( k=0 ; k<len ; k++ ) {
4538
						sort = aSort[k];
4539
 
4540
						x = dataA[ sort.col ];
4541
						y = dataB[ sort.col ];
4542
 
4543
						test = x<y ? -1 : x>y ? 1 : 0;
4544
						if ( test !== 0 ) {
4545
							return sort.dir === 'asc' ? test : -test;
4546
						}
4547
					}
4548
 
4549
					x = aiOrig[a];
4550
					y = aiOrig[b];
4551
					return x<y ? -1 : x>y ? 1 : 0;
4552
				} );
4553
			}
4554
			else {
4555
				// Depreciated - remove in 1.11 (providing a plug-in option)
4556
				// Not all sort types have formatting methods, so we have to call their sorting
4557
				// methods.
4558
				displayMaster.sort( function ( a, b ) {
4559
					var
4560
						x, y, k, l, test, sort, fn,
4561
						len=aSort.length,
4562
						dataA = aoData[a]._aSortData,
4563
						dataB = aoData[b]._aSortData;
4564
 
4565
					for ( k=0 ; k<len ; k++ ) {
4566
						sort = aSort[k];
4567
 
4568
						x = dataA[ sort.col ];
4569
						y = dataB[ sort.col ];
4570
 
4571
						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
4572
						test = fn( x, y );
4573
						if ( test !== 0 ) {
4574
							return test;
4575
						}
4576
					}
4577
 
4578
					x = aiOrig[a];
4579
					y = aiOrig[b];
4580
					return x<y ? -1 : x>y ? 1 : 0;
4581
				} );
4582
			}
4583
		}
4584
 
4585
		/* Tell the draw function that we have sorted the data */
4586
		oSettings.bSorted = true;
4587
	}
4588
 
4589
 
4590
	function _fnSortAria ( settings )
4591
	{
4592
		var label;
4593
		var nextSort;
4594
		var columns = settings.aoColumns;
4595
		var aSort = _fnSortFlatten( settings );
4596
		var oAria = settings.oLanguage.oAria;
4597
 
4598
		// ARIA attributes - need to loop all columns, to update all (removing old
4599
		// attributes as needed)
4600
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4601
		{
4602
			var col = columns[i];
4603
			var asSorting = col.asSorting;
4604
			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
4605
			var th = col.nTh;
4606
 
4607
			// IE7 is throwing an error when setting these properties with jQuery's
4608
			// attr() and removeAttr() methods...
4609
			th.removeAttribute('aria-sort');
4610
 
4611
			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4612
			if ( col.bSortable ) {
4613
				if ( aSort.length > 0 && aSort[0].col == i ) {
4614
					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
4615
					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
4616
				}
4617
				else {
4618
					nextSort = asSorting[0];
4619
				}
4620
 
4621
				label = sTitle + ( nextSort === "asc" ?
4622
					oAria.sSortAscending :
4623
					oAria.sSortDescending
4624
				);
4625
			}
4626
			else {
4627
				label = sTitle;
4628
			}
4629
 
4630
			th.setAttribute('aria-label', label);
4631
		}
4632
	}
4633
 
4634
 
4635
	/**
4636
	 * Function to run on user sort request
4637
	 *  @param {object} settings dataTables settings object
4638
	 *  @param {node} attachTo node to attach the handler to
4639
	 *  @param {int} colIdx column sorting index
4640
	 *  @param {boolean} [append=false] Append the requested sort to the existing
4641
	 *    sort if true (i.e. multi-column sort)
4642
	 *  @param {function} [callback] callback function
4643
	 *  @memberof DataTable#oApi
4644
	 */
4645
	function _fnSortListener ( settings, colIdx, append, callback )
4646
	{
4647
		var col = settings.aoColumns[ colIdx ];
4648
		var sorting = settings.aaSorting;
4649
		var asSorting = col.asSorting;
4650
		var nextSortIdx;
4651
		var next = function ( a, overflow ) {
4652
			var idx = a._idx;
4653
			if ( idx === undefined ) {
4654
				idx = $.inArray( a[1], asSorting );
4655
			}
4656
 
4657
			return idx+1 < asSorting.length ?
4658
				idx+1 :
4659
				overflow ?
4660
					null :
4661
					0;
4662
		};
4663
 
4664
		// Convert to 2D array if needed
4665
		if ( typeof sorting[0] === 'number' ) {
4666
			sorting = settings.aaSorting = [ sorting ];
4667
		}
4668
 
4669
		// If appending the sort then we are multi-column sorting
4670
		if ( append && settings.oFeatures.bSortMulti ) {
4671
			// Are we already doing some kind of sort on this column?
4672
			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
4673
 
4674
			if ( sortIdx !== -1 ) {
4675
				// Yes, modify the sort
4676
				nextSortIdx = next( sorting[sortIdx], true );
4677
 
4678
				if ( nextSortIdx === null ) {
4679
					sorting.splice( sortIdx, 1 );
4680
				}
4681
				else {
4682
					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
4683
					sorting[sortIdx]._idx = nextSortIdx;
4684
				}
4685
			}
4686
			else {
4687
				// No sort on this column yet
4688
				sorting.push( [ colIdx, asSorting[0], 0 ] );
4689
				sorting[sorting.length-1]._idx = 0;
4690
			}
4691
		}
4692
		else if ( sorting.length && sorting[0][0] == colIdx ) {
4693
			// Single column - already sorting on this column, modify the sort
4694
			nextSortIdx = next( sorting[0] );
4695
 
4696
			sorting.length = 1;
4697
			sorting[0][1] = asSorting[ nextSortIdx ];
4698
			sorting[0]._idx = nextSortIdx;
4699
		}
4700
		else {
4701
			// Single column - sort only on this column
4702
			sorting.length = 0;
4703
			sorting.push( [ colIdx, asSorting[0] ] );
4704
			sorting[0]._idx = 0;
4705
		}
4706
 
4707
		// Run the sort by calling a full redraw
4708
		_fnReDraw( settings );
4709
 
4710
		// callback used for async user interaction
4711
		if ( typeof callback == 'function' ) {
4712
			callback( settings );
4713
		}
4714
	}
4715
 
4716
 
4717
	/**
4718
	 * Attach a sort handler (click) to a node
4719
	 *  @param {object} settings dataTables settings object
4720
	 *  @param {node} attachTo node to attach the handler to
4721
	 *  @param {int} colIdx column sorting index
4722
	 *  @param {function} [callback] callback function
4723
	 *  @memberof DataTable#oApi
4724
	 */
4725
	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
4726
	{
4727
		var col = settings.aoColumns[ colIdx ];
4728
 
4729
		_fnBindAction( attachTo, {}, function (e) {
4730
			/* If the column is not sortable - don't to anything */
4731
			if ( col.bSortable === false ) {
4732
				return;
4733
			}
4734
 
4735
			// If processing is enabled use a timeout to allow the processing
4736
			// display to be shown - otherwise to it synchronously
4737
			if ( settings.oFeatures.bProcessing ) {
4738
				_fnProcessingDisplay( settings, true );
4739
 
4740
				setTimeout( function() {
4741
					_fnSortListener( settings, colIdx, e.shiftKey, callback );
4742
 
4743
					// In server-side processing, the draw callback will remove the
4744
					// processing display
4745
					if ( _fnDataSource( settings ) !== 'ssp' ) {
4746
						_fnProcessingDisplay( settings, false );
4747
					}
4748
				}, 0 );
4749
			}
4750
			else {
4751
				_fnSortListener( settings, colIdx, e.shiftKey, callback );
4752
			}
4753
		} );
4754
	}
4755
 
4756
 
4757
	/**
4758
	 * Set the sorting classes on table's body, Note: it is safe to call this function
4759
	 * when bSort and bSortClasses are false
4760
	 *  @param {object} oSettings dataTables settings object
4761
	 *  @memberof DataTable#oApi
4762
	 */
4763
	function _fnSortingClasses( settings )
4764
	{
4765
		var oldSort = settings.aLastSort;
4766
		var sortClass = settings.oClasses.sSortColumn;
4767
		var sort = _fnSortFlatten( settings );
4768
		var features = settings.oFeatures;
4769
		var i, ien, colIdx;
4770
 
4771
		if ( features.bSort && features.bSortClasses ) {
4772
			// Remove old sorting classes
4773
			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
4774
				colIdx = oldSort[i].src;
4775
 
4776
				// Remove column sorting
4777
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4778
					.removeClass( sortClass + (i<2 ? i+1 : 3) );
4779
			}
4780
 
4781
			// Add new column sorting
4782
			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
4783
				colIdx = sort[i].src;
4784
 
4785
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4786
					.addClass( sortClass + (i<2 ? i+1 : 3) );
4787
			}
4788
		}
4789
 
4790
		settings.aLastSort = sort;
4791
	}
4792
 
4793
 
4794
	// Get the data to sort a column, be it from cache, fresh (populating the
4795
	// cache), or from a sort formatter
4796
	function _fnSortData( settings, idx )
4797
	{
4798
		// Custom sorting function - provided by the sort data type
4799
		var column = settings.aoColumns[ idx ];
4800
		var customSort = DataTable.ext.order[ column.sSortDataType ];
4801
		var customData;
4802
 
4803
		if ( customSort ) {
4804
			customData = customSort.call( settings.oInstance, settings, idx,
4805
				_fnColumnIndexToVisible( settings, idx )
4806
			);
4807
		}
4808
 
4809
		// Use / populate cache
4810
		var row, cellData;
4811
		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
4812
 
4813
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4814
			row = settings.aoData[i];
4815
 
4816
			if ( ! row._aSortData ) {
4817
				row._aSortData = [];
4818
			}
4819
 
4820
			if ( ! row._aSortData[idx] || customSort ) {
4821
				cellData = customSort ?
4822
					customData[i] : // If there was a custom sort function, use data from there
4823
					_fnGetCellData( settings, i, idx, 'sort' );
4824
 
4825
				row._aSortData[ idx ] = formatter ?
4826
					formatter( cellData ) :
4827
					cellData;
4828
			}
4829
		}
4830
	}
4831
 
4832
 
4833
 
4834
	/**
4835
	 * Save the state of a table
4836
	 *  @param {object} oSettings dataTables settings object
4837
	 *  @memberof DataTable#oApi
4838
	 */
4839
	function _fnSaveState ( settings )
4840
	{
4841
		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
4842
		{
4843
			return;
4844
		}
4845
 
4846
		/* Store the interesting variables */
4847
		var state = {
4848
			time:    +new Date(),
4849
			start:   settings._iDisplayStart,
4850
			length:  settings._iDisplayLength,
4851
			order:   $.extend( true, [], settings.aaSorting ),
4852
			search:  _fnSearchToCamel( settings.oPreviousSearch ),
4853
			columns: $.map( settings.aoColumns, function ( col, i ) {
4854
				return {
4855
					visible: col.bVisible,
4856
					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
4857
				};
4858
			} )
4859
		};
4860
 
4861
		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
4862
 
4863
		settings.oSavedState = state;
4864
		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
4865
	}
4866
 
4867
 
4868
	/**
4869
	 * Attempt to load a saved table state
4870
	 *  @param {object} oSettings dataTables settings object
4871
	 *  @param {object} oInit DataTables init object so we can override settings
4872
	 *  @memberof DataTable#oApi
4873
	 */
4874
	function _fnLoadState ( settings, oInit )
4875
	{
4876
		var i, ien;
4877
		var columns = settings.aoColumns;
4878
 
4879
		if ( ! settings.oFeatures.bStateSave ) {
4880
			return;
4881
		}
4882
 
4883
		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
4884
		if ( ! state || ! state.time ) {
4885
			return;
4886
		}
4887
 
4888
		/* Allow custom and plug-in manipulation functions to alter the saved data set and
4889
		 * cancelling of loading by returning false
4890
		 */
4891
		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
4892
		if ( $.inArray( false, abStateLoad ) !== -1 ) {
4893
			return;
4894
		}
4895
 
4896
		/* Reject old data */
4897
		var duration = settings.iStateDuration;
4898
		if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
4899
			return;
4900
		}
4901
 
4902
		// Number of columns have changed - all bets are off, no restore of settings
4903
		if ( columns.length !== state.columns.length ) {
4904
			return;
4905
		}
4906
 
4907
		// Store the saved state so it might be accessed at any time
4908
		settings.oLoadedState = $.extend( true, {}, state );
4909
 
4910
		// Restore key features - todo - for 1.11 this needs to be done by
4911
		// subscribed events
4912
		settings._iDisplayStart    = state.start;
4913
		settings.iInitDisplayStart = state.start;
4914
		settings._iDisplayLength   = state.length;
4915
		settings.aaSorting = [];
4916
 
4917
		// Order
4918
		$.each( state.order, function ( i, col ) {
4919
			settings.aaSorting.push( col[0] >= columns.length ?
4920
				[ 0, col[1] ] :
4921
				col
4922
			);
4923
		} );
4924
 
4925
		// Search
4926
		$.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
4927
 
4928
		// Columns
4929
		for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
4930
			var col = state.columns[i];
4931
 
4932
			// Visibility
4933
			columns[i].bVisible = col.visible;
4934
 
4935
			// Search
4936
			$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
4937
		}
4938
 
4939
		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
4940
	}
4941
 
4942
 
4943
	/**
4944
	 * Return the settings object for a particular table
4945
	 *  @param {node} table table we are using as a dataTable
4946
	 *  @returns {object} Settings object - or null if not found
4947
	 *  @memberof DataTable#oApi
4948
	 */
4949
	function _fnSettingsFromNode ( table )
4950
	{
4951
		var settings = DataTable.settings;
4952
		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
4953
 
4954
		return idx !== -1 ?
4955
			settings[ idx ] :
4956
			null;
4957
	}
4958
 
4959
 
4960
	/**
4961
	 * Log an error message
4962
	 *  @param {object} settings dataTables settings object
4963
	 *  @param {int} level log error messages, or display them to the user
4964
	 *  @param {string} msg error message
4965
	 *  @param {int} tn Technical note id to get more information about the error.
4966
	 *  @memberof DataTable#oApi
4967
	 */
4968
	function _fnLog( settings, level, msg, tn )
4969
	{
4970
		msg = 'DataTables warning: '+
4971
			(settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
4972
 
4973
		if ( tn ) {
4974
			msg += '. For more information about this error, please see '+
4975
			'http://datatables.net/tn/'+tn;
4976
		}
4977
 
4978
		if ( ! level  ) {
4979
			// Backwards compatibility pre 1.10
4980
			var ext = DataTable.ext;
4981
			var type = ext.sErrMode || ext.errMode;
4982
 
4983
			if ( type == 'alert' ) {
4984
				alert( msg );
4985
			}
4986
			else {
4987
				throw new Error(msg);
4988
			}
4989
		}
4990
		else if ( window.console && console.log ) {
4991
			console.log( msg );
4992
		}
4993
	}
4994
 
4995
 
4996
	/**
4997
	 * See if a property is defined on one object, if so assign it to the other object
4998
	 *  @param {object} ret target object
4999
	 *  @param {object} src source object
5000
	 *  @param {string} name property
5001
	 *  @param {string} [mappedName] name to map too - optional, name used if not given
5002
	 *  @memberof DataTable#oApi
5003
	 */
5004
	function _fnMap( ret, src, name, mappedName )
5005
	{
5006
		if ( $.isArray( name ) ) {
5007
			$.each( name, function (i, val) {
5008
				if ( $.isArray( val ) ) {
5009
					_fnMap( ret, src, val[0], val[1] );
5010
				}
5011
				else {
5012
					_fnMap( ret, src, val );
5013
				}
5014
			} );
5015
 
5016
			return;
5017
		}
5018
 
5019
		if ( mappedName === undefined ) {
5020
			mappedName = name;
5021
		}
5022
 
5023
		if ( src[name] !== undefined ) {
5024
			ret[mappedName] = src[name];
5025
		}
5026
	}
5027
 
5028
 
5029
	/**
5030
	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
5031
	 * shallow copy arrays. The reason we need to do this, is that we don't want to
5032
	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
5033
	 * able to override them, but we do want to deep copy arrays.
5034
	 *  @param {object} out Object to extend
5035
	 *  @param {object} extender Object from which the properties will be applied to
5036
	 *      out
5037
	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
5038
	 *      independent copy with the exception of the `data` or `aaData` parameters
5039
	 *      if they are present. This is so you can pass in a collection to
5040
	 *      DataTables and have that used as your data source without breaking the
5041
	 *      references
5042
	 *  @returns {object} out Reference, just for convenience - out === the return.
5043
	 *  @memberof DataTable#oApi
5044
	 *  @todo This doesn't take account of arrays inside the deep copied objects.
5045
	 */
5046
	function _fnExtend( out, extender, breakRefs )
5047
	{
5048
		var val;
5049
 
5050
		for ( var prop in extender ) {
5051
			if ( extender.hasOwnProperty(prop) ) {
5052
				val = extender[prop];
5053
 
5054
				if ( $.isPlainObject( val ) ) {
5055
					if ( ! $.isPlainObject( out[prop] ) ) {
5056
						out[prop] = {};
5057
					}
5058
					$.extend( true, out[prop], val );
5059
				}
5060
				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
5061
					out[prop] = val.slice();
5062
				}
5063
				else {
5064
					out[prop] = val;
5065
				}
5066
			}
5067
		}
5068
 
5069
		return out;
5070
	}
5071
 
5072
 
5073
	/**
5074
	 * Bind an event handers to allow a click or return key to activate the callback.
5075
	 * This is good for accessibility since a return on the keyboard will have the
5076
	 * same effect as a click, if the element has focus.
5077
	 *  @param {element} n Element to bind the action to
5078
	 *  @param {object} oData Data object to pass to the triggered function
5079
	 *  @param {function} fn Callback function for when the event is triggered
5080
	 *  @memberof DataTable#oApi
5081
	 */
5082
	function _fnBindAction( n, oData, fn )
5083
	{
5084
		$(n)
5085
			.bind( 'click.DT', oData, function (e) {
5086
					n.blur(); // Remove focus outline for mouse users
5087
					fn(e);
5088
				} )
5089
			.bind( 'keypress.DT', oData, function (e){
5090
					if ( e.which === 13 ) {
5091
						e.preventDefault();
5092
						fn(e);
5093
					}
5094
				} )
5095
			.bind( 'selectstart.DT', function () {
5096
					/* Take the brutal approach to cancelling text selection */
5097
					return false;
5098
				} );
5099
	}
5100
 
5101
 
5102
	/**
5103
	 * Register a callback function. Easily allows a callback function to be added to
5104
	 * an array store of callback functions that can then all be called together.
5105
	 *  @param {object} oSettings dataTables settings object
5106
	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
5107
	 *  @param {function} fn Function to be called back
5108
	 *  @param {string} sName Identifying name for the callback (i.e. a label)
5109
	 *  @memberof DataTable#oApi
5110
	 */
5111
	function _fnCallbackReg( oSettings, sStore, fn, sName )
5112
	{
5113
		if ( fn )
5114
		{
5115
			oSettings[sStore].push( {
5116
				"fn": fn,
5117
				"sName": sName
5118
			} );
5119
		}
5120
	}
5121
 
5122
 
5123
	/**
5124
	 * Fire callback functions and trigger events. Note that the loop over the
5125
	 * callback array store is done backwards! Further note that you do not want to
5126
	 * fire off triggers in time sensitive applications (for example cell creation)
5127
	 * as its slow.
5128
	 *  @param {object} settings dataTables settings object
5129
	 *  @param {string} callbackArr Name of the array storage for the callbacks in
5130
	 *      oSettings
5131
	 *  @param {string} event Name of the jQuery custom event to trigger. If null no
5132
	 *      trigger is fired
5133
	 *  @param {array} args Array of arguments to pass to the callback function /
5134
	 *      trigger
5135
	 *  @memberof DataTable#oApi
5136
	 */
5137
	function _fnCallbackFire( settings, callbackArr, e, args )
5138
	{
5139
		var ret = [];
5140
 
5141
		if ( callbackArr ) {
5142
			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
5143
				return val.fn.apply( settings.oInstance, args );
5144
			} );
5145
		}
5146
 
5147
		if ( e !== null ) {
5148
			$(settings.nTable).trigger( e+'.dt', args );
5149
		}
5150
 
5151
		return ret;
5152
	}
5153
 
5154
 
5155
	function _fnLengthOverflow ( settings )
5156
	{
5157
		var
5158
			start = settings._iDisplayStart,
5159
			end = settings.fnDisplayEnd(),
5160
			len = settings._iDisplayLength;
5161
 
5162
		/* If we have space to show extra rows (backing up from the end point - then do so */
5163
		if (start >= end) 
5164
		{
5165
			start = end - len;
5166
		}
5167
 
5168
		if ( len === -1 || start < 0 )
5169
		{
5170
			start = 0;
5171
		}
5172
 
5173
		settings._iDisplayStart = start;
5174
	}
5175
 
5176
 
5177
	function _fnRenderer( settings, type )
5178
	{
5179
		var renderer = settings.renderer;
5180
		var host = DataTable.ext.renderer[type];
5181
 
5182
		if ( $.isPlainObject( renderer ) && renderer[type] ) {
5183
			// Specific renderer for this type. If available use it, otherwise use
5184
			// the default.
5185
			return host[renderer[type]] || host._;
5186
		}
5187
		else if ( typeof renderer === 'string' ) {
5188
			// Common renderer - if there is one available for this type use it,
5189
			// otherwise use the default
5190
			return host[renderer] || host._;
5191
		}
5192
 
5193
		// Use the default
5194
		return host._;
5195
	}
5196
 
5197
 
5198
	/**
5199
	 * Detect the data source being used for the table. Used to simplify the code
5200
	 * a little (ajax) and to make it compress a little smaller.
5201
	 *
5202
	 *  @param {object} settings dataTables settings object
5203
	 *  @returns {string} Data source
5204
	 *  @memberof DataTable#oApi
5205
	 */
5206
	function _fnDataSource ( settings )
5207
	{
5208
		if ( settings.oFeatures.bServerSide ) {
5209
			return 'ssp';
5210
		}
5211
		else if ( settings.ajax || settings.sAjaxSource ) {
5212
			return 'ajax';
5213
		}
5214
		return 'dom';
5215
	}
5216
 
5217
 
5218
	DataTable = function( options )
5219
	{
5220
		/**
5221
		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5222
		 * return the resulting jQuery object.
5223
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5224
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5225
		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5226
		 *    criterion ("applied") or all TR elements (i.e. no filter).
5227
		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5228
		 *    Can be either 'current', whereby the current sorting of the table is used, or
5229
		 *    'original' whereby the original order the data was read into the table is used.
5230
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5231
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5232
		 *    'current' and filter is 'applied', regardless of what they might be given as.
5233
		 *  @returns {object} jQuery object, filtered by the given selector.
5234
		 *  @dtopt API
5235
		 *  @deprecated Since v1.10
5236
		 *
5237
		 *  @example
5238
		 *    $(document).ready(function() {
5239
		 *      var oTable = $('#example').dataTable();
5240
		 *
5241
		 *      // Highlight every second row
5242
		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
5243
		 *    } );
5244
		 *
5245
		 *  @example
5246
		 *    $(document).ready(function() {
5247
		 *      var oTable = $('#example').dataTable();
5248
		 *
5249
		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
5250
		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
5251
		 *      oTable.fnFilter('Webkit');
5252
		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5253
		 *      oTable.fnFilter('');
5254
		 *    } );
5255
		 */
5256
		this.$ = function ( sSelector, oOpts )
5257
		{
5258
			return this.api(true).$( sSelector, oOpts );
5259
		};
5260
 
5261
 
5262
		/**
5263
		 * Almost identical to $ in operation, but in this case returns the data for the matched
5264
		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5265
		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
5266
		 * rows are found, the data returned is the original data array/object that was used to
5267
		 * create the row (or a generated array if from a DOM source).
5268
		 *
5269
		 * This method is often useful in-combination with $ where both functions are given the
5270
		 * same parameters and the array indexes will match identically.
5271
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5272
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5273
		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
5274
		 *    criterion ("applied") or all elements (i.e. no filter).
5275
		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
5276
		 *    Can be either 'current', whereby the current sorting of the table is used, or
5277
		 *    'original' whereby the original order the data was read into the table is used.
5278
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5279
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5280
		 *    'current' and filter is 'applied', regardless of what they might be given as.
5281
		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
5282
		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
5283
		 *    entry in the array.
5284
		 *  @dtopt API
5285
		 *  @deprecated Since v1.10
5286
		 *
5287
		 *  @example
5288
		 *    $(document).ready(function() {
5289
		 *      var oTable = $('#example').dataTable();
5290
		 *
5291
		 *      // Get the data from the first row in the table
5292
		 *      var data = oTable._('tr:first');
5293
		 *
5294
		 *      // Do something useful with the data
5295
		 *      alert( "First cell is: "+data[0] );
5296
		 *    } );
5297
		 *
5298
		 *  @example
5299
		 *    $(document).ready(function() {
5300
		 *      var oTable = $('#example').dataTable();
5301
		 *
5302
		 *      // Filter to 'Webkit' and get all data for
5303
		 *      oTable.fnFilter('Webkit');
5304
		 *      var data = oTable._('tr', {"search": "applied"});
5305
		 *
5306
		 *      // Do something with the data
5307
		 *      alert( data.length+" rows matched the search" );
5308
		 *    } );
5309
		 */
5310
		this._ = function ( sSelector, oOpts )
5311
		{
5312
			return this.api(true).rows( sSelector, oOpts ).data();
5313
		};
5314
 
5315
 
5316
		/**
5317
		 * Create a DataTables Api instance, with the currently selected tables for
5318
		 * the Api's context.
5319
		 * @param {boolean} [traditional=false] Set the API instance's context to be
5320
		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5321
		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5322
		 *   or if all tables captured in the jQuery object should be used.
5323
		 * @return {DataTables.Api}
5324
		 */
5325
		this.api = function ( traditional )
5326
		{
5327
			return traditional ?
5328
				new _Api(
5329
					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
5330
				) :
5331
				new _Api( this );
5332
		};
5333
 
5334
 
5335
		/**
5336
		 * Add a single new row or multiple rows of data to the table. Please note
5337
		 * that this is suitable for client-side processing only - if you are using
5338
		 * server-side processing (i.e. "bServerSide": true), then to add data, you
5339
		 * must add it to the data source, i.e. the server-side, through an Ajax call.
5340
		 *  @param {array|object} data The data to be added to the table. This can be:
5341
		 *    <ul>
5342
		 *      <li>1D array of data - add a single row with the data provided</li>
5343
		 *      <li>2D array of arrays - add multiple rows in a single call</li>
5344
		 *      <li>object - data object when using <i>mData</i></li>
5345
		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
5346
		 *    </ul>
5347
		 *  @param {bool} [redraw=true] redraw the table or not
5348
		 *  @returns {array} An array of integers, representing the list of indexes in
5349
		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5350
		 *    the table.
5351
		 *  @dtopt API
5352
		 *  @deprecated Since v1.10
5353
		 *
5354
		 *  @example
5355
		 *    // Global var for counter
5356
		 *    var giCount = 2;
5357
		 *
5358
		 *    $(document).ready(function() {
5359
		 *      $('#example').dataTable();
5360
		 *    } );
5361
		 *
5362
		 *    function fnClickAddRow() {
5363
		 *      $('#example').dataTable().fnAddData( [
5364
		 *        giCount+".1",
5365
		 *        giCount+".2",
5366
		 *        giCount+".3",
5367
		 *        giCount+".4" ]
5368
		 *      );
5369
		 *
5370
		 *      giCount++;
5371
		 *    }
5372
		 */
5373
		this.fnAddData = function( data, redraw )
5374
		{
5375
			var api = this.api( true );
5376
 
5377
			/* Check if we want to add multiple rows or not */
5378
			var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
5379
				api.rows.add( data ) :
5380
				api.row.add( data );
5381
 
5382
			if ( redraw === undefined || redraw ) {
5383
				api.draw();
5384
			}
5385
 
5386
			return rows.flatten().toArray();
5387
		};
5388
 
5389
 
5390
		/**
5391
		 * This function will make DataTables recalculate the column sizes, based on the data
5392
		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5393
		 * through the sWidth parameter). This can be useful when the width of the table's
5394
		 * parent element changes (for example a window resize).
5395
		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5396
		 *  @dtopt API
5397
		 *  @deprecated Since v1.10
5398
		 *
5399
		 *  @example
5400
		 *    $(document).ready(function() {
5401
		 *      var oTable = $('#example').dataTable( {
5402
		 *        "sScrollY": "200px",
5403
		 *        "bPaginate": false
5404
		 *      } );
5405
		 *
5406
		 *      $(window).bind('resize', function () {
5407
		 *        oTable.fnAdjustColumnSizing();
5408
		 *      } );
5409
		 *    } );
5410
		 */
5411
		this.fnAdjustColumnSizing = function ( bRedraw )
5412
		{
5413
			var api = this.api( true ).columns.adjust();
5414
			var settings = api.settings()[0];
5415
			var scroll = settings.oScroll;
5416
 
5417
			if ( bRedraw === undefined || bRedraw ) {
5418
				api.draw( false );
5419
			}
5420
			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
5421
				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5422
				_fnScrollDraw( settings );
5423
			}
5424
		};
5425
 
5426
 
5427
		/**
5428
		 * Quickly and simply clear a table
5429
		 *  @param {bool} [bRedraw=true] redraw the table or not
5430
		 *  @dtopt API
5431
		 *  @deprecated Since v1.10
5432
		 *
5433
		 *  @example
5434
		 *    $(document).ready(function() {
5435
		 *      var oTable = $('#example').dataTable();
5436
		 *
5437
		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5438
		 *      oTable.fnClearTable();
5439
		 *    } );
5440
		 */
5441
		this.fnClearTable = function( bRedraw )
5442
		{
5443
			var api = this.api( true ).clear();
5444
 
5445
			if ( bRedraw === undefined || bRedraw ) {
5446
				api.draw();
5447
			}
5448
		};
5449
 
5450
 
5451
		/**
5452
		 * The exact opposite of 'opening' a row, this function will close any rows which
5453
		 * are currently 'open'.
5454
		 *  @param {node} nTr the table row to 'close'
5455
		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
5456
		 *  @dtopt API
5457
		 *  @deprecated Since v1.10
5458
		 *
5459
		 *  @example
5460
		 *    $(document).ready(function() {
5461
		 *      var oTable;
5462
		 *
5463
		 *      // 'open' an information row when a row is clicked on
5464
		 *      $('#example tbody tr').click( function () {
5465
		 *        if ( oTable.fnIsOpen(this) ) {
5466
		 *          oTable.fnClose( this );
5467
		 *        } else {
5468
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5469
		 *        }
5470
		 *      } );
5471
		 *
5472
		 *      oTable = $('#example').dataTable();
5473
		 *    } );
5474
		 */
5475
		this.fnClose = function( nTr )
5476
		{
5477
			this.api( true ).row( nTr ).child.hide();
5478
		};
5479
 
5480
 
5481
		/**
5482
		 * Remove a row for the table
5483
		 *  @param {mixed} target The index of the row from aoData to be deleted, or
5484
		 *    the TR element you want to delete
5485
		 *  @param {function|null} [callBack] Callback function
5486
		 *  @param {bool} [redraw=true] Redraw the table or not
5487
		 *  @returns {array} The row that was deleted
5488
		 *  @dtopt API
5489
		 *  @deprecated Since v1.10
5490
		 *
5491
		 *  @example
5492
		 *    $(document).ready(function() {
5493
		 *      var oTable = $('#example').dataTable();
5494
		 *
5495
		 *      // Immediately remove the first row
5496
		 *      oTable.fnDeleteRow( 0 );
5497
		 *    } );
5498
		 */
5499
		this.fnDeleteRow = function( target, callback, redraw )
5500
		{
5501
			var api = this.api( true );
5502
			var rows = api.rows( target );
5503
			var settings = rows.settings()[0];
5504
			var data = settings.aoData[ rows[0][0] ];
5505
 
5506
			rows.remove();
5507
 
5508
			if ( callback ) {
5509
				callback.call( this, settings, data );
5510
			}
5511
 
5512
			if ( redraw === undefined || redraw ) {
5513
				api.draw();
5514
			}
5515
 
5516
			return data;
5517
		};
5518
 
5519
 
5520
		/**
5521
		 * Restore the table to it's original state in the DOM by removing all of DataTables
5522
		 * enhancements, alterations to the DOM structure of the table and event listeners.
5523
		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
5524
		 *  @dtopt API
5525
		 *  @deprecated Since v1.10
5526
		 *
5527
		 *  @example
5528
		 *    $(document).ready(function() {
5529
		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
5530
		 *      var oTable = $('#example').dataTable();
5531
		 *      oTable.fnDestroy();
5532
		 *    } );
5533
		 */
5534
		this.fnDestroy = function ( remove )
5535
		{
5536
			this.api( true ).destroy( remove );
5537
		};
5538
 
5539
 
5540
		/**
5541
		 * Redraw the table
5542
		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5543
		 *  @dtopt API
5544
		 *  @deprecated Since v1.10
5545
		 *
5546
		 *  @example
5547
		 *    $(document).ready(function() {
5548
		 *      var oTable = $('#example').dataTable();
5549
		 *
5550
		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5551
		 *      oTable.fnDraw();
5552
		 *    } );
5553
		 */
5554
		this.fnDraw = function( complete )
5555
		{
5556
			// Note that this isn't an exact match to the old call to _fnDraw - it takes
5557
			// into account the new data, but can old position.
5558
			this.api( true ).draw( ! complete );
5559
		};
5560
 
5561
 
5562
		/**
5563
		 * Filter the input based on data
5564
		 *  @param {string} sInput String to filter the table on
5565
		 *  @param {int|null} [iColumn] Column to limit filtering to
5566
		 *  @param {bool} [bRegex=false] Treat as regular expression or not
5567
		 *  @param {bool} [bSmart=true] Perform smart filtering or not
5568
		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5569
		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5570
		 *  @dtopt API
5571
		 *  @deprecated Since v1.10
5572
		 *
5573
		 *  @example
5574
		 *    $(document).ready(function() {
5575
		 *      var oTable = $('#example').dataTable();
5576
		 *
5577
		 *      // Sometime later - filter...
5578
		 *      oTable.fnFilter( 'test string' );
5579
		 *    } );
5580
		 */
5581
		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
5582
		{
5583
			var api = this.api( true );
5584
 
5585
			if ( iColumn === null || iColumn === undefined ) {
5586
				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
5587
			}
5588
			else {
5589
				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
5590
			}
5591
 
5592
			api.draw();
5593
		};
5594
 
5595
 
5596
		/**
5597
		 * Get the data for the whole table, an individual row or an individual cell based on the
5598
		 * provided parameters.
5599
		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5600
		 *    a TR node then the data source for the whole row will be returned. If given as a
5601
		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
5602
		 *    cell returned. If given as an integer, then this is treated as the aoData internal
5603
		 *    data index for the row (see fnGetPosition) and the data for that row used.
5604
		 *  @param {int} [col] Optional column index that you want the data of.
5605
		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
5606
		 *    returned. If mRow is defined, just data for that row, and is iCol is
5607
		 *    defined, only data for the designated cell is returned.
5608
		 *  @dtopt API
5609
		 *  @deprecated Since v1.10
5610
		 *
5611
		 *  @example
5612
		 *    // Row data
5613
		 *    $(document).ready(function() {
5614
		 *      oTable = $('#example').dataTable();
5615
		 *
5616
		 *      oTable.$('tr').click( function () {
5617
		 *        var data = oTable.fnGetData( this );
5618
		 *        // ... do something with the array / object of data for the row
5619
		 *      } );
5620
		 *    } );
5621
		 *
5622
		 *  @example
5623
		 *    // Individual cell data
5624
		 *    $(document).ready(function() {
5625
		 *      oTable = $('#example').dataTable();
5626
		 *
5627
		 *      oTable.$('td').click( function () {
5628
		 *        var sData = oTable.fnGetData( this );
5629
		 *        alert( 'The cell clicked on had the value of '+sData );
5630
		 *      } );
5631
		 *    } );
5632
		 */
5633
		this.fnGetData = function( src, col )
5634
		{
5635
			var api = this.api( true );
5636
 
5637
			if ( src !== undefined ) {
5638
				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
5639
 
5640
				return col !== undefined || type == 'td' || type == 'th' ?
5641
					api.cell( src, col ).data() :
5642
					api.row( src ).data() || null;
5643
			}
5644
 
5645
			return api.data().toArray();
5646
		};
5647
 
5648
 
5649
		/**
5650
		 * Get an array of the TR nodes that are used in the table's body. Note that you will
5651
		 * typically want to use the '$' API method in preference to this as it is more
5652
		 * flexible.
5653
		 *  @param {int} [iRow] Optional row index for the TR element you want
5654
		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
5655
		 *    in the table's body, or iRow is defined, just the TR element requested.
5656
		 *  @dtopt API
5657
		 *  @deprecated Since v1.10
5658
		 *
5659
		 *  @example
5660
		 *    $(document).ready(function() {
5661
		 *      var oTable = $('#example').dataTable();
5662
		 *
5663
		 *      // Get the nodes from the table
5664
		 *      var nNodes = oTable.fnGetNodes( );
5665
		 *    } );
5666
		 */
5667
		this.fnGetNodes = function( iRow )
5668
		{
5669
			var api = this.api( true );
5670
 
5671
			return iRow !== undefined ?
5672
				api.row( iRow ).node() :
5673
				api.rows().nodes().flatten().toArray();
5674
		};
5675
 
5676
 
5677
		/**
5678
		 * Get the array indexes of a particular cell from it's DOM element
5679
		 * and column index including hidden columns
5680
		 *  @param {node} node this can either be a TR, TD or TH in the table's body
5681
		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
5682
		 *    if given as a cell, an array of [row index, column index (visible),
5683
		 *    column index (all)] is given.
5684
		 *  @dtopt API
5685
		 *  @deprecated Since v1.10
5686
		 *
5687
		 *  @example
5688
		 *    $(document).ready(function() {
5689
		 *      $('#example tbody td').click( function () {
5690
		 *        // Get the position of the current data from the node
5691
		 *        var aPos = oTable.fnGetPosition( this );
5692
		 *
5693
		 *        // Get the data array for this row
5694
		 *        var aData = oTable.fnGetData( aPos[0] );
5695
		 *
5696
		 *        // Update the data array and return the value
5697
		 *        aData[ aPos[1] ] = 'clicked';
5698
		 *        this.innerHTML = 'clicked';
5699
		 *      } );
5700
		 *
5701
		 *      // Init DataTables
5702
		 *      oTable = $('#example').dataTable();
5703
		 *    } );
5704
		 */
5705
		this.fnGetPosition = function( node )
5706
		{
5707
			var api = this.api( true );
5708
			var nodeName = node.nodeName.toUpperCase();
5709
 
5710
			if ( nodeName == 'TR' ) {
5711
				return api.row( node ).index();
5712
			}
5713
			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
5714
				var cell = api.cell( node ).index();
5715
 
5716
				return [
5717
					cell.row,
5718
					cell.columnVisible,
5719
					cell.column
5720
				];
5721
			}
5722
			return null;
5723
		};
5724
 
5725
 
5726
		/**
5727
		 * Check to see if a row is 'open' or not.
5728
		 *  @param {node} nTr the table row to check
5729
		 *  @returns {boolean} true if the row is currently open, false otherwise
5730
		 *  @dtopt API
5731
		 *  @deprecated Since v1.10
5732
		 *
5733
		 *  @example
5734
		 *    $(document).ready(function() {
5735
		 *      var oTable;
5736
		 *
5737
		 *      // 'open' an information row when a row is clicked on
5738
		 *      $('#example tbody tr').click( function () {
5739
		 *        if ( oTable.fnIsOpen(this) ) {
5740
		 *          oTable.fnClose( this );
5741
		 *        } else {
5742
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5743
		 *        }
5744
		 *      } );
5745
		 *
5746
		 *      oTable = $('#example').dataTable();
5747
		 *    } );
5748
		 */
5749
		this.fnIsOpen = function( nTr )
5750
		{
5751
			return this.api( true ).row( nTr ).child.isShown();
5752
		};
5753
 
5754
 
5755
		/**
5756
		 * This function will place a new row directly after a row which is currently
5757
		 * on display on the page, with the HTML contents that is passed into the
5758
		 * function. This can be used, for example, to ask for confirmation that a
5759
		 * particular record should be deleted.
5760
		 *  @param {node} nTr The table row to 'open'
5761
		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
5762
		 *  @param {string} sClass Class to give the new TD cell
5763
		 *  @returns {node} The row opened. Note that if the table row passed in as the
5764
		 *    first parameter, is not found in the table, this method will silently
5765
		 *    return.
5766
		 *  @dtopt API
5767
		 *  @deprecated Since v1.10
5768
		 *
5769
		 *  @example
5770
		 *    $(document).ready(function() {
5771
		 *      var oTable;
5772
		 *
5773
		 *      // 'open' an information row when a row is clicked on
5774
		 *      $('#example tbody tr').click( function () {
5775
		 *        if ( oTable.fnIsOpen(this) ) {
5776
		 *          oTable.fnClose( this );
5777
		 *        } else {
5778
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5779
		 *        }
5780
		 *      } );
5781
		 *
5782
		 *      oTable = $('#example').dataTable();
5783
		 *    } );
5784
		 */
5785
		this.fnOpen = function( nTr, mHtml, sClass )
5786
		{
5787
			return this.api( true )
5788
				.row( nTr )
5789
				.child( mHtml, sClass )
5790
				.show()
5791
				.child()[0];
5792
		};
5793
 
5794
 
5795
		/**
5796
		 * Change the pagination - provides the internal logic for pagination in a simple API
5797
		 * function. With this function you can have a DataTables table go to the next,
5798
		 * previous, first or last pages.
5799
		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5800
		 *    or page number to jump to (integer), note that page 0 is the first page.
5801
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5802
		 *  @dtopt API
5803
		 *  @deprecated Since v1.10
5804
		 *
5805
		 *  @example
5806
		 *    $(document).ready(function() {
5807
		 *      var oTable = $('#example').dataTable();
5808
		 *      oTable.fnPageChange( 'next' );
5809
		 *    } );
5810
		 */
5811
		this.fnPageChange = function ( mAction, bRedraw )
5812
		{
5813
			var api = this.api( true ).page( mAction );
5814
 
5815
			if ( bRedraw === undefined || bRedraw ) {
5816
				api.draw(false);
5817
			}
5818
		};
5819
 
5820
 
5821
		/**
5822
		 * Show a particular column
5823
		 *  @param {int} iCol The column whose display should be changed
5824
		 *  @param {bool} bShow Show (true) or hide (false) the column
5825
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5826
		 *  @dtopt API
5827
		 *  @deprecated Since v1.10
5828
		 *
5829
		 *  @example
5830
		 *    $(document).ready(function() {
5831
		 *      var oTable = $('#example').dataTable();
5832
		 *
5833
		 *      // Hide the second column after initialisation
5834
		 *      oTable.fnSetColumnVis( 1, false );
5835
		 *    } );
5836
		 */
5837
		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
5838
		{
5839
			var api = this.api( true ).column( iCol ).visible( bShow );
5840
 
5841
			if ( bRedraw === undefined || bRedraw ) {
5842
				api.columns.adjust().draw();
5843
			}
5844
		};
5845
 
5846
 
5847
		/**
5848
		 * Get the settings for a particular table for external manipulation
5849
		 *  @returns {object} DataTables settings object. See
5850
		 *    {@link DataTable.models.oSettings}
5851
		 *  @dtopt API
5852
		 *  @deprecated Since v1.10
5853
		 *
5854
		 *  @example
5855
		 *    $(document).ready(function() {
5856
		 *      var oTable = $('#example').dataTable();
5857
		 *      var oSettings = oTable.fnSettings();
5858
		 *
5859
		 *      // Show an example parameter from the settings
5860
		 *      alert( oSettings._iDisplayStart );
5861
		 *    } );
5862
		 */
5863
		this.fnSettings = function()
5864
		{
5865
			return _fnSettingsFromNode( this[_ext.iApiIndex] );
5866
		};
5867
 
5868
 
5869
		/**
5870
		 * Sort the table by a particular column
5871
		 *  @param {int} iCol the data index to sort on. Note that this will not match the
5872
		 *    'display index' if you have hidden data entries
5873
		 *  @dtopt API
5874
		 *  @deprecated Since v1.10
5875
		 *
5876
		 *  @example
5877
		 *    $(document).ready(function() {
5878
		 *      var oTable = $('#example').dataTable();
5879
		 *
5880
		 *      // Sort immediately with columns 0 and 1
5881
		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
5882
		 *    } );
5883
		 */
5884
		this.fnSort = function( aaSort )
5885
		{
5886
			this.api( true ).order( aaSort ).draw();
5887
		};
5888
 
5889
 
5890
		/**
5891
		 * Attach a sort listener to an element for a given column
5892
		 *  @param {node} nNode the element to attach the sort listener to
5893
		 *  @param {int} iColumn the column that a click on this node will sort on
5894
		 *  @param {function} [fnCallback] callback function when sort is run
5895
		 *  @dtopt API
5896
		 *  @deprecated Since v1.10
5897
		 *
5898
		 *  @example
5899
		 *    $(document).ready(function() {
5900
		 *      var oTable = $('#example').dataTable();
5901
		 *
5902
		 *      // Sort on column 1, when 'sorter' is clicked on
5903
		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
5904
		 *    } );
5905
		 */
5906
		this.fnSortListener = function( nNode, iColumn, fnCallback )
5907
		{
5908
			this.api( true ).order.listener( nNode, iColumn, fnCallback );
5909
		};
5910
 
5911
 
5912
		/**
5913
		 * Update a table cell or row - this method will accept either a single value to
5914
		 * update the cell with, an array of values with one element for each column or
5915
		 * an object in the same format as the original data source. The function is
5916
		 * self-referencing in order to make the multi column updates easier.
5917
		 *  @param {object|array|string} mData Data to update the cell/row with
5918
		 *  @param {node|int} mRow TR element you want to update or the aoData index
5919
		 *  @param {int} [iColumn] The column to update, give as null or undefined to
5920
		 *    update a whole row.
5921
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5922
		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
5923
		 *  @returns {int} 0 on success, 1 on error
5924
		 *  @dtopt API
5925
		 *  @deprecated Since v1.10
5926
		 *
5927
		 *  @example
5928
		 *    $(document).ready(function() {
5929
		 *      var oTable = $('#example').dataTable();
5930
		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
5931
		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
5932
		 *    } );
5933
		 */
5934
		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
5935
		{
5936
			var api = this.api( true );
5937
 
5938
			if ( iColumn === undefined || iColumn === null ) {
5939
				api.row( mRow ).data( mData );
5940
			}
5941
			else {
5942
				api.cell( mRow, iColumn ).data( mData );
5943
			}
5944
 
5945
			if ( bAction === undefined || bAction ) {
5946
				api.columns.adjust();
5947
			}
5948
 
5949
			if ( bRedraw === undefined || bRedraw ) {
5950
				api.draw();
5951
			}
5952
			return 0;
5953
		};
5954
 
5955
 
5956
		/**
5957
		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
5958
		 * to ensure compatibility.
5959
		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
5960
		 *    formats "X" and "X.Y" are also acceptable.
5961
		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
5962
		 *    version, or false if this version of DataTales is not suitable
5963
		 *  @method
5964
		 *  @dtopt API
5965
		 *  @deprecated Since v1.10
5966
		 *
5967
		 *  @example
5968
		 *    $(document).ready(function() {
5969
		 *      var oTable = $('#example').dataTable();
5970
		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
5971
		 *    } );
5972
		 */
5973
		this.fnVersionCheck = _ext.fnVersionCheck;
5974
 
5975
 
5976
		var _that = this;
5977
		var emptyInit = options === undefined;
5978
		var len = this.length;
5979
 
5980
		if ( emptyInit ) {
5981
			options = {};
5982
		}
5983
 
5984
		this.oApi = this.internal = _ext.internal;
5985
 
5986
		// Extend with old style plug-in API methods
5987
		for ( var fn in DataTable.ext.internal ) {
5988
			if ( fn ) {
5989
				this[fn] = _fnExternApiFunc(fn);
5990
			}
5991
		}
5992
 
5993
		this.each(function() {
5994
			// For each initialisation we want to give it a clean initialisation
5995
			// object that can be bashed around
5996
			var o = {};
5997
			var oInit = len > 1 ? // optimisation for single table case
5998
				_fnExtend( o, options, true ) :
5999
				options;
6000
 
6001
			/*global oInit,_that,emptyInit*/
6002
			var i=0, iLen, j, jLen, k, kLen;
6003
			var sId = this.getAttribute( 'id' );
6004
			var bInitHandedOff = false;
6005
			var defaults = DataTable.defaults;
6006
 
6007
 
6008
			/* Sanity check */
6009
			if ( this.nodeName.toLowerCase() != 'table' )
6010
			{
6011
				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
6012
				return;
6013
			}
6014
 
6015
			/* Backwards compatibility for the defaults */
6016
			_fnCompatOpts( defaults );
6017
			_fnCompatCols( defaults.column );
6018
 
6019
			/* Convert the camel-case defaults to Hungarian */
6020
			_fnCamelToHungarian( defaults, defaults, true );
6021
			_fnCamelToHungarian( defaults.column, defaults.column, true );
6022
 
6023
			/* Setting up the initialisation object */
6024
			_fnCamelToHungarian( defaults, oInit );
6025
 
6026
			/* Check to see if we are re-initialising a table */
6027
			var allSettings = DataTable.settings;
6028
			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
6029
			{
6030
				/* Base check on table node */
6031
				if ( allSettings[i].nTable == this )
6032
				{
6033
					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
6034
					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
6035
 
6036
					if ( emptyInit || bRetrieve )
6037
					{
6038
						return allSettings[i].oInstance;
6039
					}
6040
					else if ( bDestroy )
6041
					{
6042
						allSettings[i].oInstance.fnDestroy();
6043
						break;
6044
					}
6045
					else
6046
					{
6047
						_fnLog( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );
6048
						return;
6049
					}
6050
				}
6051
 
6052
				/* If the element we are initialising has the same ID as a table which was previously
6053
				 * initialised, but the table nodes don't match (from before) then we destroy the old
6054
				 * instance by simply deleting it. This is under the assumption that the table has been
6055
				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6056
				 */
6057
				if ( allSettings[i].sTableId == this.id )
6058
				{
6059
					allSettings.splice( i, 1 );
6060
					break;
6061
				}
6062
			}
6063
 
6064
			/* Ensure the table has an ID - required for accessibility */
6065
			if ( sId === null || sId === "" )
6066
			{
6067
				sId = "DataTables_Table_"+(DataTable.ext._unique++);
6068
				this.id = sId;
6069
			}
6070
 
6071
			/* Create the settings object for this table and set some of the default parameters */
6072
			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
6073
				"nTable":        this,
6074
				"oApi":          _that.internal,
6075
				"oInit":         oInit,
6076
				"sDestroyWidth": $(this)[0].style.width,
6077
				"sInstance":     sId,
6078
				"sTableId":      sId
6079
			} );
6080
			allSettings.push( oSettings );
6081
 
6082
			// Need to add the instance after the instance after the settings object has been added
6083
			// to the settings array, so we can self reference the table instance if more than one
6084
			oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
6085
 
6086
			// Backwards compatibility, before we apply all the defaults
6087
			_fnCompatOpts( oInit );
6088
 
6089
			if ( oInit.oLanguage )
6090
			{
6091
				_fnLanguageCompat( oInit.oLanguage );
6092
			}
6093
 
6094
			// If the length menu is given, but the init display length is not, use the length menu
6095
			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
6096
			{
6097
				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
6098
					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
6099
			}
6100
 
6101
			// Apply the defaults and init options to make a single init object will all
6102
			// options defined from defaults and instance options.
6103
			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
6104
 
6105
 
6106
			// Map the initialisation options onto the settings object
6107
			_fnMap( oSettings.oFeatures, oInit, [
6108
				"bPaginate",
6109
				"bLengthChange",
6110
				"bFilter",
6111
				"bSort",
6112
				"bSortMulti",
6113
				"bInfo",
6114
				"bProcessing",
6115
				"bAutoWidth",
6116
				"bSortClasses",
6117
				"bServerSide",
6118
				"bDeferRender"
6119
			] );
6120
			_fnMap( oSettings, oInit, [
6121
				"asStripeClasses",
6122
				"ajax",
6123
				"fnServerData",
6124
				"fnFormatNumber",
6125
				"sServerMethod",
6126
				"aaSorting",
6127
				"aaSortingFixed",
6128
				"aLengthMenu",
6129
				"sPaginationType",
6130
				"sAjaxSource",
6131
				"sAjaxDataProp",
6132
				"iStateDuration",
6133
				"sDom",
6134
				"bSortCellsTop",
6135
				"iTabIndex",
6136
				"fnStateLoadCallback",
6137
				"fnStateSaveCallback",
6138
				"renderer",
6139
				"searchDelay",
6140
				[ "iCookieDuration", "iStateDuration" ], // backwards compat
6141
				[ "oSearch", "oPreviousSearch" ],
6142
				[ "aoSearchCols", "aoPreSearchCols" ],
6143
				[ "iDisplayLength", "_iDisplayLength" ],
6144
				[ "bJQueryUI", "bJUI" ]
6145
			] );
6146
			_fnMap( oSettings.oScroll, oInit, [
6147
				[ "sScrollX", "sX" ],
6148
				[ "sScrollXInner", "sXInner" ],
6149
				[ "sScrollY", "sY" ],
6150
				[ "bScrollCollapse", "bCollapse" ]
6151
			] );
6152
			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
6153
 
6154
			/* Callback functions which are array driven */
6155
			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
6156
			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
6157
			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
6158
			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
6159
			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
6160
			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
6161
			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
6162
			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
6163
			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
6164
			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
6165
			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
6166
 
6167
			var oClasses = oSettings.oClasses;
6168
 
6169
			// @todo Remove in 1.11
6170
			if ( oInit.bJQueryUI )
6171
			{
6172
				/* Use the JUI classes object for display. You could clone the oStdClasses object if
6173
				 * you want to have multiple tables with multiple independent classes
6174
				 */
6175
				$.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
6176
 
6177
				if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
6178
				{
6179
					/* Set the DOM to use a layout suitable for jQuery UI's theming */
6180
					oSettings.sDom = '<"H"lfr>t<"F"ip>';
6181
				}
6182
 
6183
				if ( ! oSettings.renderer ) {
6184
					oSettings.renderer = 'jqueryui';
6185
				}
6186
				else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
6187
					oSettings.renderer.header = 'jqueryui';
6188
				}
6189
			}
6190
			else
6191
			{
6192
				$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6193
			}
6194
			$(this).addClass( oClasses.sTable );
6195
 
6196
			/* Calculate the scroll bar width and cache it for use later on */
6197
			if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6198
			{
6199
				oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6200
			}
6201
			if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6202
				oSettings.oScroll.sX = '100%';
6203
			}
6204
 
6205
			if ( oSettings.iInitDisplayStart === undefined )
6206
			{
6207
				/* Display start point, taking into account the save saving */
6208
				oSettings.iInitDisplayStart = oInit.iDisplayStart;
6209
				oSettings._iDisplayStart = oInit.iDisplayStart;
6210
			}
6211
 
6212
			if ( oInit.iDeferLoading !== null )
6213
			{
6214
				oSettings.bDeferLoading = true;
6215
				var tmp = $.isArray( oInit.iDeferLoading );
6216
				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
6217
				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
6218
			}
6219
 
6220
			/* Language definitions */
6221
			if ( oInit.oLanguage.sUrl !== "" )
6222
			{
6223
				/* Get the language definitions from a file - because this Ajax call makes the language
6224
				 * get async to the remainder of this function we use bInitHandedOff to indicate that
6225
				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6226
				 */
6227
				oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
6228
				$.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
6229
					_fnLanguageCompat( json );
6230
					_fnCamelToHungarian( defaults.oLanguage, json );
6231
					$.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
6232
					_fnInitialise( oSettings );
6233
				} );
6234
				bInitHandedOff = true;
6235
			}
6236
			else
6237
			{
6238
				$.extend( true, oSettings.oLanguage, oInit.oLanguage );
6239
			}
6240
 
6241
 
6242
			/*
6243
			 * Stripes
6244
			 */
6245
			if ( oInit.asStripeClasses === null )
6246
			{
6247
				oSettings.asStripeClasses =[
6248
					oClasses.sStripeOdd,
6249
					oClasses.sStripeEven
6250
				];
6251
			}
6252
 
6253
			/* Remove row stripe classes if they are already on the table row */
6254
			var stripeClasses = oSettings.asStripeClasses;
6255
			var rowOne = $('tbody tr:eq(0)', this);
6256
			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6257
				return rowOne.hasClass(el);
6258
			} ) ) !== -1 ) {
6259
				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
6260
				oSettings.asDestroyStripes = stripeClasses.slice();
6261
			}
6262
 
6263
			/*
6264
			 * Columns
6265
			 * See if we should load columns automatically or use defined ones
6266
			 */
6267
			var anThs = [];
6268
			var aoColumnsInit;
6269
			var nThead = this.getElementsByTagName('thead');
6270
			if ( nThead.length !== 0 )
6271
			{
6272
				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
6273
				anThs = _fnGetUniqueThs( oSettings );
6274
			}
6275
 
6276
			/* If not given a column array, generate one with nulls */
6277
			if ( oInit.aoColumns === null )
6278
			{
6279
				aoColumnsInit = [];
6280
				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6281
				{
6282
					aoColumnsInit.push( null );
6283
				}
6284
			}
6285
			else
6286
			{
6287
				aoColumnsInit = oInit.aoColumns;
6288
			}
6289
 
6290
			/* Add the columns */
6291
			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6292
			{
6293
				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
6294
			}
6295
 
6296
			/* Apply the column definitions */
6297
			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
6298
				_fnColumnOptions( oSettings, iCol, oDef );
6299
			} );
6300
 
6301
			/* HTML5 attribute detection - build an mData object automatically if the
6302
			 * attributes are found
6303
			 */
6304
			if ( rowOne.length ) {
6305
				var a = function ( cell, name ) {
6306
					return cell.getAttribute( 'data-'+name ) ? name : null;
6307
				};
6308
 
6309
				$.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
6310
					var col = oSettings.aoColumns[i];
6311
 
6312
					if ( col.mData === i ) {
6313
						var sort = a( cell, 'sort' ) || a( cell, 'order' );
6314
						var filter = a( cell, 'filter' ) || a( cell, 'search' );
6315
 
6316
						if ( sort !== null || filter !== null ) {
6317
							col.mData = {
6318
								_:      i+'.display',
6319
								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
6320
								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
6321
								filter: filter !== null ? i+'.@data-'+filter : undefined
6322
							};
6323
 
6324
							_fnColumnOptions( oSettings, i );
6325
						}
6326
					}
6327
				} );
6328
			}
6329
 
6330
			var features = oSettings.oFeatures;
6331
 
6332
			/* Must be done after everything which can be overridden by the state saving! */
6333
			if ( oInit.bStateSave )
6334
			{
6335
				features.bStateSave = true;
6336
				_fnLoadState( oSettings, oInit );
6337
				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
6338
			}
6339
 
6340
 
6341
			/*
6342
			 * Sorting
6343
			 * @todo For modularisation (1.11) this needs to do into a sort start up handler
6344
			 */
6345
 
6346
			// If aaSorting is not defined, then we use the first indicator in asSorting
6347
			// in case that has been altered, so the default sort reflects that option
6348
			if ( oInit.aaSorting === undefined )
6349
			{
6350
				var sorting = oSettings.aaSorting;
6351
				for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
6352
				{
6353
					sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
6354
				}
6355
			}
6356
 
6357
			/* Do a first pass on the sorting classes (allows any size changes to be taken into
6358
			 * account, and also will apply sorting disabled classes if disabled
6359
			 */
6360
			_fnSortingClasses( oSettings );
6361
 
6362
			if ( features.bSort )
6363
			{
6364
				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6365
					if ( oSettings.bSorted ) {
6366
						var aSort = _fnSortFlatten( oSettings );
6367
						var sortedColumns = {};
6368
 
6369
						$.each( aSort, function (i, val) {
6370
							sortedColumns[ val.src ] = val.dir;
6371
						} );
6372
 
6373
						_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
6374
						_fnSortAria( oSettings );
6375
					}
6376
				} );
6377
			}
6378
 
6379
			_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6380
				if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
6381
					_fnSortingClasses( oSettings );
6382
				}
6383
			}, 'sc' );
6384
 
6385
 
6386
			/*
6387
			 * Final init
6388
			 * Cache the header, body and footer as required, creating them if needed
6389
			 */
6390
 
6391
			/* Browser support detection */
6392
			_fnBrowserDetect( oSettings );
6393
 
6394
			// Work around for Webkit bug 83867 - store the caption-side before removing from doc
6395
			var captions = $(this).children('caption').each( function () {
6396
				this._captionSide = $(this).css('caption-side');
6397
			} );
6398
 
6399
			var thead = $(this).children('thead');
6400
			if ( thead.length === 0 )
6401
			{
6402
				thead = $('<thead/>').appendTo(this);
6403
			}
6404
			oSettings.nTHead = thead[0];
6405
 
6406
			var tbody = $(this).children('tbody');
6407
			if ( tbody.length === 0 )
6408
			{
6409
				tbody = $('<tbody/>').appendTo(this);
6410
			}
6411
			oSettings.nTBody = tbody[0];
6412
 
6413
			var tfoot = $(this).children('tfoot');
6414
			if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6415
			{
6416
				// If we are a scrolling table, and no footer has been given, then we need to create
6417
				// a tfoot element for the caption element to be appended to
6418
				tfoot = $('<tfoot/>').appendTo(this);
6419
			}
6420
 
6421
			if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6422
				$(this).addClass( oClasses.sNoFooter );
6423
			}
6424
			else if ( tfoot.length > 0 ) {
6425
				oSettings.nTFoot = tfoot[0];
6426
				_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
6427
			}
6428
 
6429
			/* Check if there is data passing into the constructor */
6430
			if ( oInit.aaData )
6431
			{
6432
				for ( i=0 ; i<oInit.aaData.length ; i++ )
6433
				{
6434
					_fnAddData( oSettings, oInit.aaData[ i ] );
6435
				}
6436
			}
6437
			else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
6438
			{
6439
				/* Grab the data from the page - only do this when deferred loading or no Ajax
6440
				 * source since there is no point in reading the DOM data if we are then going
6441
				 * to replace it with Ajax data
6442
				 */
6443
				_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
6444
			}
6445
 
6446
			/* Copy the data index array */
6447
			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6448
 
6449
			/* Initialisation complete - table can be drawn */
6450
			oSettings.bInitialised = true;
6451
 
6452
			/* Check if we need to initialise the table (it might not have been handed off to the
6453
			 * language processor)
6454
			 */
6455
			if ( bInitHandedOff === false )
6456
			{
6457
				_fnInitialise( oSettings );
6458
			}
6459
		} );
6460
		_that = null;
6461
		return this;
6462
	};
6463
 
6464
 
6465
 
6466
	/**
6467
	 * Computed structure of the DataTables API, defined by the options passed to
6468
	 * `DataTable.Api.register()` when building the API.
6469
	 *
6470
	 * The structure is built in order to speed creation and extension of the Api
6471
	 * objects since the extensions are effectively pre-parsed.
6472
	 *
6473
	 * The array is an array of objects with the following structure, where this
6474
	 * base array represents the Api prototype base:
6475
	 *
6476
	 *     [
6477
	 *       {
6478
	 *         name:      'data'                -- string   - Property name
6479
	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6480
	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6481
	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6482
	 *       },
6483
	 *       {
6484
	 *         name:     'row'
6485
	 *         val:       {},
6486
	 *         methodExt: [ ... ],
6487
	 *         propExt:   [
6488
	 *           {
6489
	 *             name:      'data'
6490
	 *             val:       function () {},
6491
	 *             methodExt: [ ... ],
6492
	 *             propExt:   [ ... ]
6493
	 *           },
6494
	 *           ...
6495
	 *         ]
6496
	 *       }
6497
	 *     ]
6498
	 *
6499
	 * @type {Array}
6500
	 * @ignore
6501
	 */
6502
	var __apiStruct = [];
6503
 
6504
 
6505
	/**
6506
	 * `Array.prototype` reference.
6507
	 *
6508
	 * @type object
6509
	 * @ignore
6510
	 */
6511
	var __arrayProto = Array.prototype;
6512
 
6513
 
6514
	/**
6515
	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6516
	 * take several different forms for ease of use.
6517
	 *
6518
	 * Each of the input parameter types will be converted to a DataTables settings
6519
	 * object where possible.
6520
	 *
6521
	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6522
	 *   of:
6523
	 *
6524
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6525
	 *     with be found and used.
6526
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6527
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6528
	 *   * `object` - DataTables settings object
6529
	 *   * `DataTables.Api` - API instance
6530
	 * @return {array|null} Matching DataTables settings objects. `null` or
6531
	 *   `undefined` is returned if no matching DataTable is found.
6532
	 * @ignore
6533
	 */
6534
	var _toSettings = function ( mixed )
6535
	{
6536
		var idx, jq;
6537
		var settings = DataTable.settings;
6538
		var tables = $.map( settings, function (el, i) {
6539
			return el.nTable;
6540
		} );
6541
 
6542
		if ( ! mixed ) {
6543
			return [];
6544
		}
6545
		else if ( mixed.nTable && mixed.oApi ) {
6546
			// DataTables settings object
6547
			return [ mixed ];
6548
		}
6549
		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6550
			// Table node
6551
			idx = $.inArray( mixed, tables );
6552
			return idx !== -1 ? [ settings[idx] ] : null;
6553
		}
6554
		else if ( mixed && typeof mixed.settings === 'function' ) {
6555
			return mixed.settings().toArray();
6556
		}
6557
		else if ( typeof mixed === 'string' ) {
6558
			// jQuery selector
6559
			jq = $(mixed);
6560
		}
6561
		else if ( mixed instanceof $ ) {
6562
			// jQuery object (also DataTables instance)
6563
			jq = mixed;
6564
		}
6565
 
6566
		if ( jq ) {
6567
			return jq.map( function(i) {
6568
				idx = $.inArray( this, tables );
6569
				return idx !== -1 ? settings[idx] : null;
6570
			} ).toArray();
6571
		}
6572
	};
6573
 
6574
 
6575
	/**
6576
	 * DataTables API class - used to control and interface with  one or more
6577
	 * DataTables enhanced tables.
6578
	 *
6579
	 * The API class is heavily based on jQuery, presenting a chainable interface
6580
	 * that you can use to interact with tables. Each instance of the API class has
6581
	 * a "context" - i.e. the tables that it will operate on. This could be a single
6582
	 * table, all tables on a page or a sub-set thereof.
6583
	 *
6584
	 * Additionally the API is designed to allow you to easily work with the data in
6585
	 * the tables, retrieving and manipulating it as required. This is done by
6586
	 * presenting the API class as an array like interface. The contents of the
6587
	 * array depend upon the actions requested by each method (for example
6588
	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6589
	 * return an array of objects or arrays depending upon your table's
6590
	 * configuration). The API object has a number of array like methods (`push`,
6591
	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6592
	 * `unique` etc) to assist your working with the data held in a table.
6593
	 *
6594
	 * Most methods (those which return an Api instance) are chainable, which means
6595
	 * the return from a method call also has all of the methods available that the
6596
	 * top level object had. For example, these two calls are equivalent:
6597
	 *
6598
	 *     // Not chained
6599
	 *     api.row.add( {...} );
6600
	 *     api.draw();
6601
	 *
6602
	 *     // Chained
6603
	 *     api.row.add( {...} ).draw();
6604
	 *
6605
	 * @class DataTable.Api
6606
	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6607
	 *   used to define which DataTables enhanced tables this API will operate on.
6608
	 *   Can be one of:
6609
	 *
6610
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6611
	 *     with be found and used.
6612
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6613
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6614
	 *   * `object` - DataTables settings object
6615
	 * @param {array} [data] Data to initialise the Api instance with.
6616
	 *
6617
	 * @example
6618
	 *   // Direct initialisation during DataTables construction
6619
	 *   var api = $('#example').DataTable();
6620
	 *
6621
	 * @example
6622
	 *   // Initialisation using a DataTables jQuery object
6623
	 *   var api = $('#example').dataTable().api();
6624
	 *
6625
	 * @example
6626
	 *   // Initialisation as a constructor
6627
	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6628
	 */
6629
	_Api = function ( context, data )
6630
	{
6631
		if ( ! this instanceof _Api ) {
6632
			throw 'DT API must be constructed as a new object';
6633
			// or should it do the 'new' for the caller?
6634
			// return new _Api.apply( this, arguments );
6635
		}
6636
 
6637
		var settings = [];
6638
		var ctxSettings = function ( o ) {
6639
			var a = _toSettings( o );
6640
			if ( a ) {
6641
				settings.push.apply( settings, a );
6642
			}
6643
		};
6644
 
6645
		if ( $.isArray( context ) ) {
6646
			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6647
				ctxSettings( context[i] );
6648
			}
6649
		}
6650
		else {
6651
			ctxSettings( context );
6652
		}
6653
 
6654
		// Remove duplicates
6655
		this.context = _unique( settings );
6656
 
6657
		// Initial data
6658
		if ( data ) {
6659
			this.push.apply( this, data.toArray ? data.toArray() : data );
6660
		}
6661
 
6662
		// selector
6663
		this.selector = {
6664
			rows: null,
6665
			cols: null,
6666
			opts: null
6667
		};
6668
 
6669
		_Api.extend( this, this, __apiStruct );
6670
	};
6671
 
6672
	DataTable.Api = _Api;
6673
 
6674
	_Api.prototype = /** @lends DataTables.Api */{
6675
		/**
6676
		 * Return a new Api instance, comprised of the data held in the current
6677
		 * instance, join with the other array(s) and/or value(s).
6678
		 *
6679
		 * An alias for `Array.prototype.concat`.
6680
		 *
6681
		 * @type method
6682
		 * @param {*} value1 Arrays and/or values to concatenate.
6683
		 * @param {*} [...] Additional arrays and/or values to concatenate.
6684
		 * @returns {DataTables.Api} New API instance, comprising of the combined
6685
		 *   array.
6686
		 */
6687
		concat:  __arrayProto.concat,
6688
 
6689
 
6690
		context: [], // array of table settings objects
6691
 
6692
 
6693
		each: function ( fn )
6694
		{
6695
			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6696
				fn.call( this, this[i], i, this );
6697
			}
6698
 
6699
			return this;
6700
		},
6701
 
6702
 
6703
		eq: function ( idx )
6704
		{
6705
			var ctx = this.context;
6706
 
6707
			return ctx.length > idx ?
6708
				new _Api( ctx[idx], this[idx] ) :
6709
				null;
6710
		},
6711
 
6712
 
6713
		filter: function ( fn )
6714
		{
6715
			var a = [];
6716
 
6717
			if ( __arrayProto.filter ) {
6718
				a = __arrayProto.filter.call( this, fn, this );
6719
			}
6720
			else {
6721
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6722
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6723
					if ( fn.call( this, this[i], i, this ) ) {
6724
						a.push( this[i] );
6725
					}
6726
				}
6727
			}
6728
 
6729
			return new _Api( this.context, a );
6730
		},
6731
 
6732
 
6733
		flatten: function ()
6734
		{
6735
			var a = [];
6736
			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6737
		},
6738
 
6739
 
6740
		join:    __arrayProto.join,
6741
 
6742
 
6743
		indexOf: __arrayProto.indexOf || function (obj, start)
6744
		{
6745
			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6746
				if ( this[i] === obj ) {
6747
					return i;
6748
				}
6749
			}
6750
			return -1;
6751
		},
6752
 
6753
		// Internal only at the moment - relax?
6754
		iterator: function ( flatten, type, fn ) {
6755
			var
6756
				a = [], ret,
6757
				i, ien, j, jen,
6758
				context = this.context,
6759
				rows, items, item,
6760
				selector = this.selector;
6761
 
6762
			// Argument shifting
6763
			if ( typeof flatten === 'string' ) {
6764
				fn = type;
6765
				type = flatten;
6766
				flatten = false;
6767
			}
6768
 
6769
			for ( i=0, ien=context.length ; i<ien ; i++ ) {
6770
				var apiInst = new _Api( context[i] );
6771
 
6772
				if ( type === 'table' ) {
6773
					ret = fn.call( apiInst, context[i], i );
6774
 
6775
					if ( ret !== undefined ) {
6776
						a.push( ret );
6777
					}
6778
				}
6779
				else if ( type === 'columns' || type === 'rows' ) {
6780
					// this has same length as context - one entry for each table
6781
					ret = fn.call( apiInst, context[i], this[i], i );
6782
 
6783
					if ( ret !== undefined ) {
6784
						a.push( ret );
6785
					}
6786
				}
6787
				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6788
					// columns and rows share the same structure.
6789
					// 'this' is an array of column indexes for each context
6790
					items = this[i];
6791
 
6792
					if ( type === 'column-rows' ) {
6793
						rows = _selector_row_indexes( context[i], selector.opts );
6794
					}
6795
 
6796
					for ( j=0, jen=items.length ; j<jen ; j++ ) {
6797
						item = items[j];
6798
 
6799
						if ( type === 'cell' ) {
6800
							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
6801
						}
6802
						else {
6803
							ret = fn.call( apiInst, context[i], item, i, j, rows );
6804
						}
6805
 
6806
						if ( ret !== undefined ) {
6807
							a.push( ret );
6808
						}
6809
					}
6810
				}
6811
			}
6812
 
6813
			if ( a.length ) {
6814
				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6815
				var apiSelector = api.selector;
6816
				apiSelector.rows = selector.rows;
6817
				apiSelector.cols = selector.cols;
6818
				apiSelector.opts = selector.opts;
6819
				return api;
6820
			}
6821
			return this;
6822
		},
6823
 
6824
 
6825
		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
6826
		{
6827
			// Bit cheeky...
6828
			return this.indexOf.apply( this.toArray.reverse(), arguments );
6829
		},
6830
 
6831
 
6832
		length:  0,
6833
 
6834
 
6835
		map: function ( fn )
6836
		{
6837
			var a = [];
6838
 
6839
			if ( __arrayProto.map ) {
6840
				a = __arrayProto.map.call( this, fn, this );
6841
			}
6842
			else {
6843
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6844
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6845
					a.push( fn.call( this, this[i], i ) );
6846
				}
6847
			}
6848
 
6849
			return new _Api( this.context, a );
6850
		},
6851
 
6852
 
6853
		pluck: function ( prop )
6854
		{
6855
			return this.map( function ( el ) {
6856
				return el[ prop ];
6857
			} );
6858
		},
6859
 
6860
		pop:     __arrayProto.pop,
6861
 
6862
 
6863
		push:    __arrayProto.push,
6864
 
6865
 
6866
		// Does not return an API instance
6867
		reduce: __arrayProto.reduce || function ( fn, init )
6868
		{
6869
			return _fnReduce( this, fn, init, 0, this.length, 1 );
6870
		},
6871
 
6872
 
6873
		reduceRight: __arrayProto.reduceRight || function ( fn, init )
6874
		{
6875
			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
6876
		},
6877
 
6878
 
6879
		reverse: __arrayProto.reverse,
6880
 
6881
 
6882
		// Object with rows, columns and opts
6883
		selector: null,
6884
 
6885
 
6886
		shift:   __arrayProto.shift,
6887
 
6888
 
6889
		sort:    __arrayProto.sort, // ? name - order?
6890
 
6891
 
6892
		splice:  __arrayProto.splice,
6893
 
6894
 
6895
		toArray: function ()
6896
		{
6897
			return __arrayProto.slice.call( this );
6898
		},
6899
 
6900
 
6901
		to$: function ()
6902
		{
6903
			return $( this );
6904
		},
6905
 
6906
 
6907
		toJQuery: function ()
6908
		{
6909
			return $( this );
6910
		},
6911
 
6912
 
6913
		unique: function ()
6914
		{
6915
			return new _Api( this.context, _unique(this) );
6916
		},
6917
 
6918
 
6919
		unshift: __arrayProto.unshift
6920
	};
6921
 
6922
 
6923
	_Api.extend = function ( scope, obj, ext )
6924
	{
6925
		// Only extend API instances and static properties of the API
6926
		if ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
6927
			return;
6928
		}
6929
 
6930
		var
6931
			i, ien,
6932
			j, jen,
6933
			struct, inner,
6934
			methodScoping = function ( scope, fn, struc ) {
6935
				return function () {
6936
					var ret = fn.apply( scope, arguments );
6937
 
6938
					// Method extension
6939
					_Api.extend( ret, ret, struc.methodExt );
6940
					return ret;
6941
				};
6942
			};
6943
 
6944
		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
6945
			struct = ext[i];
6946
 
6947
			// Value
6948
			obj[ struct.name ] = typeof struct.val === 'function' ?
6949
				methodScoping( scope, struct.val, struct ) :
6950
				$.isPlainObject( struct.val ) ?
6951
					{} :
6952
					struct.val;
6953
 
6954
			obj[ struct.name ].__dt_wrapper = true;
6955
 
6956
			// Property extension
6957
			_Api.extend( scope, obj[ struct.name ], struct.propExt );
6958
		}
6959
	};
6960
 
6961
 
6962
	// @todo - Is there need for an augment function?
6963
	// _Api.augment = function ( inst, name )
6964
	// {
6965
	// 	// Find src object in the structure from the name
6966
	// 	var parts = name.split('.');
6967
 
6968
	// 	_Api.extend( inst, obj );
6969
	// };
6970
 
6971
 
6972
	//     [
6973
	//       {
6974
	//         name:      'data'                -- string   - Property name
6975
	//         val:       function () {},       -- function - Api method (or undefined if just an object
6976
	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6977
	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6978
	//       },
6979
	//       {
6980
	//         name:     'row'
6981
	//         val:       {},
6982
	//         methodExt: [ ... ],
6983
	//         propExt:   [
6984
	//           {
6985
	//             name:      'data'
6986
	//             val:       function () {},
6987
	//             methodExt: [ ... ],
6988
	//             propExt:   [ ... ]
6989
	//           },
6990
	//           ...
6991
	//         ]
6992
	//       }
6993
	//     ]
6994
 
6995
	_Api.register = _api_register = function ( name, val )
6996
	{
6997
		if ( $.isArray( name ) ) {
6998
			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
6999
				_Api.register( name[j], val );
7000
			}
7001
			return;
7002
		}
7003
 
7004
		var
7005
			i, ien,
7006
			heir = name.split('.'),
7007
			struct = __apiStruct,
7008
			key, method;
7009
 
7010
		var find = function ( src, name ) {
7011
			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7012
				if ( src[i].name === name ) {
7013
					return src[i];
7014
				}
7015
			}
7016
			return null;
7017
		};
7018
 
7019
		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7020
			method = heir[i].indexOf('()') !== -1;
7021
			key = method ?
7022
				heir[i].replace('()', '') :
7023
				heir[i];
7024
 
7025
			var src = find( struct, key );
7026
			if ( ! src ) {
7027
				src = {
7028
					name:      key,
7029
					val:       {},
7030
					methodExt: [],
7031
					propExt:   []
7032
				};
7033
				struct.push( src );
7034
			}
7035
 
7036
			if ( i === ien-1 ) {
7037
				src.val = val;
7038
			}
7039
			else {
7040
				struct = method ?
7041
					src.methodExt :
7042
					src.propExt;
7043
			}
7044
		}
7045
	};
7046
 
7047
 
7048
	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7049
		_Api.register( pluralName, val );
7050
 
7051
		_Api.register( singularName, function () {
7052
			var ret = val.apply( this, arguments );
7053
 
7054
			if ( ret === this ) {
7055
				// Returned item is the API instance that was passed in, return it
7056
				return this;
7057
			}
7058
			else if ( ret instanceof _Api ) {
7059
				// New API instance returned, want the value from the first item
7060
				// in the returned array for the singular result.
7061
				return ret.length ?
7062
					$.isArray( ret[0] ) ?
7063
						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7064
						ret[0] :
7065
					undefined;
7066
			}
7067
 
7068
			// Non-API return - just fire it back
7069
			return ret;
7070
		} );
7071
	};
7072
 
7073
 
7074
	/**
7075
	 * Selector for HTML tables. Apply the given selector to the give array of
7076
	 * DataTables settings objects.
7077
	 *
7078
	 * @param {string|integer} [selector] jQuery selector string or integer
7079
	 * @param  {array} Array of DataTables settings objects to be filtered
7080
	 * @return {array}
7081
	 * @ignore
7082
	 */
7083
	var __table_selector = function ( selector, a )
7084
	{
7085
		// Integer is used to pick out a table by index
7086
		if ( typeof selector === 'number' ) {
7087
			return [ a[ selector ] ];
7088
		}
7089
 
7090
		// Perform a jQuery selector on the table nodes
7091
		var nodes = $.map( a, function (el, i) {
7092
			return el.nTable;
7093
		} );
7094
 
7095
		return $(nodes)
7096
			.filter( selector )
7097
			.map( function (i) {
7098
				// Need to translate back from the table node to the settings
7099
				var idx = $.inArray( this, nodes );
7100
				return a[ idx ];
7101
			} )
7102
			.toArray();
7103
	};
7104
 
7105
 
7106
 
7107
	/**
7108
	 * Context selector for the API's context (i.e. the tables the API instance
7109
	 * refers to.
7110
	 *
7111
	 * @name    DataTable.Api#tables
7112
	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7113
	 *   should operate on. If not given, all tables in the current context are
7114
	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7115
	 *   select multiple tables or as an integer to select a single table.
7116
	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7117
	 */
7118
	_api_register( 'tables()', function ( selector ) {
7119
		// A new instance is created if there was a selector specified
7120
		return selector ?
7121
			new _Api( __table_selector( selector, this.context ) ) :
7122
			this;
7123
	} );
7124
 
7125
 
7126
	_api_register( 'table()', function ( selector ) {
7127
		var tables = this.tables( selector );
7128
		var ctx = tables.context;
7129
 
7130
		// Truncate to the first matched table
7131
		return ctx.length ?
7132
			new _Api( ctx[0] ) :
7133
			tables;
7134
	} );
7135
 
7136
 
7137
	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7138
		return this.iterator( 'table', function ( ctx ) {
7139
			return ctx.nTable;
7140
		} );
7141
	} );
7142
 
7143
 
7144
	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7145
		return this.iterator( 'table', function ( ctx ) {
7146
			return ctx.nTBody;
7147
		} );
7148
	} );
7149
 
7150
 
7151
	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7152
		return this.iterator( 'table', function ( ctx ) {
7153
			return ctx.nTHead;
7154
		} );
7155
	} );
7156
 
7157
 
7158
	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7159
		return this.iterator( 'table', function ( ctx ) {
7160
			return ctx.nTFoot;
7161
		} );
7162
	} );
7163
 
7164
 
7165
	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7166
		return this.iterator( 'table', function ( ctx ) {
7167
			return ctx.nTableWrapper;
7168
		} );
7169
	} );
7170
 
7171
 
7172
 
7173
	/**
7174
	 * Redraw the tables in the current context.
7175
	 *
7176
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7177
	 *   position. A full re-sort and re-filter is performed when this method is
7178
	 *   called, which is why the pagination reset is the default action.
7179
	 * @returns {DataTables.Api} this
7180
	 */
7181
	_api_register( 'draw()', function ( resetPaging ) {
7182
		return this.iterator( 'table', function ( settings ) {
7183
			_fnReDraw( settings, resetPaging===false );
7184
		} );
7185
	} );
7186
 
7187
 
7188
 
7189
	/**
7190
	 * Get the current page index.
7191
	 *
7192
	 * @return {integer} Current page index (zero based)
7193
	 *//**
7194
	 * Set the current page.
7195
	 *
7196
	 * Note that if you attempt to show a page which does not exist, DataTables will
7197
	 * not throw an error, but rather reset the paging.
7198
	 *
7199
	 * @param {integer|string} action The paging action to take. This can be one of:
7200
	 *  * `integer` - The page index to jump to
7201
	 *  * `string` - An action to take:
7202
	 *    * `first` - Jump to first page.
7203
	 *    * `next` - Jump to the next page
7204
	 *    * `previous` - Jump to previous page
7205
	 *    * `last` - Jump to the last page.
7206
	 * @returns {DataTables.Api} this
7207
	 */
7208
	_api_register( 'page()', function ( action ) {
7209
		if ( action === undefined ) {
7210
			return this.page.info().page; // not an expensive call
7211
		}
7212
 
7213
		// else, have an action to take on all tables
7214
		return this.iterator( 'table', function ( settings ) {
7215
			_fnPageChange( settings, action );
7216
		} );
7217
	} );
7218
 
7219
 
7220
	/**
7221
	 * Paging information for the first table in the current context.
7222
	 *
7223
	 * If you require paging information for another table, use the `table()` method
7224
	 * with a suitable selector.
7225
	 *
7226
	 * @return {object} Object with the following properties set:
7227
	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7228
	 *  * `pages` - Total number of pages
7229
	 *  * `start` - Display index for the first record shown on the current page
7230
	 *  * `end` - Display index for the last record shown on the current page
7231
	 *  * `length` - Display length (number of records). Note that generally `start
7232
	 *    + length = end`, but this is not always true, for example if there are
7233
	 *    only 2 records to show on the final page, with a length of 10.
7234
	 *  * `recordsTotal` - Full data set length
7235
	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7236
	 *    are applied.
7237
	 */
7238
	_api_register( 'page.info()', function ( action ) {
7239
		if ( this.context.length === 0 ) {
7240
			return undefined;
7241
		}
7242
 
7243
		var
7244
			settings   = this.context[0],
7245
			start      = settings._iDisplayStart,
7246
			len        = settings._iDisplayLength,
7247
			visRecords = settings.fnRecordsDisplay(),
7248
			all        = len === -1;
7249
 
7250
		return {
7251
			"page":           all ? 0 : Math.floor( start / len ),
7252
			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7253
			"start":          start,
7254
			"end":            settings.fnDisplayEnd(),
7255
			"length":         len,
7256
			"recordsTotal":   settings.fnRecordsTotal(),
7257
			"recordsDisplay": visRecords
7258
		};
7259
	} );
7260
 
7261
 
7262
	/**
7263
	 * Get the current page length.
7264
	 *
7265
	 * @return {integer} Current page length. Note `-1` indicates that all records
7266
	 *   are to be shown.
7267
	 *//**
7268
	 * Set the current page length.
7269
	 *
7270
	 * @param {integer} Page length to set. Use `-1` to show all records.
7271
	 * @returns {DataTables.Api} this
7272
	 */
7273
	_api_register( 'page.len()', function ( len ) {
7274
		// Note that we can't call this function 'length()' because `length`
7275
		// is a Javascript property of functions which defines how many arguments
7276
		// the function expects.
7277
		if ( len === undefined ) {
7278
			return this.context.length !== 0 ?
7279
				this.context[0]._iDisplayLength :
7280
				undefined;
7281
		}
7282
 
7283
		// else, set the page length
7284
		return this.iterator( 'table', function ( settings ) {
7285
			_fnLengthChange( settings, len );
7286
		} );
7287
	} );
7288
 
7289
 
7290
 
7291
	var __reload = function ( settings, holdPosition, callback ) {
7292
		if ( _fnDataSource( settings ) == 'ssp' ) {
7293
			_fnReDraw( settings, holdPosition );
7294
		}
7295
		else {
7296
			// Trigger xhr
7297
			_fnProcessingDisplay( settings, true );
7298
 
7299
			_fnBuildAjax( settings, [], function( json ) {
7300
				_fnClearTable( settings );
7301
 
7302
				var data = _fnAjaxDataSrc( settings, json );
7303
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7304
					_fnAddData( settings, data[i] );
7305
				}
7306
 
7307
				_fnReDraw( settings, holdPosition );
7308
				_fnProcessingDisplay( settings, false );
7309
			} );
7310
		}
7311
 
7312
		// Use the draw event to trigger a callback, regardless of if it is an async
7313
		// or sync draw
7314
		if ( callback ) {
7315
			var api = new _Api( settings );
7316
 
7317
			api.one( 'draw', function () {
7318
				callback( api.ajax.json() );
7319
			} );
7320
		}
7321
	};
7322
 
7323
 
7324
	/**
7325
	 * Get the JSON response from the last Ajax request that DataTables made to the
7326
	 * server. Note that this returns the JSON from the first table in the current
7327
	 * context.
7328
	 *
7329
	 * @return {object} JSON received from the server.
7330
	 */
7331
	_api_register( 'ajax.json()', function () {
7332
		var ctx = this.context;
7333
 
7334
		if ( ctx.length > 0 ) {
7335
			return ctx[0].json;
7336
		}
7337
 
7338
		// else return undefined;
7339
	} );
7340
 
7341
 
7342
	/**
7343
	 * Get the data submitted in the last Ajax request
7344
	 */
7345
	_api_register( 'ajax.params()', function () {
7346
		var ctx = this.context;
7347
 
7348
		if ( ctx.length > 0 ) {
7349
			return ctx[0].oAjaxData;
7350
		}
7351
 
7352
		// else return undefined;
7353
	} );
7354
 
7355
 
7356
	/**
7357
	 * Reload tables from the Ajax data source. Note that this function will
7358
	 * automatically re-draw the table when the remote data has been loaded.
7359
	 *
7360
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7361
	 *   position. A full re-sort and re-filter is performed when this method is
7362
	 *   called, which is why the pagination reset is the default action.
7363
	 * @returns {DataTables.Api} this
7364
	 */
7365
	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7366
		return this.iterator( 'table', function (settings) {
7367
			__reload( settings, resetPaging===false, callback );
7368
		} );
7369
	} );
7370
 
7371
 
7372
	/**
7373
	 * Get the current Ajax URL. Note that this returns the URL from the first
7374
	 * table in the current context.
7375
	 *
7376
	 * @return {string} Current Ajax source URL
7377
	 *//**
7378
	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7379
	 * current context.
7380
	 *
7381
	 * @param {string} url URL to set.
7382
	 * @returns {DataTables.Api} this
7383
	 */
7384
	_api_register( 'ajax.url()', function ( url ) {
7385
		var ctx = this.context;
7386
 
7387
		if ( url === undefined ) {
7388
			// get
7389
			if ( ctx.length === 0 ) {
7390
				return undefined;
7391
			}
7392
			ctx = ctx[0];
7393
 
7394
			return ctx.ajax ?
7395
				$.isPlainObject( ctx.ajax ) ?
7396
					ctx.ajax.url :
7397
					ctx.ajax :
7398
				ctx.sAjaxSource;
7399
		}
7400
 
7401
		// set
7402
		return this.iterator( 'table', function ( settings ) {
7403
			if ( $.isPlainObject( settings.ajax ) ) {
7404
				settings.ajax.url = url;
7405
			}
7406
			else {
7407
				settings.ajax = url;
7408
			}
7409
			// No need to consider sAjaxSource here since DataTables gives priority
7410
			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7411
			// value of `sAjaxSource` redundant.
7412
		} );
7413
	} );
7414
 
7415
 
7416
	/**
7417
	 * Load data from the newly set Ajax URL. Note that this method is only
7418
	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7419
	 * has the same effect as calling `ajax.reload()` but is provided for
7420
	 * convenience when setting a new URL. Like `ajax.reload()` it will
7421
	 * automatically redraw the table once the remote data has been loaded.
7422
	 *
7423
	 * @returns {DataTables.Api} this
7424
	 */
7425
	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7426
		// Same as a reload, but makes sense to present it for easy access after a
7427
		// url change
7428
		return this.iterator( 'table', function ( ctx ) {
7429
			__reload( ctx, resetPaging===false, callback );
7430
		} );
7431
	} );
7432
 
7433
 
7434
 
7435
 
7436
	var _selector_run = function ( selector, select )
7437
	{
7438
		var
7439
			out = [], res,
7440
			a, i, ien, j, jen,
7441
			selectorType = typeof selector;
7442
 
7443
		// Can't just check for isArray here, as an API or jQuery instance might be
7444
		// given with their array like look
7445
		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7446
			selector = [ selector ];
7447
		}
7448
 
7449
		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7450
			a = selector[i] && selector[i].split ?
7451
				selector[i].split(',') :
7452
				[ selector[i] ];
7453
 
7454
			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7455
				res = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7456
 
7457
				if ( res && res.length ) {
7458
					out.push.apply( out, res );
7459
				}
7460
			}
7461
		}
7462
 
7463
		return out;
7464
	};
7465
 
7466
 
7467
	var _selector_opts = function ( opts )
7468
	{
7469
		if ( ! opts ) {
7470
			opts = {};
7471
		}
7472
 
7473
		// Backwards compatibility for 1.9- which used the terminology filter rather
7474
		// than search
7475
		if ( opts.filter && ! opts.search ) {
7476
			opts.search = opts.filter;
7477
		}
7478
 
7479
		return {
7480
			search: opts.search || 'none',
7481
			order:  opts.order  || 'current',
7482
			page:   opts.page   || 'all'
7483
		};
7484
	};
7485
 
7486
 
7487
	var _selector_first = function ( inst )
7488
	{
7489
		// Reduce the API instance to the first item found
7490
		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7491
			if ( inst[i].length > 0 ) {
7492
				// Assign the first element to the first item in the instance
7493
				// and truncate the instance and context
7494
				inst[0] = inst[i];
7495
				inst.length = 1;
7496
				inst.context = [ inst.context[i] ];
7497
 
7498
				return inst;
7499
			}
7500
		}
7501
 
7502
		// Not found - return an empty instance
7503
		inst.length = 0;
7504
		return inst;
7505
	};
7506
 
7507
 
7508
	var _selector_row_indexes = function ( settings, opts )
7509
	{
7510
		var
7511
			i, ien, tmp, a=[],
7512
			displayFiltered = settings.aiDisplay,
7513
			displayMaster = settings.aiDisplayMaster;
7514
 
7515
		var
7516
			search = opts.search,  // none, applied, removed
7517
			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7518
			page   = opts.page;    // all, current
7519
 
7520
		if ( _fnDataSource( settings ) == 'ssp' ) {
7521
			// In server-side processing mode, most options are irrelevant since
7522
			// rows not shown don't exist and the index order is the applied order
7523
			// Removed is a special case - for consistency just return an empty
7524
			// array
7525
			return search === 'removed' ?
7526
				[] :
7527
				_range( 0, displayMaster.length );
7528
		}
7529
		else if ( page == 'current' ) {
7530
			// Current page implies that order=current and fitler=applied, since it is
7531
			// fairly senseless otherwise, regardless of what order and search actually
7532
			// are
7533
			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7534
				a.push( displayFiltered[i] );
7535
			}
7536
		}
7537
		else if ( order == 'current' || order == 'applied' ) {
7538
			a = search == 'none' ?
7539
				displayMaster.slice() :                      // no search
7540
				search == 'applied' ?
7541
					displayFiltered.slice() :                // applied search
7542
					$.map( displayMaster, function (el, i) { // removed search
7543
						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7544
					} );
7545
		}
7546
		else if ( order == 'index' || order == 'original' ) {
7547
			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7548
				if ( search == 'none' ) {
7549
					a.push( i );
7550
				}
7551
				else { // applied | removed
7552
					tmp = $.inArray( i, displayFiltered );
7553
 
7554
					if ((tmp === -1 && search == 'removed') ||
7555
						(tmp >= 0   && search == 'applied') )
7556
					{
7557
						a.push( i );
7558
					}
7559
				}
7560
			}
7561
		}
7562
 
7563
		return a;
7564
	};
7565
 
7566
 
7567
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7568
	 * Rows
7569
	 *
7570
	 * {}          - no selector - use all available rows
7571
	 * {integer}   - row aoData index
7572
	 * {node}      - TR node
7573
	 * {string}    - jQuery selector to apply to the TR elements
7574
	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7575
	 *
7576
	 */
7577
 
7578
 
7579
	var __row_selector = function ( settings, selector, opts )
7580
	{
7581
		return _selector_run( selector, function ( sel ) {
7582
			var selInt = _intVal( sel );
7583
			var i, ien;
7584
 
7585
			// Short cut - selector is a number and no options provided (default is
7586
			// all records, so no need to check if the index is in there, since it
7587
			// must be - dev error if the index doesn't exist).
7588
			if ( selInt !== null && ! opts ) {
7589
				return [ selInt ];
7590
			}
7591
 
7592
			var rows = _selector_row_indexes( settings, opts );
7593
 
7594
			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7595
				// Selector - integer
7596
				return [ selInt ];
7597
			}
7598
			else if ( ! sel ) {
7599
				// Selector - none
7600
				return rows;
7601
			}
7602
 
7603
			// Get nodes in the order from the `rows` array
7604
			var nodes = _pluck_order( settings.aoData, rows, 'nTr' );
7605
 
7606
			// Selector - function
7607
			if ( typeof sel === 'function' ) {
7608
				return $.map( rows, function (idx) {
7609
					var row = settings.aoData[ idx ];
7610
					return sel( idx, row._aData, row.nTr ) ? idx : null;
7611
				} );
7612
			}
7613
 
7614
			// Selector - node
7615
			if ( sel.nodeName ) {
7616
				if ( $.inArray( sel, nodes ) !== -1 ) {
7617
					return [ sel._DT_RowIndex ];// sel is a TR node that is in the table
7618
											// and DataTables adds a prop for fast lookup
7619
				}
7620
			}
7621
 
7622
			// Selector - jQuery selector string, array of nodes or jQuery object/
7623
			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7624
			// it also allows arrays, so this will cope with all three options
7625
			return $(nodes)
7626
				.filter( sel )
7627
				.map( function () {
7628
					return this._DT_RowIndex;
7629
				} )
7630
				.toArray();
7631
		} );
7632
	};
7633
 
7634
 
7635
	/**
7636
	 *
7637
	 */
7638
	_api_register( 'rows()', function ( selector, opts ) {
7639
		// argument shifting
7640
		if ( selector === undefined ) {
7641
			selector = '';
7642
		}
7643
		else if ( $.isPlainObject( selector ) ) {
7644
			opts = selector;
7645
			selector = '';
7646
		}
7647
 
7648
		opts = _selector_opts( opts );
7649
 
7650
		var inst = this.iterator( 'table', function ( settings ) {
7651
			return __row_selector( settings, selector, opts );
7652
		} );
7653
 
7654
		// Want argument shifting here and in __row_selector?
7655
		inst.selector.rows = selector;
7656
		inst.selector.opts = opts;
7657
 
7658
		return inst;
7659
	} );
7660
 
7661
 
7662
	_api_register( 'rows().nodes()', function () {
7663
		return this.iterator( 'row', function ( settings, row ) {
7664
			return settings.aoData[ row ].nTr || undefined;
7665
		} );
7666
	} );
7667
 
7668
	_api_register( 'rows().data()', function () {
7669
		return this.iterator( true, 'rows', function ( settings, rows ) {
7670
			return _pluck_order( settings.aoData, rows, '_aData' );
7671
		} );
7672
	} );
7673
 
7674
	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7675
		return this.iterator( 'row', function ( settings, row ) {
7676
			var r = settings.aoData[ row ];
7677
			return type === 'search' ? r._aFilterData : r._aSortData;
7678
		} );
7679
	} );
7680
 
7681
	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7682
		return this.iterator( 'row', function ( settings, row ) {
7683
			_fnInvalidateRow( settings, row, src );
7684
		} );
7685
	} );
7686
 
7687
	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7688
		return this.iterator( 'row', function ( settings, row ) {
7689
			return row;
7690
		} );
7691
	} );
7692
 
7693
	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7694
		var that = this;
7695
 
7696
		return this.iterator( 'row', function ( settings, row, thatIdx ) {
7697
			var data = settings.aoData;
7698
 
7699
			data.splice( row, 1 );
7700
 
7701
			// Update the _DT_RowIndex parameter on all rows in the table
7702
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7703
				if ( data[i].nTr !== null ) {
7704
					data[i].nTr._DT_RowIndex = i;
7705
				}
7706
			}
7707
 
7708
			// Remove the target row from the search array
7709
			var displayIndex = $.inArray( row, settings.aiDisplay );
7710
 
7711
			// Delete from the display arrays
7712
			_fnDeleteIndex( settings.aiDisplayMaster, row );
7713
			_fnDeleteIndex( settings.aiDisplay, row );
7714
			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7715
 
7716
			// Check for an 'overflow' they case for displaying the table
7717
			_fnLengthOverflow( settings );
7718
		} );
7719
	} );
7720
 
7721
 
7722
	_api_register( 'rows.add()', function ( rows ) {
7723
		var newRows = this.iterator( 'table', function ( settings ) {
7724
				var row, i, ien;
7725
				var out = [];
7726
 
7727
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
7728
					row = rows[i];
7729
 
7730
					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7731
						out.push( _fnAddTr( settings, row )[0] );
7732
					}
7733
					else {
7734
						out.push( _fnAddData( settings, row ) );
7735
					}
7736
				}
7737
 
7738
				return out;
7739
			} );
7740
 
7741
		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
7742
		var modRows = this.rows( -1 );
7743
		modRows.pop();
7744
		modRows.push.apply( modRows, newRows.toArray() );
7745
 
7746
		return modRows;
7747
	} );
7748
 
7749
 
7750
 
7751
 
7752
 
7753
	/**
7754
	 *
7755
	 */
7756
	_api_register( 'row()', function ( selector, opts ) {
7757
		return _selector_first( this.rows( selector, opts ) );
7758
	} );
7759
 
7760
 
7761
	_api_register( 'row().data()', function ( data ) {
7762
		var ctx = this.context;
7763
 
7764
		if ( data === undefined ) {
7765
			// Get
7766
			return ctx.length && this.length ?
7767
				ctx[0].aoData[ this[0] ]._aData :
7768
				undefined;
7769
		}
7770
 
7771
		// Set
7772
		ctx[0].aoData[ this[0] ]._aData = data;
7773
 
7774
		// Automatically invalidate
7775
		_fnInvalidateRow( ctx[0], this[0], 'data' );
7776
 
7777
		return this;
7778
	} );
7779
 
7780
 
7781
	_api_register( 'row().node()', function () {
7782
		var ctx = this.context;
7783
 
7784
		return ctx.length && this.length ?
7785
			ctx[0].aoData[ this[0] ].nTr || null :
7786
			null;
7787
	} );
7788
 
7789
 
7790
	_api_register( 'row.add()', function ( row ) {
7791
		// Allow a jQuery object to be passed in - only a single row is added from
7792
		// it though - the first element in the set
7793
		if ( row instanceof $ && row.length ) {
7794
			row = row[0];
7795
		}
7796
 
7797
		var rows = this.iterator( 'table', function ( settings ) {
7798
			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7799
				return _fnAddTr( settings, row )[0];
7800
			}
7801
			return _fnAddData( settings, row );
7802
		} );
7803
 
7804
		// Return an Api.rows() extended instance, with the newly added row selected
7805
		return this.row( rows[0] );
7806
	} );
7807
 
7808
 
7809
 
7810
	var __details_add = function ( ctx, row, data, klass )
7811
	{
7812
		// Convert to array of TR elements
7813
		var rows = [];
7814
		var addRow = function ( r, k ) {
7815
			// If we get a TR element, then just add it directly - up to the dev
7816
			// to add the correct number of columns etc
7817
			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
7818
				rows.push( r );
7819
			}
7820
			else {
7821
				// Otherwise create a row with a wrapper
7822
				var created = $('<tr><td/></tr>').addClass( k );
7823
				$('td', created)
7824
					.addClass( k )
7825
					.html( r )
7826
					[0].colSpan = _fnVisbleColumns( ctx );
7827
 
7828
				rows.push( created[0] );
7829
			}
7830
		};
7831
 
7832
		if ( $.isArray( data ) || data instanceof $ ) {
7833
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7834
				addRow( data[i], klass );
7835
			}
7836
		}
7837
		else {
7838
			addRow( data, klass );
7839
		}
7840
 
7841
		if ( row._details ) {
7842
			row._details.remove();
7843
		}
7844
 
7845
		row._details = $(rows);
7846
 
7847
		// If the children were already shown, that state should be retained
7848
		if ( row._detailsShow ) {
7849
			row._details.insertAfter( row.nTr );
7850
		}
7851
	};
7852
 
7853
 
7854
	var __details_remove = function ( api, idx )
7855
	{
7856
		var ctx = api.context;
7857
 
7858
		if ( ctx.length ) {
7859
			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
7860
 
7861
			if ( row._details ) {
7862
				row._details.remove();
7863
 
7864
				row._detailsShow = undefined;
7865
				row._details = undefined;
7866
			}
7867
		}
7868
	};
7869
 
7870
 
7871
	var __details_display = function ( api, show ) {
7872
		var ctx = api.context;
7873
 
7874
		if ( ctx.length && api.length ) {
7875
			var row = ctx[0].aoData[ api[0] ];
7876
 
7877
			if ( row._details ) {
7878
				row._detailsShow = show;
7879
 
7880
				if ( show ) {
7881
					row._details.insertAfter( row.nTr );
7882
				}
7883
				else {
7884
					row._details.detach();
7885
				}
7886
 
7887
				__details_events( ctx[0] );
7888
			}
7889
		}
7890
	};
7891
 
7892
 
7893
	var __details_events = function ( settings )
7894
	{
7895
		var api = new _Api( settings );
7896
		var namespace = '.dt.DT_details';
7897
		var drawEvent = 'draw'+namespace;
7898
		var colvisEvent = 'column-visibility'+namespace;
7899
		var destroyEvent = 'destroy'+namespace;
7900
		var data = settings.aoData;
7901
 
7902
		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
7903
 
7904
		if ( _pluck( data, '_details' ).length > 0 ) {
7905
			// On each draw, insert the required elements into the document
7906
			api.on( drawEvent, function ( e, ctx ) {
7907
				if ( settings !== ctx ) {
7908
					return;
7909
				}
7910
 
7911
				api.rows( {page:'current'} ).eq(0).each( function (idx) {
7912
					// Internal data grab
7913
					var row = data[ idx ];
7914
 
7915
					if ( row._detailsShow ) {
7916
						row._details.insertAfter( row.nTr );
7917
					}
7918
				} );
7919
			} );
7920
 
7921
			// Column visibility change - update the colspan
7922
			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
7923
				if ( settings !== ctx ) {
7924
					return;
7925
				}
7926
 
7927
				// Update the colspan for the details rows (note, only if it already has
7928
				// a colspan)
7929
				var row, visible = _fnVisbleColumns( ctx );
7930
 
7931
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7932
					row = data[i];
7933
 
7934
					if ( row._details ) {
7935
						row._details.children('td[colspan]').attr('colspan', visible );
7936
					}
7937
				}
7938
			} );
7939
 
7940
			// Table destroyed - nuke any child rows
7941
			api.on( destroyEvent, function ( e, ctx ) {
7942
				if ( settings !== ctx ) {
7943
					return;
7944
				}
7945
 
7946
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7947
					if ( data[i]._details ) {
7948
						__details_remove( api, i );
7949
					}
7950
				}
7951
			} );
7952
		}
7953
	};
7954
 
7955
	// Strings for the method names to help minification
7956
	var _emp = '';
7957
	var _child_obj = _emp+'row().child';
7958
	var _child_mth = _child_obj+'()';
7959
 
7960
	// data can be:
7961
	//  tr
7962
	//  string
7963
	//  jQuery or array of any of the above
7964
	_api_register( _child_mth, function ( data, klass ) {
7965
		var ctx = this.context;
7966
 
7967
		if ( data === undefined ) {
7968
			// get
7969
			return ctx.length && this.length ?
7970
				ctx[0].aoData[ this[0] ]._details :
7971
				undefined;
7972
		}
7973
		else if ( data === true ) {
7974
			// show
7975
			this.child.show();
7976
		}
7977
		else if ( data === false ) {
7978
			// remove
7979
			__details_remove( this );
7980
		}
7981
		else if ( ctx.length && this.length ) {
7982
			// set
7983
			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
7984
		}
7985
 
7986
		return this;
7987
	} );
7988
 
7989
 
7990
	_api_register( [
7991
		_child_obj+'.show()',
7992
		_child_mth+'.show()' // only when `child()` was called with parameters (without
7993
	], function ( show ) {   // it returns an object and this method is not executed)
7994
		__details_display( this, true );
7995
		return this;
7996
	} );
7997
 
7998
 
7999
	_api_register( [
8000
		_child_obj+'.hide()',
8001
		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8002
	], function () {         // it returns an object and this method is not executed)
8003
		__details_display( this, false );
8004
		return this;
8005
	} );
8006
 
8007
 
8008
	_api_register( [
8009
		_child_obj+'.remove()',
8010
		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8011
	], function () {           // it returns an object and this method is not executed)
8012
		__details_remove( this );
8013
		return this;
8014
	} );
8015
 
8016
 
8017
	_api_register( _child_obj+'.isShown()', function () {
8018
		var ctx = this.context;
8019
 
8020
		if ( ctx.length && this.length ) {
8021
			// _detailsShown as false or undefined will fall through to return false
8022
			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8023
		}
8024
		return false;
8025
	} );
8026
 
8027
 
8028
 
8029
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8030
	 * Columns
8031
	 *
8032
	 * {integer}           - column index (>=0 count from left, <0 count from right)
8033
	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8034
	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8035
	 * "{string}:name"     - column name
8036
	 * "{string}"          - jQuery selector on column header nodes
8037
	 *
8038
	 */
8039
 
8040
	// can be an array of these items, comma separated list, or an array of comma
8041
	// separated lists
8042
 
8043
	var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
8044
 
8045
 
8046
	// r1 and r2 are redundant - but it means that the parameters match for the
8047
	// iterator callback in columns().data()
8048
	var __columnData = function ( settings, column, r1, r2, rows ) {
8049
		var a = [];
8050
		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8051
			a.push( _fnGetCellData( settings, rows[row], column ) );
8052
		}
8053
		return a;
8054
	};
8055
 
8056
 
8057
	var __column_selector = function ( settings, selector, opts )
8058
	{
8059
		var
8060
			columns = settings.aoColumns,
8061
			names = _pluck( columns, 'sName' ),
8062
			nodes = _pluck( columns, 'nTh' );
8063
 
8064
		return _selector_run( selector, function ( s ) {
8065
			var selInt = _intVal( s );
8066
 
8067
			// Selector - all
8068
			if ( s === '' ) {
8069
				return _range( columns.length );
8070
			}
8071
 
8072
			// Selector - index
8073
			if ( selInt !== null ) {
8074
				return [ selInt >= 0 ?
8075
					selInt : // Count from left
8076
					columns.length + selInt // Count from right (+ because its a negative value)
8077
				];
8078
			}
8079
 
8080
			// Selector = function
8081
			if ( typeof s === 'function' ) {
8082
				var rows = _selector_row_indexes( settings, opts );
8083
 
8084
				return $.map( columns, function (col, idx) {
8085
					return s(
8086
							idx,
8087
							__columnData( settings, idx, 0, 0, rows ),
8088
							nodes[ idx ]
8089
						) ? idx : null;
8090
				} );
8091
			}
8092
 
8093
			// jQuery or string selector
8094
			var match = typeof s === 'string' ?
8095
				s.match( __re_column_selector ) :
8096
				'';
8097
 
8098
			if ( match ) {
8099
				switch( match[2] ) {
8100
					case 'visIdx':
8101
					case 'visible':
8102
						var idx = parseInt( match[1], 10 );
8103
						// Visible index given, convert to column index
8104
						if ( idx < 0 ) {
8105
							// Counting from the right
8106
							var visColumns = $.map( columns, function (col,i) {
8107
								return col.bVisible ? i : null;
8108
							} );
8109
							return [ visColumns[ visColumns.length + idx ] ];
8110
						}
8111
						// Counting from the left
8112
						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8113
 
8114
					case 'name':
8115
						// match by name. `names` is column index complete and in order
8116
						return $.map( names, function (name, i) {
8117
							return name === match[1] ? i : null;
8118
						} );
8119
				}
8120
			}
8121
			else {
8122
				// jQuery selector on the TH elements for the columns
8123
				return $( nodes )
8124
					.filter( s )
8125
					.map( function () {
8126
						return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8127
					} )
8128
					.toArray();
8129
			}
8130
		} );
8131
	};
8132
 
8133
 
8134
	var __setColumnVis = function ( settings, column, vis, recalc ) {
8135
		var
8136
			cols = settings.aoColumns,
8137
			col  = cols[ column ],
8138
			data = settings.aoData,
8139
			row, cells, i, ien, tr;
8140
 
8141
		// Get
8142
		if ( vis === undefined ) {
8143
			return col.bVisible;
8144
		}
8145
 
8146
		// Set
8147
		// No change
8148
		if ( col.bVisible === vis ) {
8149
			return;
8150
		}
8151
 
8152
		if ( vis ) {
8153
			// Insert column
8154
			// Need to decide if we should use appendChild or insertBefore
8155
			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8156
 
8157
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8158
				tr = data[i].nTr;
8159
				cells = data[i].anCells;
8160
 
8161
				if ( tr ) {
8162
					// insertBefore can act like appendChild if 2nd arg is null
8163
					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8164
				}
8165
			}
8166
		}
8167
		else {
8168
			// Remove column
8169
			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8170
		}
8171
 
8172
		// Common actions
8173
		col.bVisible = vis;
8174
		_fnDrawHead( settings, settings.aoHeader );
8175
		_fnDrawHead( settings, settings.aoFooter );
8176
 
8177
		if ( recalc === undefined || recalc ) {
8178
			// Automatically adjust column sizing
8179
			_fnAdjustColumnSizing( settings );
8180
 
8181
			// Realign columns for scrolling
8182
			if ( settings.oScroll.sX || settings.oScroll.sY ) {
8183
				_fnScrollDraw( settings );
8184
			}
8185
		}
8186
 
8187
		_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
8188
 
8189
		_fnSaveState( settings );
8190
	};
8191
 
8192
 
8193
	/**
8194
	 *
8195
	 */
8196
	_api_register( 'columns()', function ( selector, opts ) {
8197
		// argument shifting
8198
		if ( selector === undefined ) {
8199
			selector = '';
8200
		}
8201
		else if ( $.isPlainObject( selector ) ) {
8202
			opts = selector;
8203
			selector = '';
8204
		}
8205
 
8206
		opts = _selector_opts( opts );
8207
 
8208
		var inst = this.iterator( 'table', function ( settings ) {
8209
			return __column_selector( settings, selector, opts );
8210
		} );
8211
 
8212
		// Want argument shifting here and in _row_selector?
8213
		inst.selector.cols = selector;
8214
		inst.selector.opts = opts;
8215
 
8216
		return inst;
8217
	} );
8218
 
8219
 
8220
	/**
8221
	 *
8222
	 */
8223
	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8224
		return this.iterator( 'column', function ( settings, column ) {
8225
			return settings.aoColumns[column].nTh;
8226
		} );
8227
	} );
8228
 
8229
 
8230
	/**
8231
	 *
8232
	 */
8233
	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8234
		return this.iterator( 'column', function ( settings, column ) {
8235
			return settings.aoColumns[column].nTf;
8236
		} );
8237
	} );
8238
 
8239
 
8240
	/**
8241
	 *
8242
	 */
8243
	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8244
		return this.iterator( 'column-rows', __columnData );
8245
	} );
8246
 
8247
 
8248
	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8249
		return this.iterator( 'column', function ( settings, column ) {
8250
			return settings.aoColumns[column].mData;
8251
		} );
8252
	} );
8253
 
8254
 
8255
	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8256
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8257
			return _pluck_order( settings.aoData, rows,
8258
				type === 'search' ? '_aFilterData' : '_aSortData', column
8259
			);
8260
		} );
8261
	} );
8262
 
8263
 
8264
	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8265
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8266
			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8267
		} );
8268
	} );
8269
 
8270
 
8271
 
8272
	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8273
		return this.iterator( 'column', function ( settings, column ) {
8274
			return vis === undefined ?
8275
				settings.aoColumns[ column ].bVisible :
8276
				__setColumnVis( settings, column, vis, calc );
8277
		} );
8278
	} );
8279
 
8280
 
8281
 
8282
	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8283
		return this.iterator( 'column', function ( settings, column ) {
8284
			return type === 'visible' ?
8285
				_fnColumnIndexToVisible( settings, column ) :
8286
				column;
8287
		} );
8288
	} );
8289
 
8290
 
8291
	// _api_register( 'columns().show()', function () {
8292
	// 	var selector = this.selector;
8293
	// 	return this.columns( selector.cols, selector.opts ).visible( true );
8294
	// } );
8295
 
8296
 
8297
	// _api_register( 'columns().hide()', function () {
8298
	// 	var selector = this.selector;
8299
	// 	return this.columns( selector.cols, selector.opts ).visible( false );
8300
	// } );
8301
 
8302
 
8303
 
8304
	_api_register( 'columns.adjust()', function () {
8305
		return this.iterator( 'table', function ( settings ) {
8306
			_fnAdjustColumnSizing( settings );
8307
		} );
8308
	} );
8309
 
8310
 
8311
	// Convert from one column index type, to another type
8312
	_api_register( 'column.index()', function ( type, idx ) {
8313
		if ( this.context.length !== 0 ) {
8314
			var ctx = this.context[0];
8315
 
8316
			if ( type === 'fromVisible' || type === 'toData' ) {
8317
				return _fnVisibleToColumnIndex( ctx, idx );
8318
			}
8319
			else if ( type === 'fromData' || type === 'toVisible' ) {
8320
				return _fnColumnIndexToVisible( ctx, idx );
8321
			}
8322
		}
8323
	} );
8324
 
8325
 
8326
	_api_register( 'column()', function ( selector, opts ) {
8327
		return _selector_first( this.columns( selector, opts ) );
8328
	} );
8329
 
8330
 
8331
 
8332
 
8333
	var __cell_selector = function ( settings, selector, opts )
8334
	{
8335
		var data = settings.aoData;
8336
		var rows = _selector_row_indexes( settings, opts );
8337
		var cells = _pluck_order( data, rows, 'anCells' );
8338
		var allCells = $( [].concat.apply([], cells) );
8339
		var row;
8340
		var columns = settings.aoColumns.length;
8341
		var a, i, ien, j, o, host;
8342
 
8343
		return _selector_run( selector, function ( s ) {
8344
			var fnSelector = typeof s === 'function';
8345
 
8346
			if ( s === null || s === undefined || fnSelector ) {
8347
				// All cells and function selectors
8348
				a = [];
8349
 
8350
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8351
					row = rows[i];
8352
 
8353
					for ( j=0 ; j<columns ; j++ ) {
8354
						o = {
8355
							row: row,
8356
							column: j
8357
						};
8358
 
8359
						if ( fnSelector ) {
8360
							// Selector - function
8361
							host = settings.aoData[ row ];
8362
 
8363
							if ( s( o, _fnGetCellData(settings, row, j), host.anCells[j] ) ) {
8364
								a.push( o );
8365
							}
8366
						}
8367
						else {
8368
							// Selector - all
8369
							a.push( o );
8370
						}
8371
					}
8372
				}
8373
 
8374
				return a;
8375
			}
8376
 
8377
			// Selector - index
8378
			if ( $.isPlainObject( s ) ) {
8379
				return [s];
8380
			}
8381
 
8382
			// Selector - jQuery filtered cells
8383
			return allCells
8384
				.filter( s )
8385
				.map( function (i, el) {
8386
					row = el.parentNode._DT_RowIndex;
8387
 
8388
					return {
8389
						row: row,
8390
						column: $.inArray( el, data[ row ].anCells )
8391
					};
8392
				} )
8393
				.toArray();
8394
		} );
8395
	};
8396
 
8397
 
8398
 
8399
 
8400
	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8401
		// Argument shifting
8402
		if ( $.isPlainObject( rowSelector ) ) {
8403
			// Indexes
8404
			if ( typeof rowSelector.row !== undefined ) {
8405
				opts = columnSelector;
8406
				columnSelector = null;
8407
			}
8408
			else {
8409
				opts = rowSelector;
8410
				rowSelector = null;
8411
			}
8412
		}
8413
		if ( $.isPlainObject( columnSelector ) ) {
8414
			opts = columnSelector;
8415
			columnSelector = null;
8416
		}
8417
 
8418
		// Cell selector
8419
		if ( columnSelector === null || columnSelector === undefined ) {
8420
			return this.iterator( 'table', function ( settings ) {
8421
				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8422
			} );
8423
		}
8424
 
8425
		// Row + column selector
8426
		var columns = this.columns( columnSelector, opts );
8427
		var rows = this.rows( rowSelector, opts );
8428
		var a, i, ien, j, jen;
8429
 
8430
		var cells = this.iterator( 'table', function ( settings, idx ) {
8431
			a = [];
8432
 
8433
			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8434
				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8435
					a.push( {
8436
						row:    rows[idx][i],
8437
						column: columns[idx][j]
8438
					} );
8439
				}
8440
			}
8441
 
8442
			return a;
8443
		} );
8444
 
8445
		$.extend( cells.selector, {
8446
			cols: columnSelector,
8447
			rows: rowSelector,
8448
			opts: opts
8449
		} );
8450
 
8451
		return cells;
8452
	} );
8453
 
8454
 
8455
	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8456
		return this.iterator( 'cell', function ( settings, row, column ) {
8457
			return settings.aoData[ row ].anCells[ column ];
8458
		} );
8459
	} );
8460
 
8461
 
8462
	_api_register( 'cells().data()', function () {
8463
		return this.iterator( 'cell', function ( settings, row, column ) {
8464
			return _fnGetCellData( settings, row, column );
8465
		} );
8466
	} );
8467
 
8468
 
8469
	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8470
		type = type === 'search' ? '_aFilterData' : '_aSortData';
8471
 
8472
		return this.iterator( 'cell', function ( settings, row, column ) {
8473
			return settings.aoData[ row ][ type ][ column ];
8474
		} );
8475
	} );
8476
 
8477
 
8478
	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8479
		return this.iterator( 'cell', function ( settings, row, column ) {
8480
			return _fnGetCellData( settings, row, column, type );
8481
		} );
8482
	} );
8483
 
8484
 
8485
	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8486
		return this.iterator( 'cell', function ( settings, row, column ) {
8487
			return {
8488
				row: row,
8489
				column: column,
8490
				columnVisible: _fnColumnIndexToVisible( settings, column )
8491
			};
8492
		} );
8493
	} );
8494
 
8495
 
8496
	_api_register( [
8497
		'cells().invalidate()',
8498
		'cell().invalidate()'
8499
	], function ( src ) {
8500
		var selector = this.selector;
8501
 
8502
		// Use the rows method of the instance to perform the invalidation, rather
8503
		// than doing it here. This avoids needing to handle duplicate rows from
8504
		// the cells.
8505
		this.rows( selector.rows, selector.opts ).invalidate( src );
8506
 
8507
		return this;
8508
	} );
8509
 
8510
 
8511
 
8512
 
8513
	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8514
		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8515
	} );
8516
 
8517
 
8518
 
8519
	_api_register( 'cell().data()', function ( data ) {
8520
		var ctx = this.context;
8521
		var cell = this[0];
8522
 
8523
		if ( data === undefined ) {
8524
			// Get
8525
			return ctx.length && cell.length ?
8526
				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8527
				undefined;
8528
		}
8529
 
8530
		// Set
8531
		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8532
		_fnInvalidateRow( ctx[0], cell[0].row, 'data', cell[0].column );
8533
 
8534
		return this;
8535
	} );
8536
 
8537
 
8538
 
8539
	/**
8540
	 * Get current ordering (sorting) that has been applied to the table.
8541
	 *
8542
	 * @returns {array} 2D array containing the sorting information for the first
8543
	 *   table in the current context. Each element in the parent array represents
8544
	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8545
	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8546
	 *   the column index that the sorting condition applies to, the second is the
8547
	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8548
	 *   index of the sorting order from the `column.sorting` initialisation array.
8549
	 *//**
8550
	 * Set the ordering for the table.
8551
	 *
8552
	 * @param {integer} order Column index to sort upon.
8553
	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8554
	 * @returns {DataTables.Api} this
8555
	 *//**
8556
	 * Set the ordering for the table.
8557
	 *
8558
	 * @param {array} order 1D array of sorting information to be applied.
8559
	 * @param {array} [...] Optional additional sorting conditions
8560
	 * @returns {DataTables.Api} this
8561
	 *//**
8562
	 * Set the ordering for the table.
8563
	 *
8564
	 * @param {array} order 2D array of sorting information to be applied.
8565
	 * @returns {DataTables.Api} this
8566
	 */
8567
	_api_register( 'order()', function ( order, dir ) {
8568
		var ctx = this.context;
8569
 
8570
		if ( order === undefined ) {
8571
			// get
8572
			return ctx.length !== 0 ?
8573
				ctx[0].aaSorting :
8574
				undefined;
8575
		}
8576
 
8577
		// set
8578
		if ( typeof order === 'number' ) {
8579
			// Simple column / direction passed in
8580
			order = [ [ order, dir ] ];
8581
		}
8582
		else if ( ! $.isArray( order[0] ) ) {
8583
			// Arguments passed in (list of 1D arrays)
8584
			order = Array.prototype.slice.call( arguments );
8585
		}
8586
		// otherwise a 2D array was passed in
8587
 
8588
		return this.iterator( 'table', function ( settings ) {
8589
			settings.aaSorting = order.slice();
8590
		} );
8591
	} );
8592
 
8593
 
8594
	/**
8595
	 * Attach a sort listener to an element for a given column
8596
	 *
8597
	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8598
	 *   listener to. This can take the form of a single DOM node, a jQuery
8599
	 *   collection of nodes or a jQuery selector which will identify the node(s).
8600
	 * @param {integer} column the column that a click on this node will sort on
8601
	 * @param {function} [callback] callback function when sort is run
8602
	 * @returns {DataTables.Api} this
8603
	 */
8604
	_api_register( 'order.listener()', function ( node, column, callback ) {
8605
		return this.iterator( 'table', function ( settings ) {
8606
			_fnSortAttachListener( settings, node, column, callback );
8607
		} );
8608
	} );
8609
 
8610
 
8611
	// Order by the selected column(s)
8612
	_api_register( [
8613
		'columns().order()',
8614
		'column().order()'
8615
	], function ( dir ) {
8616
		var that = this;
8617
 
8618
		return this.iterator( 'table', function ( settings, i ) {
8619
			var sort = [];
8620
 
8621
			$.each( that[i], function (j, col) {
8622
				sort.push( [ col, dir ] );
8623
			} );
8624
 
8625
			settings.aaSorting = sort;
8626
		} );
8627
	} );
8628
 
8629
 
8630
 
8631
	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8632
		var ctx = this.context;
8633
 
8634
		if ( input === undefined ) {
8635
			// get
8636
			return ctx.length !== 0 ?
8637
				ctx[0].oPreviousSearch.sSearch :
8638
				undefined;
8639
		}
8640
 
8641
		// set
8642
		return this.iterator( 'table', function ( settings ) {
8643
			if ( ! settings.oFeatures.bFilter ) {
8644
				return;
8645
			}
8646
 
8647
			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8648
				"sSearch": input+"",
8649
				"bRegex":  regex === null ? false : regex,
8650
				"bSmart":  smart === null ? true  : smart,
8651
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
8652
			} ), 1 );
8653
		} );
8654
	} );
8655
 
8656
 
8657
	_api_registerPlural(
8658
		'columns().search()',
8659
		'column().search()',
8660
		function ( input, regex, smart, caseInsen ) {
8661
			return this.iterator( 'column', function ( settings, column ) {
8662
				var preSearch = settings.aoPreSearchCols;
8663
 
8664
				if ( input === undefined ) {
8665
					// get
8666
					return preSearch[ column ].sSearch;
8667
				}
8668
 
8669
				// set
8670
				if ( ! settings.oFeatures.bFilter ) {
8671
					return;
8672
				}
8673
 
8674
				$.extend( preSearch[ column ], {
8675
					"sSearch": input+"",
8676
					"bRegex":  regex === null ? false : regex,
8677
					"bSmart":  smart === null ? true  : smart,
8678
					"bCaseInsensitive": caseInsen === null ? true : caseInsen
8679
				} );
8680
 
8681
				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8682
			} );
8683
		}
8684
	);
8685
 
8686
	/*
8687
	 * State API methods
8688
	 */
8689
 
8690
	_api_register( 'state()', function () {
8691
		return this.context.length ?
8692
			this.context[0].oSavedState :
8693
			null;
8694
	} );
8695
 
8696
 
8697
	_api_register( 'state.clear()', function () {
8698
		return this.iterator( 'table', function ( settings ) {
8699
			// Save an empty object
8700
			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
8701
		} );
8702
	} );
8703
 
8704
 
8705
	_api_register( 'state.loaded()', function () {
8706
		return this.context.length ?
8707
			this.context[0].oLoadedState :
8708
			null;
8709
	} );
8710
 
8711
 
8712
	_api_register( 'state.save()', function () {
8713
		return this.iterator( 'table', function ( settings ) {
8714
			_fnSaveState( settings );
8715
		} );
8716
	} );
8717
 
8718
 
8719
 
8720
	/**
8721
	 * Provide a common method for plug-ins to check the version of DataTables being
8722
	 * used, in order to ensure compatibility.
8723
	 *
8724
	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
8725
	 *    Note that the formats "X" and "X.Y" are also acceptable.
8726
	 *  @returns {boolean} true if this version of DataTables is greater or equal to
8727
	 *    the required version, or false if this version of DataTales is not
8728
	 *    suitable
8729
	 *  @static
8730
	 *  @dtopt API-Static
8731
	 *
8732
	 *  @example
8733
	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8734
	 */
8735
	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
8736
	{
8737
		var aThis = DataTable.version.split('.');
8738
		var aThat = version.split('.');
8739
		var iThis, iThat;
8740
 
8741
		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
8742
			iThis = parseInt( aThis[i], 10 ) || 0;
8743
			iThat = parseInt( aThat[i], 10 ) || 0;
8744
 
8745
			// Parts are the same, keep comparing
8746
			if (iThis === iThat) {
8747
				continue;
8748
			}
8749
 
8750
			// Parts are different, return immediately
8751
			return iThis > iThat;
8752
		}
8753
 
8754
		return true;
8755
	};
8756
 
8757
 
8758
	/**
8759
	 * Check if a `<table>` node is a DataTable table already or not.
8760
	 *
8761
	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
8762
	 *      selector for the table to test. Note that if more than more than one
8763
	 *      table is passed on, only the first will be checked
8764
	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
8765
	 *  @static
8766
	 *  @dtopt API-Static
8767
	 *
8768
	 *  @example
8769
	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8770
	 *      $('#example').dataTable();
8771
	 *    }
8772
	 */
8773
	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
8774
	{
8775
		var t = $(table).get(0);
8776
		var is = false;
8777
 
8778
		$.each( DataTable.settings, function (i, o) {
8779
			if ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {
8780
				is = true;
8781
			}
8782
		} );
8783
 
8784
		return is;
8785
	};
8786
 
8787
 
8788
	/**
8789
	 * Get all DataTable tables that have been initialised - optionally you can
8790
	 * select to get only currently visible tables.
8791
	 *
8792
	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
8793
	 *    or visible tables only.
8794
	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
8795
	 *    DataTables
8796
	 *  @static
8797
	 *  @dtopt API-Static
8798
	 *
8799
	 *  @example
8800
	 *    $.each( $.fn.dataTable.tables(true), function () {
8801
	 *      $(table).DataTable().columns.adjust();
8802
	 *    } );
8803
	 */
8804
	DataTable.tables = DataTable.fnTables = function ( visible )
8805
	{
8806
		return jQuery.map( DataTable.settings, function (o) {
8807
			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8808
				return o.nTable;
8809
			}
8810
		} );
8811
	};
8812
 
8813
 
8814
	/**
8815
	 * DataTables utility methods
8816
	 * 
8817
	 * This namespace provides helper methods that DataTables uses internally to
8818
	 * create a DataTable, but which are not exclusively used only for DataTables.
8819
	 * These methods can be used by extension authors to save the duplication of
8820
	 * code.
8821
	 *
8822
	 *  @namespace
8823
	 */
8824
	DataTable.util = {
8825
		/**
8826
		 * Throttle the calls to a function. Arguments and context are maintained
8827
		 * for the throttled function.
8828
		 *
8829
		 * @param {function} fn Function to be called
8830
		 * @param {integer} freq Call frequency in mS
8831
		 * @return {function} Wrapped function
8832
		 */
8833
		throttle: _fnThrottle
8834
	};
8835
 
8836
 
8837
	/**
8838
	 * Convert from camel case parameters to Hungarian notation. This is made public
8839
	 * for the extensions to provide the same ability as DataTables core to accept
8840
	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
8841
	 * parameters.
8842
	 *
8843
	 *  @param {object} src The model object which holds all parameters that can be
8844
	 *    mapped.
8845
	 *  @param {object} user The object to convert from camel case to Hungarian.
8846
	 *  @param {boolean} force When set to `true`, properties which already have a
8847
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
8848
	 *    won't be.
8849
	 */
8850
	DataTable.camelToHungarian = _fnCamelToHungarian;
8851
 
8852
 
8853
 
8854
	/**
8855
	 *
8856
	 */
8857
	_api_register( '$()', function ( selector, opts ) {
8858
		var
8859
			rows   = this.rows( opts ).nodes(), // Get all rows
8860
			jqRows = $(rows);
8861
 
8862
		return $( [].concat(
8863
			jqRows.filter( selector ).toArray(),
8864
			jqRows.find( selector ).toArray()
8865
		) );
8866
	} );
8867
 
8868
 
8869
	// jQuery functions to operate on the tables
8870
	$.each( [ 'on', 'one', 'off' ], function (i, key) {
8871
		_api_register( key+'()', function ( /* event, handler */ ) {
8872
			var args = Array.prototype.slice.call(arguments);
8873
 
8874
			// Add the `dt` namespace automatically if it isn't already present
8875
			if ( ! args[0].match(/\.dt\b/) ) {
8876
				args[0] += '.dt';
8877
			}
8878
 
8879
			var inst = $( this.tables().nodes() );
8880
			inst[key].apply( inst, args );
8881
			return this;
8882
		} );
8883
	} );
8884
 
8885
 
8886
	_api_register( 'clear()', function () {
8887
		return this.iterator( 'table', function ( settings ) {
8888
			_fnClearTable( settings );
8889
		} );
8890
	} );
8891
 
8892
 
8893
	_api_register( 'settings()', function () {
8894
		return new _Api( this.context, this.context );
8895
	} );
8896
 
8897
 
8898
	_api_register( 'data()', function () {
8899
		return this.iterator( 'table', function ( settings ) {
8900
			return _pluck( settings.aoData, '_aData' );
8901
		} ).flatten();
8902
	} );
8903
 
8904
 
8905
	_api_register( 'destroy()', function ( remove ) {
8906
		remove = remove || false;
8907
 
8908
		return this.iterator( 'table', function ( settings ) {
8909
			var orig      = settings.nTableWrapper.parentNode;
8910
			var classes   = settings.oClasses;
8911
			var table     = settings.nTable;
8912
			var tbody     = settings.nTBody;
8913
			var thead     = settings.nTHead;
8914
			var tfoot     = settings.nTFoot;
8915
			var jqTable   = $(table);
8916
			var jqTbody   = $(tbody);
8917
			var jqWrapper = $(settings.nTableWrapper);
8918
			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
8919
			var i, ien;
8920
 
8921
			// Flag to note that the table is currently being destroyed - no action
8922
			// should be taken
8923
			settings.bDestroying = true;
8924
 
8925
			// Fire off the destroy callbacks for plug-ins etc
8926
			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
8927
 
8928
			// If not being removed from the document, make all columns visible
8929
			if ( ! remove ) {
8930
				new _Api( settings ).columns().visible( true );
8931
			}
8932
 
8933
			// Blitz all `DT` namespaced events (these are internal events, the
8934
			// lowercase, `dt` events are user subscribed and they are responsible
8935
			// for removing them
8936
			jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
8937
			$(window).unbind('.DT-'+settings.sInstance);
8938
 
8939
			// When scrolling we had to break the table up - restore it
8940
			if ( table != thead.parentNode ) {
8941
				jqTable.children('thead').detach();
8942
				jqTable.append( thead );
8943
			}
8944
 
8945
			if ( tfoot && table != tfoot.parentNode ) {
8946
				jqTable.children('tfoot').detach();
8947
				jqTable.append( tfoot );
8948
			}
8949
 
8950
			// Remove the DataTables generated nodes, events and classes
8951
			jqTable.detach();
8952
			jqWrapper.detach();
8953
 
8954
			settings.aaSorting = [];
8955
			settings.aaSortingFixed = [];
8956
			_fnSortingClasses( settings );
8957
 
8958
			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
8959
 
8960
			$('th, td', thead).removeClass( classes.sSortable+' '+
8961
				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
8962
			);
8963
 
8964
			if ( settings.bJUI ) {
8965
				$('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
8966
				$('th, td', thead).each( function () {
8967
					var wrapper = $('div.'+classes.sSortJUIWrapper, this);
8968
					$(this).append( wrapper.contents() );
8969
					wrapper.detach();
8970
				} );
8971
			}
8972
 
8973
			if ( ! remove && orig ) {
8974
				// insertBefore acts like appendChild if !arg[1]
8975
				orig.insertBefore( table, settings.nTableReinsertBefore );
8976
			}
8977
 
8978
			// Add the TR elements back into the table in their original order
8979
			jqTbody.children().detach();
8980
			jqTbody.append( rows );
8981
 
8982
			// Restore the width of the original table - was read from the style property,
8983
			// so we can restore directly to that
8984
			jqTable
8985
				.css( 'width', settings.sDestroyWidth )
8986
				.removeClass( classes.sTable );
8987
 
8988
			// If the were originally stripe classes - then we add them back here.
8989
			// Note this is not fool proof (for example if not all rows had stripe
8990
			// classes - but it's a good effort without getting carried away
8991
			ien = settings.asDestroyStripes.length;
8992
 
8993
			if ( ien ) {
8994
				jqTbody.children().each( function (i) {
8995
					$(this).addClass( settings.asDestroyStripes[i % ien] );
8996
				} );
8997
			}
8998
 
8999
			/* Remove the settings object from the settings array */
9000
			var idx = $.inArray( settings, DataTable.settings );
9001
			if ( idx !== -1 ) {
9002
				DataTable.settings.splice( idx, 1 );
9003
			}
9004
		} );
9005
	} );
9006
 
9007
 
9008
	/**
9009
	 * Version string for plug-ins to check compatibility. Allowed format is
9010
	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9011
	 * only for non-release builds. See http://semver.org/ for more information.
9012
	 *  @member
9013
	 *  @type string
9014
	 *  @default Version number
9015
	 */
9016
	DataTable.version = "1.10.3";
9017
 
9018
	/**
9019
	 * Private data store, containing all of the settings objects that are
9020
	 * created for the tables on a given page.
9021
	 *
9022
	 * Note that the `DataTable.settings` object is aliased to
9023
	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9024
	 * manipulated, or `jQuery.fn.dataTable.settings`.
9025
	 *  @member
9026
	 *  @type array
9027
	 *  @default []
9028
	 *  @private
9029
	 */
9030
	DataTable.settings = [];
9031
 
9032
	/**
9033
	 * Object models container, for the various models that DataTables has
9034
	 * available to it. These models define the objects that are used to hold
9035
	 * the active state and configuration of the table.
9036
	 *  @namespace
9037
	 */
9038
	DataTable.models = {};
9039
 
9040
 
9041
 
9042
	/**
9043
	 * Template object for the way in which DataTables holds information about
9044
	 * search information for the global filter and individual column filters.
9045
	 *  @namespace
9046
	 */
9047
	DataTable.models.oSearch = {
9048
		/**
9049
		 * Flag to indicate if the filtering should be case insensitive or not
9050
		 *  @type boolean
9051
		 *  @default true
9052
		 */
9053
		"bCaseInsensitive": true,
9054
 
9055
		/**
9056
		 * Applied search term
9057
		 *  @type string
9058
		 *  @default <i>Empty string</i>
9059
		 */
9060
		"sSearch": "",
9061
 
9062
		/**
9063
		 * Flag to indicate if the search term should be interpreted as a
9064
		 * regular expression (true) or not (false) and therefore and special
9065
		 * regex characters escaped.
9066
		 *  @type boolean
9067
		 *  @default false
9068
		 */
9069
		"bRegex": false,
9070
 
9071
		/**
9072
		 * Flag to indicate if DataTables is to use its smart filtering or not.
9073
		 *  @type boolean
9074
		 *  @default true
9075
		 */
9076
		"bSmart": true
9077
	};
9078
 
9079
 
9080
 
9081
 
9082
	/**
9083
	 * Template object for the way in which DataTables holds information about
9084
	 * each individual row. This is the object format used for the settings
9085
	 * aoData array.
9086
	 *  @namespace
9087
	 */
9088
	DataTable.models.oRow = {
9089
		/**
9090
		 * TR element for the row
9091
		 *  @type node
9092
		 *  @default null
9093
		 */
9094
		"nTr": null,
9095
 
9096
		/**
9097
		 * Array of TD elements for each row. This is null until the row has been
9098
		 * created.
9099
		 *  @type array nodes
9100
		 *  @default []
9101
		 */
9102
		"anCells": null,
9103
 
9104
		/**
9105
		 * Data object from the original data source for the row. This is either
9106
		 * an array if using the traditional form of DataTables, or an object if
9107
		 * using mData options. The exact type will depend on the passed in
9108
		 * data from the data source, or will be an array if using DOM a data
9109
		 * source.
9110
		 *  @type array|object
9111
		 *  @default []
9112
		 */
9113
		"_aData": [],
9114
 
9115
		/**
9116
		 * Sorting data cache - this array is ostensibly the same length as the
9117
		 * number of columns (although each index is generated only as it is
9118
		 * needed), and holds the data that is used for sorting each column in the
9119
		 * row. We do this cache generation at the start of the sort in order that
9120
		 * the formatting of the sort data need be done only once for each cell
9121
		 * per sort. This array should not be read from or written to by anything
9122
		 * other than the master sorting methods.
9123
		 *  @type array
9124
		 *  @default null
9125
		 *  @private
9126
		 */
9127
		"_aSortData": null,
9128
 
9129
		/**
9130
		 * Per cell filtering data cache. As per the sort data cache, used to
9131
		 * increase the performance of the filtering in DataTables
9132
		 *  @type array
9133
		 *  @default null
9134
		 *  @private
9135
		 */
9136
		"_aFilterData": null,
9137
 
9138
		/**
9139
		 * Filtering data cache. This is the same as the cell filtering cache, but
9140
		 * in this case a string rather than an array. This is easily computed with
9141
		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9142
		 * needed on every search (memory traded for performance)
9143
		 *  @type array
9144
		 *  @default null
9145
		 *  @private
9146
		 */
9147
		"_sFilterRow": null,
9148
 
9149
		/**
9150
		 * Cache of the class name that DataTables has applied to the row, so we
9151
		 * can quickly look at this variable rather than needing to do a DOM check
9152
		 * on className for the nTr property.
9153
		 *  @type string
9154
		 *  @default <i>Empty string</i>
9155
		 *  @private
9156
		 */
9157
		"_sRowStripe": "",
9158
 
9159
		/**
9160
		 * Denote if the original data source was from the DOM, or the data source
9161
		 * object. This is used for invalidating data, so DataTables can
9162
		 * automatically read data from the original source, unless uninstructed
9163
		 * otherwise.
9164
		 *  @type string
9165
		 *  @default null
9166
		 *  @private
9167
		 */
9168
		"src": null
9169
	};
9170
 
9171
 
9172
	/**
9173
	 * Template object for the column information object in DataTables. This object
9174
	 * is held in the settings aoColumns array and contains all the information that
9175
	 * DataTables needs about each individual column.
9176
	 *
9177
	 * Note that this object is related to {@link DataTable.defaults.column}
9178
	 * but this one is the internal data store for DataTables's cache of columns.
9179
	 * It should NOT be manipulated outside of DataTables. Any configuration should
9180
	 * be done through the initialisation options.
9181
	 *  @namespace
9182
	 */
9183
	DataTable.models.oColumn = {
9184
		/**
9185
		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9186
		 * is faster to just hold it as a variable
9187
		 *  @type integer
9188
		 *  @default null
9189
		 */
9190
		"idx": null,
9191
 
9192
		/**
9193
		 * A list of the columns that sorting should occur on when this column
9194
		 * is sorted. That this property is an array allows multi-column sorting
9195
		 * to be defined for a column (for example first name / last name columns
9196
		 * would benefit from this). The values are integers pointing to the
9197
		 * columns to be sorted on (typically it will be a single integer pointing
9198
		 * at itself, but that doesn't need to be the case).
9199
		 *  @type array
9200
		 */
9201
		"aDataSort": null,
9202
 
9203
		/**
9204
		 * Define the sorting directions that are applied to the column, in sequence
9205
		 * as the column is repeatedly sorted upon - i.e. the first value is used
9206
		 * as the sorting direction when the column if first sorted (clicked on).
9207
		 * Sort it again (click again) and it will move on to the next index.
9208
		 * Repeat until loop.
9209
		 *  @type array
9210
		 */
9211
		"asSorting": null,
9212
 
9213
		/**
9214
		 * Flag to indicate if the column is searchable, and thus should be included
9215
		 * in the filtering or not.
9216
		 *  @type boolean
9217
		 */
9218
		"bSearchable": null,
9219
 
9220
		/**
9221
		 * Flag to indicate if the column is sortable or not.
9222
		 *  @type boolean
9223
		 */
9224
		"bSortable": null,
9225
 
9226
		/**
9227
		 * Flag to indicate if the column is currently visible in the table or not
9228
		 *  @type boolean
9229
		 */
9230
		"bVisible": null,
9231
 
9232
		/**
9233
		 * Store for manual type assignment using the `column.type` option. This
9234
		 * is held in store so we can manipulate the column's `sType` property.
9235
		 *  @type string
9236
		 *  @default null
9237
		 *  @private
9238
		 */
9239
		"_sManualType": null,
9240
 
9241
		/**
9242
		 * Flag to indicate if HTML5 data attributes should be used as the data
9243
		 * source for filtering or sorting. True is either are.
9244
		 *  @type boolean
9245
		 *  @default false
9246
		 *  @private
9247
		 */
9248
		"_bAttrSrc": false,
9249
 
9250
		/**
9251
		 * Developer definable function that is called whenever a cell is created (Ajax source,
9252
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9253
		 * allowing you to modify the DOM element (add background colour for example) when the
9254
		 * element is available.
9255
		 *  @type function
9256
		 *  @param {element} nTd The TD node that has been created
9257
		 *  @param {*} sData The Data for the cell
9258
		 *  @param {array|object} oData The data for the whole row
9259
		 *  @param {int} iRow The row index for the aoData data store
9260
		 *  @default null
9261
		 */
9262
		"fnCreatedCell": null,
9263
 
9264
		/**
9265
		 * Function to get data from a cell in a column. You should <b>never</b>
9266
		 * access data directly through _aData internally in DataTables - always use
9267
		 * the method attached to this property. It allows mData to function as
9268
		 * required. This function is automatically assigned by the column
9269
		 * initialisation method
9270
		 *  @type function
9271
		 *  @param {array|object} oData The data array/object for the array
9272
		 *    (i.e. aoData[]._aData)
9273
		 *  @param {string} sSpecific The specific data type you want to get -
9274
		 *    'display', 'type' 'filter' 'sort'
9275
		 *  @returns {*} The data for the cell from the given row's data
9276
		 *  @default null
9277
		 */
9278
		"fnGetData": null,
9279
 
9280
		/**
9281
		 * Function to set data for a cell in the column. You should <b>never</b>
9282
		 * set the data directly to _aData internally in DataTables - always use
9283
		 * this method. It allows mData to function as required. This function
9284
		 * is automatically assigned by the column initialisation method
9285
		 *  @type function
9286
		 *  @param {array|object} oData The data array/object for the array
9287
		 *    (i.e. aoData[]._aData)
9288
		 *  @param {*} sValue Value to set
9289
		 *  @default null
9290
		 */
9291
		"fnSetData": null,
9292
 
9293
		/**
9294
		 * Property to read the value for the cells in the column from the data
9295
		 * source array / object. If null, then the default content is used, if a
9296
		 * function is given then the return from the function is used.
9297
		 *  @type function|int|string|null
9298
		 *  @default null
9299
		 */
9300
		"mData": null,
9301
 
9302
		/**
9303
		 * Partner property to mData which is used (only when defined) to get
9304
		 * the data - i.e. it is basically the same as mData, but without the
9305
		 * 'set' option, and also the data fed to it is the result from mData.
9306
		 * This is the rendering method to match the data method of mData.
9307
		 *  @type function|int|string|null
9308
		 *  @default null
9309
		 */
9310
		"mRender": null,
9311
 
9312
		/**
9313
		 * Unique header TH/TD element for this column - this is what the sorting
9314
		 * listener is attached to (if sorting is enabled.)
9315
		 *  @type node
9316
		 *  @default null
9317
		 */
9318
		"nTh": null,
9319
 
9320
		/**
9321
		 * Unique footer TH/TD element for this column (if there is one). Not used
9322
		 * in DataTables as such, but can be used for plug-ins to reference the
9323
		 * footer for each column.
9324
		 *  @type node
9325
		 *  @default null
9326
		 */
9327
		"nTf": null,
9328
 
9329
		/**
9330
		 * The class to apply to all TD elements in the table's TBODY for the column
9331
		 *  @type string
9332
		 *  @default null
9333
		 */
9334
		"sClass": null,
9335
 
9336
		/**
9337
		 * When DataTables calculates the column widths to assign to each column,
9338
		 * it finds the longest string in each column and then constructs a
9339
		 * temporary table and reads the widths from that. The problem with this
9340
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9341
		 * string - thus the calculation can go wrong (doing it properly and putting
9342
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9343
		 * a "work around" we provide this option. It will append its value to the
9344
		 * text that is found to be the longest string for the column - i.e. padding.
9345
		 *  @type string
9346
		 */
9347
		"sContentPadding": null,
9348
 
9349
		/**
9350
		 * Allows a default value to be given for a column's data, and will be used
9351
		 * whenever a null data source is encountered (this can be because mData
9352
		 * is set to null, or because the data source itself is null).
9353
		 *  @type string
9354
		 *  @default null
9355
		 */
9356
		"sDefaultContent": null,
9357
 
9358
		/**
9359
		 * Name for the column, allowing reference to the column by name as well as
9360
		 * by index (needs a lookup to work by name).
9361
		 *  @type string
9362
		 */
9363
		"sName": null,
9364
 
9365
		/**
9366
		 * Custom sorting data type - defines which of the available plug-ins in
9367
		 * afnSortData the custom sorting will use - if any is defined.
9368
		 *  @type string
9369
		 *  @default std
9370
		 */
9371
		"sSortDataType": 'std',
9372
 
9373
		/**
9374
		 * Class to be applied to the header element when sorting on this column
9375
		 *  @type string
9376
		 *  @default null
9377
		 */
9378
		"sSortingClass": null,
9379
 
9380
		/**
9381
		 * Class to be applied to the header element when sorting on this column -
9382
		 * when jQuery UI theming is used.
9383
		 *  @type string
9384
		 *  @default null
9385
		 */
9386
		"sSortingClassJUI": null,
9387
 
9388
		/**
9389
		 * Title of the column - what is seen in the TH element (nTh).
9390
		 *  @type string
9391
		 */
9392
		"sTitle": null,
9393
 
9394
		/**
9395
		 * Column sorting and filtering type
9396
		 *  @type string
9397
		 *  @default null
9398
		 */
9399
		"sType": null,
9400
 
9401
		/**
9402
		 * Width of the column
9403
		 *  @type string
9404
		 *  @default null
9405
		 */
9406
		"sWidth": null,
9407
 
9408
		/**
9409
		 * Width of the column when it was first "encountered"
9410
		 *  @type string
9411
		 *  @default null
9412
		 */
9413
		"sWidthOrig": null
9414
	};
9415
 
9416
 
9417
	/*
9418
	 * Developer note: The properties of the object below are given in Hungarian
9419
	 * notation, that was used as the interface for DataTables prior to v1.10, however
9420
	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9421
	 * breaking backwards compatibility utterly with this change, the Hungarian
9422
	 * version is still, internally the primary interface, but is is not documented
9423
	 * - hence the @name tags in each doc comment. This allows a Javascript function
9424
	 * to create a map from Hungarian notation to camel case (going the other direction
9425
	 * would require each property to be listed, which would at around 3K to the size
9426
	 * of DataTables, while this method is about a 0.5K hit.
9427
	 *
9428
	 * Ultimately this does pave the way for Hungarian notation to be dropped
9429
	 * completely, but that is a massive amount of work and will break current
9430
	 * installs (therefore is on-hold until v2).
9431
	 */
9432
 
9433
	/**
9434
	 * Initialisation options that can be given to DataTables at initialisation
9435
	 * time.
9436
	 *  @namespace
9437
	 */
9438
	DataTable.defaults = {
9439
		/**
9440
		 * An array of data to use for the table, passed in at initialisation which
9441
		 * will be used in preference to any data which is already in the DOM. This is
9442
		 * particularly useful for constructing tables purely in Javascript, for
9443
		 * example with a custom Ajax call.
9444
		 *  @type array
9445
		 *  @default null
9446
		 *
9447
		 *  @dtopt Option
9448
		 *  @name DataTable.defaults.data
9449
		 *
9450
		 *  @example
9451
		 *    // Using a 2D array data source
9452
		 *    $(document).ready( function () {
9453
		 *      $('#example').dataTable( {
9454
		 *        "data": [
9455
		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9456
		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9457
		 *        ],
9458
		 *        "columns": [
9459
		 *          { "title": "Engine" },
9460
		 *          { "title": "Browser" },
9461
		 *          { "title": "Platform" },
9462
		 *          { "title": "Version" },
9463
		 *          { "title": "Grade" }
9464
		 *        ]
9465
		 *      } );
9466
		 *    } );
9467
		 *
9468
		 *  @example
9469
		 *    // Using an array of objects as a data source (`data`)
9470
		 *    $(document).ready( function () {
9471
		 *      $('#example').dataTable( {
9472
		 *        "data": [
9473
		 *          {
9474
		 *            "engine":   "Trident",
9475
		 *            "browser":  "Internet Explorer 4.0",
9476
		 *            "platform": "Win 95+",
9477
		 *            "version":  4,
9478
		 *            "grade":    "X"
9479
		 *          },
9480
		 *          {
9481
		 *            "engine":   "Trident",
9482
		 *            "browser":  "Internet Explorer 5.0",
9483
		 *            "platform": "Win 95+",
9484
		 *            "version":  5,
9485
		 *            "grade":    "C"
9486
		 *          }
9487
		 *        ],
9488
		 *        "columns": [
9489
		 *          { "title": "Engine",   "data": "engine" },
9490
		 *          { "title": "Browser",  "data": "browser" },
9491
		 *          { "title": "Platform", "data": "platform" },
9492
		 *          { "title": "Version",  "data": "version" },
9493
		 *          { "title": "Grade",    "data": "grade" }
9494
		 *        ]
9495
		 *      } );
9496
		 *    } );
9497
		 */
9498
		"aaData": null,
9499
 
9500
 
9501
		/**
9502
		 * If ordering is enabled, then DataTables will perform a first pass sort on
9503
		 * initialisation. You can define which column(s) the sort is performed
9504
		 * upon, and the sorting direction, with this variable. The `sorting` array
9505
		 * should contain an array for each column to be sorted initially containing
9506
		 * the column's index and a direction string ('asc' or 'desc').
9507
		 *  @type array
9508
		 *  @default [[0,'asc']]
9509
		 *
9510
		 *  @dtopt Option
9511
		 *  @name DataTable.defaults.order
9512
		 *
9513
		 *  @example
9514
		 *    // Sort by 3rd column first, and then 4th column
9515
		 *    $(document).ready( function() {
9516
		 *      $('#example').dataTable( {
9517
		 *        "order": [[2,'asc'], [3,'desc']]
9518
		 *      } );
9519
		 *    } );
9520
		 *
9521
		 *    // No initial sorting
9522
		 *    $(document).ready( function() {
9523
		 *      $('#example').dataTable( {
9524
		 *        "order": []
9525
		 *      } );
9526
		 *    } );
9527
		 */
9528
		"aaSorting": [[0,'asc']],
9529
 
9530
 
9531
		/**
9532
		 * This parameter is basically identical to the `sorting` parameter, but
9533
		 * cannot be overridden by user interaction with the table. What this means
9534
		 * is that you could have a column (visible or hidden) which the sorting
9535
		 * will always be forced on first - any sorting after that (from the user)
9536
		 * will then be performed as required. This can be useful for grouping rows
9537
		 * together.
9538
		 *  @type array
9539
		 *  @default null
9540
		 *
9541
		 *  @dtopt Option
9542
		 *  @name DataTable.defaults.orderFixed
9543
		 *
9544
		 *  @example
9545
		 *    $(document).ready( function() {
9546
		 *      $('#example').dataTable( {
9547
		 *        "orderFixed": [[0,'asc']]
9548
		 *      } );
9549
		 *    } )
9550
		 */
9551
		"aaSortingFixed": [],
9552
 
9553
 
9554
		/**
9555
		 * DataTables can be instructed to load data to display in the table from a
9556
		 * Ajax source. This option defines how that Ajax call is made and where to.
9557
		 *
9558
		 * The `ajax` property has three different modes of operation, depending on
9559
		 * how it is defined. These are:
9560
		 *
9561
		 * * `string` - Set the URL from where the data should be loaded from.
9562
		 * * `object` - Define properties for `jQuery.ajax`.
9563
		 * * `function` - Custom data get function
9564
		 *
9565
		 * `string`
9566
		 * --------
9567
		 *
9568
		 * As a string, the `ajax` property simply defines the URL from which
9569
		 * DataTables will load data.
9570
		 *
9571
		 * `object`
9572
		 * --------
9573
		 *
9574
		 * As an object, the parameters in the object are passed to
9575
		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9576
		 * of the Ajax request. DataTables has a number of default parameters which
9577
		 * you can override using this option. Please refer to the jQuery
9578
		 * documentation for a full description of the options available, although
9579
		 * the following parameters provide additional options in DataTables or
9580
		 * require special consideration:
9581
		 *
9582
		 * * `data` - As with jQuery, `data` can be provided as an object, but it
9583
		 *   can also be used as a function to manipulate the data DataTables sends
9584
		 *   to the server. The function takes a single parameter, an object of
9585
		 *   parameters with the values that DataTables has readied for sending. An
9586
		 *   object may be returned which will be merged into the DataTables
9587
		 *   defaults, or you can add the items to the object that was passed in and
9588
		 *   not return anything from the function. This supersedes `fnServerParams`
9589
		 *   from DataTables 1.9-.
9590
		 *
9591
		 * * `dataSrc` - By default DataTables will look for the property `data` (or
9592
		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9593
		 *   from an Ajax source or for server-side processing - this parameter
9594
		 *   allows that property to be changed. You can use Javascript dotted
9595
		 *   object notation to get a data source for multiple levels of nesting, or
9596
		 *   it my be used as a function. As a function it takes a single parameter,
9597
		 *   the JSON returned from the server, which can be manipulated as
9598
		 *   required, with the returned value being that used by DataTables as the
9599
		 *   data source for the table. This supersedes `sAjaxDataProp` from
9600
		 *   DataTables 1.9-.
9601
		 *
9602
		 * * `success` - Should not be overridden it is used internally in
9603
		 *   DataTables. To manipulate / transform the data returned by the server
9604
		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9605
		 *
9606
		 * `function`
9607
		 * ----------
9608
		 *
9609
		 * As a function, making the Ajax call is left up to yourself allowing
9610
		 * complete control of the Ajax request. Indeed, if desired, a method other
9611
		 * than Ajax could be used to obtain the required data, such as Web storage
9612
		 * or an AIR database.
9613
		 *
9614
		 * The function is given four parameters and no return is required. The
9615
		 * parameters are:
9616
		 *
9617
		 * 1. _object_ - Data to send to the server
9618
		 * 2. _function_ - Callback function that must be executed when the required
9619
		 *    data has been obtained. That data should be passed into the callback
9620
		 *    as the only parameter
9621
		 * 3. _object_ - DataTables settings object for the table
9622
		 *
9623
		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
9624
		 *
9625
		 *  @type string|object|function
9626
		 *  @default null
9627
		 *
9628
		 *  @dtopt Option
9629
		 *  @name DataTable.defaults.ajax
9630
		 *  @since 1.10.0
9631
		 *
9632
		 * @example
9633
		 *   // Get JSON data from a file via Ajax.
9634
		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9635
		 *   $('#example').dataTable( {
9636
		 *     "ajax": "data.json"
9637
		 *   } );
9638
		 *
9639
		 * @example
9640
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
9641
		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9642
		 *   $('#example').dataTable( {
9643
		 *     "ajax": {
9644
		 *       "url": "data.json",
9645
		 *       "dataSrc": "tableData"
9646
		 *     }
9647
		 *   } );
9648
		 *
9649
		 * @example
9650
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
9651
		 *   // from a plain array rather than an array in an object
9652
		 *   $('#example').dataTable( {
9653
		 *     "ajax": {
9654
		 *       "url": "data.json",
9655
		 *       "dataSrc": ""
9656
		 *     }
9657
		 *   } );
9658
		 *
9659
		 * @example
9660
		 *   // Manipulate the data returned from the server - add a link to data
9661
		 *   // (note this can, should, be done using `render` for the column - this
9662
		 *   // is just a simple example of how the data can be manipulated).
9663
		 *   $('#example').dataTable( {
9664
		 *     "ajax": {
9665
		 *       "url": "data.json",
9666
		 *       "dataSrc": function ( json ) {
9667
		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9668
		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9669
		 *         }
9670
		 *         return json;
9671
		 *       }
9672
		 *     }
9673
		 *   } );
9674
		 *
9675
		 * @example
9676
		 *   // Add data to the request
9677
		 *   $('#example').dataTable( {
9678
		 *     "ajax": {
9679
		 *       "url": "data.json",
9680
		 *       "data": function ( d ) {
9681
		 *         return {
9682
		 *           "extra_search": $('#extra').val()
9683
		 *         };
9684
		 *       }
9685
		 *     }
9686
		 *   } );
9687
		 *
9688
		 * @example
9689
		 *   // Send request as POST
9690
		 *   $('#example').dataTable( {
9691
		 *     "ajax": {
9692
		 *       "url": "data.json",
9693
		 *       "type": "POST"
9694
		 *     }
9695
		 *   } );
9696
		 *
9697
		 * @example
9698
		 *   // Get the data from localStorage (could interface with a form for
9699
		 *   // adding, editing and removing rows).
9700
		 *   $('#example').dataTable( {
9701
		 *     "ajax": function (data, callback, settings) {
9702
		 *       callback(
9703
		 *         JSON.parse( localStorage.getItem('dataTablesData') )
9704
		 *       );
9705
		 *     }
9706
		 *   } );
9707
		 */
9708
		"ajax": null,
9709
 
9710
 
9711
		/**
9712
		 * This parameter allows you to readily specify the entries in the length drop
9713
		 * down menu that DataTables shows when pagination is enabled. It can be
9714
		 * either a 1D array of options which will be used for both the displayed
9715
		 * option and the value, or a 2D array which will use the array in the first
9716
		 * position as the value, and the array in the second position as the
9717
		 * displayed options (useful for language strings such as 'All').
9718
		 *
9719
		 * Note that the `pageLength` property will be automatically set to the
9720
		 * first value given in this array, unless `pageLength` is also provided.
9721
		 *  @type array
9722
		 *  @default [ 10, 25, 50, 100 ]
9723
		 *
9724
		 *  @dtopt Option
9725
		 *  @name DataTable.defaults.lengthMenu
9726
		 *
9727
		 *  @example
9728
		 *    $(document).ready( function() {
9729
		 *      $('#example').dataTable( {
9730
		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9731
		 *      } );
9732
		 *    } );
9733
		 */
9734
		"aLengthMenu": [ 10, 25, 50, 100 ],
9735
 
9736
 
9737
		/**
9738
		 * The `columns` option in the initialisation parameter allows you to define
9739
		 * details about the way individual columns behave. For a full list of
9740
		 * column options that can be set, please see
9741
		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
9742
		 * define your columns, you must have an entry in the array for every single
9743
		 * column that you have in your table (these can be null if you don't which
9744
		 * to specify any options).
9745
		 *  @member
9746
		 *
9747
		 *  @name DataTable.defaults.column
9748
		 */
9749
		"aoColumns": null,
9750
 
9751
		/**
9752
		 * Very similar to `columns`, `columnDefs` allows you to target a specific
9753
		 * column, multiple columns, or all columns, using the `targets` property of
9754
		 * each object in the array. This allows great flexibility when creating
9755
		 * tables, as the `columnDefs` arrays can be of any length, targeting the
9756
		 * columns you specifically want. `columnDefs` may use any of the column
9757
		 * options available: {@link DataTable.defaults.column}, but it _must_
9758
		 * have `targets` defined in each object in the array. Values in the `targets`
9759
		 * array may be:
9760
		 *   <ul>
9761
		 *     <li>a string - class name will be matched on the TH for the column</li>
9762
		 *     <li>0 or a positive integer - column index counting from the left</li>
9763
		 *     <li>a negative integer - column index counting from the right</li>
9764
		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
9765
		 *   </ul>
9766
		 *  @member
9767
		 *
9768
		 *  @name DataTable.defaults.columnDefs
9769
		 */
9770
		"aoColumnDefs": null,
9771
 
9772
 
9773
		/**
9774
		 * Basically the same as `search`, this parameter defines the individual column
9775
		 * filtering state at initialisation time. The array must be of the same size
9776
		 * as the number of columns, and each element be an object with the parameters
9777
		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
9778
		 * accepted and the default will be used.
9779
		 *  @type array
9780
		 *  @default []
9781
		 *
9782
		 *  @dtopt Option
9783
		 *  @name DataTable.defaults.searchCols
9784
		 *
9785
		 *  @example
9786
		 *    $(document).ready( function() {
9787
		 *      $('#example').dataTable( {
9788
		 *        "searchCols": [
9789
		 *          null,
9790
		 *          { "search": "My filter" },
9791
		 *          null,
9792
		 *          { "search": "^[0-9]", "escapeRegex": false }
9793
		 *        ]
9794
		 *      } );
9795
		 *    } )
9796
		 */
9797
		"aoSearchCols": [],
9798
 
9799
 
9800
		/**
9801
		 * An array of CSS classes that should be applied to displayed rows. This
9802
		 * array may be of any length, and DataTables will apply each class
9803
		 * sequentially, looping when required.
9804
		 *  @type array
9805
		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
9806
		 *    options</i>
9807
		 *
9808
		 *  @dtopt Option
9809
		 *  @name DataTable.defaults.stripeClasses
9810
		 *
9811
		 *  @example
9812
		 *    $(document).ready( function() {
9813
		 *      $('#example').dataTable( {
9814
		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
9815
		 *      } );
9816
		 *    } )
9817
		 */
9818
		"asStripeClasses": null,
9819
 
9820
 
9821
		/**
9822
		 * Enable or disable automatic column width calculation. This can be disabled
9823
		 * as an optimisation (it takes some time to calculate the widths) if the
9824
		 * tables widths are passed in using `columns`.
9825
		 *  @type boolean
9826
		 *  @default true
9827
		 *
9828
		 *  @dtopt Features
9829
		 *  @name DataTable.defaults.autoWidth
9830
		 *
9831
		 *  @example
9832
		 *    $(document).ready( function () {
9833
		 *      $('#example').dataTable( {
9834
		 *        "autoWidth": false
9835
		 *      } );
9836
		 *    } );
9837
		 */
9838
		"bAutoWidth": true,
9839
 
9840
 
9841
		/**
9842
		 * Deferred rendering can provide DataTables with a huge speed boost when you
9843
		 * are using an Ajax or JS data source for the table. This option, when set to
9844
		 * true, will cause DataTables to defer the creation of the table elements for
9845
		 * each row until they are needed for a draw - saving a significant amount of
9846
		 * time.
9847
		 *  @type boolean
9848
		 *  @default false
9849
		 *
9850
		 *  @dtopt Features
9851
		 *  @name DataTable.defaults.deferRender
9852
		 *
9853
		 *  @example
9854
		 *    $(document).ready( function() {
9855
		 *      $('#example').dataTable( {
9856
		 *        "ajax": "sources/arrays.txt",
9857
		 *        "deferRender": true
9858
		 *      } );
9859
		 *    } );
9860
		 */
9861
		"bDeferRender": false,
9862
 
9863
 
9864
		/**
9865
		 * Replace a DataTable which matches the given selector and replace it with
9866
		 * one which has the properties of the new initialisation object passed. If no
9867
		 * table matches the selector, then the new DataTable will be constructed as
9868
		 * per normal.
9869
		 *  @type boolean
9870
		 *  @default false
9871
		 *
9872
		 *  @dtopt Options
9873
		 *  @name DataTable.defaults.destroy
9874
		 *
9875
		 *  @example
9876
		 *    $(document).ready( function() {
9877
		 *      $('#example').dataTable( {
9878
		 *        "srollY": "200px",
9879
		 *        "paginate": false
9880
		 *      } );
9881
		 *
9882
		 *      // Some time later....
9883
		 *      $('#example').dataTable( {
9884
		 *        "filter": false,
9885
		 *        "destroy": true
9886
		 *      } );
9887
		 *    } );
9888
		 */
9889
		"bDestroy": false,
9890
 
9891
 
9892
		/**
9893
		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
9894
		 * that it allows the end user to input multiple words (space separated) and
9895
		 * will match a row containing those words, even if not in the order that was
9896
		 * specified (this allow matching across multiple columns). Note that if you
9897
		 * wish to use filtering in DataTables this must remain 'true' - to remove the
9898
		 * default filtering input box and retain filtering abilities, please use
9899
		 * {@link DataTable.defaults.dom}.
9900
		 *  @type boolean
9901
		 *  @default true
9902
		 *
9903
		 *  @dtopt Features
9904
		 *  @name DataTable.defaults.searching
9905
		 *
9906
		 *  @example
9907
		 *    $(document).ready( function () {
9908
		 *      $('#example').dataTable( {
9909
		 *        "searching": false
9910
		 *      } );
9911
		 *    } );
9912
		 */
9913
		"bFilter": true,
9914
 
9915
 
9916
		/**
9917
		 * Enable or disable the table information display. This shows information
9918
		 * about the data that is currently visible on the page, including information
9919
		 * about filtered data if that action is being performed.
9920
		 *  @type boolean
9921
		 *  @default true
9922
		 *
9923
		 *  @dtopt Features
9924
		 *  @name DataTable.defaults.info
9925
		 *
9926
		 *  @example
9927
		 *    $(document).ready( function () {
9928
		 *      $('#example').dataTable( {
9929
		 *        "info": false
9930
		 *      } );
9931
		 *    } );
9932
		 */
9933
		"bInfo": true,
9934
 
9935
 
9936
		/**
9937
		 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
9938
		 * slightly different and additional mark-up from what DataTables has
9939
		 * traditionally used).
9940
		 *  @type boolean
9941
		 *  @default false
9942
		 *
9943
		 *  @dtopt Features
9944
		 *  @name DataTable.defaults.jQueryUI
9945
		 *
9946
		 *  @example
9947
		 *    $(document).ready( function() {
9948
		 *      $('#example').dataTable( {
9949
		 *        "jQueryUI": true
9950
		 *      } );
9951
		 *    } );
9952
		 */
9953
		"bJQueryUI": false,
9954
 
9955
 
9956
		/**
9957
		 * Allows the end user to select the size of a formatted page from a select
9958
		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
9959
		 *  @type boolean
9960
		 *  @default true
9961
		 *
9962
		 *  @dtopt Features
9963
		 *  @name DataTable.defaults.lengthChange
9964
		 *
9965
		 *  @example
9966
		 *    $(document).ready( function () {
9967
		 *      $('#example').dataTable( {
9968
		 *        "lengthChange": false
9969
		 *      } );
9970
		 *    } );
9971
		 */
9972
		"bLengthChange": true,
9973
 
9974
 
9975
		/**
9976
		 * Enable or disable pagination.
9977
		 *  @type boolean
9978
		 *  @default true
9979
		 *
9980
		 *  @dtopt Features
9981
		 *  @name DataTable.defaults.paging
9982
		 *
9983
		 *  @example
9984
		 *    $(document).ready( function () {
9985
		 *      $('#example').dataTable( {
9986
		 *        "paging": false
9987
		 *      } );
9988
		 *    } );
9989
		 */
9990
		"bPaginate": true,
9991
 
9992
 
9993
		/**
9994
		 * Enable or disable the display of a 'processing' indicator when the table is
9995
		 * being processed (e.g. a sort). This is particularly useful for tables with
9996
		 * large amounts of data where it can take a noticeable amount of time to sort
9997
		 * the entries.
9998
		 *  @type boolean
9999
		 *  @default false
10000
		 *
10001
		 *  @dtopt Features
10002
		 *  @name DataTable.defaults.processing
10003
		 *
10004
		 *  @example
10005
		 *    $(document).ready( function () {
10006
		 *      $('#example').dataTable( {
10007
		 *        "processing": true
10008
		 *      } );
10009
		 *    } );
10010
		 */
10011
		"bProcessing": false,
10012
 
10013
 
10014
		/**
10015
		 * Retrieve the DataTables object for the given selector. Note that if the
10016
		 * table has already been initialised, this parameter will cause DataTables
10017
		 * to simply return the object that has already been set up - it will not take
10018
		 * account of any changes you might have made to the initialisation object
10019
		 * passed to DataTables (setting this parameter to true is an acknowledgement
10020
		 * that you understand this). `destroy` can be used to reinitialise a table if
10021
		 * you need.
10022
		 *  @type boolean
10023
		 *  @default false
10024
		 *
10025
		 *  @dtopt Options
10026
		 *  @name DataTable.defaults.retrieve
10027
		 *
10028
		 *  @example
10029
		 *    $(document).ready( function() {
10030
		 *      initTable();
10031
		 *      tableActions();
10032
		 *    } );
10033
		 *
10034
		 *    function initTable ()
10035
		 *    {
10036
		 *      return $('#example').dataTable( {
10037
		 *        "scrollY": "200px",
10038
		 *        "paginate": false,
10039
		 *        "retrieve": true
10040
		 *      } );
10041
		 *    }
10042
		 *
10043
		 *    function tableActions ()
10044
		 *    {
10045
		 *      var table = initTable();
10046
		 *      // perform API operations with oTable
10047
		 *    }
10048
		 */
10049
		"bRetrieve": false,
10050
 
10051
 
10052
		/**
10053
		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10054
		 * the table's viewport to the given height at all times (useful for layout).
10055
		 * However, this can look odd when filtering data down to a small data set,
10056
		 * and the footer is left "floating" further down. This parameter (when
10057
		 * enabled) will cause DataTables to collapse the table's viewport down when
10058
		 * the result set will fit within the given Y height.
10059
		 *  @type boolean
10060
		 *  @default false
10061
		 *
10062
		 *  @dtopt Options
10063
		 *  @name DataTable.defaults.scrollCollapse
10064
		 *
10065
		 *  @example
10066
		 *    $(document).ready( function() {
10067
		 *      $('#example').dataTable( {
10068
		 *        "scrollY": "200",
10069
		 *        "scrollCollapse": true
10070
		 *      } );
10071
		 *    } );
10072
		 */
10073
		"bScrollCollapse": false,
10074
 
10075
 
10076
		/**
10077
		 * Configure DataTables to use server-side processing. Note that the
10078
		 * `ajax` parameter must also be given in order to give DataTables a
10079
		 * source to obtain the required data for each draw.
10080
		 *  @type boolean
10081
		 *  @default false
10082
		 *
10083
		 *  @dtopt Features
10084
		 *  @dtopt Server-side
10085
		 *  @name DataTable.defaults.serverSide
10086
		 *
10087
		 *  @example
10088
		 *    $(document).ready( function () {
10089
		 *      $('#example').dataTable( {
10090
		 *        "serverSide": true,
10091
		 *        "ajax": "xhr.php"
10092
		 *      } );
10093
		 *    } );
10094
		 */
10095
		"bServerSide": false,
10096
 
10097
 
10098
		/**
10099
		 * Enable or disable sorting of columns. Sorting of individual columns can be
10100
		 * disabled by the `sortable` option for each column.
10101
		 *  @type boolean
10102
		 *  @default true
10103
		 *
10104
		 *  @dtopt Features
10105
		 *  @name DataTable.defaults.ordering
10106
		 *
10107
		 *  @example
10108
		 *    $(document).ready( function () {
10109
		 *      $('#example').dataTable( {
10110
		 *        "ordering": false
10111
		 *      } );
10112
		 *    } );
10113
		 */
10114
		"bSort": true,
10115
 
10116
 
10117
		/**
10118
		 * Enable or display DataTables' ability to sort multiple columns at the
10119
		 * same time (activated by shift-click by the user).
10120
		 *  @type boolean
10121
		 *  @default true
10122
		 *
10123
		 *  @dtopt Options
10124
		 *  @name DataTable.defaults.orderMulti
10125
		 *
10126
		 *  @example
10127
		 *    // Disable multiple column sorting ability
10128
		 *    $(document).ready( function () {
10129
		 *      $('#example').dataTable( {
10130
		 *        "orderMulti": false
10131
		 *      } );
10132
		 *    } );
10133
		 */
10134
		"bSortMulti": true,
10135
 
10136
 
10137
		/**
10138
		 * Allows control over whether DataTables should use the top (true) unique
10139
		 * cell that is found for a single column, or the bottom (false - default).
10140
		 * This is useful when using complex headers.
10141
		 *  @type boolean
10142
		 *  @default false
10143
		 *
10144
		 *  @dtopt Options
10145
		 *  @name DataTable.defaults.orderCellsTop
10146
		 *
10147
		 *  @example
10148
		 *    $(document).ready( function() {
10149
		 *      $('#example').dataTable( {
10150
		 *        "orderCellsTop": true
10151
		 *      } );
10152
		 *    } );
10153
		 */
10154
		"bSortCellsTop": false,
10155
 
10156
 
10157
		/**
10158
		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10159
		 * `sorting\_3` to the columns which are currently being sorted on. This is
10160
		 * presented as a feature switch as it can increase processing time (while
10161
		 * classes are removed and added) so for large data sets you might want to
10162
		 * turn this off.
10163
		 *  @type boolean
10164
		 *  @default true
10165
		 *
10166
		 *  @dtopt Features
10167
		 *  @name DataTable.defaults.orderClasses
10168
		 *
10169
		 *  @example
10170
		 *    $(document).ready( function () {
10171
		 *      $('#example').dataTable( {
10172
		 *        "orderClasses": false
10173
		 *      } );
10174
		 *    } );
10175
		 */
10176
		"bSortClasses": true,
10177
 
10178
 
10179
		/**
10180
		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10181
		 * used to save table display information such as pagination information,
10182
		 * display length, filtering and sorting. As such when the end user reloads
10183
		 * the page the display display will match what thy had previously set up.
10184
		 *
10185
		 * Due to the use of `localStorage` the default state saving is not supported
10186
		 * in IE6 or 7. If state saving is required in those browsers, use
10187
		 * `stateSaveCallback` to provide a storage solution such as cookies.
10188
		 *  @type boolean
10189
		 *  @default false
10190
		 *
10191
		 *  @dtopt Features
10192
		 *  @name DataTable.defaults.stateSave
10193
		 *
10194
		 *  @example
10195
		 *    $(document).ready( function () {
10196
		 *      $('#example').dataTable( {
10197
		 *        "stateSave": true
10198
		 *      } );
10199
		 *    } );
10200
		 */
10201
		"bStateSave": false,
10202
 
10203
 
10204
		/**
10205
		 * This function is called when a TR element is created (and all TD child
10206
		 * elements have been inserted), or registered if using a DOM source, allowing
10207
		 * manipulation of the TR element (adding classes etc).
10208
		 *  @type function
10209
		 *  @param {node} row "TR" element for the current row
10210
		 *  @param {array} data Raw data array for this row
10211
		 *  @param {int} dataIndex The index of this row in the internal aoData array
10212
		 *
10213
		 *  @dtopt Callbacks
10214
		 *  @name DataTable.defaults.createdRow
10215
		 *
10216
		 *  @example
10217
		 *    $(document).ready( function() {
10218
		 *      $('#example').dataTable( {
10219
		 *        "createdRow": function( row, data, dataIndex ) {
10220
		 *          // Bold the grade for all 'A' grade browsers
10221
		 *          if ( data[4] == "A" )
10222
		 *          {
10223
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10224
		 *          }
10225
		 *        }
10226
		 *      } );
10227
		 *    } );
10228
		 */
10229
		"fnCreatedRow": null,
10230
 
10231
 
10232
		/**
10233
		 * This function is called on every 'draw' event, and allows you to
10234
		 * dynamically modify any aspect you want about the created DOM.
10235
		 *  @type function
10236
		 *  @param {object} settings DataTables settings object
10237
		 *
10238
		 *  @dtopt Callbacks
10239
		 *  @name DataTable.defaults.drawCallback
10240
		 *
10241
		 *  @example
10242
		 *    $(document).ready( function() {
10243
		 *      $('#example').dataTable( {
10244
		 *        "drawCallback": function( settings ) {
10245
		 *          alert( 'DataTables has redrawn the table' );
10246
		 *        }
10247
		 *      } );
10248
		 *    } );
10249
		 */
10250
		"fnDrawCallback": null,
10251
 
10252
 
10253
		/**
10254
		 * Identical to fnHeaderCallback() but for the table footer this function
10255
		 * allows you to modify the table footer on every 'draw' event.
10256
		 *  @type function
10257
		 *  @param {node} foot "TR" element for the footer
10258
		 *  @param {array} data Full table data (as derived from the original HTML)
10259
		 *  @param {int} start Index for the current display starting point in the
10260
		 *    display array
10261
		 *  @param {int} end Index for the current display ending point in the
10262
		 *    display array
10263
		 *  @param {array int} display Index array to translate the visual position
10264
		 *    to the full data array
10265
		 *
10266
		 *  @dtopt Callbacks
10267
		 *  @name DataTable.defaults.footerCallback
10268
		 *
10269
		 *  @example
10270
		 *    $(document).ready( function() {
10271
		 *      $('#example').dataTable( {
10272
		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10273
		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10274
		 *        }
10275
		 *      } );
10276
		 *    } )
10277
		 */
10278
		"fnFooterCallback": null,
10279
 
10280
 
10281
		/**
10282
		 * When rendering large numbers in the information element for the table
10283
		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10284
		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10285
		 * rendered as "1,000,000") to help readability for the end user. This
10286
		 * function will override the default method DataTables uses.
10287
		 *  @type function
10288
		 *  @member
10289
		 *  @param {int} toFormat number to be formatted
10290
		 *  @returns {string} formatted string for DataTables to show the number
10291
		 *
10292
		 *  @dtopt Callbacks
10293
		 *  @name DataTable.defaults.formatNumber
10294
		 *
10295
		 *  @example
10296
		 *    // Format a number using a single quote for the separator (note that
10297
		 *    // this can also be done with the language.thousands option)
10298
		 *    $(document).ready( function() {
10299
		 *      $('#example').dataTable( {
10300
		 *        "formatNumber": function ( toFormat ) {
10301
		 *          return toFormat.toString().replace(
10302
		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10303
		 *          );
10304
		 *        };
10305
		 *      } );
10306
		 *    } );
10307
		 */
10308
		"fnFormatNumber": function ( toFormat ) {
10309
			return toFormat.toString().replace(
10310
				/\B(?=(\d{3})+(?!\d))/g,
10311
				this.oLanguage.sThousands
10312
			);
10313
		},
10314
 
10315
 
10316
		/**
10317
		 * This function is called on every 'draw' event, and allows you to
10318
		 * dynamically modify the header row. This can be used to calculate and
10319
		 * display useful information about the table.
10320
		 *  @type function
10321
		 *  @param {node} head "TR" element for the header
10322
		 *  @param {array} data Full table data (as derived from the original HTML)
10323
		 *  @param {int} start Index for the current display starting point in the
10324
		 *    display array
10325
		 *  @param {int} end Index for the current display ending point in the
10326
		 *    display array
10327
		 *  @param {array int} display Index array to translate the visual position
10328
		 *    to the full data array
10329
		 *
10330
		 *  @dtopt Callbacks
10331
		 *  @name DataTable.defaults.headerCallback
10332
		 *
10333
		 *  @example
10334
		 *    $(document).ready( function() {
10335
		 *      $('#example').dataTable( {
10336
		 *        "fheaderCallback": function( head, data, start, end, display ) {
10337
		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10338
		 *        }
10339
		 *      } );
10340
		 *    } )
10341
		 */
10342
		"fnHeaderCallback": null,
10343
 
10344
 
10345
		/**
10346
		 * The information element can be used to convey information about the current
10347
		 * state of the table. Although the internationalisation options presented by
10348
		 * DataTables are quite capable of dealing with most customisations, there may
10349
		 * be times where you wish to customise the string further. This callback
10350
		 * allows you to do exactly that.
10351
		 *  @type function
10352
		 *  @param {object} oSettings DataTables settings object
10353
		 *  @param {int} start Starting position in data for the draw
10354
		 *  @param {int} end End position in data for the draw
10355
		 *  @param {int} max Total number of rows in the table (regardless of
10356
		 *    filtering)
10357
		 *  @param {int} total Total number of rows in the data set, after filtering
10358
		 *  @param {string} pre The string that DataTables has formatted using it's
10359
		 *    own rules
10360
		 *  @returns {string} The string to be displayed in the information element.
10361
		 *
10362
		 *  @dtopt Callbacks
10363
		 *  @name DataTable.defaults.infoCallback
10364
		 *
10365
		 *  @example
10366
		 *    $('#example').dataTable( {
10367
		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10368
		 *        return start +" to "+ end;
10369
		 *      }
10370
		 *    } );
10371
		 */
10372
		"fnInfoCallback": null,
10373
 
10374
 
10375
		/**
10376
		 * Called when the table has been initialised. Normally DataTables will
10377
		 * initialise sequentially and there will be no need for this function,
10378
		 * however, this does not hold true when using external language information
10379
		 * since that is obtained using an async XHR call.
10380
		 *  @type function
10381
		 *  @param {object} settings DataTables settings object
10382
		 *  @param {object} json The JSON object request from the server - only
10383
		 *    present if client-side Ajax sourced data is used
10384
		 *
10385
		 *  @dtopt Callbacks
10386
		 *  @name DataTable.defaults.initComplete
10387
		 *
10388
		 *  @example
10389
		 *    $(document).ready( function() {
10390
		 *      $('#example').dataTable( {
10391
		 *        "initComplete": function(settings, json) {
10392
		 *          alert( 'DataTables has finished its initialisation.' );
10393
		 *        }
10394
		 *      } );
10395
		 *    } )
10396
		 */
10397
		"fnInitComplete": null,
10398
 
10399
 
10400
		/**
10401
		 * Called at the very start of each table draw and can be used to cancel the
10402
		 * draw by returning false, any other return (including undefined) results in
10403
		 * the full draw occurring).
10404
		 *  @type function
10405
		 *  @param {object} settings DataTables settings object
10406
		 *  @returns {boolean} False will cancel the draw, anything else (including no
10407
		 *    return) will allow it to complete.
10408
		 *
10409
		 *  @dtopt Callbacks
10410
		 *  @name DataTable.defaults.preDrawCallback
10411
		 *
10412
		 *  @example
10413
		 *    $(document).ready( function() {
10414
		 *      $('#example').dataTable( {
10415
		 *        "preDrawCallback": function( settings ) {
10416
		 *          if ( $('#test').val() == 1 ) {
10417
		 *            return false;
10418
		 *          }
10419
		 *        }
10420
		 *      } );
10421
		 *    } );
10422
		 */
10423
		"fnPreDrawCallback": null,
10424
 
10425
 
10426
		/**
10427
		 * This function allows you to 'post process' each row after it have been
10428
		 * generated for each table draw, but before it is rendered on screen. This
10429
		 * function might be used for setting the row class name etc.
10430
		 *  @type function
10431
		 *  @param {node} row "TR" element for the current row
10432
		 *  @param {array} data Raw data array for this row
10433
		 *  @param {int} displayIndex The display index for the current table draw
10434
		 *  @param {int} displayIndexFull The index of the data in the full list of
10435
		 *    rows (after filtering)
10436
		 *
10437
		 *  @dtopt Callbacks
10438
		 *  @name DataTable.defaults.rowCallback
10439
		 *
10440
		 *  @example
10441
		 *    $(document).ready( function() {
10442
		 *      $('#example').dataTable( {
10443
		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10444
		 *          // Bold the grade for all 'A' grade browsers
10445
		 *          if ( data[4] == "A" ) {
10446
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10447
		 *          }
10448
		 *        }
10449
		 *      } );
10450
		 *    } );
10451
		 */
10452
		"fnRowCallback": null,
10453
 
10454
 
10455
		/**
10456
		 * __Deprecated__ The functionality provided by this parameter has now been
10457
		 * superseded by that provided through `ajax`, which should be used instead.
10458
		 *
10459
		 * This parameter allows you to override the default function which obtains
10460
		 * the data from the server so something more suitable for your application.
10461
		 * For example you could use POST data, or pull information from a Gears or
10462
		 * AIR database.
10463
		 *  @type function
10464
		 *  @member
10465
		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10466
		 *  @param {array} data A key/value pair object containing the data to send
10467
		 *    to the server
10468
		 *  @param {function} callback to be called on completion of the data get
10469
		 *    process that will draw the data on the page.
10470
		 *  @param {object} settings DataTables settings object
10471
		 *
10472
		 *  @dtopt Callbacks
10473
		 *  @dtopt Server-side
10474
		 *  @name DataTable.defaults.serverData
10475
		 *
10476
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10477
		 */
10478
		"fnServerData": null,
10479
 
10480
 
10481
		/**
10482
		 * __Deprecated__ The functionality provided by this parameter has now been
10483
		 * superseded by that provided through `ajax`, which should be used instead.
10484
		 *
10485
		 *  It is often useful to send extra data to the server when making an Ajax
10486
		 * request - for example custom filtering information, and this callback
10487
		 * function makes it trivial to send extra information to the server. The
10488
		 * passed in parameter is the data set that has been constructed by
10489
		 * DataTables, and you can add to this or modify it as you require.
10490
		 *  @type function
10491
		 *  @param {array} data Data array (array of objects which are name/value
10492
		 *    pairs) that has been constructed by DataTables and will be sent to the
10493
		 *    server. In the case of Ajax sourced data with server-side processing
10494
		 *    this will be an empty array, for server-side processing there will be a
10495
		 *    significant number of parameters!
10496
		 *  @returns {undefined} Ensure that you modify the data array passed in,
10497
		 *    as this is passed by reference.
10498
		 *
10499
		 *  @dtopt Callbacks
10500
		 *  @dtopt Server-side
10501
		 *  @name DataTable.defaults.serverParams
10502
		 *
10503
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10504
		 */
10505
		"fnServerParams": null,
10506
 
10507
 
10508
		/**
10509
		 * Load the table state. With this function you can define from where, and how, the
10510
		 * state of a table is loaded. By default DataTables will load from `localStorage`
10511
		 * but you might wish to use a server-side database or cookies.
10512
		 *  @type function
10513
		 *  @member
10514
		 *  @param {object} settings DataTables settings object
10515
		 *  @return {object} The DataTables state object to be loaded
10516
		 *
10517
		 *  @dtopt Callbacks
10518
		 *  @name DataTable.defaults.stateLoadCallback
10519
		 *
10520
		 *  @example
10521
		 *    $(document).ready( function() {
10522
		 *      $('#example').dataTable( {
10523
		 *        "stateSave": true,
10524
		 *        "stateLoadCallback": function (settings) {
10525
		 *          var o;
10526
		 *
10527
		 *          // Send an Ajax request to the server to get the data. Note that
10528
		 *          // this is a synchronous request.
10529
		 *          $.ajax( {
10530
		 *            "url": "/state_load",
10531
		 *            "async": false,
10532
		 *            "dataType": "json",
10533
		 *            "success": function (json) {
10534
		 *              o = json;
10535
		 *            }
10536
		 *          } );
10537
		 *
10538
		 *          return o;
10539
		 *        }
10540
		 *      } );
10541
		 *    } );
10542
		 */
10543
		"fnStateLoadCallback": function ( settings ) {
10544
			try {
10545
				return JSON.parse(
10546
					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10547
						'DataTables_'+settings.sInstance+'_'+location.pathname
10548
					)
10549
				);
10550
			} catch (e) {}
10551
		},
10552
 
10553
 
10554
		/**
10555
		 * Callback which allows modification of the saved state prior to loading that state.
10556
		 * This callback is called when the table is loading state from the stored data, but
10557
		 * prior to the settings object being modified by the saved state. Note that for
10558
		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10559
		 * a plug-in.
10560
		 *  @type function
10561
		 *  @param {object} settings DataTables settings object
10562
		 *  @param {object} data The state object that is to be loaded
10563
		 *
10564
		 *  @dtopt Callbacks
10565
		 *  @name DataTable.defaults.stateLoadParams
10566
		 *
10567
		 *  @example
10568
		 *    // Remove a saved filter, so filtering is never loaded
10569
		 *    $(document).ready( function() {
10570
		 *      $('#example').dataTable( {
10571
		 *        "stateSave": true,
10572
		 *        "stateLoadParams": function (settings, data) {
10573
		 *          data.oSearch.sSearch = "";
10574
		 *        }
10575
		 *      } );
10576
		 *    } );
10577
		 *
10578
		 *  @example
10579
		 *    // Disallow state loading by returning false
10580
		 *    $(document).ready( function() {
10581
		 *      $('#example').dataTable( {
10582
		 *        "stateSave": true,
10583
		 *        "stateLoadParams": function (settings, data) {
10584
		 *          return false;
10585
		 *        }
10586
		 *      } );
10587
		 *    } );
10588
		 */
10589
		"fnStateLoadParams": null,
10590
 
10591
 
10592
		/**
10593
		 * Callback that is called when the state has been loaded from the state saving method
10594
		 * and the DataTables settings object has been modified as a result of the loaded state.
10595
		 *  @type function
10596
		 *  @param {object} settings DataTables settings object
10597
		 *  @param {object} data The state object that was loaded
10598
		 *
10599
		 *  @dtopt Callbacks
10600
		 *  @name DataTable.defaults.stateLoaded
10601
		 *
10602
		 *  @example
10603
		 *    // Show an alert with the filtering value that was saved
10604
		 *    $(document).ready( function() {
10605
		 *      $('#example').dataTable( {
10606
		 *        "stateSave": true,
10607
		 *        "stateLoaded": function (settings, data) {
10608
		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10609
		 *        }
10610
		 *      } );
10611
		 *    } );
10612
		 */
10613
		"fnStateLoaded": null,
10614
 
10615
 
10616
		/**
10617
		 * Save the table state. This function allows you to define where and how the state
10618
		 * information for the table is stored By default DataTables will use `localStorage`
10619
		 * but you might wish to use a server-side database or cookies.
10620
		 *  @type function
10621
		 *  @member
10622
		 *  @param {object} settings DataTables settings object
10623
		 *  @param {object} data The state object to be saved
10624
		 *
10625
		 *  @dtopt Callbacks
10626
		 *  @name DataTable.defaults.stateSaveCallback
10627
		 *
10628
		 *  @example
10629
		 *    $(document).ready( function() {
10630
		 *      $('#example').dataTable( {
10631
		 *        "stateSave": true,
10632
		 *        "stateSaveCallback": function (settings, data) {
10633
		 *          // Send an Ajax request to the server with the state object
10634
		 *          $.ajax( {
10635
		 *            "url": "/state_save",
10636
		 *            "data": data,
10637
		 *            "dataType": "json",
10638
		 *            "method": "POST"
10639
		 *            "success": function () {}
10640
		 *          } );
10641
		 *        }
10642
		 *      } );
10643
		 *    } );
10644
		 */
10645
		"fnStateSaveCallback": function ( settings, data ) {
10646
			try {
10647
				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
10648
					'DataTables_'+settings.sInstance+'_'+location.pathname,
10649
					JSON.stringify( data )
10650
				);
10651
			} catch (e) {}
10652
		},
10653
 
10654
 
10655
		/**
10656
		 * Callback which allows modification of the state to be saved. Called when the table
10657
		 * has changed state a new state save is required. This method allows modification of
10658
		 * the state saving object prior to actually doing the save, including addition or
10659
		 * other state properties or modification. Note that for plug-in authors, you should
10660
		 * use the `stateSaveParams` event to save parameters for a plug-in.
10661
		 *  @type function
10662
		 *  @param {object} settings DataTables settings object
10663
		 *  @param {object} data The state object to be saved
10664
		 *
10665
		 *  @dtopt Callbacks
10666
		 *  @name DataTable.defaults.stateSaveParams
10667
		 *
10668
		 *  @example
10669
		 *    // Remove a saved filter, so filtering is never saved
10670
		 *    $(document).ready( function() {
10671
		 *      $('#example').dataTable( {
10672
		 *        "stateSave": true,
10673
		 *        "stateSaveParams": function (settings, data) {
10674
		 *          data.oSearch.sSearch = "";
10675
		 *        }
10676
		 *      } );
10677
		 *    } );
10678
		 */
10679
		"fnStateSaveParams": null,
10680
 
10681
 
10682
		/**
10683
		 * Duration for which the saved state information is considered valid. After this period
10684
		 * has elapsed the state will be returned to the default.
10685
		 * Value is given in seconds.
10686
		 *  @type int
10687
		 *  @default 7200 <i>(2 hours)</i>
10688
		 *
10689
		 *  @dtopt Options
10690
		 *  @name DataTable.defaults.stateDuration
10691
		 *
10692
		 *  @example
10693
		 *    $(document).ready( function() {
10694
		 *      $('#example').dataTable( {
10695
		 *        "stateDuration": 60*60*24; // 1 day
10696
		 *      } );
10697
		 *    } )
10698
		 */
10699
		"iStateDuration": 7200,
10700
 
10701
 
10702
		/**
10703
		 * When enabled DataTables will not make a request to the server for the first
10704
		 * page draw - rather it will use the data already on the page (no sorting etc
10705
		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10706
		 * is used to indicate that deferred loading is required, but it is also used
10707
		 * to tell DataTables how many records there are in the full table (allowing
10708
		 * the information element and pagination to be displayed correctly). In the case
10709
		 * where a filtering is applied to the table on initial load, this can be
10710
		 * indicated by giving the parameter as an array, where the first element is
10711
		 * the number of records available after filtering and the second element is the
10712
		 * number of records without filtering (allowing the table information element
10713
		 * to be shown correctly).
10714
		 *  @type int | array
10715
		 *  @default null
10716
		 *
10717
		 *  @dtopt Options
10718
		 *  @name DataTable.defaults.deferLoading
10719
		 *
10720
		 *  @example
10721
		 *    // 57 records available in the table, no filtering applied
10722
		 *    $(document).ready( function() {
10723
		 *      $('#example').dataTable( {
10724
		 *        "serverSide": true,
10725
		 *        "ajax": "scripts/server_processing.php",
10726
		 *        "deferLoading": 57
10727
		 *      } );
10728
		 *    } );
10729
		 *
10730
		 *  @example
10731
		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
10732
		 *    $(document).ready( function() {
10733
		 *      $('#example').dataTable( {
10734
		 *        "serverSide": true,
10735
		 *        "ajax": "scripts/server_processing.php",
10736
		 *        "deferLoading": [ 57, 100 ],
10737
		 *        "search": {
10738
		 *          "search": "my_filter"
10739
		 *        }
10740
		 *      } );
10741
		 *    } );
10742
		 */
10743
		"iDeferLoading": null,
10744
 
10745
 
10746
		/**
10747
		 * Number of rows to display on a single page when using pagination. If
10748
		 * feature enabled (`lengthChange`) then the end user will be able to override
10749
		 * this to a custom setting using a pop-up menu.
10750
		 *  @type int
10751
		 *  @default 10
10752
		 *
10753
		 *  @dtopt Options
10754
		 *  @name DataTable.defaults.pageLength
10755
		 *
10756
		 *  @example
10757
		 *    $(document).ready( function() {
10758
		 *      $('#example').dataTable( {
10759
		 *        "pageLength": 50
10760
		 *      } );
10761
		 *    } )
10762
		 */
10763
		"iDisplayLength": 10,
10764
 
10765
 
10766
		/**
10767
		 * Define the starting point for data display when using DataTables with
10768
		 * pagination. Note that this parameter is the number of records, rather than
10769
		 * the page number, so if you have 10 records per page and want to start on
10770
		 * the third page, it should be "20".
10771
		 *  @type int
10772
		 *  @default 0
10773
		 *
10774
		 *  @dtopt Options
10775
		 *  @name DataTable.defaults.displayStart
10776
		 *
10777
		 *  @example
10778
		 *    $(document).ready( function() {
10779
		 *      $('#example').dataTable( {
10780
		 *        "displayStart": 20
10781
		 *      } );
10782
		 *    } )
10783
		 */
10784
		"iDisplayStart": 0,
10785
 
10786
 
10787
		/**
10788
		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
10789
		 * and filtering) by adding a `tabindex` attribute to the required elements. This
10790
		 * allows you to tab through the controls and press the enter key to activate them.
10791
		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
10792
		 * You can overrule this using this parameter if you wish. Use a value of -1 to
10793
		 * disable built-in keyboard navigation.
10794
		 *  @type int
10795
		 *  @default 0
10796
		 *
10797
		 *  @dtopt Options
10798
		 *  @name DataTable.defaults.tabIndex
10799
		 *
10800
		 *  @example
10801
		 *    $(document).ready( function() {
10802
		 *      $('#example').dataTable( {
10803
		 *        "tabIndex": 1
10804
		 *      } );
10805
		 *    } );
10806
		 */
10807
		"iTabIndex": 0,
10808
 
10809
 
10810
		/**
10811
		 * Classes that DataTables assigns to the various components and features
10812
		 * that it adds to the HTML table. This allows classes to be configured
10813
		 * during initialisation in addition to through the static
10814
		 * {@link DataTable.ext.oStdClasses} object).
10815
		 *  @namespace
10816
		 *  @name DataTable.defaults.classes
10817
		 */
10818
		"oClasses": {},
10819
 
10820
 
10821
		/**
10822
		 * All strings that DataTables uses in the user interface that it creates
10823
		 * are defined in this object, allowing you to modified them individually or
10824
		 * completely replace them all as required.
10825
		 *  @namespace
10826
		 *  @name DataTable.defaults.language
10827
		 */
10828
		"oLanguage": {
10829
			/**
10830
			 * Strings that are used for WAI-ARIA labels and controls only (these are not
10831
			 * actually visible on the page, but will be read by screenreaders, and thus
10832
			 * must be internationalised as well).
10833
			 *  @namespace
10834
			 *  @name DataTable.defaults.language.aria
10835
			 */
10836
			"oAria": {
10837
				/**
10838
				 * ARIA label that is added to the table headers when the column may be
10839
				 * sorted ascending by activing the column (click or return when focused).
10840
				 * Note that the column header is prefixed to this string.
10841
				 *  @type string
10842
				 *  @default : activate to sort column ascending
10843
				 *
10844
				 *  @dtopt Language
10845
				 *  @name DataTable.defaults.language.aria.sortAscending
10846
				 *
10847
				 *  @example
10848
				 *    $(document).ready( function() {
10849
				 *      $('#example').dataTable( {
10850
				 *        "language": {
10851
				 *          "aria": {
10852
				 *            "sortAscending": " - click/return to sort ascending"
10853
				 *          }
10854
				 *        }
10855
				 *      } );
10856
				 *    } );
10857
				 */
10858
				"sSortAscending": ": activate to sort column ascending",
10859
 
10860
				/**
10861
				 * ARIA label that is added to the table headers when the column may be
10862
				 * sorted descending by activing the column (click or return when focused).
10863
				 * Note that the column header is prefixed to this string.
10864
				 *  @type string
10865
				 *  @default : activate to sort column ascending
10866
				 *
10867
				 *  @dtopt Language
10868
				 *  @name DataTable.defaults.language.aria.sortDescending
10869
				 *
10870
				 *  @example
10871
				 *    $(document).ready( function() {
10872
				 *      $('#example').dataTable( {
10873
				 *        "language": {
10874
				 *          "aria": {
10875
				 *            "sortDescending": " - click/return to sort descending"
10876
				 *          }
10877
				 *        }
10878
				 *      } );
10879
				 *    } );
10880
				 */
10881
				"sSortDescending": ": activate to sort column descending"
10882
			},
10883
 
10884
			/**
10885
			 * Pagination string used by DataTables for the built-in pagination
10886
			 * control types.
10887
			 *  @namespace
10888
			 *  @name DataTable.defaults.language.paginate
10889
			 */
10890
			"oPaginate": {
10891
				/**
10892
				 * Text to use when using the 'full_numbers' type of pagination for the
10893
				 * button to take the user to the first page.
10894
				 *  @type string
10895
				 *  @default First
10896
				 *
10897
				 *  @dtopt Language
10898
				 *  @name DataTable.defaults.language.paginate.first
10899
				 *
10900
				 *  @example
10901
				 *    $(document).ready( function() {
10902
				 *      $('#example').dataTable( {
10903
				 *        "language": {
10904
				 *          "paginate": {
10905
				 *            "first": "First page"
10906
				 *          }
10907
				 *        }
10908
				 *      } );
10909
				 *    } );
10910
				 */
10911
				"sFirst": "First",
10912
 
10913
 
10914
				/**
10915
				 * Text to use when using the 'full_numbers' type of pagination for the
10916
				 * button to take the user to the last page.
10917
				 *  @type string
10918
				 *  @default Last
10919
				 *
10920
				 *  @dtopt Language
10921
				 *  @name DataTable.defaults.language.paginate.last
10922
				 *
10923
				 *  @example
10924
				 *    $(document).ready( function() {
10925
				 *      $('#example').dataTable( {
10926
				 *        "language": {
10927
				 *          "paginate": {
10928
				 *            "last": "Last page"
10929
				 *          }
10930
				 *        }
10931
				 *      } );
10932
				 *    } );
10933
				 */
10934
				"sLast": "Last",
10935
 
10936
 
10937
				/**
10938
				 * Text to use for the 'next' pagination button (to take the user to the
10939
				 * next page).
10940
				 *  @type string
10941
				 *  @default Next
10942
				 *
10943
				 *  @dtopt Language
10944
				 *  @name DataTable.defaults.language.paginate.next
10945
				 *
10946
				 *  @example
10947
				 *    $(document).ready( function() {
10948
				 *      $('#example').dataTable( {
10949
				 *        "language": {
10950
				 *          "paginate": {
10951
				 *            "next": "Next page"
10952
				 *          }
10953
				 *        }
10954
				 *      } );
10955
				 *    } );
10956
				 */
10957
				"sNext": "Next",
10958
 
10959
 
10960
				/**
10961
				 * Text to use for the 'previous' pagination button (to take the user to
10962
				 * the previous page).
10963
				 *  @type string
10964
				 *  @default Previous
10965
				 *
10966
				 *  @dtopt Language
10967
				 *  @name DataTable.defaults.language.paginate.previous
10968
				 *
10969
				 *  @example
10970
				 *    $(document).ready( function() {
10971
				 *      $('#example').dataTable( {
10972
				 *        "language": {
10973
				 *          "paginate": {
10974
				 *            "previous": "Previous page"
10975
				 *          }
10976
				 *        }
10977
				 *      } );
10978
				 *    } );
10979
				 */
10980
				"sPrevious": "Previous"
10981
			},
10982
 
10983
			/**
10984
			 * This string is shown in preference to `zeroRecords` when the table is
10985
			 * empty of data (regardless of filtering). Note that this is an optional
10986
			 * parameter - if it is not given, the value of `zeroRecords` will be used
10987
			 * instead (either the default or given value).
10988
			 *  @type string
10989
			 *  @default No data available in table
10990
			 *
10991
			 *  @dtopt Language
10992
			 *  @name DataTable.defaults.language.emptyTable
10993
			 *
10994
			 *  @example
10995
			 *    $(document).ready( function() {
10996
			 *      $('#example').dataTable( {
10997
			 *        "language": {
10998
			 *          "emptyTable": "No data available in table"
10999
			 *        }
11000
			 *      } );
11001
			 *    } );
11002
			 */
11003
			"sEmptyTable": "No data available in table",
11004
 
11005
 
11006
			/**
11007
			 * This string gives information to the end user about the information
11008
			 * that is current on display on the page. The following tokens can be
11009
			 * used in the string and will be dynamically replaced as the table
11010
			 * display updates. This tokens can be placed anywhere in the string, or
11011
			 * removed as needed by the language requires:
11012
			 *
11013
			 * * `\_START\_` - Display index of the first record on the current page
11014
			 * * `\_END\_` - Display index of the last record on the current page
11015
			 * * `\_TOTAL\_` - Number of records in the table after filtering
11016
			 * * `\_MAX\_` - Number of records in the table without filtering
11017
			 * * `\_PAGE\_` - Current page number
11018
			 * * `\_PAGES\_` - Total number of pages of data in the table
11019
			 *
11020
			 *  @type string
11021
			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11022
			 *
11023
			 *  @dtopt Language
11024
			 *  @name DataTable.defaults.language.info
11025
			 *
11026
			 *  @example
11027
			 *    $(document).ready( function() {
11028
			 *      $('#example').dataTable( {
11029
			 *        "language": {
11030
			 *          "info": "Showing page _PAGE_ of _PAGES_"
11031
			 *        }
11032
			 *      } );
11033
			 *    } );
11034
			 */
11035
			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11036
 
11037
 
11038
			/**
11039
			 * Display information string for when the table is empty. Typically the
11040
			 * format of this string should match `info`.
11041
			 *  @type string
11042
			 *  @default Showing 0 to 0 of 0 entries
11043
			 *
11044
			 *  @dtopt Language
11045
			 *  @name DataTable.defaults.language.infoEmpty
11046
			 *
11047
			 *  @example
11048
			 *    $(document).ready( function() {
11049
			 *      $('#example').dataTable( {
11050
			 *        "language": {
11051
			 *          "infoEmpty": "No entries to show"
11052
			 *        }
11053
			 *      } );
11054
			 *    } );
11055
			 */
11056
			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11057
 
11058
 
11059
			/**
11060
			 * When a user filters the information in a table, this string is appended
11061
			 * to the information (`info`) to give an idea of how strong the filtering
11062
			 * is. The variable _MAX_ is dynamically updated.
11063
			 *  @type string
11064
			 *  @default (filtered from _MAX_ total entries)
11065
			 *
11066
			 *  @dtopt Language
11067
			 *  @name DataTable.defaults.language.infoFiltered
11068
			 *
11069
			 *  @example
11070
			 *    $(document).ready( function() {
11071
			 *      $('#example').dataTable( {
11072
			 *        "language": {
11073
			 *          "infoFiltered": " - filtering from _MAX_ records"
11074
			 *        }
11075
			 *      } );
11076
			 *    } );
11077
			 */
11078
			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11079
 
11080
 
11081
			/**
11082
			 * If can be useful to append extra information to the info string at times,
11083
			 * and this variable does exactly that. This information will be appended to
11084
			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11085
			 * being used) at all times.
11086
			 *  @type string
11087
			 *  @default <i>Empty string</i>
11088
			 *
11089
			 *  @dtopt Language
11090
			 *  @name DataTable.defaults.language.infoPostFix
11091
			 *
11092
			 *  @example
11093
			 *    $(document).ready( function() {
11094
			 *      $('#example').dataTable( {
11095
			 *        "language": {
11096
			 *          "infoPostFix": "All records shown are derived from real information."
11097
			 *        }
11098
			 *      } );
11099
			 *    } );
11100
			 */
11101
			"sInfoPostFix": "",
11102
 
11103
 
11104
			/**
11105
			 * This decimal place operator is a little different from the other
11106
			 * language options since DataTables doesn't output floating point
11107
			 * numbers, so it won't ever use this for display of a number. Rather,
11108
			 * what this parameter does is modify the sort methods of the table so
11109
			 * that numbers which are in a format which has a character other than
11110
			 * a period (`.`) as a decimal place will be sorted numerically.
11111
			 *
11112
			 * Note that numbers with different decimal places cannot be shown in
11113
			 * the same table and still be sortable, the table must be consistent.
11114
			 * However, multiple different tables on the page can use different
11115
			 * decimal place characters.
11116
			 *  @type string
11117
			 *  @default 
11118
			 *
11119
			 *  @dtopt Language
11120
			 *  @name DataTable.defaults.language.decimal
11121
			 *
11122
			 *  @example
11123
			 *    $(document).ready( function() {
11124
			 *      $('#example').dataTable( {
11125
			 *        "language": {
11126
			 *          "decimal": ","
11127
			 *          "thousands": "."
11128
			 *        }
11129
			 *      } );
11130
			 *    } );
11131
			 */
11132
			"sDecimal": "",
11133
 
11134
 
11135
			/**
11136
			 * DataTables has a build in number formatter (`formatNumber`) which is
11137
			 * used to format large numbers that are used in the table information.
11138
			 * By default a comma is used, but this can be trivially changed to any
11139
			 * character you wish with this parameter.
11140
			 *  @type string
11141
			 *  @default ,
11142
			 *
11143
			 *  @dtopt Language
11144
			 *  @name DataTable.defaults.language.thousands
11145
			 *
11146
			 *  @example
11147
			 *    $(document).ready( function() {
11148
			 *      $('#example').dataTable( {
11149
			 *        "language": {
11150
			 *          "thousands": "'"
11151
			 *        }
11152
			 *      } );
11153
			 *    } );
11154
			 */
11155
			"sThousands": ",",
11156
 
11157
 
11158
			/**
11159
			 * Detail the action that will be taken when the drop down menu for the
11160
			 * pagination length option is changed. The '_MENU_' variable is replaced
11161
			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11162
			 * with a custom select box if required.
11163
			 *  @type string
11164
			 *  @default Show _MENU_ entries
11165
			 *
11166
			 *  @dtopt Language
11167
			 *  @name DataTable.defaults.language.lengthMenu
11168
			 *
11169
			 *  @example
11170
			 *    // Language change only
11171
			 *    $(document).ready( function() {
11172
			 *      $('#example').dataTable( {
11173
			 *        "language": {
11174
			 *          "lengthMenu": "Display _MENU_ records"
11175
			 *        }
11176
			 *      } );
11177
			 *    } );
11178
			 *
11179
			 *  @example
11180
			 *    // Language and options change
11181
			 *    $(document).ready( function() {
11182
			 *      $('#example').dataTable( {
11183
			 *        "language": {
11184
			 *          "lengthMenu": 'Display <select>'+
11185
			 *            '<option value="10">10</option>'+
11186
			 *            '<option value="20">20</option>'+
11187
			 *            '<option value="30">30</option>'+
11188
			 *            '<option value="40">40</option>'+
11189
			 *            '<option value="50">50</option>'+
11190
			 *            '<option value="-1">All</option>'+
11191
			 *            '</select> records'
11192
			 *        }
11193
			 *      } );
11194
			 *    } );
11195
			 */
11196
			"sLengthMenu": "Show _MENU_ entries",
11197
 
11198
 
11199
			/**
11200
			 * When using Ajax sourced data and during the first draw when DataTables is
11201
			 * gathering the data, this message is shown in an empty row in the table to
11202
			 * indicate to the end user the the data is being loaded. Note that this
11203
			 * parameter is not used when loading data by server-side processing, just
11204
			 * Ajax sourced data with client-side processing.
11205
			 *  @type string
11206
			 *  @default Loading...
11207
			 *
11208
			 *  @dtopt Language
11209
			 *  @name DataTable.defaults.language.loadingRecords
11210
			 *
11211
			 *  @example
11212
			 *    $(document).ready( function() {
11213
			 *      $('#example').dataTable( {
11214
			 *        "language": {
11215
			 *          "loadingRecords": "Please wait - loading..."
11216
			 *        }
11217
			 *      } );
11218
			 *    } );
11219
			 */
11220
			"sLoadingRecords": "Loading...",
11221
 
11222
 
11223
			/**
11224
			 * Text which is displayed when the table is processing a user action
11225
			 * (usually a sort command or similar).
11226
			 *  @type string
11227
			 *  @default Processing...
11228
			 *
11229
			 *  @dtopt Language
11230
			 *  @name DataTable.defaults.language.processing
11231
			 *
11232
			 *  @example
11233
			 *    $(document).ready( function() {
11234
			 *      $('#example').dataTable( {
11235
			 *        "language": {
11236
			 *          "processing": "DataTables is currently busy"
11237
			 *        }
11238
			 *      } );
11239
			 *    } );
11240
			 */
11241
			"sProcessing": "Processing...",
11242
 
11243
 
11244
			/**
11245
			 * Details the actions that will be taken when the user types into the
11246
			 * filtering input text box. The variable "_INPUT_", if used in the string,
11247
			 * is replaced with the HTML text box for the filtering input allowing
11248
			 * control over where it appears in the string. If "_INPUT_" is not given
11249
			 * then the input box is appended to the string automatically.
11250
			 *  @type string
11251
			 *  @default Search:
11252
			 *
11253
			 *  @dtopt Language
11254
			 *  @name DataTable.defaults.language.search
11255
			 *
11256
			 *  @example
11257
			 *    // Input text box will be appended at the end automatically
11258
			 *    $(document).ready( function() {
11259
			 *      $('#example').dataTable( {
11260
			 *        "language": {
11261
			 *          "search": "Filter records:"
11262
			 *        }
11263
			 *      } );
11264
			 *    } );
11265
			 *
11266
			 *  @example
11267
			 *    // Specify where the filter should appear
11268
			 *    $(document).ready( function() {
11269
			 *      $('#example').dataTable( {
11270
			 *        "language": {
11271
			 *          "search": "Apply filter _INPUT_ to table"
11272
			 *        }
11273
			 *      } );
11274
			 *    } );
11275
			 */
11276
			"sSearch": "Search:",
11277
 
11278
 
11279
			/**
11280
			 * Assign a `placeholder` attribute to the search `input` element
11281
			 *  @type string
11282
			 *  @default 
11283
			 *
11284
			 *  @dtopt Language
11285
			 *  @name DataTable.defaults.language.searchPlaceholder
11286
			 */
11287
			"sSearchPlaceholder": "",
11288
 
11289
 
11290
			/**
11291
			 * All of the language information can be stored in a file on the
11292
			 * server-side, which DataTables will look up if this parameter is passed.
11293
			 * It must store the URL of the language file, which is in a JSON format,
11294
			 * and the object has the same properties as the oLanguage object in the
11295
			 * initialiser object (i.e. the above parameters). Please refer to one of
11296
			 * the example language files to see how this works in action.
11297
			 *  @type string
11298
			 *  @default <i>Empty string - i.e. disabled</i>
11299
			 *
11300
			 *  @dtopt Language
11301
			 *  @name DataTable.defaults.language.url
11302
			 *
11303
			 *  @example
11304
			 *    $(document).ready( function() {
11305
			 *      $('#example').dataTable( {
11306
			 *        "language": {
11307
			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11308
			 *        }
11309
			 *      } );
11310
			 *    } );
11311
			 */
11312
			"sUrl": "",
11313
 
11314
 
11315
			/**
11316
			 * Text shown inside the table records when the is no information to be
11317
			 * displayed after filtering. `emptyTable` is shown when there is simply no
11318
			 * information in the table at all (regardless of filtering).
11319
			 *  @type string
11320
			 *  @default No matching records found
11321
			 *
11322
			 *  @dtopt Language
11323
			 *  @name DataTable.defaults.language.zeroRecords
11324
			 *
11325
			 *  @example
11326
			 *    $(document).ready( function() {
11327
			 *      $('#example').dataTable( {
11328
			 *        "language": {
11329
			 *          "zeroRecords": "No records to display"
11330
			 *        }
11331
			 *      } );
11332
			 *    } );
11333
			 */
11334
			"sZeroRecords": "No matching records found"
11335
		},
11336
 
11337
 
11338
		/**
11339
		 * This parameter allows you to have define the global filtering state at
11340
		 * initialisation time. As an object the `search` parameter must be
11341
		 * defined, but all other parameters are optional. When `regex` is true,
11342
		 * the search string will be treated as a regular expression, when false
11343
		 * (default) it will be treated as a straight string. When `smart`
11344
		 * DataTables will use it's smart filtering methods (to word match at
11345
		 * any point in the data), when false this will not be done.
11346
		 *  @namespace
11347
		 *  @extends DataTable.models.oSearch
11348
		 *
11349
		 *  @dtopt Options
11350
		 *  @name DataTable.defaults.search
11351
		 *
11352
		 *  @example
11353
		 *    $(document).ready( function() {
11354
		 *      $('#example').dataTable( {
11355
		 *        "search": {"search": "Initial search"}
11356
		 *      } );
11357
		 *    } )
11358
		 */
11359
		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11360
 
11361
 
11362
		/**
11363
		 * __Deprecated__ The functionality provided by this parameter has now been
11364
		 * superseded by that provided through `ajax`, which should be used instead.
11365
		 *
11366
		 * By default DataTables will look for the property `data` (or `aaData` for
11367
		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11368
		 * source or for server-side processing - this parameter allows that
11369
		 * property to be changed. You can use Javascript dotted object notation to
11370
		 * get a data source for multiple levels of nesting.
11371
		 *  @type string
11372
		 *  @default data
11373
		 *
11374
		 *  @dtopt Options
11375
		 *  @dtopt Server-side
11376
		 *  @name DataTable.defaults.ajaxDataProp
11377
		 *
11378
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11379
		 */
11380
		"sAjaxDataProp": "data",
11381
 
11382
 
11383
		/**
11384
		 * __Deprecated__ The functionality provided by this parameter has now been
11385
		 * superseded by that provided through `ajax`, which should be used instead.
11386
		 *
11387
		 * You can instruct DataTables to load data from an external
11388
		 * source using this parameter (use aData if you want to pass data in you
11389
		 * already have). Simply provide a url a JSON object can be obtained from.
11390
		 *  @type string
11391
		 *  @default null
11392
		 *
11393
		 *  @dtopt Options
11394
		 *  @dtopt Server-side
11395
		 *  @name DataTable.defaults.ajaxSource
11396
		 *
11397
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11398
		 */
11399
		"sAjaxSource": null,
11400
 
11401
 
11402
		/**
11403
		 * This initialisation variable allows you to specify exactly where in the
11404
		 * DOM you want DataTables to inject the various controls it adds to the page
11405
		 * (for example you might want the pagination controls at the top of the
11406
		 * table). DIV elements (with or without a custom class) can also be added to
11407
		 * aid styling. The follow syntax is used:
11408
		 *   <ul>
11409
		 *     <li>The following options are allowed:
11410
		 *       <ul>
11411
		 *         <li>'l' - Length changing</li>
11412
		 *         <li>'f' - Filtering input</li>
11413
		 *         <li>'t' - The table!</li>
11414
		 *         <li>'i' - Information</li>
11415
		 *         <li>'p' - Pagination</li>
11416
		 *         <li>'r' - pRocessing</li>
11417
		 *       </ul>
11418
		 *     </li>
11419
		 *     <li>The following constants are allowed:
11420
		 *       <ul>
11421
		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11422
		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11423
		 *       </ul>
11424
		 *     </li>
11425
		 *     <li>The following syntax is expected:
11426
		 *       <ul>
11427
		 *         <li>'&lt;' and '&gt;' - div elements</li>
11428
		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11429
		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11430
		 *       </ul>
11431
		 *     </li>
11432
		 *     <li>Examples:
11433
		 *       <ul>
11434
		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11435
		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11436
		 *       </ul>
11437
		 *     </li>
11438
		 *   </ul>
11439
		 *  @type string
11440
		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11441
		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11442
		 *
11443
		 *  @dtopt Options
11444
		 *  @name DataTable.defaults.dom
11445
		 *
11446
		 *  @example
11447
		 *    $(document).ready( function() {
11448
		 *      $('#example').dataTable( {
11449
		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11450
		 *      } );
11451
		 *    } );
11452
		 */
11453
		"sDom": "lfrtip",
11454
 
11455
 
11456
		/**
11457
		 * Search delay option. This will throttle full table searches that use the
11458
		 * DataTables provided search input element (it does not effect calls to
11459
		 * `dt-api search()`, providing a delay before the search is made.
11460
		 *  @type integer
11461
		 *  @default 0
11462
		 *
11463
		 *  @dtopt Options
11464
		 *  @name DataTable.defaults.searchDelay
11465
		 *
11466
		 *  @example
11467
		 *    $(document).ready( function() {
11468
		 *      $('#example').dataTable( {
11469
		 *        "searchDelay": 200
11470
		 *      } );
11471
		 *    } )
11472
		 */
11473
		"searchDelay": null,
11474
 
11475
 
11476
		/**
11477
		 * DataTables features four different built-in options for the buttons to
11478
		 * display for pagination control:
11479
		 *
11480
		 * * `simple` - 'Previous' and 'Next' buttons only
11481
		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11482
		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11483
		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11484
		 *   page numbers
11485
		 *  
11486
		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11487
		 *  @type string
11488
		 *  @default simple_numbers
11489
		 *
11490
		 *  @dtopt Options
11491
		 *  @name DataTable.defaults.pagingType
11492
		 *
11493
		 *  @example
11494
		 *    $(document).ready( function() {
11495
		 *      $('#example').dataTable( {
11496
		 *        "pagingType": "full_numbers"
11497
		 *      } );
11498
		 *    } )
11499
		 */
11500
		"sPaginationType": "simple_numbers",
11501
 
11502
 
11503
		/**
11504
		 * Enable horizontal scrolling. When a table is too wide to fit into a
11505
		 * certain layout, or you have a large number of columns in the table, you
11506
		 * can enable x-scrolling to show the table in a viewport, which can be
11507
		 * scrolled. This property can be `true` which will allow the table to
11508
		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11509
		 * case it will be treated as a pixel measurement). Setting as simply `true`
11510
		 * is recommended.
11511
		 *  @type boolean|string
11512
		 *  @default <i>blank string - i.e. disabled</i>
11513
		 *
11514
		 *  @dtopt Features
11515
		 *  @name DataTable.defaults.scrollX
11516
		 *
11517
		 *  @example
11518
		 *    $(document).ready( function() {
11519
		 *      $('#example').dataTable( {
11520
		 *        "scrollX": true,
11521
		 *        "scrollCollapse": true
11522
		 *      } );
11523
		 *    } );
11524
		 */
11525
		"sScrollX": "",
11526
 
11527
 
11528
		/**
11529
		 * This property can be used to force a DataTable to use more width than it
11530
		 * might otherwise do when x-scrolling is enabled. For example if you have a
11531
		 * table which requires to be well spaced, this parameter is useful for
11532
		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11533
		 * any CSS unit, or a number (in which case it will be treated as a pixel
11534
		 * measurement).
11535
		 *  @type string
11536
		 *  @default <i>blank string - i.e. disabled</i>
11537
		 *
11538
		 *  @dtopt Options
11539
		 *  @name DataTable.defaults.scrollXInner
11540
		 *
11541
		 *  @example
11542
		 *    $(document).ready( function() {
11543
		 *      $('#example').dataTable( {
11544
		 *        "scrollX": "100%",
11545
		 *        "scrollXInner": "110%"
11546
		 *      } );
11547
		 *    } );
11548
		 */
11549
		"sScrollXInner": "",
11550
 
11551
 
11552
		/**
11553
		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11554
		 * to the given height, and enable scrolling for any data which overflows the
11555
		 * current viewport. This can be used as an alternative to paging to display
11556
		 * a lot of data in a small area (although paging and scrolling can both be
11557
		 * enabled at the same time). This property can be any CSS unit, or a number
11558
		 * (in which case it will be treated as a pixel measurement).
11559
		 *  @type string
11560
		 *  @default <i>blank string - i.e. disabled</i>
11561
		 *
11562
		 *  @dtopt Features
11563
		 *  @name DataTable.defaults.scrollY
11564
		 *
11565
		 *  @example
11566
		 *    $(document).ready( function() {
11567
		 *      $('#example').dataTable( {
11568
		 *        "scrollY": "200px",
11569
		 *        "paginate": false
11570
		 *      } );
11571
		 *    } );
11572
		 */
11573
		"sScrollY": "",
11574
 
11575
 
11576
		/**
11577
		 * __Deprecated__ The functionality provided by this parameter has now been
11578
		 * superseded by that provided through `ajax`, which should be used instead.
11579
		 *
11580
		 * Set the HTTP method that is used to make the Ajax call for server-side
11581
		 * processing or Ajax sourced data.
11582
		 *  @type string
11583
		 *  @default GET
11584
		 *
11585
		 *  @dtopt Options
11586
		 *  @dtopt Server-side
11587
		 *  @name DataTable.defaults.serverMethod
11588
		 *
11589
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11590
		 */
11591
		"sServerMethod": "GET",
11592
 
11593
 
11594
		/**
11595
		 * DataTables makes use of renderers when displaying HTML elements for
11596
		 * a table. These renderers can be added or modified by plug-ins to
11597
		 * generate suitable mark-up for a site. For example the Bootstrap
11598
		 * integration plug-in for DataTables uses a paging button renderer to
11599
		 * display pagination buttons in the mark-up required by Bootstrap.
11600
		 *
11601
		 * For further information about the renderers available see
11602
		 * DataTable.ext.renderer
11603
		 *  @type string|object
11604
		 *  @default null
11605
		 *
11606
		 *  @name DataTable.defaults.renderer
11607
		 *
11608
		 */
11609
		"renderer": null
11610
	};
11611
 
11612
	_fnHungarianMap( DataTable.defaults );
11613
 
11614
 
11615
 
11616
	/*
11617
	 * Developer note - See note in model.defaults.js about the use of Hungarian
11618
	 * notation and camel case.
11619
	 */
11620
 
11621
	/**
11622
	 * Column options that can be given to DataTables at initialisation time.
11623
	 *  @namespace
11624
	 */
11625
	DataTable.defaults.column = {
11626
		/**
11627
		 * Define which column(s) an order will occur on for this column. This
11628
		 * allows a column's ordering to take multiple columns into account when
11629
		 * doing a sort or use the data from a different column. For example first
11630
		 * name / last name columns make sense to do a multi-column sort over the
11631
		 * two columns.
11632
		 *  @type array|int
11633
		 *  @default null <i>Takes the value of the column index automatically</i>
11634
		 *
11635
		 *  @name DataTable.defaults.column.orderData
11636
		 *  @dtopt Columns
11637
		 *
11638
		 *  @example
11639
		 *    // Using `columnDefs`
11640
		 *    $(document).ready( function() {
11641
		 *      $('#example').dataTable( {
11642
		 *        "columnDefs": [
11643
		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11644
		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11645
		 *          { "orderData": 2, "targets": [ 2 ] }
11646
		 *        ]
11647
		 *      } );
11648
		 *    } );
11649
		 *
11650
		 *  @example
11651
		 *    // Using `columns`
11652
		 *    $(document).ready( function() {
11653
		 *      $('#example').dataTable( {
11654
		 *        "columns": [
11655
		 *          { "orderData": [ 0, 1 ] },
11656
		 *          { "orderData": [ 1, 0 ] },
11657
		 *          { "orderData": 2 },
11658
		 *          null,
11659
		 *          null
11660
		 *        ]
11661
		 *      } );
11662
		 *    } );
11663
		 */
11664
		"aDataSort": null,
11665
		"iDataSort": -1,
11666
 
11667
 
11668
		/**
11669
		 * You can control the default ordering direction, and even alter the
11670
		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11671
		 * using this parameter.
11672
		 *  @type array
11673
		 *  @default [ 'asc', 'desc' ]
11674
		 *
11675
		 *  @name DataTable.defaults.column.orderSequence
11676
		 *  @dtopt Columns
11677
		 *
11678
		 *  @example
11679
		 *    // Using `columnDefs`
11680
		 *    $(document).ready( function() {
11681
		 *      $('#example').dataTable( {
11682
		 *        "columnDefs": [
11683
		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11684
		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11685
		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11686
		 *        ]
11687
		 *      } );
11688
		 *    } );
11689
		 *
11690
		 *  @example
11691
		 *    // Using `columns`
11692
		 *    $(document).ready( function() {
11693
		 *      $('#example').dataTable( {
11694
		 *        "columns": [
11695
		 *          null,
11696
		 *          { "orderSequence": [ "asc" ] },
11697
		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
11698
		 *          { "orderSequence": [ "desc" ] },
11699
		 *          null
11700
		 *        ]
11701
		 *      } );
11702
		 *    } );
11703
		 */
11704
		"asSorting": [ 'asc', 'desc' ],
11705
 
11706
 
11707
		/**
11708
		 * Enable or disable filtering on the data in this column.
11709
		 *  @type boolean
11710
		 *  @default true
11711
		 *
11712
		 *  @name DataTable.defaults.column.searchable
11713
		 *  @dtopt Columns
11714
		 *
11715
		 *  @example
11716
		 *    // Using `columnDefs`
11717
		 *    $(document).ready( function() {
11718
		 *      $('#example').dataTable( {
11719
		 *        "columnDefs": [
11720
		 *          { "searchable": false, "targets": [ 0 ] }
11721
		 *        ] } );
11722
		 *    } );
11723
		 *
11724
		 *  @example
11725
		 *    // Using `columns`
11726
		 *    $(document).ready( function() {
11727
		 *      $('#example').dataTable( {
11728
		 *        "columns": [
11729
		 *          { "searchable": false },
11730
		 *          null,
11731
		 *          null,
11732
		 *          null,
11733
		 *          null
11734
		 *        ] } );
11735
		 *    } );
11736
		 */
11737
		"bSearchable": true,
11738
 
11739
 
11740
		/**
11741
		 * Enable or disable ordering on this column.
11742
		 *  @type boolean
11743
		 *  @default true
11744
		 *
11745
		 *  @name DataTable.defaults.column.orderable
11746
		 *  @dtopt Columns
11747
		 *
11748
		 *  @example
11749
		 *    // Using `columnDefs`
11750
		 *    $(document).ready( function() {
11751
		 *      $('#example').dataTable( {
11752
		 *        "columnDefs": [
11753
		 *          { "orderable": false, "targets": [ 0 ] }
11754
		 *        ] } );
11755
		 *    } );
11756
		 *
11757
		 *  @example
11758
		 *    // Using `columns`
11759
		 *    $(document).ready( function() {
11760
		 *      $('#example').dataTable( {
11761
		 *        "columns": [
11762
		 *          { "orderable": false },
11763
		 *          null,
11764
		 *          null,
11765
		 *          null,
11766
		 *          null
11767
		 *        ] } );
11768
		 *    } );
11769
		 */
11770
		"bSortable": true,
11771
 
11772
 
11773
		/**
11774
		 * Enable or disable the display of this column.
11775
		 *  @type boolean
11776
		 *  @default true
11777
		 *
11778
		 *  @name DataTable.defaults.column.visible
11779
		 *  @dtopt Columns
11780
		 *
11781
		 *  @example
11782
		 *    // Using `columnDefs`
11783
		 *    $(document).ready( function() {
11784
		 *      $('#example').dataTable( {
11785
		 *        "columnDefs": [
11786
		 *          { "visible": false, "targets": [ 0 ] }
11787
		 *        ] } );
11788
		 *    } );
11789
		 *
11790
		 *  @example
11791
		 *    // Using `columns`
11792
		 *    $(document).ready( function() {
11793
		 *      $('#example').dataTable( {
11794
		 *        "columns": [
11795
		 *          { "visible": false },
11796
		 *          null,
11797
		 *          null,
11798
		 *          null,
11799
		 *          null
11800
		 *        ] } );
11801
		 *    } );
11802
		 */
11803
		"bVisible": true,
11804
 
11805
 
11806
		/**
11807
		 * Developer definable function that is called whenever a cell is created (Ajax source,
11808
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11809
		 * allowing you to modify the DOM element (add background colour for example) when the
11810
		 * element is available.
11811
		 *  @type function
11812
		 *  @param {element} td The TD node that has been created
11813
		 *  @param {*} cellData The Data for the cell
11814
		 *  @param {array|object} rowData The data for the whole row
11815
		 *  @param {int} row The row index for the aoData data store
11816
		 *  @param {int} col The column index for aoColumns
11817
		 *
11818
		 *  @name DataTable.defaults.column.createdCell
11819
		 *  @dtopt Columns
11820
		 *
11821
		 *  @example
11822
		 *    $(document).ready( function() {
11823
		 *      $('#example').dataTable( {
11824
		 *        "columnDefs": [ {
11825
		 *          "targets": [3],
11826
		 *          "createdCell": function (td, cellData, rowData, row, col) {
11827
		 *            if ( cellData == "1.7" ) {
11828
		 *              $(td).css('color', 'blue')
11829
		 *            }
11830
		 *          }
11831
		 *        } ]
11832
		 *      });
11833
		 *    } );
11834
		 */
11835
		"fnCreatedCell": null,
11836
 
11837
 
11838
		/**
11839
		 * This parameter has been replaced by `data` in DataTables to ensure naming
11840
		 * consistency. `dataProp` can still be used, as there is backwards
11841
		 * compatibility in DataTables for this option, but it is strongly
11842
		 * recommended that you use `data` in preference to `dataProp`.
11843
		 *  @name DataTable.defaults.column.dataProp
11844
		 */
11845
 
11846
 
11847
		/**
11848
		 * This property can be used to read data from any data source property,
11849
		 * including deeply nested objects / properties. `data` can be given in a
11850
		 * number of different ways which effect its behaviour:
11851
		 *
11852
		 * * `integer` - treated as an array index for the data source. This is the
11853
		 *   default that DataTables uses (incrementally increased for each column).
11854
		 * * `string` - read an object property from the data source. There are
11855
		 *   three 'special' options that can be used in the string to alter how
11856
		 *   DataTables reads the data from the source object:
11857
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11858
		 *      Javascript to read from nested objects, so to can the options
11859
		 *      specified in `data`. For example: `browser.version` or
11860
		 *      `browser.name`. If your object parameter name contains a period, use
11861
		 *      `\\` to escape it - i.e. `first\\.name`.
11862
		 *    * `[]` - Array notation. DataTables can automatically combine data
11863
		 *      from and array source, joining the data with the characters provided
11864
		 *      between the two brackets. For example: `name[, ]` would provide a
11865
		 *      comma-space separated list from the source array. If no characters
11866
		 *      are provided between the brackets, the original array source is
11867
		 *      returned.
11868
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
11869
		 *      execute a function of the name given. For example: `browser()` for a
11870
		 *      simple function on the data source, `browser.version()` for a
11871
		 *      function in a nested property or even `browser().version` to get an
11872
		 *      object property if the function called returns an object. Note that
11873
		 *      function notation is recommended for use in `render` rather than
11874
		 *      `data` as it is much simpler to use as a renderer.
11875
		 * * `null` - use the original data source for the row rather than plucking
11876
		 *   data directly from it. This action has effects on two other
11877
		 *   initialisation options:
11878
		 *    * `defaultContent` - When null is given as the `data` option and
11879
		 *      `defaultContent` is specified for the column, the value defined by
11880
		 *      `defaultContent` will be used for the cell.
11881
		 *    * `render` - When null is used for the `data` option and the `render`
11882
		 *      option is specified for the column, the whole data source for the
11883
		 *      row is used for the renderer.
11884
		 * * `function` - the function given will be executed whenever DataTables
11885
		 *   needs to set or get the data for a cell in the column. The function
11886
		 *   takes three parameters:
11887
		 *    * Parameters:
11888
		 *      * `{array|object}` The data source for the row
11889
		 *      * `{string}` The type call data requested - this will be 'set' when
11890
		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
11891
		 *        when gathering data. Note that when `undefined` is given for the
11892
		 *        type DataTables expects to get the raw data for the object back<
11893
		 *      * `{*}` Data to set when the second parameter is 'set'.
11894
		 *    * Return:
11895
		 *      * The return value from the function is not required when 'set' is
11896
		 *        the type of call, but otherwise the return is what will be used
11897
		 *        for the data requested.
11898
		 *
11899
		 * Note that `data` is a getter and setter option. If you just require
11900
		 * formatting of data for output, you will likely want to use `render` which
11901
		 * is simply a getter and thus simpler to use.
11902
		 *
11903
		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
11904
		 * name change reflects the flexibility of this property and is consistent
11905
		 * with the naming of mRender. If 'mDataProp' is given, then it will still
11906
		 * be used by DataTables, as it automatically maps the old name to the new
11907
		 * if required.
11908
		 *
11909
		 *  @type string|int|function|null
11910
		 *  @default null <i>Use automatically calculated column index</i>
11911
		 *
11912
		 *  @name DataTable.defaults.column.data
11913
		 *  @dtopt Columns
11914
		 *
11915
		 *  @example
11916
		 *    // Read table data from objects
11917
		 *    // JSON structure for each row:
11918
		 *    //   {
11919
		 *    //      "engine": {value},
11920
		 *    //      "browser": {value},
11921
		 *    //      "platform": {value},
11922
		 *    //      "version": {value},
11923
		 *    //      "grade": {value}
11924
		 *    //   }
11925
		 *    $(document).ready( function() {
11926
		 *      $('#example').dataTable( {
11927
		 *        "ajaxSource": "sources/objects.txt",
11928
		 *        "columns": [
11929
		 *          { "data": "engine" },
11930
		 *          { "data": "browser" },
11931
		 *          { "data": "platform" },
11932
		 *          { "data": "version" },
11933
		 *          { "data": "grade" }
11934
		 *        ]
11935
		 *      } );
11936
		 *    } );
11937
		 *
11938
		 *  @example
11939
		 *    // Read information from deeply nested objects
11940
		 *    // JSON structure for each row:
11941
		 *    //   {
11942
		 *    //      "engine": {value},
11943
		 *    //      "browser": {value},
11944
		 *    //      "platform": {
11945
		 *    //         "inner": {value}
11946
		 *    //      },
11947
		 *    //      "details": [
11948
		 *    //         {value}, {value}
11949
		 *    //      ]
11950
		 *    //   }
11951
		 *    $(document).ready( function() {
11952
		 *      $('#example').dataTable( {
11953
		 *        "ajaxSource": "sources/deep.txt",
11954
		 *        "columns": [
11955
		 *          { "data": "engine" },
11956
		 *          { "data": "browser" },
11957
		 *          { "data": "platform.inner" },
11958
		 *          { "data": "platform.details.0" },
11959
		 *          { "data": "platform.details.1" }
11960
		 *        ]
11961
		 *      } );
11962
		 *    } );
11963
		 *
11964
		 *  @example
11965
		 *    // Using `data` as a function to provide different information for
11966
		 *    // sorting, filtering and display. In this case, currency (price)
11967
		 *    $(document).ready( function() {
11968
		 *      $('#example').dataTable( {
11969
		 *        "columnDefs": [ {
11970
		 *          "targets": [ 0 ],
11971
		 *          "data": function ( source, type, val ) {
11972
		 *            if (type === 'set') {
11973
		 *              source.price = val;
11974
		 *              // Store the computed dislay and filter values for efficiency
11975
		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
11976
		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
11977
		 *              return;
11978
		 *            }
11979
		 *            else if (type === 'display') {
11980
		 *              return source.price_display;
11981
		 *            }
11982
		 *            else if (type === 'filter') {
11983
		 *              return source.price_filter;
11984
		 *            }
11985
		 *            // 'sort', 'type' and undefined all just use the integer
11986
		 *            return source.price;
11987
		 *          }
11988
		 *        } ]
11989
		 *      } );
11990
		 *    } );
11991
		 *
11992
		 *  @example
11993
		 *    // Using default content
11994
		 *    $(document).ready( function() {
11995
		 *      $('#example').dataTable( {
11996
		 *        "columnDefs": [ {
11997
		 *          "targets": [ 0 ],
11998
		 *          "data": null,
11999
		 *          "defaultContent": "Click to edit"
12000
		 *        } ]
12001
		 *      } );
12002
		 *    } );
12003
		 *
12004
		 *  @example
12005
		 *    // Using array notation - outputting a list from an array
12006
		 *    $(document).ready( function() {
12007
		 *      $('#example').dataTable( {
12008
		 *        "columnDefs": [ {
12009
		 *          "targets": [ 0 ],
12010
		 *          "data": "name[, ]"
12011
		 *        } ]
12012
		 *      } );
12013
		 *    } );
12014
		 *
12015
		 */
12016
		"mData": null,
12017
 
12018
 
12019
		/**
12020
		 * This property is the rendering partner to `data` and it is suggested that
12021
		 * when you want to manipulate data for display (including filtering,
12022
		 * sorting etc) without altering the underlying data for the table, use this
12023
		 * property. `render` can be considered to be the the read only companion to
12024
		 * `data` which is read / write (then as such more complex). Like `data`
12025
		 * this option can be given in a number of different ways to effect its
12026
		 * behaviour:
12027
		 *
12028
		 * * `integer` - treated as an array index for the data source. This is the
12029
		 *   default that DataTables uses (incrementally increased for each column).
12030
		 * * `string` - read an object property from the data source. There are
12031
		 *   three 'special' options that can be used in the string to alter how
12032
		 *   DataTables reads the data from the source object:
12033
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12034
		 *      Javascript to read from nested objects, so to can the options
12035
		 *      specified in `data`. For example: `browser.version` or
12036
		 *      `browser.name`. If your object parameter name contains a period, use
12037
		 *      `\\` to escape it - i.e. `first\\.name`.
12038
		 *    * `[]` - Array notation. DataTables can automatically combine data
12039
		 *      from and array source, joining the data with the characters provided
12040
		 *      between the two brackets. For example: `name[, ]` would provide a
12041
		 *      comma-space separated list from the source array. If no characters
12042
		 *      are provided between the brackets, the original array source is
12043
		 *      returned.
12044
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12045
		 *      execute a function of the name given. For example: `browser()` for a
12046
		 *      simple function on the data source, `browser.version()` for a
12047
		 *      function in a nested property or even `browser().version` to get an
12048
		 *      object property if the function called returns an object.
12049
		 * * `object` - use different data for the different data types requested by
12050
		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12051
		 *   of the object is the data type the property refers to and the value can
12052
		 *   defined using an integer, string or function using the same rules as
12053
		 *   `render` normally does. Note that an `_` option _must_ be specified.
12054
		 *   This is the default value to use if you haven't specified a value for
12055
		 *   the data type requested by DataTables.
12056
		 * * `function` - the function given will be executed whenever DataTables
12057
		 *   needs to set or get the data for a cell in the column. The function
12058
		 *   takes three parameters:
12059
		 *    * Parameters:
12060
		 *      * {array|object} The data source for the row (based on `data`)
12061
		 *      * {string} The type call data requested - this will be 'filter',
12062
		 *        'display', 'type' or 'sort'.
12063
		 *      * {array|object} The full data source for the row (not based on
12064
		 *        `data`)
12065
		 *    * Return:
12066
		 *      * The return value from the function is what will be used for the
12067
		 *        data requested.
12068
		 *
12069
		 *  @type string|int|function|object|null
12070
		 *  @default null Use the data source value.
12071
		 *
12072
		 *  @name DataTable.defaults.column.render
12073
		 *  @dtopt Columns
12074
		 *
12075
		 *  @example
12076
		 *    // Create a comma separated list from an array of objects
12077
		 *    $(document).ready( function() {
12078
		 *      $('#example').dataTable( {
12079
		 *        "ajaxSource": "sources/deep.txt",
12080
		 *        "columns": [
12081
		 *          { "data": "engine" },
12082
		 *          { "data": "browser" },
12083
		 *          {
12084
		 *            "data": "platform",
12085
		 *            "render": "[, ].name"
12086
		 *          }
12087
		 *        ]
12088
		 *      } );
12089
		 *    } );
12090
		 *
12091
		 *  @example
12092
		 *    // Execute a function to obtain data
12093
		 *    $(document).ready( function() {
12094
		 *      $('#example').dataTable( {
12095
		 *        "columnDefs": [ {
12096
		 *          "targets": [ 0 ],
12097
		 *          "data": null, // Use the full data source object for the renderer's source
12098
		 *          "render": "browserName()"
12099
		 *        } ]
12100
		 *      } );
12101
		 *    } );
12102
		 *
12103
		 *  @example
12104
		 *    // As an object, extracting different data for the different types
12105
		 *    // This would be used with a data source such as:
12106
		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12107
		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12108
		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12109
		 *    // the formatted phone number is the one that is shown in the table.
12110
		 *    $(document).ready( function() {
12111
		 *      $('#example').dataTable( {
12112
		 *        "columnDefs": [ {
12113
		 *          "targets": [ 0 ],
12114
		 *          "data": null, // Use the full data source object for the renderer's source
12115
		 *          "render": {
12116
		 *            "_": "phone",
12117
		 *            "filter": "phone_filter",
12118
		 *            "display": "phone_display"
12119
		 *          }
12120
		 *        } ]
12121
		 *      } );
12122
		 *    } );
12123
		 *
12124
		 *  @example
12125
		 *    // Use as a function to create a link from the data source
12126
		 *    $(document).ready( function() {
12127
		 *      $('#example').dataTable( {
12128
		 *        "columnDefs": [ {
12129
		 *          "targets": [ 0 ],
12130
		 *          "data": "download_link",
12131
		 *          "render": function ( data, type, full ) {
12132
		 *            return '<a href="'+data+'">Download</a>';
12133
		 *          }
12134
		 *        } ]
12135
		 *      } );
12136
		 *    } );
12137
		 */
12138
		"mRender": null,
12139
 
12140
 
12141
		/**
12142
		 * Change the cell type created for the column - either TD cells or TH cells. This
12143
		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12144
		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12145
		 *  @type string
12146
		 *  @default td
12147
		 *
12148
		 *  @name DataTable.defaults.column.cellType
12149
		 *  @dtopt Columns
12150
		 *
12151
		 *  @example
12152
		 *    // Make the first column use TH cells
12153
		 *    $(document).ready( function() {
12154
		 *      $('#example').dataTable( {
12155
		 *        "columnDefs": [ {
12156
		 *          "targets": [ 0 ],
12157
		 *          "cellType": "th"
12158
		 *        } ]
12159
		 *      } );
12160
		 *    } );
12161
		 */
12162
		"sCellType": "td",
12163
 
12164
 
12165
		/**
12166
		 * Class to give to each cell in this column.
12167
		 *  @type string
12168
		 *  @default <i>Empty string</i>
12169
		 *
12170
		 *  @name DataTable.defaults.column.class
12171
		 *  @dtopt Columns
12172
		 *
12173
		 *  @example
12174
		 *    // Using `columnDefs`
12175
		 *    $(document).ready( function() {
12176
		 *      $('#example').dataTable( {
12177
		 *        "columnDefs": [
12178
		 *          { "class": "my_class", "targets": [ 0 ] }
12179
		 *        ]
12180
		 *      } );
12181
		 *    } );
12182
		 *
12183
		 *  @example
12184
		 *    // Using `columns`
12185
		 *    $(document).ready( function() {
12186
		 *      $('#example').dataTable( {
12187
		 *        "columns": [
12188
		 *          { "class": "my_class" },
12189
		 *          null,
12190
		 *          null,
12191
		 *          null,
12192
		 *          null
12193
		 *        ]
12194
		 *      } );
12195
		 *    } );
12196
		 */
12197
		"sClass": "",
12198
 
12199
		/**
12200
		 * When DataTables calculates the column widths to assign to each column,
12201
		 * it finds the longest string in each column and then constructs a
12202
		 * temporary table and reads the widths from that. The problem with this
12203
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12204
		 * string - thus the calculation can go wrong (doing it properly and putting
12205
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12206
		 * a "work around" we provide this option. It will append its value to the
12207
		 * text that is found to be the longest string for the column - i.e. padding.
12208
		 * Generally you shouldn't need this!
12209
		 *  @type string
12210
		 *  @default <i>Empty string<i>
12211
		 *
12212
		 *  @name DataTable.defaults.column.contentPadding
12213
		 *  @dtopt Columns
12214
		 *
12215
		 *  @example
12216
		 *    // Using `columns`
12217
		 *    $(document).ready( function() {
12218
		 *      $('#example').dataTable( {
12219
		 *        "columns": [
12220
		 *          null,
12221
		 *          null,
12222
		 *          null,
12223
		 *          {
12224
		 *            "contentPadding": "mmm"
12225
		 *          }
12226
		 *        ]
12227
		 *      } );
12228
		 *    } );
12229
		 */
12230
		"sContentPadding": "",
12231
 
12232
 
12233
		/**
12234
		 * Allows a default value to be given for a column's data, and will be used
12235
		 * whenever a null data source is encountered (this can be because `data`
12236
		 * is set to null, or because the data source itself is null).
12237
		 *  @type string
12238
		 *  @default null
12239
		 *
12240
		 *  @name DataTable.defaults.column.defaultContent
12241
		 *  @dtopt Columns
12242
		 *
12243
		 *  @example
12244
		 *    // Using `columnDefs`
12245
		 *    $(document).ready( function() {
12246
		 *      $('#example').dataTable( {
12247
		 *        "columnDefs": [
12248
		 *          {
12249
		 *            "data": null,
12250
		 *            "defaultContent": "Edit",
12251
		 *            "targets": [ -1 ]
12252
		 *          }
12253
		 *        ]
12254
		 *      } );
12255
		 *    } );
12256
		 *
12257
		 *  @example
12258
		 *    // Using `columns`
12259
		 *    $(document).ready( function() {
12260
		 *      $('#example').dataTable( {
12261
		 *        "columns": [
12262
		 *          null,
12263
		 *          null,
12264
		 *          null,
12265
		 *          {
12266
		 *            "data": null,
12267
		 *            "defaultContent": "Edit"
12268
		 *          }
12269
		 *        ]
12270
		 *      } );
12271
		 *    } );
12272
		 */
12273
		"sDefaultContent": null,
12274
 
12275
 
12276
		/**
12277
		 * This parameter is only used in DataTables' server-side processing. It can
12278
		 * be exceptionally useful to know what columns are being displayed on the
12279
		 * client side, and to map these to database fields. When defined, the names
12280
		 * also allow DataTables to reorder information from the server if it comes
12281
		 * back in an unexpected order (i.e. if you switch your columns around on the
12282
		 * client-side, your server-side code does not also need updating).
12283
		 *  @type string
12284
		 *  @default <i>Empty string</i>
12285
		 *
12286
		 *  @name DataTable.defaults.column.name
12287
		 *  @dtopt Columns
12288
		 *
12289
		 *  @example
12290
		 *    // Using `columnDefs`
12291
		 *    $(document).ready( function() {
12292
		 *      $('#example').dataTable( {
12293
		 *        "columnDefs": [
12294
		 *          { "name": "engine", "targets": [ 0 ] },
12295
		 *          { "name": "browser", "targets": [ 1 ] },
12296
		 *          { "name": "platform", "targets": [ 2 ] },
12297
		 *          { "name": "version", "targets": [ 3 ] },
12298
		 *          { "name": "grade", "targets": [ 4 ] }
12299
		 *        ]
12300
		 *      } );
12301
		 *    } );
12302
		 *
12303
		 *  @example
12304
		 *    // Using `columns`
12305
		 *    $(document).ready( function() {
12306
		 *      $('#example').dataTable( {
12307
		 *        "columns": [
12308
		 *          { "name": "engine" },
12309
		 *          { "name": "browser" },
12310
		 *          { "name": "platform" },
12311
		 *          { "name": "version" },
12312
		 *          { "name": "grade" }
12313
		 *        ]
12314
		 *      } );
12315
		 *    } );
12316
		 */
12317
		"sName": "",
12318
 
12319
 
12320
		/**
12321
		 * Defines a data source type for the ordering which can be used to read
12322
		 * real-time information from the table (updating the internally cached
12323
		 * version) prior to ordering. This allows ordering to occur on user
12324
		 * editable elements such as form inputs.
12325
		 *  @type string
12326
		 *  @default std
12327
		 *
12328
		 *  @name DataTable.defaults.column.orderDataType
12329
		 *  @dtopt Columns
12330
		 *
12331
		 *  @example
12332
		 *    // Using `columnDefs`
12333
		 *    $(document).ready( function() {
12334
		 *      $('#example').dataTable( {
12335
		 *        "columnDefs": [
12336
		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12337
		 *          { "type": "numeric", "targets": [ 3 ] },
12338
		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12339
		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12340
		 *        ]
12341
		 *      } );
12342
		 *    } );
12343
		 *
12344
		 *  @example
12345
		 *    // Using `columns`
12346
		 *    $(document).ready( function() {
12347
		 *      $('#example').dataTable( {
12348
		 *        "columns": [
12349
		 *          null,
12350
		 *          null,
12351
		 *          { "orderDataType": "dom-text" },
12352
		 *          { "orderDataType": "dom-text", "type": "numeric" },
12353
		 *          { "orderDataType": "dom-select" },
12354
		 *          { "orderDataType": "dom-checkbox" }
12355
		 *        ]
12356
		 *      } );
12357
		 *    } );
12358
		 */
12359
		"sSortDataType": "std",
12360
 
12361
 
12362
		/**
12363
		 * The title of this column.
12364
		 *  @type string
12365
		 *  @default null <i>Derived from the 'TH' value for this column in the
12366
		 *    original HTML table.</i>
12367
		 *
12368
		 *  @name DataTable.defaults.column.title
12369
		 *  @dtopt Columns
12370
		 *
12371
		 *  @example
12372
		 *    // Using `columnDefs`
12373
		 *    $(document).ready( function() {
12374
		 *      $('#example').dataTable( {
12375
		 *        "columnDefs": [
12376
		 *          { "title": "My column title", "targets": [ 0 ] }
12377
		 *        ]
12378
		 *      } );
12379
		 *    } );
12380
		 *
12381
		 *  @example
12382
		 *    // Using `columns`
12383
		 *    $(document).ready( function() {
12384
		 *      $('#example').dataTable( {
12385
		 *        "columns": [
12386
		 *          { "title": "My column title" },
12387
		 *          null,
12388
		 *          null,
12389
		 *          null,
12390
		 *          null
12391
		 *        ]
12392
		 *      } );
12393
		 *    } );
12394
		 */
12395
		"sTitle": null,
12396
 
12397
 
12398
		/**
12399
		 * The type allows you to specify how the data for this column will be
12400
		 * ordered. Four types (string, numeric, date and html (which will strip
12401
		 * HTML tags before ordering)) are currently available. Note that only date
12402
		 * formats understood by Javascript's Date() object will be accepted as type
12403
		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12404
		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12405
		 * through plug-ins.
12406
		 *  @type string
12407
		 *  @default null <i>Auto-detected from raw data</i>
12408
		 *
12409
		 *  @name DataTable.defaults.column.type
12410
		 *  @dtopt Columns
12411
		 *
12412
		 *  @example
12413
		 *    // Using `columnDefs`
12414
		 *    $(document).ready( function() {
12415
		 *      $('#example').dataTable( {
12416
		 *        "columnDefs": [
12417
		 *          { "type": "html", "targets": [ 0 ] }
12418
		 *        ]
12419
		 *      } );
12420
		 *    } );
12421
		 *
12422
		 *  @example
12423
		 *    // Using `columns`
12424
		 *    $(document).ready( function() {
12425
		 *      $('#example').dataTable( {
12426
		 *        "columns": [
12427
		 *          { "type": "html" },
12428
		 *          null,
12429
		 *          null,
12430
		 *          null,
12431
		 *          null
12432
		 *        ]
12433
		 *      } );
12434
		 *    } );
12435
		 */
12436
		"sType": null,
12437
 
12438
 
12439
		/**
12440
		 * Defining the width of the column, this parameter may take any CSS value
12441
		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12442
		 * been given a specific width through this interface ensuring that the table
12443
		 * remains readable.
12444
		 *  @type string
12445
		 *  @default null <i>Automatic</i>
12446
		 *
12447
		 *  @name DataTable.defaults.column.width
12448
		 *  @dtopt Columns
12449
		 *
12450
		 *  @example
12451
		 *    // Using `columnDefs`
12452
		 *    $(document).ready( function() {
12453
		 *      $('#example').dataTable( {
12454
		 *        "columnDefs": [
12455
		 *          { "width": "20%", "targets": [ 0 ] }
12456
		 *        ]
12457
		 *      } );
12458
		 *    } );
12459
		 *
12460
		 *  @example
12461
		 *    // Using `columns`
12462
		 *    $(document).ready( function() {
12463
		 *      $('#example').dataTable( {
12464
		 *        "columns": [
12465
		 *          { "width": "20%" },
12466
		 *          null,
12467
		 *          null,
12468
		 *          null,
12469
		 *          null
12470
		 *        ]
12471
		 *      } );
12472
		 *    } );
12473
		 */
12474
		"sWidth": null
12475
	};
12476
 
12477
	_fnHungarianMap( DataTable.defaults.column );
12478
 
12479
 
12480
 
12481
	/**
12482
	 * DataTables settings object - this holds all the information needed for a
12483
	 * given table, including configuration, data and current application of the
12484
	 * table options. DataTables does not have a single instance for each DataTable
12485
	 * with the settings attached to that instance, but rather instances of the
12486
	 * DataTable "class" are created on-the-fly as needed (typically by a
12487
	 * $().dataTable() call) and the settings object is then applied to that
12488
	 * instance.
12489
	 *
12490
	 * Note that this object is related to {@link DataTable.defaults} but this
12491
	 * one is the internal data store for DataTables's cache of columns. It should
12492
	 * NOT be manipulated outside of DataTables. Any configuration should be done
12493
	 * through the initialisation options.
12494
	 *  @namespace
12495
	 *  @todo Really should attach the settings object to individual instances so we
12496
	 *    don't need to create new instances on each $().dataTable() call (if the
12497
	 *    table already exists). It would also save passing oSettings around and
12498
	 *    into every single function. However, this is a very significant
12499
	 *    architecture change for DataTables and will almost certainly break
12500
	 *    backwards compatibility with older installations. This is something that
12501
	 *    will be done in 2.0.
12502
	 */
12503
	DataTable.models.oSettings = {
12504
		/**
12505
		 * Primary features of DataTables and their enablement state.
12506
		 *  @namespace
12507
		 */
12508
		"oFeatures": {
12509
 
12510
			/**
12511
			 * Flag to say if DataTables should automatically try to calculate the
12512
			 * optimum table and columns widths (true) or not (false).
12513
			 * Note that this parameter will be set by the initialisation routine. To
12514
			 * set a default use {@link DataTable.defaults}.
12515
			 *  @type boolean
12516
			 */
12517
			"bAutoWidth": null,
12518
 
12519
			/**
12520
			 * Delay the creation of TR and TD elements until they are actually
12521
			 * needed by a driven page draw. This can give a significant speed
12522
			 * increase for Ajax source and Javascript source data, but makes no
12523
			 * difference at all fro DOM and server-side processing tables.
12524
			 * Note that this parameter will be set by the initialisation routine. To
12525
			 * set a default use {@link DataTable.defaults}.
12526
			 *  @type boolean
12527
			 */
12528
			"bDeferRender": null,
12529
 
12530
			/**
12531
			 * Enable filtering on the table or not. Note that if this is disabled
12532
			 * then there is no filtering at all on the table, including fnFilter.
12533
			 * To just remove the filtering input use sDom and remove the 'f' option.
12534
			 * Note that this parameter will be set by the initialisation routine. To
12535
			 * set a default use {@link DataTable.defaults}.
12536
			 *  @type boolean
12537
			 */
12538
			"bFilter": null,
12539
 
12540
			/**
12541
			 * Table information element (the 'Showing x of y records' div) enable
12542
			 * flag.
12543
			 * Note that this parameter will be set by the initialisation routine. To
12544
			 * set a default use {@link DataTable.defaults}.
12545
			 *  @type boolean
12546
			 */
12547
			"bInfo": null,
12548
 
12549
			/**
12550
			 * Present a user control allowing the end user to change the page size
12551
			 * when pagination is enabled.
12552
			 * Note that this parameter will be set by the initialisation routine. To
12553
			 * set a default use {@link DataTable.defaults}.
12554
			 *  @type boolean
12555
			 */
12556
			"bLengthChange": null,
12557
 
12558
			/**
12559
			 * Pagination enabled or not. Note that if this is disabled then length
12560
			 * changing must also be disabled.
12561
			 * Note that this parameter will be set by the initialisation routine. To
12562
			 * set a default use {@link DataTable.defaults}.
12563
			 *  @type boolean
12564
			 */
12565
			"bPaginate": null,
12566
 
12567
			/**
12568
			 * Processing indicator enable flag whenever DataTables is enacting a
12569
			 * user request - typically an Ajax request for server-side processing.
12570
			 * Note that this parameter will be set by the initialisation routine. To
12571
			 * set a default use {@link DataTable.defaults}.
12572
			 *  @type boolean
12573
			 */
12574
			"bProcessing": null,
12575
 
12576
			/**
12577
			 * Server-side processing enabled flag - when enabled DataTables will
12578
			 * get all data from the server for every draw - there is no filtering,
12579
			 * sorting or paging done on the client-side.
12580
			 * Note that this parameter will be set by the initialisation routine. To
12581
			 * set a default use {@link DataTable.defaults}.
12582
			 *  @type boolean
12583
			 */
12584
			"bServerSide": null,
12585
 
12586
			/**
12587
			 * Sorting enablement flag.
12588
			 * Note that this parameter will be set by the initialisation routine. To
12589
			 * set a default use {@link DataTable.defaults}.
12590
			 *  @type boolean
12591
			 */
12592
			"bSort": null,
12593
 
12594
			/**
12595
			 * Multi-column sorting
12596
			 * Note that this parameter will be set by the initialisation routine. To
12597
			 * set a default use {@link DataTable.defaults}.
12598
			 *  @type boolean
12599
			 */
12600
			"bSortMulti": null,
12601
 
12602
			/**
12603
			 * Apply a class to the columns which are being sorted to provide a
12604
			 * visual highlight or not. This can slow things down when enabled since
12605
			 * there is a lot of DOM interaction.
12606
			 * Note that this parameter will be set by the initialisation routine. To
12607
			 * set a default use {@link DataTable.defaults}.
12608
			 *  @type boolean
12609
			 */
12610
			"bSortClasses": null,
12611
 
12612
			/**
12613
			 * State saving enablement flag.
12614
			 * Note that this parameter will be set by the initialisation routine. To
12615
			 * set a default use {@link DataTable.defaults}.
12616
			 *  @type boolean
12617
			 */
12618
			"bStateSave": null
12619
		},
12620
 
12621
 
12622
		/**
12623
		 * Scrolling settings for a table.
12624
		 *  @namespace
12625
		 */
12626
		"oScroll": {
12627
			/**
12628
			 * When the table is shorter in height than sScrollY, collapse the
12629
			 * table container down to the height of the table (when true).
12630
			 * Note that this parameter will be set by the initialisation routine. To
12631
			 * set a default use {@link DataTable.defaults}.
12632
			 *  @type boolean
12633
			 */
12634
			"bCollapse": null,
12635
 
12636
			/**
12637
			 * Width of the scrollbar for the web-browser's platform. Calculated
12638
			 * during table initialisation.
12639
			 *  @type int
12640
			 *  @default 0
12641
			 */
12642
			"iBarWidth": 0,
12643
 
12644
			/**
12645
			 * Viewport width for horizontal scrolling. Horizontal scrolling is
12646
			 * disabled if an empty string.
12647
			 * Note that this parameter will be set by the initialisation routine. To
12648
			 * set a default use {@link DataTable.defaults}.
12649
			 *  @type string
12650
			 */
12651
			"sX": null,
12652
 
12653
			/**
12654
			 * Width to expand the table to when using x-scrolling. Typically you
12655
			 * should not need to use this.
12656
			 * Note that this parameter will be set by the initialisation routine. To
12657
			 * set a default use {@link DataTable.defaults}.
12658
			 *  @type string
12659
			 *  @deprecated
12660
			 */
12661
			"sXInner": null,
12662
 
12663
			/**
12664
			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
12665
			 * if an empty string.
12666
			 * Note that this parameter will be set by the initialisation routine. To
12667
			 * set a default use {@link DataTable.defaults}.
12668
			 *  @type string
12669
			 */
12670
			"sY": null
12671
		},
12672
 
12673
		/**
12674
		 * Language information for the table.
12675
		 *  @namespace
12676
		 *  @extends DataTable.defaults.oLanguage
12677
		 */
12678
		"oLanguage": {
12679
			/**
12680
			 * Information callback function. See
12681
			 * {@link DataTable.defaults.fnInfoCallback}
12682
			 *  @type function
12683
			 *  @default null
12684
			 */
12685
			"fnInfoCallback": null
12686
		},
12687
 
12688
		/**
12689
		 * Browser support parameters
12690
		 *  @namespace
12691
		 */
12692
		"oBrowser": {
12693
			/**
12694
			 * Indicate if the browser incorrectly calculates width:100% inside a
12695
			 * scrolling element (IE6/7)
12696
			 *  @type boolean
12697
			 *  @default false
12698
			 */
12699
			"bScrollOversize": false,
12700
 
12701
			/**
12702
			 * Determine if the vertical scrollbar is on the right or left of the
12703
			 * scrolling container - needed for rtl language layout, although not
12704
			 * all browsers move the scrollbar (Safari).
12705
			 *  @type boolean
12706
			 *  @default false
12707
			 */
12708
			"bScrollbarLeft": false
12709
		},
12710
 
12711
 
12712
		"ajax": null,
12713
 
12714
 
12715
		/**
12716
		 * Array referencing the nodes which are used for the features. The
12717
		 * parameters of this object match what is allowed by sDom - i.e.
12718
		 *   <ul>
12719
		 *     <li>'l' - Length changing</li>
12720
		 *     <li>'f' - Filtering input</li>
12721
		 *     <li>'t' - The table!</li>
12722
		 *     <li>'i' - Information</li>
12723
		 *     <li>'p' - Pagination</li>
12724
		 *     <li>'r' - pRocessing</li>
12725
		 *   </ul>
12726
		 *  @type array
12727
		 *  @default []
12728
		 */
12729
		"aanFeatures": [],
12730
 
12731
		/**
12732
		 * Store data information - see {@link DataTable.models.oRow} for detailed
12733
		 * information.
12734
		 *  @type array
12735
		 *  @default []
12736
		 */
12737
		"aoData": [],
12738
 
12739
		/**
12740
		 * Array of indexes which are in the current display (after filtering etc)
12741
		 *  @type array
12742
		 *  @default []
12743
		 */
12744
		"aiDisplay": [],
12745
 
12746
		/**
12747
		 * Array of indexes for display - no filtering
12748
		 *  @type array
12749
		 *  @default []
12750
		 */
12751
		"aiDisplayMaster": [],
12752
 
12753
		/**
12754
		 * Store information about each column that is in use
12755
		 *  @type array
12756
		 *  @default []
12757
		 */
12758
		"aoColumns": [],
12759
 
12760
		/**
12761
		 * Store information about the table's header
12762
		 *  @type array
12763
		 *  @default []
12764
		 */
12765
		"aoHeader": [],
12766
 
12767
		/**
12768
		 * Store information about the table's footer
12769
		 *  @type array
12770
		 *  @default []
12771
		 */
12772
		"aoFooter": [],
12773
 
12774
		/**
12775
		 * Store the applied global search information in case we want to force a
12776
		 * research or compare the old search to a new one.
12777
		 * Note that this parameter will be set by the initialisation routine. To
12778
		 * set a default use {@link DataTable.defaults}.
12779
		 *  @namespace
12780
		 *  @extends DataTable.models.oSearch
12781
		 */
12782
		"oPreviousSearch": {},
12783
 
12784
		/**
12785
		 * Store the applied search for each column - see
12786
		 * {@link DataTable.models.oSearch} for the format that is used for the
12787
		 * filtering information for each column.
12788
		 *  @type array
12789
		 *  @default []
12790
		 */
12791
		"aoPreSearchCols": [],
12792
 
12793
		/**
12794
		 * Sorting that is applied to the table. Note that the inner arrays are
12795
		 * used in the following manner:
12796
		 * <ul>
12797
		 *   <li>Index 0 - column number</li>
12798
		 *   <li>Index 1 - current sorting direction</li>
12799
		 * </ul>
12800
		 * Note that this parameter will be set by the initialisation routine. To
12801
		 * set a default use {@link DataTable.defaults}.
12802
		 *  @type array
12803
		 *  @todo These inner arrays should really be objects
12804
		 */
12805
		"aaSorting": null,
12806
 
12807
		/**
12808
		 * Sorting that is always applied to the table (i.e. prefixed in front of
12809
		 * aaSorting).
12810
		 * Note that this parameter will be set by the initialisation routine. To
12811
		 * set a default use {@link DataTable.defaults}.
12812
		 *  @type array
12813
		 *  @default []
12814
		 */
12815
		"aaSortingFixed": [],
12816
 
12817
		/**
12818
		 * Classes to use for the striping of a table.
12819
		 * Note that this parameter will be set by the initialisation routine. To
12820
		 * set a default use {@link DataTable.defaults}.
12821
		 *  @type array
12822
		 *  @default []
12823
		 */
12824
		"asStripeClasses": null,
12825
 
12826
		/**
12827
		 * If restoring a table - we should restore its striping classes as well
12828
		 *  @type array
12829
		 *  @default []
12830
		 */
12831
		"asDestroyStripes": [],
12832
 
12833
		/**
12834
		 * If restoring a table - we should restore its width
12835
		 *  @type int
12836
		 *  @default 0
12837
		 */
12838
		"sDestroyWidth": 0,
12839
 
12840
		/**
12841
		 * Callback functions array for every time a row is inserted (i.e. on a draw).
12842
		 *  @type array
12843
		 *  @default []
12844
		 */
12845
		"aoRowCallback": [],
12846
 
12847
		/**
12848
		 * Callback functions for the header on each draw.
12849
		 *  @type array
12850
		 *  @default []
12851
		 */
12852
		"aoHeaderCallback": [],
12853
 
12854
		/**
12855
		 * Callback function for the footer on each draw.
12856
		 *  @type array
12857
		 *  @default []
12858
		 */
12859
		"aoFooterCallback": [],
12860
 
12861
		/**
12862
		 * Array of callback functions for draw callback functions
12863
		 *  @type array
12864
		 *  @default []
12865
		 */
12866
		"aoDrawCallback": [],
12867
 
12868
		/**
12869
		 * Array of callback functions for row created function
12870
		 *  @type array
12871
		 *  @default []
12872
		 */
12873
		"aoRowCreatedCallback": [],
12874
 
12875
		/**
12876
		 * Callback functions for just before the table is redrawn. A return of
12877
		 * false will be used to cancel the draw.
12878
		 *  @type array
12879
		 *  @default []
12880
		 */
12881
		"aoPreDrawCallback": [],
12882
 
12883
		/**
12884
		 * Callback functions for when the table has been initialised.
12885
		 *  @type array
12886
		 *  @default []
12887
		 */
12888
		"aoInitComplete": [],
12889
 
12890
 
12891
		/**
12892
		 * Callbacks for modifying the settings to be stored for state saving, prior to
12893
		 * saving state.
12894
		 *  @type array
12895
		 *  @default []
12896
		 */
12897
		"aoStateSaveParams": [],
12898
 
12899
		/**
12900
		 * Callbacks for modifying the settings that have been stored for state saving
12901
		 * prior to using the stored values to restore the state.
12902
		 *  @type array
12903
		 *  @default []
12904
		 */
12905
		"aoStateLoadParams": [],
12906
 
12907
		/**
12908
		 * Callbacks for operating on the settings object once the saved state has been
12909
		 * loaded
12910
		 *  @type array
12911
		 *  @default []
12912
		 */
12913
		"aoStateLoaded": [],
12914
 
12915
		/**
12916
		 * Cache the table ID for quick access
12917
		 *  @type string
12918
		 *  @default <i>Empty string</i>
12919
		 */
12920
		"sTableId": "",
12921
 
12922
		/**
12923
		 * The TABLE node for the main table
12924
		 *  @type node
12925
		 *  @default null
12926
		 */
12927
		"nTable": null,
12928
 
12929
		/**
12930
		 * Permanent ref to the thead element
12931
		 *  @type node
12932
		 *  @default null
12933
		 */
12934
		"nTHead": null,
12935
 
12936
		/**
12937
		 * Permanent ref to the tfoot element - if it exists
12938
		 *  @type node
12939
		 *  @default null
12940
		 */
12941
		"nTFoot": null,
12942
 
12943
		/**
12944
		 * Permanent ref to the tbody element
12945
		 *  @type node
12946
		 *  @default null
12947
		 */
12948
		"nTBody": null,
12949
 
12950
		/**
12951
		 * Cache the wrapper node (contains all DataTables controlled elements)
12952
		 *  @type node
12953
		 *  @default null
12954
		 */
12955
		"nTableWrapper": null,
12956
 
12957
		/**
12958
		 * Indicate if when using server-side processing the loading of data
12959
		 * should be deferred until the second draw.
12960
		 * Note that this parameter will be set by the initialisation routine. To
12961
		 * set a default use {@link DataTable.defaults}.
12962
		 *  @type boolean
12963
		 *  @default false
12964
		 */
12965
		"bDeferLoading": false,
12966
 
12967
		/**
12968
		 * Indicate if all required information has been read in
12969
		 *  @type boolean
12970
		 *  @default false
12971
		 */
12972
		"bInitialised": false,
12973
 
12974
		/**
12975
		 * Information about open rows. Each object in the array has the parameters
12976
		 * 'nTr' and 'nParent'
12977
		 *  @type array
12978
		 *  @default []
12979
		 */
12980
		"aoOpenRows": [],
12981
 
12982
		/**
12983
		 * Dictate the positioning of DataTables' control elements - see
12984
		 * {@link DataTable.model.oInit.sDom}.
12985
		 * Note that this parameter will be set by the initialisation routine. To
12986
		 * set a default use {@link DataTable.defaults}.
12987
		 *  @type string
12988
		 *  @default null
12989
		 */
12990
		"sDom": null,
12991
 
12992
		/**
12993
		 * Search delay (in mS)
12994
		 *  @type integer
12995
		 *  @default null
12996
		 */
12997
		"searchDelay": null,
12998
 
12999
		/**
13000
		 * Which type of pagination should be used.
13001
		 * Note that this parameter will be set by the initialisation routine. To
13002
		 * set a default use {@link DataTable.defaults}.
13003
		 *  @type string
13004
		 *  @default two_button
13005
		 */
13006
		"sPaginationType": "two_button",
13007
 
13008
		/**
13009
		 * The state duration (for `stateSave`) in seconds.
13010
		 * Note that this parameter will be set by the initialisation routine. To
13011
		 * set a default use {@link DataTable.defaults}.
13012
		 *  @type int
13013
		 *  @default 0
13014
		 */
13015
		"iStateDuration": 0,
13016
 
13017
		/**
13018
		 * Array of callback functions for state saving. Each array element is an
13019
		 * object with the following parameters:
13020
		 *   <ul>
13021
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13022
		 *       and the JSON string to save that has been thus far created. Returns
13023
		 *       a JSON string to be inserted into a json object
13024
		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13025
		 *     <li>string:sName - name of callback</li>
13026
		 *   </ul>
13027
		 *  @type array
13028
		 *  @default []
13029
		 */
13030
		"aoStateSave": [],
13031
 
13032
		/**
13033
		 * Array of callback functions for state loading. Each array element is an
13034
		 * object with the following parameters:
13035
		 *   <ul>
13036
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13037
		 *       and the object stored. May return false to cancel state loading</li>
13038
		 *     <li>string:sName - name of callback</li>
13039
		 *   </ul>
13040
		 *  @type array
13041
		 *  @default []
13042
		 */
13043
		"aoStateLoad": [],
13044
 
13045
		/**
13046
		 * State that was saved. Useful for back reference
13047
		 *  @type object
13048
		 *  @default null
13049
		 */
13050
		"oSavedState": null,
13051
 
13052
		/**
13053
		 * State that was loaded. Useful for back reference
13054
		 *  @type object
13055
		 *  @default null
13056
		 */
13057
		"oLoadedState": null,
13058
 
13059
		/**
13060
		 * Source url for AJAX data for the table.
13061
		 * Note that this parameter will be set by the initialisation routine. To
13062
		 * set a default use {@link DataTable.defaults}.
13063
		 *  @type string
13064
		 *  @default null
13065
		 */
13066
		"sAjaxSource": null,
13067
 
13068
		/**
13069
		 * Property from a given object from which to read the table data from. This
13070
		 * can be an empty string (when not server-side processing), in which case
13071
		 * it is  assumed an an array is given directly.
13072
		 * Note that this parameter will be set by the initialisation routine. To
13073
		 * set a default use {@link DataTable.defaults}.
13074
		 *  @type string
13075
		 */
13076
		"sAjaxDataProp": null,
13077
 
13078
		/**
13079
		 * Note if draw should be blocked while getting data
13080
		 *  @type boolean
13081
		 *  @default true
13082
		 */
13083
		"bAjaxDataGet": true,
13084
 
13085
		/**
13086
		 * The last jQuery XHR object that was used for server-side data gathering.
13087
		 * This can be used for working with the XHR information in one of the
13088
		 * callbacks
13089
		 *  @type object
13090
		 *  @default null
13091
		 */
13092
		"jqXHR": null,
13093
 
13094
		/**
13095
		 * JSON returned from the server in the last Ajax request
13096
		 *  @type object
13097
		 *  @default undefined
13098
		 */
13099
		"json": undefined,
13100
 
13101
		/**
13102
		 * Data submitted as part of the last Ajax request
13103
		 *  @type object
13104
		 *  @default undefined
13105
		 */
13106
		"oAjaxData": undefined,
13107
 
13108
		/**
13109
		 * Function to get the server-side data.
13110
		 * Note that this parameter will be set by the initialisation routine. To
13111
		 * set a default use {@link DataTable.defaults}.
13112
		 *  @type function
13113
		 */
13114
		"fnServerData": null,
13115
 
13116
		/**
13117
		 * Functions which are called prior to sending an Ajax request so extra
13118
		 * parameters can easily be sent to the server
13119
		 *  @type array
13120
		 *  @default []
13121
		 */
13122
		"aoServerParams": [],
13123
 
13124
		/**
13125
		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13126
		 * required).
13127
		 * Note that this parameter will be set by the initialisation routine. To
13128
		 * set a default use {@link DataTable.defaults}.
13129
		 *  @type string
13130
		 */
13131
		"sServerMethod": null,
13132
 
13133
		/**
13134
		 * Format numbers for display.
13135
		 * Note that this parameter will be set by the initialisation routine. To
13136
		 * set a default use {@link DataTable.defaults}.
13137
		 *  @type function
13138
		 */
13139
		"fnFormatNumber": null,
13140
 
13141
		/**
13142
		 * List of options that can be used for the user selectable length menu.
13143
		 * Note that this parameter will be set by the initialisation routine. To
13144
		 * set a default use {@link DataTable.defaults}.
13145
		 *  @type array
13146
		 *  @default []
13147
		 */
13148
		"aLengthMenu": null,
13149
 
13150
		/**
13151
		 * Counter for the draws that the table does. Also used as a tracker for
13152
		 * server-side processing
13153
		 *  @type int
13154
		 *  @default 0
13155
		 */
13156
		"iDraw": 0,
13157
 
13158
		/**
13159
		 * Indicate if a redraw is being done - useful for Ajax
13160
		 *  @type boolean
13161
		 *  @default false
13162
		 */
13163
		"bDrawing": false,
13164
 
13165
		/**
13166
		 * Draw index (iDraw) of the last error when parsing the returned data
13167
		 *  @type int
13168
		 *  @default -1
13169
		 */
13170
		"iDrawError": -1,
13171
 
13172
		/**
13173
		 * Paging display length
13174
		 *  @type int
13175
		 *  @default 10
13176
		 */
13177
		"_iDisplayLength": 10,
13178
 
13179
		/**
13180
		 * Paging start point - aiDisplay index
13181
		 *  @type int
13182
		 *  @default 0
13183
		 */
13184
		"_iDisplayStart": 0,
13185
 
13186
		/**
13187
		 * Server-side processing - number of records in the result set
13188
		 * (i.e. before filtering), Use fnRecordsTotal rather than
13189
		 * this property to get the value of the number of records, regardless of
13190
		 * the server-side processing setting.
13191
		 *  @type int
13192
		 *  @default 0
13193
		 *  @private
13194
		 */
13195
		"_iRecordsTotal": 0,
13196
 
13197
		/**
13198
		 * Server-side processing - number of records in the current display set
13199
		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13200
		 * this property to get the value of the number of records, regardless of
13201
		 * the server-side processing setting.
13202
		 *  @type boolean
13203
		 *  @default 0
13204
		 *  @private
13205
		 */
13206
		"_iRecordsDisplay": 0,
13207
 
13208
		/**
13209
		 * Flag to indicate if jQuery UI marking and classes should be used.
13210
		 * Note that this parameter will be set by the initialisation routine. To
13211
		 * set a default use {@link DataTable.defaults}.
13212
		 *  @type boolean
13213
		 */
13214
		"bJUI": null,
13215
 
13216
		/**
13217
		 * The classes to use for the table
13218
		 *  @type object
13219
		 *  @default {}
13220
		 */
13221
		"oClasses": {},
13222
 
13223
		/**
13224
		 * Flag attached to the settings object so you can check in the draw
13225
		 * callback if filtering has been done in the draw. Deprecated in favour of
13226
		 * events.
13227
		 *  @type boolean
13228
		 *  @default false
13229
		 *  @deprecated
13230
		 */
13231
		"bFiltered": false,
13232
 
13233
		/**
13234
		 * Flag attached to the settings object so you can check in the draw
13235
		 * callback if sorting has been done in the draw. Deprecated in favour of
13236
		 * events.
13237
		 *  @type boolean
13238
		 *  @default false
13239
		 *  @deprecated
13240
		 */
13241
		"bSorted": false,
13242
 
13243
		/**
13244
		 * Indicate that if multiple rows are in the header and there is more than
13245
		 * one unique cell per column, if the top one (true) or bottom one (false)
13246
		 * should be used for sorting / title by DataTables.
13247
		 * Note that this parameter will be set by the initialisation routine. To
13248
		 * set a default use {@link DataTable.defaults}.
13249
		 *  @type boolean
13250
		 */
13251
		"bSortCellsTop": null,
13252
 
13253
		/**
13254
		 * Initialisation object that is used for the table
13255
		 *  @type object
13256
		 *  @default null
13257
		 */
13258
		"oInit": null,
13259
 
13260
		/**
13261
		 * Destroy callback functions - for plug-ins to attach themselves to the
13262
		 * destroy so they can clean up markup and events.
13263
		 *  @type array
13264
		 *  @default []
13265
		 */
13266
		"aoDestroyCallback": [],
13267
 
13268
 
13269
		/**
13270
		 * Get the number of records in the current record set, before filtering
13271
		 *  @type function
13272
		 */
13273
		"fnRecordsTotal": function ()
13274
		{
13275
			return _fnDataSource( this ) == 'ssp' ?
13276
				this._iRecordsTotal * 1 :
13277
				this.aiDisplayMaster.length;
13278
		},
13279
 
13280
		/**
13281
		 * Get the number of records in the current record set, after filtering
13282
		 *  @type function
13283
		 */
13284
		"fnRecordsDisplay": function ()
13285
		{
13286
			return _fnDataSource( this ) == 'ssp' ?
13287
				this._iRecordsDisplay * 1 :
13288
				this.aiDisplay.length;
13289
		},
13290
 
13291
		/**
13292
		 * Get the display end point - aiDisplay index
13293
		 *  @type function
13294
		 */
13295
		"fnDisplayEnd": function ()
13296
		{
13297
			var
13298
				len      = this._iDisplayLength,
13299
				start    = this._iDisplayStart,
13300
				calc     = start + len,
13301
				records  = this.aiDisplay.length,
13302
				features = this.oFeatures,
13303
				paginate = features.bPaginate;
13304
 
13305
			if ( features.bServerSide ) {
13306
				return paginate === false || len === -1 ?
13307
					start + records :
13308
					Math.min( start+len, this._iRecordsDisplay );
13309
			}
13310
			else {
13311
				return ! paginate || calc>records || len===-1 ?
13312
					records :
13313
					calc;
13314
			}
13315
		},
13316
 
13317
		/**
13318
		 * The DataTables object for this table
13319
		 *  @type object
13320
		 *  @default null
13321
		 */
13322
		"oInstance": null,
13323
 
13324
		/**
13325
		 * Unique identifier for each instance of the DataTables object. If there
13326
		 * is an ID on the table node, then it takes that value, otherwise an
13327
		 * incrementing internal counter is used.
13328
		 *  @type string
13329
		 *  @default null
13330
		 */
13331
		"sInstance": null,
13332
 
13333
		/**
13334
		 * tabindex attribute value that is added to DataTables control elements, allowing
13335
		 * keyboard navigation of the table and its controls.
13336
		 */
13337
		"iTabIndex": 0,
13338
 
13339
		/**
13340
		 * DIV container for the footer scrolling table if scrolling
13341
		 */
13342
		"nScrollHead": null,
13343
 
13344
		/**
13345
		 * DIV container for the footer scrolling table if scrolling
13346
		 */
13347
		"nScrollFoot": null,
13348
 
13349
		/**
13350
		 * Last applied sort
13351
		 *  @type array
13352
		 *  @default []
13353
		 */
13354
		"aLastSort": [],
13355
 
13356
		/**
13357
		 * Stored plug-in instances
13358
		 *  @type object
13359
		 *  @default {}
13360
		 */
13361
		"oPlugins": {}
13362
	};
13363
 
13364
	/**
13365
	 * Extension object for DataTables that is used to provide all extension
13366
	 * options.
13367
	 *
13368
	 * Note that the `DataTable.ext` object is available through
13369
	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13370
	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13371
	 *  @namespace
13372
	 *  @extends DataTable.models.ext
13373
	 */
13374
 
13375
 
13376
	/**
13377
	 * DataTables extensions
13378
	 * 
13379
	 * This namespace acts as a collection area for plug-ins that can be used to
13380
	 * extend DataTables capabilities. Indeed many of the build in methods
13381
	 * use this method to provide their own capabilities (sorting methods for
13382
	 * example).
13383
	 *
13384
	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13385
	 * reasons
13386
	 *
13387
	 *  @namespace
13388
	 */
13389
	DataTable.ext = _ext = {
13390
		/**
13391
		 * Element class names
13392
		 *
13393
		 *  @type object
13394
		 *  @default {}
13395
		 */
13396
		classes: {},
13397
 
13398
 
13399
		/**
13400
		 * Error reporting.
13401
		 * 
13402
		 * How should DataTables report an error. Can take the value 'alert' or
13403
		 * 'throw'
13404
		 *
13405
		 *  @type string
13406
		 *  @default alert
13407
		 */
13408
		errMode: "alert",
13409
 
13410
 
13411
		/**
13412
		 * Feature plug-ins.
13413
		 * 
13414
		 * This is an array of objects which describe the feature plug-ins that are
13415
		 * available to DataTables. These feature plug-ins are then available for
13416
		 * use through the `dom` initialisation option.
13417
		 * 
13418
		 * Each feature plug-in is described by an object which must have the
13419
		 * following properties:
13420
		 * 
13421
		 * * `fnInit` - function that is used to initialise the plug-in,
13422
		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13423
		 *   instillation option. This is case sensitive.
13424
		 *
13425
		 * The `fnInit` function has the following input parameters:
13426
		 *
13427
		 * 1. `{object}` DataTables settings object: see
13428
		 *    {@link DataTable.models.oSettings}
13429
		 *
13430
		 * And the following return is expected:
13431
		 * 
13432
		 * * {node|null} The element which contains your feature. Note that the
13433
		 *   return may also be void if your plug-in does not require to inject any
13434
		 *   DOM elements into DataTables control (`dom`) - for example this might
13435
		 *   be useful when developing a plug-in which allows table control via
13436
		 *   keyboard entry
13437
		 *
13438
		 *  @type array
13439
		 *
13440
		 *  @example
13441
		 *    $.fn.dataTable.ext.features.push( {
13442
		 *      "fnInit": function( oSettings ) {
13443
		 *        return new TableTools( { "oDTSettings": oSettings } );
13444
		 *      },
13445
		 *      "cFeature": "T"
13446
		 *    } );
13447
		 */
13448
		feature: [],
13449
 
13450
 
13451
		/**
13452
		 * Row searching.
13453
		 * 
13454
		 * This method of searching is complimentary to the default type based
13455
		 * searching, and a lot more comprehensive as it allows you complete control
13456
		 * over the searching logic. Each element in this array is a function
13457
		 * (parameters described below) that is called for every row in the table,
13458
		 * and your logic decides if it should be included in the searching data set
13459
		 * or not.
13460
		 *
13461
		 * Searching functions have the following input parameters:
13462
		 *
13463
		 * 1. `{object}` DataTables settings object: see
13464
		 *    {@link DataTable.models.oSettings}
13465
		 * 2. `{array|object}` Data for the row to be processed (same as the
13466
		 *    original format that was passed in as the data source, or an array
13467
		 *    from a DOM data source
13468
		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13469
		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13470
		 *
13471
		 * And the following return is expected:
13472
		 *
13473
		 * * {boolean} Include the row in the searched result set (true) or not
13474
		 *   (false)
13475
		 *
13476
		 * Note that as with the main search ability in DataTables, technically this
13477
		 * is "filtering", since it is subtractive. However, for consistency in
13478
		 * naming we call it searching here.
13479
		 *
13480
		 *  @type array
13481
		 *  @default []
13482
		 *
13483
		 *  @example
13484
		 *    // The following example shows custom search being applied to the
13485
		 *    // fourth column (i.e. the data[3] index) based on two input values
13486
		 *    // from the end-user, matching the data in a certain range.
13487
		 *    $.fn.dataTable.ext.search.push(
13488
		 *      function( settings, data, dataIndex ) {
13489
		 *        var min = document.getElementById('min').value * 1;
13490
		 *        var max = document.getElementById('max').value * 1;
13491
		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13492
		 *
13493
		 *        if ( min == "" && max == "" ) {
13494
		 *          return true;
13495
		 *        }
13496
		 *        else if ( min == "" && version < max ) {
13497
		 *          return true;
13498
		 *        }
13499
		 *        else if ( min < version && "" == max ) {
13500
		 *          return true;
13501
		 *        }
13502
		 *        else if ( min < version && version < max ) {
13503
		 *          return true;
13504
		 *        }
13505
		 *        return false;
13506
		 *      }
13507
		 *    );
13508
		 */
13509
		search: [],
13510
 
13511
 
13512
		/**
13513
		 * Internal functions, exposed for used in plug-ins.
13514
		 * 
13515
		 * Please note that you should not need to use the internal methods for
13516
		 * anything other than a plug-in (and even then, try to avoid if possible).
13517
		 * The internal function may change between releases.
13518
		 *
13519
		 *  @type object
13520
		 *  @default {}
13521
		 */
13522
		internal: {},
13523
 
13524
 
13525
		/**
13526
		 * Legacy configuration options. Enable and disable legacy options that
13527
		 * are available in DataTables.
13528
		 *
13529
		 *  @type object
13530
		 */
13531
		legacy: {
13532
			/**
13533
			 * Enable / disable DataTables 1.9 compatible server-side processing
13534
			 * requests
13535
			 *
13536
			 *  @type boolean
13537
			 *  @default null
13538
			 */
13539
			ajax: null
13540
		},
13541
 
13542
 
13543
		/**
13544
		 * Pagination plug-in methods.
13545
		 * 
13546
		 * Each entry in this object is a function and defines which buttons should
13547
		 * be shown by the pagination rendering method that is used for the table:
13548
		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13549
		 * buttons are displayed in the document, while the functions here tell it
13550
		 * what buttons to display. This is done by returning an array of button
13551
		 * descriptions (what each button will do).
13552
		 *
13553
		 * Pagination types (the four built in options and any additional plug-in
13554
		 * options defined here) can be used through the `paginationType`
13555
		 * initialisation parameter.
13556
		 *
13557
		 * The functions defined take two parameters:
13558
		 *
13559
		 * 1. `{int} page` The current page index
13560
		 * 2. `{int} pages` The number of pages in the table
13561
		 *
13562
		 * Each function is expected to return an array where each element of the
13563
		 * array can be one of:
13564
		 *
13565
		 * * `first` - Jump to first page when activated
13566
		 * * `last` - Jump to last page when activated
13567
		 * * `previous` - Show previous page when activated
13568
		 * * `next` - Show next page when activated
13569
		 * * `{int}` - Show page of the index given
13570
		 * * `{array}` - A nested array containing the above elements to add a
13571
		 *   containing 'DIV' element (might be useful for styling).
13572
		 *
13573
		 * Note that DataTables v1.9- used this object slightly differently whereby
13574
		 * an object with two functions would be defined for each plug-in. That
13575
		 * ability is still supported by DataTables 1.10+ to provide backwards
13576
		 * compatibility, but this option of use is now decremented and no longer
13577
		 * documented in DataTables 1.10+.
13578
		 *
13579
		 *  @type object
13580
		 *  @default {}
13581
		 *
13582
		 *  @example
13583
		 *    // Show previous, next and current page buttons only
13584
		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13585
		 *      return [ 'previous', page, 'next' ];
13586
		 *    };
13587
		 */
13588
		pager: {},
13589
 
13590
 
13591
		renderer: {
13592
			pageButton: {},
13593
			header: {}
13594
		},
13595
 
13596
 
13597
		/**
13598
		 * Ordering plug-ins - custom data source
13599
		 * 
13600
		 * The extension options for ordering of data available here is complimentary
13601
		 * to the default type based ordering that DataTables typically uses. It
13602
		 * allows much greater control over the the data that is being used to
13603
		 * order a column, but is necessarily therefore more complex.
13604
		 * 
13605
		 * This type of ordering is useful if you want to do ordering based on data
13606
		 * live from the DOM (for example the contents of an 'input' element) rather
13607
		 * than just the static string that DataTables knows of.
13608
		 * 
13609
		 * The way these plug-ins work is that you create an array of the values you
13610
		 * wish to be ordering for the column in question and then return that
13611
		 * array. The data in the array much be in the index order of the rows in
13612
		 * the table (not the currently ordering order!). Which order data gathering
13613
		 * function is run here depends on the `dt-init columns.orderDataType`
13614
		 * parameter that is used for the column (if any).
13615
		 *
13616
		 * The functions defined take two parameters:
13617
		 *
13618
		 * 1. `{object}` DataTables settings object: see
13619
		 *    {@link DataTable.models.oSettings}
13620
		 * 2. `{int}` Target column index
13621
		 *
13622
		 * Each function is expected to return an array:
13623
		 *
13624
		 * * `{array}` Data for the column to be ordering upon
13625
		 *
13626
		 *  @type array
13627
		 *
13628
		 *  @example
13629
		 *    // Ordering using `input` node values
13630
		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
13631
		 *    {
13632
		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13633
		 *        return $('input', td).val();
13634
		 *      } );
13635
		 *    }
13636
		 */
13637
		order: {},
13638
 
13639
 
13640
		/**
13641
		 * Type based plug-ins.
13642
		 *
13643
		 * Each column in DataTables has a type assigned to it, either by automatic
13644
		 * detection or by direct assignment using the `type` option for the column.
13645
		 * The type of a column will effect how it is ordering and search (plug-ins
13646
		 * can also make use of the column type if required).
13647
		 *
13648
		 * @namespace
13649
		 */
13650
		type: {
13651
			/**
13652
			 * Type detection functions.
13653
			 *
13654
			 * The functions defined in this object are used to automatically detect
13655
			 * a column's type, making initialisation of DataTables super easy, even
13656
			 * when complex data is in the table.
13657
			 *
13658
			 * The functions defined take two parameters:
13659
			 *
13660
		     *  1. `{*}` Data from the column cell to be analysed
13661
		     *  2. `{settings}` DataTables settings object. This can be used to
13662
		     *     perform context specific type detection - for example detection
13663
		     *     based on language settings such as using a comma for a decimal
13664
		     *     place. Generally speaking the options from the settings will not
13665
		     *     be required
13666
			 *
13667
			 * Each function is expected to return:
13668
			 *
13669
			 * * `{string|null}` Data type detected, or null if unknown (and thus
13670
			 *   pass it on to the other type detection functions.
13671
			 *
13672
			 *  @type array
13673
			 *
13674
			 *  @example
13675
			 *    // Currency type detection plug-in:
13676
			 *    $.fn.dataTable.ext.type.detect.push(
13677
			 *      function ( data, settings ) {
13678
			 *        // Check the numeric part
13679
			 *        if ( ! $.isNumeric( data.substring(1) ) ) {
13680
			 *          return null;
13681
			 *        }
13682
			 *
13683
			 *        // Check prefixed by currency
13684
			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
13685
			 *          return 'currency';
13686
			 *        }
13687
			 *        return null;
13688
			 *      }
13689
			 *    );
13690
			 */
13691
			detect: [],
13692
 
13693
 
13694
			/**
13695
			 * Type based search formatting.
13696
			 *
13697
			 * The type based searching functions can be used to pre-format the
13698
			 * data to be search on. For example, it can be used to strip HTML
13699
			 * tags or to de-format telephone numbers for numeric only searching.
13700
			 *
13701
			 * Note that is a search is not defined for a column of a given type,
13702
			 * no search formatting will be performed.
13703
			 * 
13704
			 * Pre-processing of searching data plug-ins - When you assign the sType
13705
			 * for a column (or have it automatically detected for you by DataTables
13706
			 * or a type detection plug-in), you will typically be using this for
13707
			 * custom sorting, but it can also be used to provide custom searching
13708
			 * by allowing you to pre-processing the data and returning the data in
13709
			 * the format that should be searched upon. This is done by adding
13710
			 * functions this object with a parameter name which matches the sType
13711
			 * for that target column. This is the corollary of <i>afnSortData</i>
13712
			 * for searching data.
13713
			 *
13714
			 * The functions defined take a single parameter:
13715
			 *
13716
		     *  1. `{*}` Data from the column cell to be prepared for searching
13717
			 *
13718
			 * Each function is expected to return:
13719
			 *
13720
			 * * `{string|null}` Formatted string that will be used for the searching.
13721
			 *
13722
			 *  @type object
13723
			 *  @default {}
13724
			 *
13725
			 *  @example
13726
			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
13727
			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
13728
			 *    }
13729
			 */
13730
			search: {},
13731
 
13732
 
13733
			/**
13734
			 * Type based ordering.
13735
			 *
13736
			 * The column type tells DataTables what ordering to apply to the table
13737
			 * when a column is sorted upon. The order for each type that is defined,
13738
			 * is defined by the functions available in this object.
13739
			 *
13740
			 * Each ordering option can be described by three properties added to
13741
			 * this object:
13742
			 *
13743
			 * * `{type}-pre` - Pre-formatting function
13744
			 * * `{type}-asc` - Ascending order function
13745
			 * * `{type}-desc` - Descending order function
13746
			 *
13747
			 * All three can be used together, only `{type}-pre` or only
13748
			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
13749
			 * that only `{type}-pre` is used, as this provides the optimal
13750
			 * implementation in terms of speed, although the others are provided
13751
			 * for compatibility with existing Javascript sort functions.
13752
			 *
13753
			 * `{type}-pre`: Functions defined take a single parameter:
13754
			 *
13755
		     *  1. `{*}` Data from the column cell to be prepared for ordering
13756
			 *
13757
			 * And return:
13758
			 *
13759
			 * * `{*}` Data to be sorted upon
13760
			 *
13761
			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
13762
			 * functions, taking two parameters:
13763
			 *
13764
		     *  1. `{*}` Data to compare to the second parameter
13765
		     *  2. `{*}` Data to compare to the first parameter
13766
			 *
13767
			 * And returning:
13768
			 *
13769
			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
13770
			 *   than the second parameter, ===0 if the two parameters are equal and
13771
			 *   >0 if the first parameter should be sorted height than the second
13772
			 *   parameter.
13773
			 * 
13774
			 *  @type object
13775
			 *  @default {}
13776
			 *
13777
			 *  @example
13778
			 *    // Numeric ordering of formatted numbers with a pre-formatter
13779
			 *    $.extend( $.fn.dataTable.ext.type.order, {
13780
			 *      "string-pre": function(x) {
13781
			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
13782
			 *        return parseFloat( a );
13783
			 *      }
13784
			 *    } );
13785
			 *
13786
			 *  @example
13787
			 *    // Case-sensitive string ordering, with no pre-formatting method
13788
			 *    $.extend( $.fn.dataTable.ext.order, {
13789
			 *      "string-case-asc": function(x,y) {
13790
			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13791
			 *      },
13792
			 *      "string-case-desc": function(x,y) {
13793
			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13794
			 *      }
13795
			 *    } );
13796
			 */
13797
			order: {}
13798
		},
13799
 
13800
		/**
13801
		 * Unique DataTables instance counter
13802
		 *
13803
		 * @type int
13804
		 * @private
13805
		 */
13806
		_unique: 0,
13807
 
13808
 
13809
		//
13810
		// Depreciated
13811
		// The following properties are retained for backwards compatiblity only.
13812
		// The should not be used in new projects and will be removed in a future
13813
		// version
13814
		//
13815
 
13816
		/**
13817
		 * Version check function.
13818
		 *  @type function
13819
		 *  @depreciated Since 1.10
13820
		 */
13821
		fnVersionCheck: DataTable.fnVersionCheck,
13822
 
13823
 
13824
		/**
13825
		 * Index for what 'this' index API functions should use
13826
		 *  @type int
13827
		 *  @deprecated Since v1.10
13828
		 */
13829
		iApiIndex: 0,
13830
 
13831
 
13832
		/**
13833
		 * jQuery UI class container
13834
		 *  @type object
13835
		 *  @deprecated Since v1.10
13836
		 */
13837
		oJUIClasses: {},
13838
 
13839
 
13840
		/**
13841
		 * Software version
13842
		 *  @type string
13843
		 *  @deprecated Since v1.10
13844
		 */
13845
		sVersion: DataTable.version
13846
	};
13847
 
13848
 
13849
	//
13850
	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
13851
	//
13852
	$.extend( _ext, {
13853
		afnFiltering: _ext.search,
13854
		aTypes:       _ext.type.detect,
13855
		ofnSearch:    _ext.type.search,
13856
		oSort:        _ext.type.order,
13857
		afnSortData:  _ext.order,
13858
		aoFeatures:   _ext.feature,
13859
		oApi:         _ext.internal,
13860
		oStdClasses:  _ext.classes,
13861
		oPagination:  _ext.pager
13862
	} );
13863
 
13864
 
13865
	$.extend( DataTable.ext.classes, {
13866
		"sTable": "dataTable",
13867
		"sNoFooter": "no-footer",
13868
 
13869
		/* Paging buttons */
13870
		"sPageButton": "paginate_button",
13871
		"sPageButtonActive": "current",
13872
		"sPageButtonDisabled": "disabled",
13873
 
13874
		/* Striping classes */
13875
		"sStripeOdd": "odd",
13876
		"sStripeEven": "even",
13877
 
13878
		/* Empty row */
13879
		"sRowEmpty": "dataTables_empty",
13880
 
13881
		/* Features */
13882
		"sWrapper": "dataTables_wrapper",
13883
		"sFilter": "dataTables_filter",
13884
		"sInfo": "dataTables_info",
13885
		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
13886
		"sLength": "dataTables_length",
13887
		"sProcessing": "dataTables_processing",
13888
 
13889
		/* Sorting */
13890
		"sSortAsc": "sorting_asc",
13891
		"sSortDesc": "sorting_desc",
13892
		"sSortable": "sorting", /* Sortable in both directions */
13893
		"sSortableAsc": "sorting_asc_disabled",
13894
		"sSortableDesc": "sorting_desc_disabled",
13895
		"sSortableNone": "sorting_disabled",
13896
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
13897
 
13898
		/* Filtering */
13899
		"sFilterInput": "",
13900
 
13901
		/* Page length */
13902
		"sLengthSelect": "",
13903
 
13904
		/* Scrolling */
13905
		"sScrollWrapper": "dataTables_scroll",
13906
		"sScrollHead": "dataTables_scrollHead",
13907
		"sScrollHeadInner": "dataTables_scrollHeadInner",
13908
		"sScrollBody": "dataTables_scrollBody",
13909
		"sScrollFoot": "dataTables_scrollFoot",
13910
		"sScrollFootInner": "dataTables_scrollFootInner",
13911
 
13912
		/* Misc */
13913
		"sHeaderTH": "",
13914
		"sFooterTH": "",
13915
 
13916
		// Deprecated
13917
		"sSortJUIAsc": "",
13918
		"sSortJUIDesc": "",
13919
		"sSortJUI": "",
13920
		"sSortJUIAscAllowed": "",
13921
		"sSortJUIDescAllowed": "",
13922
		"sSortJUIWrapper": "",
13923
		"sSortIcon": "",
13924
		"sJUIHeader": "",
13925
		"sJUIFooter": ""
13926
	} );
13927
 
13928
 
13929
	(function() {
13930
 
13931
	// Reused strings for better compression. Closure compiler appears to have a
13932
	// weird edge case where it is trying to expand strings rather than use the
13933
	// variable version. This results in about 200 bytes being added, for very
13934
	// little preference benefit since it this run on script load only.
13935
	var _empty = '';
13936
	_empty = '';
13937
 
13938
	var _stateDefault = _empty + 'ui-state-default';
13939
	var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
13940
	var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
13941
 
13942
	$.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
13943
		/* Full numbers paging buttons */
13944
		"sPageButton":         "fg-button ui-button "+_stateDefault,
13945
		"sPageButtonActive":   "ui-state-disabled",
13946
		"sPageButtonDisabled": "ui-state-disabled",
13947
 
13948
		/* Features */
13949
		"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
13950
			"ui-buttonset-multi paging_", /* Note that the type is postfixed */
13951
 
13952
		/* Sorting */
13953
		"sSortAsc":            _stateDefault+" sorting_asc",
13954
		"sSortDesc":           _stateDefault+" sorting_desc",
13955
		"sSortable":           _stateDefault+" sorting",
13956
		"sSortableAsc":        _stateDefault+" sorting_asc_disabled",
13957
		"sSortableDesc":       _stateDefault+" sorting_desc_disabled",
13958
		"sSortableNone":       _stateDefault+" sorting_disabled",
13959
		"sSortJUIAsc":         _sortIcon+"triangle-1-n",
13960
		"sSortJUIDesc":        _sortIcon+"triangle-1-s",
13961
		"sSortJUI":            _sortIcon+"carat-2-n-s",
13962
		"sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
13963
		"sSortJUIDescAllowed": _sortIcon+"carat-1-s",
13964
		"sSortJUIWrapper":     "DataTables_sort_wrapper",
13965
		"sSortIcon":           "DataTables_sort_icon",
13966
 
13967
		/* Scrolling */
13968
		"sScrollHead": "dataTables_scrollHead "+_stateDefault,
13969
		"sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
13970
 
13971
		/* Misc */
13972
		"sHeaderTH":  _stateDefault,
13973
		"sFooterTH":  _stateDefault,
13974
		"sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
13975
		"sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
13976
	} );
13977
 
13978
	}());
13979
 
13980
 
13981
 
13982
	var extPagination = DataTable.ext.pager;
13983
 
13984
	function _numbers ( page, pages ) {
13985
		var
13986
			numbers = [],
13987
			buttons = extPagination.numbers_length,
13988
			half = Math.floor( buttons / 2 ),
13989
			i = 1;
13990
 
13991
		if ( pages <= buttons ) {
13992
			numbers = _range( 0, pages );
13993
		}
13994
		else if ( page <= half ) {
13995
			numbers = _range( 0, buttons-2 );
13996
			numbers.push( 'ellipsis' );
13997
			numbers.push( pages-1 );
13998
		}
13999
		else if ( page >= pages - 1 - half ) {
14000
			numbers = _range( pages-(buttons-2), pages );
14001
			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14002
			numbers.splice( 0, 0, 0 );
14003
		}
14004
		else {
14005
			numbers = _range( page-1, page+2 );
14006
			numbers.push( 'ellipsis' );
14007
			numbers.push( pages-1 );
14008
			numbers.splice( 0, 0, 'ellipsis' );
14009
			numbers.splice( 0, 0, 0 );
14010
		}
14011
 
14012
		numbers.DT_el = 'span';
14013
		return numbers;
14014
	}
14015
 
14016
 
14017
	$.extend( extPagination, {
14018
		simple: function ( page, pages ) {
14019
			return [ 'previous', 'next' ];
14020
		},
14021
 
14022
		full: function ( page, pages ) {
14023
			return [  'first', 'previous', 'next', 'last' ];
14024
		},
14025
 
14026
		simple_numbers: function ( page, pages ) {
14027
			return [ 'previous', _numbers(page, pages), 'next' ];
14028
		},
14029
 
14030
		full_numbers: function ( page, pages ) {
14031
			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14032
		},
14033
 
14034
		// For testing and plug-ins to use
14035
		_numbers: _numbers,
14036
		numbers_length: 7
14037
	} );
14038
 
14039
 
14040
	$.extend( true, DataTable.ext.renderer, {
14041
		pageButton: {
14042
			_: function ( settings, host, idx, buttons, page, pages ) {
14043
				var classes = settings.oClasses;
14044
				var lang = settings.oLanguage.oPaginate;
14045
				var btnDisplay, btnClass, counter=0;
14046
 
14047
				var attach = function( container, buttons ) {
14048
					var i, ien, node, button;
14049
					var clickHandler = function ( e ) {
14050
						_fnPageChange( settings, e.data.action, true );
14051
					};
14052
 
14053
					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14054
						button = buttons[i];
14055
 
14056
						if ( $.isArray( button ) ) {
14057
							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14058
								.appendTo( container );
14059
							attach( inner, button );
14060
						}
14061
						else {
14062
							btnDisplay = '';
14063
							btnClass = '';
14064
 
14065
							switch ( button ) {
14066
								case 'ellipsis':
14067
									container.append('<span>&hellip;</span>');
14068
									break;
14069
 
14070
								case 'first':
14071
									btnDisplay = lang.sFirst;
14072
									btnClass = button + (page > 0 ?
14073
										'' : ' '+classes.sPageButtonDisabled);
14074
									break;
14075
 
14076
								case 'previous':
14077
									btnDisplay = lang.sPrevious;
14078
									btnClass = button + (page > 0 ?
14079
										'' : ' '+classes.sPageButtonDisabled);
14080
									break;
14081
 
14082
								case 'next':
14083
									btnDisplay = lang.sNext;
14084
									btnClass = button + (page < pages-1 ?
14085
										'' : ' '+classes.sPageButtonDisabled);
14086
									break;
14087
 
14088
								case 'last':
14089
									btnDisplay = lang.sLast;
14090
									btnClass = button + (page < pages-1 ?
14091
										'' : ' '+classes.sPageButtonDisabled);
14092
									break;
14093
 
14094
								default:
14095
									btnDisplay = button + 1;
14096
									btnClass = page === button ?
14097
										classes.sPageButtonActive : '';
14098
									break;
14099
							}
14100
 
14101
							if ( btnDisplay ) {
14102
								node = $('<a>', {
14103
										'class': classes.sPageButton+' '+btnClass,
14104
										'aria-controls': settings.sTableId,
14105
										'data-dt-idx': counter,
14106
										'tabindex': settings.iTabIndex,
14107
										'id': idx === 0 && typeof button === 'string' ?
14108
											settings.sTableId +'_'+ button :
14109
											null
14110
									} )
14111
									.html( btnDisplay )
14112
									.appendTo( container );
14113
 
14114
								_fnBindAction(
14115
									node, {action: button}, clickHandler
14116
								);
14117
 
14118
								counter++;
14119
							}
14120
						}
14121
					}
14122
				};
14123
 
14124
				// IE9 throws an 'unknown error' if document.activeElement is used
14125
				// inside an iframe or frame. Try / catch the error. Not good for
14126
				// accessibility, but neither are frames.
14127
				try {
14128
					// Because this approach is destroying and recreating the paging
14129
					// elements, focus is lost on the select button which is bad for
14130
					// accessibility. So we want to restore focus once the draw has
14131
					// completed
14132
					var activeEl = $(document.activeElement).data('dt-idx');
14133
 
14134
					attach( $(host).empty(), buttons );
14135
 
14136
					if ( activeEl !== null ) {
14137
						$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14138
					}
14139
				}
14140
				catch (e) {}
14141
			}
14142
		}
14143
	} );
14144
 
14145
 
14146
 
14147
	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14148
		if ( d !== 0 && (!d || d === '-') ) {
14149
			return -Infinity;
14150
		}
14151
 
14152
		// If a decimal place other than `.` is used, it needs to be given to the
14153
		// function so we can detect it and replace with a `.` which is the only
14154
		// decimal place Javascript recognises - it is not locale aware.
14155
		if ( decimalPlace ) {
14156
			d = _numToDecimal( d, decimalPlace );
14157
		}
14158
 
14159
		if ( d.replace ) {
14160
			if ( re1 ) {
14161
				d = d.replace( re1, '' );
14162
			}
14163
 
14164
			if ( re2 ) {
14165
				d = d.replace( re2, '' );
14166
			}
14167
		}
14168
 
14169
		return d * 1;
14170
	};
14171
 
14172
 
14173
	// Add the numeric 'deformatting' functions for sorting. This is done in a
14174
	// function to provide an easy ability for the language options to add
14175
	// additional methods if a non-period decimal place is used.
14176
	function _addNumericSort ( decimalPlace ) {
14177
		$.each(
14178
			{
14179
				// Plain numbers
14180
				"num": function ( d ) {
14181
					return __numericReplace( d, decimalPlace );
14182
				},
14183
 
14184
				// Formatted numbers
14185
				"num-fmt": function ( d ) {
14186
					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14187
				},
14188
 
14189
				// HTML numeric
14190
				"html-num": function ( d ) {
14191
					return __numericReplace( d, decimalPlace, _re_html );
14192
				},
14193
 
14194
				// HTML numeric, formatted
14195
				"html-num-fmt": function ( d ) {
14196
					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14197
				}
14198
			},
14199
			function ( key, fn ) {
14200
				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14201
			}
14202
		);
14203
	}
14204
 
14205
 
14206
	// Default sort methods
14207
	$.extend( _ext.type.order, {
14208
		// Dates
14209
		"date-pre": function ( d ) {
14210
			return Date.parse( d ) || 0;
14211
		},
14212
 
14213
		// html
14214
		"html-pre": function ( a ) {
14215
			return _empty(a) ?
14216
				'' :
14217
				a.replace ?
14218
					a.replace( /<.*?>/g, "" ).toLowerCase() :
14219
					a+'';
14220
		},
14221
 
14222
		// string
14223
		"string-pre": function ( a ) {
14224
			// This is a little complex, but faster than always calling toString,
14225
			// http://jsperf.com/tostring-v-check
14226
			return _empty(a) ?
14227
				'' :
14228
				typeof a === 'string' ?
14229
					a.toLowerCase() :
14230
					! a.toString ?
14231
						'' :
14232
						a.toString();
14233
		},
14234
 
14235
		// string-asc and -desc are retained only for compatibility with the old
14236
		// sort methods
14237
		"string-asc": function ( x, y ) {
14238
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14239
		},
14240
 
14241
		"string-desc": function ( x, y ) {
14242
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14243
		}
14244
	} );
14245
 
14246
 
14247
	// Numeric sorting types - order doesn't matter here
14248
	_addNumericSort( '' );
14249
 
14250
 
14251
	// Built in type detection. See model.ext.aTypes for information about
14252
	// what is required from this methods.
14253
	$.extend( DataTable.ext.type.detect, [
14254
		// Plain numbers - first since V8 detects some plain numbers as dates
14255
		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14256
		function ( d, settings )
14257
		{
14258
			var decimal = settings.oLanguage.sDecimal;
14259
			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14260
		},
14261
 
14262
		// Dates (only those recognised by the browser's Date.parse)
14263
		function ( d, settings )
14264
		{
14265
			// V8 will remove any unknown characters at the start and end of the
14266
			// expression, leading to false matches such as `$245.12` or `10%` being
14267
			// a valid date. See forum thread 18941 for detail.
14268
			if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14269
				return null;
14270
			}
14271
			var parsed = Date.parse(d);
14272
			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14273
		},
14274
 
14275
		// Formatted numbers
14276
		function ( d, settings )
14277
		{
14278
			var decimal = settings.oLanguage.sDecimal;
14279
			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14280
		},
14281
 
14282
		// HTML numeric
14283
		function ( d, settings )
14284
		{
14285
			var decimal = settings.oLanguage.sDecimal;
14286
			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14287
		},
14288
 
14289
		// HTML numeric, formatted
14290
		function ( d, settings )
14291
		{
14292
			var decimal = settings.oLanguage.sDecimal;
14293
			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14294
		},
14295
 
14296
		// HTML (this is strict checking - there must be html)
14297
		function ( d, settings )
14298
		{
14299
			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14300
				'html' : null;
14301
		}
14302
	] );
14303
 
14304
 
14305
 
14306
	// Filter formatting functions. See model.ext.ofnSearch for information about
14307
	// what is required from these methods.
14308
 
14309
 
14310
	$.extend( DataTable.ext.type.search, {
14311
		html: function ( data ) {
14312
			return _empty(data) ?
14313
				data :
14314
				typeof data === 'string' ?
14315
					data
14316
						.replace( _re_new_lines, " " )
14317
						.replace( _re_html, "" ) :
14318
					'';
14319
		},
14320
 
14321
		string: function ( data ) {
14322
			return _empty(data) ?
14323
				data :
14324
				typeof data === 'string' ?
14325
					data.replace( _re_new_lines, " " ) :
14326
					data;
14327
		}
14328
	} );
14329
 
14330
 
14331
 
14332
	$.extend( true, DataTable.ext.renderer, {
14333
		header: {
14334
			_: function ( settings, cell, column, classes ) {
14335
				// No additional mark-up required
14336
				// Attach a sort listener to update on sort - note that using the
14337
				// `DT` namespace will allow the event to be removed automatically
14338
				// on destroy, while the `dt` namespaced event is the one we are
14339
				// listening for
14340
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14341
					if ( settings !== ctx ) { // need to check this this is the host
14342
						return;               // table, not a nested one
14343
					}
14344
 
14345
					var colIdx = column.idx;
14346
 
14347
					cell
14348
						.removeClass(
14349
							column.sSortingClass +' '+
14350
							classes.sSortAsc +' '+
14351
							classes.sSortDesc
14352
						)
14353
						.addClass( columns[ colIdx ] == 'asc' ?
14354
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14355
								classes.sSortDesc :
14356
								column.sSortingClass
14357
						);
14358
				} );
14359
			},
14360
 
14361
			jqueryui: function ( settings, cell, column, classes ) {
14362
				$('<div/>')
14363
					.addClass( classes.sSortJUIWrapper )
14364
					.append( cell.contents() )
14365
					.append( $('<span/>')
14366
						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14367
					)
14368
					.appendTo( cell );
14369
 
14370
				// Attach a sort listener to update on sort
14371
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14372
					if ( settings !== ctx ) {
14373
						return;
14374
					}
14375
 
14376
					var colIdx = column.idx;
14377
 
14378
					cell
14379
						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14380
						.addClass( columns[ colIdx ] == 'asc' ?
14381
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14382
								classes.sSortDesc :
14383
								column.sSortingClass
14384
						);
14385
 
14386
					cell
14387
						.find( 'span.'+classes.sSortIcon )
14388
						.removeClass(
14389
							classes.sSortJUIAsc +" "+
14390
							classes.sSortJUIDesc +" "+
14391
							classes.sSortJUI +" "+
14392
							classes.sSortJUIAscAllowed +" "+
14393
							classes.sSortJUIDescAllowed
14394
						)
14395
						.addClass( columns[ colIdx ] == 'asc' ?
14396
							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14397
								classes.sSortJUIDesc :
14398
								column.sSortingClassJUI
14399
						);
14400
				} );
14401
			}
14402
		}
14403
	} );
14404
 
14405
	/*
14406
	 * Public helper functions. These aren't used internally by DataTables, or
14407
	 * called by any of the options passed into DataTables, but they can be used
14408
	 * externally by developers working with DataTables. They are helper functions
14409
	 * to make working with DataTables a little bit easier.
14410
	 */
14411
 
14412
	/**
14413
	 * Helpers for `columns.render`.
14414
	 *
14415
	 * The options defined here can be used with the `columns.render` initialisation
14416
	 * option to provide a display renderer. The following functions are defined:
14417
	 *
14418
	 * * `number` - Will format numeric data (defined by `columns.data`) for
14419
	 *   display, retaining the original unformatted data for sorting and filtering.
14420
	 *   It takes 4 parameters:
14421
	 *   * `string` - Thousands grouping separator
14422
	 *   * `string` - Decimal point indicator
14423
	 *   * `integer` - Number of decimal points to show
14424
	 *   * `string` (optional) - Prefix.
14425
	 *
14426
	 * @example
14427
	 *   // Column definition using the number renderer
14428
	 *   {
14429
	 *     data: "salary",
14430
	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14431
	 *   }
14432
	 *
14433
	 * @namespace
14434
	 */
14435
	DataTable.render = {
14436
		number: function ( thousands, decimal, precision, prefix ) {
14437
			return {
14438
				display: function ( d ) {
14439
					var negative = d < 0 ? '-' : '';
14440
					d = Math.abs( parseFloat( d ) );
14441
 
14442
					var intPart = parseInt( d, 10 );
14443
					var floatPart = precision ?
14444
						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14445
						'';
14446
 
14447
					return negative + (prefix||'') +
14448
						intPart.toString().replace(
14449
							/\B(?=(\d{3})+(?!\d))/g, thousands
14450
						) +
14451
						floatPart;
14452
				}
14453
			};
14454
		}
14455
	};
14456
 
14457
 
14458
	/*
14459
	 * This is really a good bit rubbish this method of exposing the internal methods
14460
	 * publicly... - To be fixed in 2.0 using methods on the prototype
14461
	 */
14462
 
14463
 
14464
	/**
14465
	 * Create a wrapper function for exporting an internal functions to an external API.
14466
	 *  @param {string} fn API function name
14467
	 *  @returns {function} wrapped function
14468
	 *  @memberof DataTable#internal
14469
	 */
14470
	function _fnExternApiFunc (fn)
14471
	{
14472
		return function() {
14473
			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14474
				Array.prototype.slice.call(arguments)
14475
			);
14476
			return DataTable.ext.internal[fn].apply( this, args );
14477
		};
14478
	}
14479
 
14480
 
14481
	/**
14482
	 * Reference to internal functions for use by plug-in developers. Note that
14483
	 * these methods are references to internal functions and are considered to be
14484
	 * private. If you use these methods, be aware that they are liable to change
14485
	 * between versions.
14486
	 *  @namespace
14487
	 */
14488
	$.extend( DataTable.ext.internal, {
14489
		_fnExternApiFunc: _fnExternApiFunc,
14490
		_fnBuildAjax: _fnBuildAjax,
14491
		_fnAjaxUpdate: _fnAjaxUpdate,
14492
		_fnAjaxParameters: _fnAjaxParameters,
14493
		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14494
		_fnAjaxDataSrc: _fnAjaxDataSrc,
14495
		_fnAddColumn: _fnAddColumn,
14496
		_fnColumnOptions: _fnColumnOptions,
14497
		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
14498
		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14499
		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
14500
		_fnVisbleColumns: _fnVisbleColumns,
14501
		_fnGetColumns: _fnGetColumns,
14502
		_fnColumnTypes: _fnColumnTypes,
14503
		_fnApplyColumnDefs: _fnApplyColumnDefs,
14504
		_fnHungarianMap: _fnHungarianMap,
14505
		_fnCamelToHungarian: _fnCamelToHungarian,
14506
		_fnLanguageCompat: _fnLanguageCompat,
14507
		_fnBrowserDetect: _fnBrowserDetect,
14508
		_fnAddData: _fnAddData,
14509
		_fnAddTr: _fnAddTr,
14510
		_fnNodeToDataIndex: _fnNodeToDataIndex,
14511
		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
14512
		_fnGetCellData: _fnGetCellData,
14513
		_fnSetCellData: _fnSetCellData,
14514
		_fnSplitObjNotation: _fnSplitObjNotation,
14515
		_fnGetObjectDataFn: _fnGetObjectDataFn,
14516
		_fnSetObjectDataFn: _fnSetObjectDataFn,
14517
		_fnGetDataMaster: _fnGetDataMaster,
14518
		_fnClearTable: _fnClearTable,
14519
		_fnDeleteIndex: _fnDeleteIndex,
14520
		_fnInvalidateRow: _fnInvalidateRow,
14521
		_fnGetRowElements: _fnGetRowElements,
14522
		_fnCreateTr: _fnCreateTr,
14523
		_fnBuildHead: _fnBuildHead,
14524
		_fnDrawHead: _fnDrawHead,
14525
		_fnDraw: _fnDraw,
14526
		_fnReDraw: _fnReDraw,
14527
		_fnAddOptionsHtml: _fnAddOptionsHtml,
14528
		_fnDetectHeader: _fnDetectHeader,
14529
		_fnGetUniqueThs: _fnGetUniqueThs,
14530
		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
14531
		_fnFilterComplete: _fnFilterComplete,
14532
		_fnFilterCustom: _fnFilterCustom,
14533
		_fnFilterColumn: _fnFilterColumn,
14534
		_fnFilter: _fnFilter,
14535
		_fnFilterCreateSearch: _fnFilterCreateSearch,
14536
		_fnEscapeRegex: _fnEscapeRegex,
14537
		_fnFilterData: _fnFilterData,
14538
		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
14539
		_fnUpdateInfo: _fnUpdateInfo,
14540
		_fnInfoMacros: _fnInfoMacros,
14541
		_fnInitialise: _fnInitialise,
14542
		_fnInitComplete: _fnInitComplete,
14543
		_fnLengthChange: _fnLengthChange,
14544
		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
14545
		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
14546
		_fnPageChange: _fnPageChange,
14547
		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
14548
		_fnProcessingDisplay: _fnProcessingDisplay,
14549
		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
14550
		_fnScrollDraw: _fnScrollDraw,
14551
		_fnApplyToChildren: _fnApplyToChildren,
14552
		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
14553
		_fnThrottle: _fnThrottle,
14554
		_fnConvertToWidth: _fnConvertToWidth,
14555
		_fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14556
		_fnGetWidestNode: _fnGetWidestNode,
14557
		_fnGetMaxLenString: _fnGetMaxLenString,
14558
		_fnStringToCss: _fnStringToCss,
14559
		_fnScrollBarWidth: _fnScrollBarWidth,
14560
		_fnSortFlatten: _fnSortFlatten,
14561
		_fnSort: _fnSort,
14562
		_fnSortAria: _fnSortAria,
14563
		_fnSortListener: _fnSortListener,
14564
		_fnSortAttachListener: _fnSortAttachListener,
14565
		_fnSortingClasses: _fnSortingClasses,
14566
		_fnSortData: _fnSortData,
14567
		_fnSaveState: _fnSaveState,
14568
		_fnLoadState: _fnLoadState,
14569
		_fnSettingsFromNode: _fnSettingsFromNode,
14570
		_fnLog: _fnLog,
14571
		_fnMap: _fnMap,
14572
		_fnBindAction: _fnBindAction,
14573
		_fnCallbackReg: _fnCallbackReg,
14574
		_fnCallbackFire: _fnCallbackFire,
14575
		_fnLengthOverflow: _fnLengthOverflow,
14576
		_fnRenderer: _fnRenderer,
14577
		_fnDataSource: _fnDataSource,
14578
		_fnRowAttributes: _fnRowAttributes,
14579
		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14580
		                                // in 1.10, so this dead-end function is
14581
		                                // added to prevent errors
14582
	} );
14583
 
14584
 
14585
	// jQuery access
14586
	$.fn.dataTable = DataTable;
14587
 
14588
	// Legacy aliases
14589
	$.fn.dataTableSettings = DataTable.settings;
14590
	$.fn.dataTableExt = DataTable.ext;
14591
 
14592
	// With a capital `D` we return a DataTables API instance rather than a
14593
	// jQuery object
14594
	$.fn.DataTable = function ( opts ) {
14595
		return $(this).dataTable( opts ).api();
14596
	};
14597
 
14598
	// All properties that are available to $.fn.dataTable should also be
14599
	// available on $.fn.DataTable
14600
	$.each( DataTable, function ( prop, val ) {
14601
		$.fn.DataTable[ prop ] = val;
14602
	} );
14603
 
14604
 
14605
	// Information about events fired by DataTables - for documentation.
14606
	/**
14607
	 * Draw event, fired whenever the table is redrawn on the page, at the same
14608
	 * point as fnDrawCallback. This may be useful for binding events or
14609
	 * performing calculations when the table is altered at all.
14610
	 *  @name DataTable#draw.dt
14611
	 *  @event
14612
	 *  @param {event} e jQuery event object
14613
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14614
	 */
14615
 
14616
	/**
14617
	 * Search event, fired when the searching applied to the table (using the
14618
	 * built-in global search, or column filters) is altered.
14619
	 *  @name DataTable#search.dt
14620
	 *  @event
14621
	 *  @param {event} e jQuery event object
14622
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14623
	 */
14624
 
14625
	/**
14626
	 * Page change event, fired when the paging of the table is altered.
14627
	 *  @name DataTable#page.dt
14628
	 *  @event
14629
	 *  @param {event} e jQuery event object
14630
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14631
	 */
14632
 
14633
	/**
14634
	 * Order event, fired when the ordering applied to the table is altered.
14635
	 *  @name DataTable#order.dt
14636
	 *  @event
14637
	 *  @param {event} e jQuery event object
14638
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14639
	 */
14640
 
14641
	/**
14642
	 * DataTables initialisation complete event, fired when the table is fully
14643
	 * drawn, including Ajax data loaded, if Ajax data is required.
14644
	 *  @name DataTable#init.dt
14645
	 *  @event
14646
	 *  @param {event} e jQuery event object
14647
	 *  @param {object} oSettings DataTables settings object
14648
	 *  @param {object} json The JSON object request from the server - only
14649
	 *    present if client-side Ajax sourced data is used</li></ol>
14650
	 */
14651
 
14652
	/**
14653
	 * State save event, fired when the table has changed state a new state save
14654
	 * is required. This event allows modification of the state saving object
14655
	 * prior to actually doing the save, including addition or other state
14656
	 * properties (for plug-ins) or modification of a DataTables core property.
14657
	 *  @name DataTable#stateSaveParams.dt
14658
	 *  @event
14659
	 *  @param {event} e jQuery event object
14660
	 *  @param {object} oSettings DataTables settings object
14661
	 *  @param {object} json The state information to be saved
14662
	 */
14663
 
14664
	/**
14665
	 * State load event, fired when the table is loading state from the stored
14666
	 * data, but prior to the settings object being modified by the saved state
14667
	 * - allowing modification of the saved state is required or loading of
14668
	 * state for a plug-in.
14669
	 *  @name DataTable#stateLoadParams.dt
14670
	 *  @event
14671
	 *  @param {event} e jQuery event object
14672
	 *  @param {object} oSettings DataTables settings object
14673
	 *  @param {object} json The saved state information
14674
	 */
14675
 
14676
	/**
14677
	 * State loaded event, fired when state has been loaded from stored data and
14678
	 * the settings object has been modified by the loaded data.
14679
	 *  @name DataTable#stateLoaded.dt
14680
	 *  @event
14681
	 *  @param {event} e jQuery event object
14682
	 *  @param {object} oSettings DataTables settings object
14683
	 *  @param {object} json The saved state information
14684
	 */
14685
 
14686
	/**
14687
	 * Processing event, fired when DataTables is doing some kind of processing
14688
	 * (be it, order, searcg or anything else). It can be used to indicate to
14689
	 * the end user that there is something happening, or that something has
14690
	 * finished.
14691
	 *  @name DataTable#processing.dt
14692
	 *  @event
14693
	 *  @param {event} e jQuery event object
14694
	 *  @param {object} oSettings DataTables settings object
14695
	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
14696
	 */
14697
 
14698
	/**
14699
	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
14700
	 * request to made to the server for new data. This event is called before
14701
	 * DataTables processed the returned data, so it can also be used to pre-
14702
	 * process the data returned from the server, if needed.
14703
	 *
14704
	 * Note that this trigger is called in `fnServerData`, if you override
14705
	 * `fnServerData` and which to use this event, you need to trigger it in you
14706
	 * success function.
14707
	 *  @name DataTable#xhr.dt
14708
	 *  @event
14709
	 *  @param {event} e jQuery event object
14710
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14711
	 *  @param {object} json JSON returned from the server
14712
	 *
14713
	 *  @example
14714
	 *     // Use a custom property returned from the server in another DOM element
14715
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14716
	 *       $('#status').html( json.status );
14717
	 *     } );
14718
	 *
14719
	 *  @example
14720
	 *     // Pre-process the data returned from the server
14721
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14722
	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
14723
	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
14724
	 *       }
14725
	 *       // Note no return - manipulate the data directly in the JSON object.
14726
	 *     } );
14727
	 */
14728
 
14729
	/**
14730
	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
14731
	 * or passing the bDestroy:true parameter in the initialisation object. This
14732
	 * can be used to remove bound events, added DOM nodes, etc.
14733
	 *  @name DataTable#destroy.dt
14734
	 *  @event
14735
	 *  @param {event} e jQuery event object
14736
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14737
	 */
14738
 
14739
	/**
14740
	 * Page length change event, fired when number of records to show on each
14741
	 * page (the length) is changed.
14742
	 *  @name DataTable#length.dt
14743
	 *  @event
14744
	 *  @param {event} e jQuery event object
14745
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14746
	 *  @param {integer} len New length
14747
	 */
14748
 
14749
	/**
14750
	 * Column sizing has changed.
14751
	 *  @name DataTable#column-sizing.dt
14752
	 *  @event
14753
	 *  @param {event} e jQuery event object
14754
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14755
	 */
14756
 
14757
	/**
14758
	 * Column visibility has changed.
14759
	 *  @name DataTable#column-visibility.dt
14760
	 *  @event
14761
	 *  @param {event} e jQuery event object
14762
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14763
	 *  @param {int} column Column index
14764
	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
14765
	 */
14766
 
14767
	return $.fn.dataTable;
14768
}));
14769
 
14770
}(window, document));
14771