Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
875 lars 1
/*! DataTables 1.10.9
2
 * ©2008-2015 SpryMedia Ltd - datatables.net/license
3
 */
4
 
5
/**
6
 * @summary     DataTables
7
 * @description Paginate, search and order HTML tables
8
 * @version     1.10.9
9
 * @file        jquery.dataTables.js
10
 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11
 * @contact     www.sprymedia.co.uk/contact
12
 * @copyright   Copyright 2008-2015 SpryMedia Ltd.
13
 *
14
 * This source file is free software, available under the following license:
15
 *   MIT license - http://datatables.net/license
16
 *
17
 * This source file is distributed in the hope that it will be useful, but
18
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20
 *
21
 * For details please refer to: http://www.datatables.net
22
 */
23
 
24
/*jslint evil: true, undef: true, browser: true */
25
/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26
 
27
(/** @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
		module.exports = 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
	// http://en.wikipedia.org/wiki/Foreign_exchange_market
115
	// - \u20BD - Russian ruble.
116
	// - \u20a9 - South Korean Won
117
	// - \u20BA - Turkish Lira
118
	// - \u20B9 - Indian Rupee
119
	// - R - Brazil (R$) and South Africa
120
	// - fr - Swiss Franc
121
	// - kr - Swedish krona, Norwegian krone and Danish krone
122
	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
123
	//   standards as thousands separators.
124
	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
125
 
126
 
127
	var _empty = function ( d ) {
128
		return !d || d === true || d === '-' ? true : false;
129
	};
130
 
131
 
132
	var _intVal = function ( s ) {
133
		var integer = parseInt( s, 10 );
134
		return !isNaN(integer) && isFinite(s) ? integer : null;
135
	};
136
 
137
	// Convert from a formatted number with characters other than `.` as the
138
	// decimal place, to a Javascript number
139
	var _numToDecimal = function ( num, decimalPoint ) {
140
		// Cache created regular expressions for speed as this function is called often
141
		if ( ! _re_dic[ decimalPoint ] ) {
142
			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
143
		}
144
		return typeof num === 'string' && decimalPoint !== '.' ?
145
			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
146
			num;
147
	};
148
 
149
 
150
	var _isNumber = function ( d, decimalPoint, formatted ) {
151
		var strType = typeof d === 'string';
152
 
153
		// If empty return immediately so there must be a number if it is a
154
		// formatted string (this stops the string "k", or "kr", etc being detected
155
		// as a formatted number for currency
156
		if ( _empty( d ) ) {
157
			return true;
158
		}
159
 
160
		if ( decimalPoint && strType ) {
161
			d = _numToDecimal( d, decimalPoint );
162
		}
163
 
164
		if ( formatted && strType ) {
165
			d = d.replace( _re_formatted_numeric, '' );
166
		}
167
 
168
		return !isNaN( parseFloat(d) ) && isFinite( d );
169
	};
170
 
171
 
172
	// A string without HTML in it can be considered to be HTML still
173
	var _isHtml = function ( d ) {
174
		return _empty( d ) || typeof d === 'string';
175
	};
176
 
177
 
178
	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
179
		if ( _empty( d ) ) {
180
			return true;
181
		}
182
 
183
		var html = _isHtml( d );
184
		return ! html ?
185
			null :
186
			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
187
				true :
188
				null;
189
	};
190
 
191
 
192
	var _pluck = function ( a, prop, prop2 ) {
193
		var out = [];
194
		var i=0, ien=a.length;
195
 
196
		// Could have the test in the loop for slightly smaller code, but speed
197
		// is essential here
198
		if ( prop2 !== undefined ) {
199
			for ( ; i<ien ; i++ ) {
200
				if ( a[i] && a[i][ prop ] ) {
201
					out.push( a[i][ prop ][ prop2 ] );
202
				}
203
			}
204
		}
205
		else {
206
			for ( ; i<ien ; i++ ) {
207
				if ( a[i] ) {
208
					out.push( a[i][ prop ] );
209
				}
210
			}
211
		}
212
 
213
		return out;
214
	};
215
 
216
 
217
	// Basically the same as _pluck, but rather than looping over `a` we use `order`
218
	// as the indexes to pick from `a`
219
	var _pluck_order = function ( a, order, prop, prop2 )
220
	{
221
		var out = [];
222
		var i=0, ien=order.length;
223
 
224
		// Could have the test in the loop for slightly smaller code, but speed
225
		// is essential here
226
		if ( prop2 !== undefined ) {
227
			for ( ; i<ien ; i++ ) {
228
				if ( a[ order[i] ][ prop ] ) {
229
					out.push( a[ order[i] ][ prop ][ prop2 ] );
230
				}
231
			}
232
		}
233
		else {
234
			for ( ; i<ien ; i++ ) {
235
				out.push( a[ order[i] ][ prop ] );
236
			}
237
		}
238
 
239
		return out;
240
	};
241
 
242
 
243
	var _range = function ( len, start )
244
	{
245
		var out = [];
246
		var end;
247
 
248
		if ( start === undefined ) {
249
			start = 0;
250
			end = len;
251
		}
252
		else {
253
			end = start;
254
			start = len;
255
		}
256
 
257
		for ( var i=start ; i<end ; i++ ) {
258
			out.push( i );
259
		}
260
 
261
		return out;
262
	};
263
 
264
 
265
	var _removeEmpty = function ( a )
266
	{
267
		var out = [];
268
 
269
		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
270
			if ( a[i] ) { // careful - will remove all falsy values!
271
				out.push( a[i] );
272
			}
273
		}
274
 
275
		return out;
276
	};
277
 
278
 
279
	var _stripHtml = function ( d ) {
280
		return d.replace( _re_html, '' );
281
	};
282
 
283
 
284
	/**
285
	 * Find the unique elements in a source array.
286
	 *
287
	 * @param  {array} src Source array
288
	 * @return {array} Array of unique items
289
	 * @ignore
290
	 */
291
	var _unique = function ( src )
292
	{
293
		// A faster unique method is to use object keys to identify used values,
294
		// but this doesn't work with arrays or objects, which we must also
295
		// consider. See jsperf.com/compare-array-unique-versions/4 for more
296
		// information.
297
		var
298
			out = [],
299
			val,
300
			i, ien=src.length,
301
			j, k=0;
302
 
303
		again: for ( i=0 ; i<ien ; i++ ) {
304
			val = src[i];
305
 
306
			for ( j=0 ; j<k ; j++ ) {
307
				if ( out[j] === val ) {
308
					continue again;
309
				}
310
			}
311
 
312
			out.push( val );
313
			k++;
314
		}
315
 
316
		return out;
317
	};
318
 
319
 
320
 
321
	/**
322
	 * Create a mapping object that allows camel case parameters to be looked up
323
	 * for their Hungarian counterparts. The mapping is stored in a private
324
	 * parameter called `_hungarianMap` which can be accessed on the source object.
325
	 *  @param {object} o
326
	 *  @memberof DataTable#oApi
327
	 */
328
	function _fnHungarianMap ( o )
329
	{
330
		var
331
			hungarian = 'a aa ai ao as b fn i m o s ',
332
			match,
333
			newKey,
334
			map = {};
335
 
336
		$.each( o, function (key, val) {
337
			match = key.match(/^([^A-Z]+?)([A-Z])/);
338
 
339
			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
340
			{
341
				newKey = key.replace( match[0], match[2].toLowerCase() );
342
				map[ newKey ] = key;
343
 
344
				if ( match[1] === 'o' )
345
				{
346
					_fnHungarianMap( o[key] );
347
				}
348
			}
349
		} );
350
 
351
		o._hungarianMap = map;
352
	}
353
 
354
 
355
	/**
356
	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
357
	 * created by _fnHungarianMap.
358
	 *  @param {object} src The model object which holds all parameters that can be
359
	 *    mapped.
360
	 *  @param {object} user The object to convert from camel case to Hungarian.
361
	 *  @param {boolean} force When set to `true`, properties which already have a
362
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
363
	 *    won't be.
364
	 *  @memberof DataTable#oApi
365
	 */
366
	function _fnCamelToHungarian ( src, user, force )
367
	{
368
		if ( ! src._hungarianMap ) {
369
			_fnHungarianMap( src );
370
		}
371
 
372
		var hungarianKey;
373
 
374
		$.each( user, function (key, val) {
375
			hungarianKey = src._hungarianMap[ key ];
376
 
377
			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
378
			{
379
				// For objects, we need to buzz down into the object to copy parameters
380
				if ( hungarianKey.charAt(0) === 'o' )
381
				{
382
					// Copy the camelCase options over to the hungarian
383
					if ( ! user[ hungarianKey ] ) {
384
						user[ hungarianKey ] = {};
385
					}
386
					$.extend( true, user[hungarianKey], user[key] );
387
 
388
					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
389
				}
390
				else {
391
					user[hungarianKey] = user[ key ];
392
				}
393
			}
394
		} );
395
	}
396
 
397
 
398
	/**
399
	 * Language compatibility - when certain options are given, and others aren't, we
400
	 * need to duplicate the values over, in order to provide backwards compatibility
401
	 * with older language files.
402
	 *  @param {object} oSettings dataTables settings object
403
	 *  @memberof DataTable#oApi
404
	 */
405
	function _fnLanguageCompat( lang )
406
	{
407
		var defaults = DataTable.defaults.oLanguage;
408
		var zeroRecords = lang.sZeroRecords;
409
 
410
		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
411
		 * sZeroRecords - assuming that is given.
412
		 */
413
		if ( ! lang.sEmptyTable && zeroRecords &&
414
			defaults.sEmptyTable === "No data available in table" )
415
		{
416
			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
417
		}
418
 
419
		/* Likewise with loading records */
420
		if ( ! lang.sLoadingRecords && zeroRecords &&
421
			defaults.sLoadingRecords === "Loading..." )
422
		{
423
			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
424
		}
425
 
426
		// Old parameter name of the thousands separator mapped onto the new
427
		if ( lang.sInfoThousands ) {
428
			lang.sThousands = lang.sInfoThousands;
429
		}
430
 
431
		var decimal = lang.sDecimal;
432
		if ( decimal ) {
433
			_addNumericSort( decimal );
434
		}
435
	}
436
 
437
 
438
	/**
439
	 * Map one parameter onto another
440
	 *  @param {object} o Object to map
441
	 *  @param {*} knew The new parameter name
442
	 *  @param {*} old The old parameter name
443
	 */
444
	var _fnCompatMap = function ( o, knew, old ) {
445
		if ( o[ knew ] !== undefined ) {
446
			o[ old ] = o[ knew ];
447
		}
448
	};
449
 
450
 
451
	/**
452
	 * Provide backwards compatibility for the main DT options. Note that the new
453
	 * options are mapped onto the old parameters, so this is an external interface
454
	 * change only.
455
	 *  @param {object} init Object to map
456
	 */
457
	function _fnCompatOpts ( init )
458
	{
459
		_fnCompatMap( init, 'ordering',      'bSort' );
460
		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
461
		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
462
		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
463
		_fnCompatMap( init, 'order',         'aaSorting' );
464
		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
465
		_fnCompatMap( init, 'paging',        'bPaginate' );
466
		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
467
		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
468
		_fnCompatMap( init, 'searching',     'bFilter' );
469
 
470
		// Boolean initialisation of x-scrolling
471
		if ( typeof init.sScrollX === 'boolean' ) {
472
			init.sScrollX = init.sScrollX ? '100%' : '';
473
		}
474
 
475
		// Column search objects are in an array, so it needs to be converted
476
		// element by element
477
		var searchCols = init.aoSearchCols;
478
 
479
		if ( searchCols ) {
480
			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
481
				if ( searchCols[i] ) {
482
					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
483
				}
484
			}
485
		}
486
	}
487
 
488
 
489
	/**
490
	 * Provide backwards compatibility for column options. Note that the new options
491
	 * are mapped onto the old parameters, so this is an external interface change
492
	 * only.
493
	 *  @param {object} init Object to map
494
	 */
495
	function _fnCompatCols ( init )
496
	{
497
		_fnCompatMap( init, 'orderable',     'bSortable' );
498
		_fnCompatMap( init, 'orderData',     'aDataSort' );
499
		_fnCompatMap( init, 'orderSequence', 'asSorting' );
500
		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
501
 
502
		// orderData can be given as an integer
503
		var dataSort = init.aDataSort;
504
		if ( dataSort && ! $.isArray( dataSort ) ) {
505
			init.aDataSort = [ dataSort ];
506
		}
507
	}
508
 
509
 
510
	/**
511
	 * Browser feature detection for capabilities, quirks
512
	 *  @param {object} settings dataTables settings object
513
	 *  @memberof DataTable#oApi
514
	 */
515
	function _fnBrowserDetect( settings )
516
	{
517
		// We don't need to do this every time DataTables is constructed, the values
518
		// calculated are specific to the browser and OS configuration which we
519
		// don't expect to change between initialisations
520
		if ( ! DataTable.__browser ) {
521
			var browser = {};
522
			DataTable.__browser = browser;
523
 
524
			// Scrolling feature / quirks detection
525
			var n = $('<div/>')
526
				.css( {
527
					position: 'fixed',
528
					top: 0,
529
					left: 0,
530
					height: 1,
531
					width: 1,
532
					overflow: 'hidden'
533
				} )
534
				.append(
535
					$('<div/>')
536
						.css( {
537
							position: 'absolute',
538
							top: 1,
539
							left: 1,
540
							width: 100,
541
							overflow: 'scroll'
542
						} )
543
						.append(
544
							$('<div/>')
545
								.css( {
546
									width: '100%',
547
									height: 10
548
								} )
549
						)
550
				)
551
				.appendTo( 'body' );
552
 
553
			var outer = n.children();
554
			var inner = outer.children();
555
 
556
			// Numbers below, in order, are:
557
			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
558
			//
559
			// IE6 XP:                           100 100 100  83
560
			// IE7 Vista:                        100 100 100  83
561
			// IE 8+ Windows:                     83  83 100  83
562
			// Evergreen Windows:                 83  83 100  83
563
			// Evergreen Mac with scrollbars:     85  85 100  85
564
			// Evergreen Mac without scrollbars: 100 100 100 100
565
 
566
			// Get scrollbar width
567
			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
568
 
569
			// IE6/7 will oversize a width 100% element inside a scrolling element, to
570
			// include the width of the scrollbar, while other browsers ensure the inner
571
			// element is contained without forcing scrolling
572
			//console.log( inner.offsetWidth );
573
			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
574
 
575
			// In rtl text layout, some browsers (most, but not all) will place the
576
			// scrollbar on the left, rather than the right.
577
			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
578
 
579
			// IE8- don't provide height and width for getBoundingClientRect
580
			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
581
 
582
			n.remove();
583
		}
584
 
585
		$.extend( settings.oBrowser, DataTable.__browser );
586
		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
587
	}
588
 
589
 
590
	/**
591
	 * Array.prototype reduce[Right] method, used for browsers which don't support
592
	 * JS 1.6. Done this way to reduce code size, since we iterate either way
593
	 *  @param {object} settings dataTables settings object
594
	 *  @memberof DataTable#oApi
595
	 */
596
	function _fnReduce ( that, fn, init, start, end, inc )
597
	{
598
		var
599
			i = start,
600
			value,
601
			isSet = false;
602
 
603
		if ( init !== undefined ) {
604
			value = init;
605
			isSet = true;
606
		}
607
 
608
		while ( i !== end ) {
609
			if ( ! that.hasOwnProperty(i) ) {
610
				continue;
611
			}
612
 
613
			value = isSet ?
614
				fn( value, that[i], i, that ) :
615
				that[i];
616
 
617
			isSet = true;
618
			i += inc;
619
		}
620
 
621
		return value;
622
	}
623
 
624
	/**
625
	 * Add a column to the list used for the table with default values
626
	 *  @param {object} oSettings dataTables settings object
627
	 *  @param {node} nTh The th element for this column
628
	 *  @memberof DataTable#oApi
629
	 */
630
	function _fnAddColumn( oSettings, nTh )
631
	{
632
		// Add column to aoColumns array
633
		var oDefaults = DataTable.defaults.column;
634
		var iCol = oSettings.aoColumns.length;
635
		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
636
			"nTh": nTh ? nTh : document.createElement('th'),
637
			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
638
			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
639
			"mData": oDefaults.mData ? oDefaults.mData : iCol,
640
			idx: iCol
641
		} );
642
		oSettings.aoColumns.push( oCol );
643
 
644
		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
645
		// passed into extend can be undefined. This allows the user to give a default
646
		// with only some of the parameters defined, and also not give a default
647
		var searchCols = oSettings.aoPreSearchCols;
648
		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
649
 
650
		// Use the default column options function to initialise classes etc
651
		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
652
	}
653
 
654
 
655
	/**
656
	 * Apply options for a column
657
	 *  @param {object} oSettings dataTables settings object
658
	 *  @param {int} iCol column index to consider
659
	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
660
	 *  @memberof DataTable#oApi
661
	 */
662
	function _fnColumnOptions( oSettings, iCol, oOptions )
663
	{
664
		var oCol = oSettings.aoColumns[ iCol ];
665
		var oClasses = oSettings.oClasses;
666
		var th = $(oCol.nTh);
667
 
668
		// Try to get width information from the DOM. We can't get it from CSS
669
		// as we'd need to parse the CSS stylesheet. `width` option can override
670
		if ( ! oCol.sWidthOrig ) {
671
			// Width attribute
672
			oCol.sWidthOrig = th.attr('width') || null;
673
 
674
			// Style attribute
675
			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
676
			if ( t ) {
677
				oCol.sWidthOrig = t[1];
678
			}
679
		}
680
 
681
		/* User specified column options */
682
		if ( oOptions !== undefined && oOptions !== null )
683
		{
684
			// Backwards compatibility
685
			_fnCompatCols( oOptions );
686
 
687
			// Map camel case parameters to their Hungarian counterparts
688
			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
689
 
690
			/* Backwards compatibility for mDataProp */
691
			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
692
			{
693
				oOptions.mData = oOptions.mDataProp;
694
			}
695
 
696
			if ( oOptions.sType )
697
			{
698
				oCol._sManualType = oOptions.sType;
699
			}
700
 
701
			// `class` is a reserved word in Javascript, so we need to provide
702
			// the ability to use a valid name for the camel case input
703
			if ( oOptions.className && ! oOptions.sClass )
704
			{
705
				oOptions.sClass = oOptions.className;
706
			}
707
 
708
			$.extend( oCol, oOptions );
709
			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
710
 
711
			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
712
			 * priority if defined
713
			 */
714
			if ( oOptions.iDataSort !== undefined )
715
			{
716
				oCol.aDataSort = [ oOptions.iDataSort ];
717
			}
718
			_fnMap( oCol, oOptions, "aDataSort" );
719
		}
720
 
721
		/* Cache the data get and set functions for speed */
722
		var mDataSrc = oCol.mData;
723
		var mData = _fnGetObjectDataFn( mDataSrc );
724
		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
725
 
726
		var attrTest = function( src ) {
727
			return typeof src === 'string' && src.indexOf('@') !== -1;
728
		};
729
		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
730
			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
731
		);
732
 
733
		oCol.fnGetData = function (rowData, type, meta) {
734
			var innerData = mData( rowData, type, undefined, meta );
735
 
736
			return mRender && type ?
737
				mRender( innerData, type, rowData, meta ) :
738
				innerData;
739
		};
740
		oCol.fnSetData = function ( rowData, val, meta ) {
741
			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
742
		};
743
 
744
		// Indicate if DataTables should read DOM data as an object or array
745
		// Used in _fnGetRowElements
746
		if ( typeof mDataSrc !== 'number' ) {
747
			oSettings._rowReadObject = true;
748
		}
749
 
750
		/* Feature sorting overrides column specific when off */
751
		if ( !oSettings.oFeatures.bSort )
752
		{
753
			oCol.bSortable = false;
754
			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
755
		}
756
 
757
		/* Check that the class assignment is correct for sorting */
758
		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
759
		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
760
		if ( !oCol.bSortable || (!bAsc && !bDesc) )
761
		{
762
			oCol.sSortingClass = oClasses.sSortableNone;
763
			oCol.sSortingClassJUI = "";
764
		}
765
		else if ( bAsc && !bDesc )
766
		{
767
			oCol.sSortingClass = oClasses.sSortableAsc;
768
			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
769
		}
770
		else if ( !bAsc && bDesc )
771
		{
772
			oCol.sSortingClass = oClasses.sSortableDesc;
773
			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
774
		}
775
		else
776
		{
777
			oCol.sSortingClass = oClasses.sSortable;
778
			oCol.sSortingClassJUI = oClasses.sSortJUI;
779
		}
780
	}
781
 
782
 
783
	/**
784
	 * Adjust the table column widths for new data. Note: you would probably want to
785
	 * do a redraw after calling this function!
786
	 *  @param {object} settings dataTables settings object
787
	 *  @memberof DataTable#oApi
788
	 */
789
	function _fnAdjustColumnSizing ( settings )
790
	{
791
		/* Not interested in doing column width calculation if auto-width is disabled */
792
		if ( settings.oFeatures.bAutoWidth !== false )
793
		{
794
			var columns = settings.aoColumns;
795
 
796
			_fnCalculateColumnWidths( settings );
797
			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
798
			{
799
				columns[i].nTh.style.width = columns[i].sWidth;
800
			}
801
		}
802
 
803
		var scroll = settings.oScroll;
804
		if ( scroll.sY !== '' || scroll.sX !== '')
805
		{
806
			_fnScrollDraw( settings );
807
		}
808
 
809
		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
810
	}
811
 
812
 
813
	/**
814
	 * Covert the index of a visible column to the index in the data array (take account
815
	 * of hidden columns)
816
	 *  @param {object} oSettings dataTables settings object
817
	 *  @param {int} iMatch Visible column index to lookup
818
	 *  @returns {int} i the data index
819
	 *  @memberof DataTable#oApi
820
	 */
821
	function _fnVisibleToColumnIndex( oSettings, iMatch )
822
	{
823
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
824
 
825
		return typeof aiVis[iMatch] === 'number' ?
826
			aiVis[iMatch] :
827
			null;
828
	}
829
 
830
 
831
	/**
832
	 * Covert the index of an index in the data array and convert it to the visible
833
	 *   column index (take account of hidden columns)
834
	 *  @param {int} iMatch Column index to lookup
835
	 *  @param {object} oSettings dataTables settings object
836
	 *  @returns {int} i the data index
837
	 *  @memberof DataTable#oApi
838
	 */
839
	function _fnColumnIndexToVisible( oSettings, iMatch )
840
	{
841
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
842
		var iPos = $.inArray( iMatch, aiVis );
843
 
844
		return iPos !== -1 ? iPos : null;
845
	}
846
 
847
 
848
	/**
849
	 * Get the number of visible columns
850
	 *  @param {object} oSettings dataTables settings object
851
	 *  @returns {int} i the number of visible columns
852
	 *  @memberof DataTable#oApi
853
	 */
854
	function _fnVisbleColumns( oSettings )
855
	{
856
		return _fnGetColumns( oSettings, 'bVisible' ).length;
857
	}
858
 
859
 
860
	/**
861
	 * Get an array of column indexes that match a given property
862
	 *  @param {object} oSettings dataTables settings object
863
	 *  @param {string} sParam Parameter in aoColumns to look for - typically
864
	 *    bVisible or bSearchable
865
	 *  @returns {array} Array of indexes with matched properties
866
	 *  @memberof DataTable#oApi
867
	 */
868
	function _fnGetColumns( oSettings, sParam )
869
	{
870
		var a = [];
871
 
872
		$.map( oSettings.aoColumns, function(val, i) {
873
			if ( val[sParam] ) {
874
				a.push( i );
875
			}
876
		} );
877
 
878
		return a;
879
	}
880
 
881
 
882
	/**
883
	 * Calculate the 'type' of a column
884
	 *  @param {object} settings dataTables settings object
885
	 *  @memberof DataTable#oApi
886
	 */
887
	function _fnColumnTypes ( settings )
888
	{
889
		var columns = settings.aoColumns;
890
		var data = settings.aoData;
891
		var types = DataTable.ext.type.detect;
892
		var i, ien, j, jen, k, ken;
893
		var col, cell, detectedType, cache;
894
 
895
		// For each column, spin over the
896
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
897
			col = columns[i];
898
			cache = [];
899
 
900
			if ( ! col.sType && col._sManualType ) {
901
				col.sType = col._sManualType;
902
			}
903
			else if ( ! col.sType ) {
904
				for ( j=0, jen=types.length ; j<jen ; j++ ) {
905
					for ( k=0, ken=data.length ; k<ken ; k++ ) {
906
						// Use a cache array so we only need to get the type data
907
						// from the formatter once (when using multiple detectors)
908
						if ( cache[k] === undefined ) {
909
							cache[k] = _fnGetCellData( settings, k, i, 'type' );
910
						}
911
 
912
						detectedType = types[j]( cache[k], settings );
913
 
914
						// If null, then this type can't apply to this column, so
915
						// rather than testing all cells, break out. There is an
916
						// exception for the last type which is `html`. We need to
917
						// scan all rows since it is possible to mix string and HTML
918
						// types
919
						if ( ! detectedType && j !== types.length-1 ) {
920
							break;
921
						}
922
 
923
						// Only a single match is needed for html type since it is
924
						// bottom of the pile and very similar to string
925
						if ( detectedType === 'html' ) {
926
							break;
927
						}
928
					}
929
 
930
					// Type is valid for all data points in the column - use this
931
					// type
932
					if ( detectedType ) {
933
						col.sType = detectedType;
934
						break;
935
					}
936
				}
937
 
938
				// Fall back - if no type was detected, always use string
939
				if ( ! col.sType ) {
940
					col.sType = 'string';
941
				}
942
			}
943
		}
944
	}
945
 
946
 
947
	/**
948
	 * Take the column definitions and static columns arrays and calculate how
949
	 * they relate to column indexes. The callback function will then apply the
950
	 * definition found for a column to a suitable configuration object.
951
	 *  @param {object} oSettings dataTables settings object
952
	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
953
	 *  @param {array} aoCols The aoColumns array that defines columns individually
954
	 *  @param {function} fn Callback function - takes two parameters, the calculated
955
	 *    column index and the definition for that column.
956
	 *  @memberof DataTable#oApi
957
	 */
958
	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
959
	{
960
		var i, iLen, j, jLen, k, kLen, def;
961
		var columns = oSettings.aoColumns;
962
 
963
		// Column definitions with aTargets
964
		if ( aoColDefs )
965
		{
966
			/* Loop over the definitions array - loop in reverse so first instance has priority */
967
			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
968
			{
969
				def = aoColDefs[i];
970
 
971
				/* Each definition can target multiple columns, as it is an array */
972
				var aTargets = def.targets !== undefined ?
973
					def.targets :
974
					def.aTargets;
975
 
976
				if ( ! $.isArray( aTargets ) )
977
				{
978
					aTargets = [ aTargets ];
979
				}
980
 
981
				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
982
				{
983
					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
984
					{
985
						/* Add columns that we don't yet know about */
986
						while( columns.length <= aTargets[j] )
987
						{
988
							_fnAddColumn( oSettings );
989
						}
990
 
991
						/* Integer, basic index */
992
						fn( aTargets[j], def );
993
					}
994
					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
995
					{
996
						/* Negative integer, right to left column counting */
997
						fn( columns.length+aTargets[j], def );
998
					}
999
					else if ( typeof aTargets[j] === 'string' )
1000
					{
1001
						/* Class name matching on TH element */
1002
						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
1003
						{
1004
							if ( aTargets[j] == "_all" ||
1005
							     $(columns[k].nTh).hasClass( aTargets[j] ) )
1006
							{
1007
								fn( k, def );
1008
							}
1009
						}
1010
					}
1011
				}
1012
			}
1013
		}
1014
 
1015
		// Statically defined columns array
1016
		if ( aoCols )
1017
		{
1018
			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
1019
			{
1020
				fn( i, aoCols[i] );
1021
			}
1022
		}
1023
	}
1024
 
1025
	/**
1026
	 * Add a data array to the table, creating DOM node etc. This is the parallel to
1027
	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
1028
	 * DOM source.
1029
	 *  @param {object} oSettings dataTables settings object
1030
	 *  @param {array} aData data array to be added
1031
	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
1032
	 *    DataTables will create a row automatically
1033
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1034
	 *    if nTr is.
1035
	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
1036
	 *  @memberof DataTable#oApi
1037
	 */
1038
	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
1039
	{
1040
		/* Create the object for storing information about this new row */
1041
		var iRow = oSettings.aoData.length;
1042
		var oData = $.extend( true, {}, DataTable.models.oRow, {
1043
			src: nTr ? 'dom' : 'data',
1044
			idx: iRow
1045
		} );
1046
 
1047
		oData._aData = aDataIn;
1048
		oSettings.aoData.push( oData );
1049
 
1050
		/* Create the cells */
1051
		var nTd, sThisType;
1052
		var columns = oSettings.aoColumns;
1053
 
1054
		// Invalidate the column types as the new data needs to be revalidated
1055
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
1056
		{
1057
			columns[i].sType = null;
1058
		}
1059
 
1060
		/* Add to the display array */
1061
		oSettings.aiDisplayMaster.push( iRow );
1062
 
1063
		var id = oSettings.rowIdFn( aDataIn );
1064
		if ( id !== undefined ) {
1065
			oSettings.aIds[ id ] = oData;
1066
		}
1067
 
1068
		/* Create the DOM information, or register it if already present */
1069
		if ( nTr || ! oSettings.oFeatures.bDeferRender )
1070
		{
1071
			_fnCreateTr( oSettings, iRow, nTr, anTds );
1072
		}
1073
 
1074
		return iRow;
1075
	}
1076
 
1077
 
1078
	/**
1079
	 * Add one or more TR elements to the table. Generally we'd expect to
1080
	 * use this for reading data from a DOM sourced table, but it could be
1081
	 * used for an TR element. Note that if a TR is given, it is used (i.e.
1082
	 * it is not cloned).
1083
	 *  @param {object} settings dataTables settings object
1084
	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
1085
	 *  @returns {array} Array of indexes for the added rows
1086
	 *  @memberof DataTable#oApi
1087
	 */
1088
	function _fnAddTr( settings, trs )
1089
	{
1090
		var row;
1091
 
1092
		// Allow an individual node to be passed in
1093
		if ( ! (trs instanceof $) ) {
1094
			trs = $(trs);
1095
		}
1096
 
1097
		return trs.map( function (i, el) {
1098
			row = _fnGetRowElements( settings, el );
1099
			return _fnAddData( settings, row.data, el, row.cells );
1100
		} );
1101
	}
1102
 
1103
 
1104
	/**
1105
	 * Take a TR element and convert it to an index in aoData
1106
	 *  @param {object} oSettings dataTables settings object
1107
	 *  @param {node} n the TR element to find
1108
	 *  @returns {int} index if the node is found, null if not
1109
	 *  @memberof DataTable#oApi
1110
	 */
1111
	function _fnNodeToDataIndex( oSettings, n )
1112
	{
1113
		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
1114
	}
1115
 
1116
 
1117
	/**
1118
	 * Take a TD element and convert it into a column data index (not the visible index)
1119
	 *  @param {object} oSettings dataTables settings object
1120
	 *  @param {int} iRow The row number the TD/TH can be found in
1121
	 *  @param {node} n The TD/TH element to find
1122
	 *  @returns {int} index if the node is found, -1 if not
1123
	 *  @memberof DataTable#oApi
1124
	 */
1125
	function _fnNodeToColumnIndex( oSettings, iRow, n )
1126
	{
1127
		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
1128
	}
1129
 
1130
 
1131
	/**
1132
	 * Get the data for a given cell from the internal cache, taking into account data mapping
1133
	 *  @param {object} settings dataTables settings object
1134
	 *  @param {int} rowIdx aoData row id
1135
	 *  @param {int} colIdx Column index
1136
	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
1137
	 *  @returns {*} Cell data
1138
	 *  @memberof DataTable#oApi
1139
	 */
1140
	function _fnGetCellData( settings, rowIdx, colIdx, type )
1141
	{
1142
		var draw           = settings.iDraw;
1143
		var col            = settings.aoColumns[colIdx];
1144
		var rowData        = settings.aoData[rowIdx]._aData;
1145
		var defaultContent = col.sDefaultContent;
1146
		var cellData       = col.fnGetData( rowData, type, {
1147
			settings: settings,
1148
			row:      rowIdx,
1149
			col:      colIdx
1150
		} );
1151
 
1152
		if ( cellData === undefined ) {
1153
			if ( settings.iDrawError != draw && defaultContent === null ) {
1154
				_fnLog( settings, 0, "Requested unknown parameter "+
1155
					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
1156
					" for row "+rowIdx, 4 );
1157
				settings.iDrawError = draw;
1158
			}
1159
			return defaultContent;
1160
		}
1161
 
1162
		/* When the data source is null, we can use default column data */
1163
		if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
1164
			cellData = defaultContent;
1165
		}
1166
		else if ( typeof cellData === 'function' ) {
1167
			// If the data source is a function, then we run it and use the return,
1168
			// executing in the scope of the data object (for instances)
1169
			return cellData.call( rowData );
1170
		}
1171
 
1172
		if ( cellData === null && type == 'display' ) {
1173
			return '';
1174
		}
1175
		return cellData;
1176
	}
1177
 
1178
 
1179
	/**
1180
	 * Set the value for a specific cell, into the internal data cache
1181
	 *  @param {object} settings dataTables settings object
1182
	 *  @param {int} rowIdx aoData row id
1183
	 *  @param {int} colIdx Column index
1184
	 *  @param {*} val Value to set
1185
	 *  @memberof DataTable#oApi
1186
	 */
1187
	function _fnSetCellData( settings, rowIdx, colIdx, val )
1188
	{
1189
		var col     = settings.aoColumns[colIdx];
1190
		var rowData = settings.aoData[rowIdx]._aData;
1191
 
1192
		col.fnSetData( rowData, val, {
1193
			settings: settings,
1194
			row:      rowIdx,
1195
			col:      colIdx
1196
		}  );
1197
	}
1198
 
1199
 
1200
	// Private variable that is used to match action syntax in the data property object
1201
	var __reArray = /\[.*?\]$/;
1202
	var __reFn = /\(\)$/;
1203
 
1204
	/**
1205
	 * Split string on periods, taking into account escaped periods
1206
	 * @param  {string} str String to split
1207
	 * @return {array} Split string
1208
	 */
1209
	function _fnSplitObjNotation( str )
1210
	{
1211
		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
1212
			return s.replace(/\\./g, '.');
1213
		} );
1214
	}
1215
 
1216
 
1217
	/**
1218
	 * Return a function that can be used to get data from a source object, taking
1219
	 * into account the ability to use nested objects as a source
1220
	 *  @param {string|int|function} mSource The data source for the object
1221
	 *  @returns {function} Data get function
1222
	 *  @memberof DataTable#oApi
1223
	 */
1224
	function _fnGetObjectDataFn( mSource )
1225
	{
1226
		if ( $.isPlainObject( mSource ) )
1227
		{
1228
			/* Build an object of get functions, and wrap them in a single call */
1229
			var o = {};
1230
			$.each( mSource, function (key, val) {
1231
				if ( val ) {
1232
					o[key] = _fnGetObjectDataFn( val );
1233
				}
1234
			} );
1235
 
1236
			return function (data, type, row, meta) {
1237
				var t = o[type] || o._;
1238
				return t !== undefined ?
1239
					t(data, type, row, meta) :
1240
					data;
1241
			};
1242
		}
1243
		else if ( mSource === null )
1244
		{
1245
			/* Give an empty string for rendering / sorting etc */
1246
			return function (data) { // type, row and meta also passed, but not used
1247
				return data;
1248
			};
1249
		}
1250
		else if ( typeof mSource === 'function' )
1251
		{
1252
			return function (data, type, row, meta) {
1253
				return mSource( data, type, row, meta );
1254
			};
1255
		}
1256
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1257
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1258
		{
1259
			/* If there is a . in the source string then the data source is in a
1260
			 * nested object so we loop over the data for each level to get the next
1261
			 * level down. On each loop we test for undefined, and if found immediately
1262
			 * return. This allows entire objects to be missing and sDefaultContent to
1263
			 * be used if defined, rather than throwing an error
1264
			 */
1265
			var fetchData = function (data, type, src) {
1266
				var arrayNotation, funcNotation, out, innerSrc;
1267
 
1268
				if ( src !== "" )
1269
				{
1270
					var a = _fnSplitObjNotation( src );
1271
 
1272
					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1273
					{
1274
						// Check if we are dealing with special notation
1275
						arrayNotation = a[i].match(__reArray);
1276
						funcNotation = a[i].match(__reFn);
1277
 
1278
						if ( arrayNotation )
1279
						{
1280
							// Array notation
1281
							a[i] = a[i].replace(__reArray, '');
1282
 
1283
							// Condition allows simply [] to be passed in
1284
							if ( a[i] !== "" ) {
1285
								data = data[ a[i] ];
1286
							}
1287
							out = [];
1288
 
1289
							// Get the remainder of the nested object to get
1290
							a.splice( 0, i+1 );
1291
							innerSrc = a.join('.');
1292
 
1293
							// Traverse each entry in the array getting the properties requested
1294
							if ( $.isArray( data ) ) {
1295
								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1296
									out.push( fetchData( data[j], type, innerSrc ) );
1297
								}
1298
							}
1299
 
1300
							// If a string is given in between the array notation indicators, that
1301
							// is used to join the strings together, otherwise an array is returned
1302
							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1303
							data = (join==="") ? out : out.join(join);
1304
 
1305
							// The inner call to fetchData has already traversed through the remainder
1306
							// of the source requested, so we exit from the loop
1307
							break;
1308
						}
1309
						else if ( funcNotation )
1310
						{
1311
							// Function call
1312
							a[i] = a[i].replace(__reFn, '');
1313
							data = data[ a[i] ]();
1314
							continue;
1315
						}
1316
 
1317
						if ( data === null || data[ a[i] ] === undefined )
1318
						{
1319
							return undefined;
1320
						}
1321
						data = data[ a[i] ];
1322
					}
1323
				}
1324
 
1325
				return data;
1326
			};
1327
 
1328
			return function (data, type) { // row and meta also passed, but not used
1329
				return fetchData( data, type, mSource );
1330
			};
1331
		}
1332
		else
1333
		{
1334
			/* Array or flat object mapping */
1335
			return function (data, type) { // row and meta also passed, but not used
1336
				return data[mSource];
1337
			};
1338
		}
1339
	}
1340
 
1341
 
1342
	/**
1343
	 * Return a function that can be used to set data from a source object, taking
1344
	 * into account the ability to use nested objects as a source
1345
	 *  @param {string|int|function} mSource The data source for the object
1346
	 *  @returns {function} Data set function
1347
	 *  @memberof DataTable#oApi
1348
	 */
1349
	function _fnSetObjectDataFn( mSource )
1350
	{
1351
		if ( $.isPlainObject( mSource ) )
1352
		{
1353
			/* Unlike get, only the underscore (global) option is used for for
1354
			 * setting data since we don't know the type here. This is why an object
1355
			 * option is not documented for `mData` (which is read/write), but it is
1356
			 * for `mRender` which is read only.
1357
			 */
1358
			return _fnSetObjectDataFn( mSource._ );
1359
		}
1360
		else if ( mSource === null )
1361
		{
1362
			/* Nothing to do when the data source is null */
1363
			return function () {};
1364
		}
1365
		else if ( typeof mSource === 'function' )
1366
		{
1367
			return function (data, val, meta) {
1368
				mSource( data, 'set', val, meta );
1369
			};
1370
		}
1371
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1372
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1373
		{
1374
			/* Like the get, we need to get data from a nested object */
1375
			var setData = function (data, val, src) {
1376
				var a = _fnSplitObjNotation( src ), b;
1377
				var aLast = a[a.length-1];
1378
				var arrayNotation, funcNotation, o, innerSrc;
1379
 
1380
				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
1381
				{
1382
					// Check if we are dealing with an array notation request
1383
					arrayNotation = a[i].match(__reArray);
1384
					funcNotation = a[i].match(__reFn);
1385
 
1386
					if ( arrayNotation )
1387
					{
1388
						a[i] = a[i].replace(__reArray, '');
1389
						data[ a[i] ] = [];
1390
 
1391
						// Get the remainder of the nested object to set so we can recurse
1392
						b = a.slice();
1393
						b.splice( 0, i+1 );
1394
						innerSrc = b.join('.');
1395
 
1396
						// Traverse each entry in the array setting the properties requested
1397
						if ( $.isArray( val ) )
1398
						{
1399
							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1400
							{
1401
								o = {};
1402
								setData( o, val[j], innerSrc );
1403
								data[ a[i] ].push( o );
1404
							}
1405
						}
1406
						else
1407
						{
1408
							// We've been asked to save data to an array, but it
1409
							// isn't array data to be saved. Best that can be done
1410
							// is to just save the value.
1411
							data[ a[i] ] = val;
1412
						}
1413
 
1414
						// The inner call to setData has already traversed through the remainder
1415
						// of the source and has set the data, thus we can exit here
1416
						return;
1417
					}
1418
					else if ( funcNotation )
1419
					{
1420
						// Function call
1421
						a[i] = a[i].replace(__reFn, '');
1422
						data = data[ a[i] ]( val );
1423
					}
1424
 
1425
					// If the nested object doesn't currently exist - since we are
1426
					// trying to set the value - create it
1427
					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
1428
					{
1429
						data[ a[i] ] = {};
1430
					}
1431
					data = data[ a[i] ];
1432
				}
1433
 
1434
				// Last item in the input - i.e, the actual set
1435
				if ( aLast.match(__reFn ) )
1436
				{
1437
					// Function call
1438
					data = data[ aLast.replace(__reFn, '') ]( val );
1439
				}
1440
				else
1441
				{
1442
					// If array notation is used, we just want to strip it and use the property name
1443
					// and assign the value. If it isn't used, then we get the result we want anyway
1444
					data[ aLast.replace(__reArray, '') ] = val;
1445
				}
1446
			};
1447
 
1448
			return function (data, val) { // meta is also passed in, but not used
1449
				return setData( data, val, mSource );
1450
			};
1451
		}
1452
		else
1453
		{
1454
			/* Array or flat object mapping */
1455
			return function (data, val) { // meta is also passed in, but not used
1456
				data[mSource] = val;
1457
			};
1458
		}
1459
	}
1460
 
1461
 
1462
	/**
1463
	 * Return an array with the full table data
1464
	 *  @param {object} oSettings dataTables settings object
1465
	 *  @returns array {array} aData Master data array
1466
	 *  @memberof DataTable#oApi
1467
	 */
1468
	function _fnGetDataMaster ( settings )
1469
	{
1470
		return _pluck( settings.aoData, '_aData' );
1471
	}
1472
 
1473
 
1474
	/**
1475
	 * Nuke the table
1476
	 *  @param {object} oSettings dataTables settings object
1477
	 *  @memberof DataTable#oApi
1478
	 */
1479
	function _fnClearTable( settings )
1480
	{
1481
		settings.aoData.length = 0;
1482
		settings.aiDisplayMaster.length = 0;
1483
		settings.aiDisplay.length = 0;
1484
		settings.aIds = {};
1485
	}
1486
 
1487
 
1488
	 /**
1489
	 * Take an array of integers (index array) and remove a target integer (value - not
1490
	 * the key!)
1491
	 *  @param {array} a Index array to target
1492
	 *  @param {int} iTarget value to find
1493
	 *  @memberof DataTable#oApi
1494
	 */
1495
	function _fnDeleteIndex( a, iTarget, splice )
1496
	{
1497
		var iTargetIndex = -1;
1498
 
1499
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1500
		{
1501
			if ( a[i] == iTarget )
1502
			{
1503
				iTargetIndex = i;
1504
			}
1505
			else if ( a[i] > iTarget )
1506
			{
1507
				a[i]--;
1508
			}
1509
		}
1510
 
1511
		if ( iTargetIndex != -1 && splice === undefined )
1512
		{
1513
			a.splice( iTargetIndex, 1 );
1514
		}
1515
	}
1516
 
1517
 
1518
	/**
1519
	 * Mark cached data as invalid such that a re-read of the data will occur when
1520
	 * the cached data is next requested. Also update from the data source object.
1521
	 *
1522
	 * @param {object} settings DataTables settings object
1523
	 * @param {int}    rowIdx   Row index to invalidate
1524
	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
1525
	 *     or 'data'
1526
	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
1527
	 *     row will be invalidated
1528
	 * @memberof DataTable#oApi
1529
	 *
1530
	 * @todo For the modularisation of v1.11 this will need to become a callback, so
1531
	 *   the sort and filter methods can subscribe to it. That will required
1532
	 *   initialisation options for sorting, which is why it is not already baked in
1533
	 */
1534
	function _fnInvalidate( settings, rowIdx, src, colIdx )
1535
	{
1536
		var row = settings.aoData[ rowIdx ];
1537
		var i, ien;
1538
		var cellWrite = function ( cell, col ) {
1539
			// This is very frustrating, but in IE if you just write directly
1540
			// to innerHTML, and elements that are overwritten are GC'ed,
1541
			// even if there is a reference to them elsewhere
1542
			while ( cell.childNodes.length ) {
1543
				cell.removeChild( cell.firstChild );
1544
			}
1545
 
1546
			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
1547
		};
1548
 
1549
		// Are we reading last data from DOM or the data object?
1550
		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1551
			// Read the data from the DOM
1552
			row._aData = _fnGetRowElements(
1553
					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
1554
				)
1555
				.data;
1556
		}
1557
		else {
1558
			// Reading from data object, update the DOM
1559
			var cells = row.anCells;
1560
 
1561
			if ( cells ) {
1562
				if ( colIdx !== undefined ) {
1563
					cellWrite( cells[colIdx], colIdx );
1564
				}
1565
				else {
1566
					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1567
						cellWrite( cells[i], i );
1568
					}
1569
				}
1570
			}
1571
		}
1572
 
1573
		// For both row and cell invalidation, the cached data for sorting and
1574
		// filtering is nulled out
1575
		row._aSortData = null;
1576
		row._aFilterData = null;
1577
 
1578
		// Invalidate the type for a specific column (if given) or all columns since
1579
		// the data might have changed
1580
		var cols = settings.aoColumns;
1581
		if ( colIdx !== undefined ) {
1582
			cols[ colIdx ].sType = null;
1583
		}
1584
		else {
1585
			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1586
				cols[i].sType = null;
1587
			}
1588
 
1589
			// Update DataTables special `DT_*` attributes for the row
1590
			_fnRowAttributes( settings, row );
1591
		}
1592
	}
1593
 
1594
 
1595
	/**
1596
	 * Build a data source object from an HTML row, reading the contents of the
1597
	 * cells that are in the row.
1598
	 *
1599
	 * @param {object} settings DataTables settings object
1600
	 * @param {node|object} TR element from which to read data or existing row
1601
	 *   object from which to re-read the data from the cells
1602
	 * @param {int} [colIdx] Optional column index
1603
	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
1604
	 *   parameter should also be given and will be used to write the data into.
1605
	 *   Only the column in question will be written
1606
	 * @returns {object} Object with two parameters: `data` the data read, in
1607
	 *   document order, and `cells` and array of nodes (they can be useful to the
1608
	 *   caller, so rather than needing a second traversal to get them, just return
1609
	 *   them from here).
1610
	 * @memberof DataTable#oApi
1611
	 */
1612
	function _fnGetRowElements( settings, row, colIdx, d )
1613
	{
1614
		var
1615
			tds = [],
1616
			td = row.firstChild,
1617
			name, col, o, i=0, contents,
1618
			columns = settings.aoColumns,
1619
			objectRead = settings._rowReadObject;
1620
 
1621
		// Allow the data object to be passed in, or construct
1622
		d = d !== undefined ?
1623
			d :
1624
			objectRead ?
1625
				{} :
1626
				[];
1627
 
1628
		var attr = function ( str, td  ) {
1629
			if ( typeof str === 'string' ) {
1630
				var idx = str.indexOf('@');
1631
 
1632
				if ( idx !== -1 ) {
1633
					var attr = str.substring( idx+1 );
1634
					var setter = _fnSetObjectDataFn( str );
1635
					setter( d, td.getAttribute( attr ) );
1636
				}
1637
			}
1638
		};
1639
 
1640
		// Read data from a cell and store into the data object
1641
		var cellProcess = function ( cell ) {
1642
			if ( colIdx === undefined || colIdx === i ) {
1643
				col = columns[i];
1644
				contents = $.trim(cell.innerHTML);
1645
 
1646
				if ( col && col._bAttrSrc ) {
1647
					var setter = _fnSetObjectDataFn( col.mData._ );
1648
					setter( d, contents );
1649
 
1650
					attr( col.mData.sort, cell );
1651
					attr( col.mData.type, cell );
1652
					attr( col.mData.filter, cell );
1653
				}
1654
				else {
1655
					// Depending on the `data` option for the columns the data can
1656
					// be read to either an object or an array.
1657
					if ( objectRead ) {
1658
						if ( ! col._setter ) {
1659
							// Cache the setter function
1660
							col._setter = _fnSetObjectDataFn( col.mData );
1661
						}
1662
						col._setter( d, contents );
1663
					}
1664
					else {
1665
						d[i] = contents;
1666
					}
1667
				}
1668
			}
1669
 
1670
			i++;
1671
		};
1672
 
1673
		if ( td ) {
1674
			// `tr` element was passed in
1675
			while ( td ) {
1676
				name = td.nodeName.toUpperCase();
1677
 
1678
				if ( name == "TD" || name == "TH" ) {
1679
					cellProcess( td );
1680
					tds.push( td );
1681
				}
1682
 
1683
				td = td.nextSibling;
1684
			}
1685
		}
1686
		else {
1687
			// Existing row object passed in
1688
			tds = row.anCells;
1689
 
1690
			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1691
				cellProcess( tds[j] );
1692
			}
1693
		}
1694
 
1695
		// Read the ID from the DOM if present
1696
		var rowNode = td ? row : row.nTr;
1697
 
1698
		if ( rowNode ) {
1699
			var id = rowNode.getAttribute( 'id' );
1700
 
1701
			if ( id ) {
1702
				_fnSetObjectDataFn( settings.rowId )( d, id );
1703
			}
1704
		}
1705
 
1706
		return {
1707
			data: d,
1708
			cells: tds
1709
		};
1710
	}
1711
	/**
1712
	 * Create a new TR element (and it's TD children) for a row
1713
	 *  @param {object} oSettings dataTables settings object
1714
	 *  @param {int} iRow Row to consider
1715
	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1716
	 *    DataTables will create a row automatically
1717
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1718
	 *    if nTr is.
1719
	 *  @memberof DataTable#oApi
1720
	 */
1721
	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
1722
	{
1723
		var
1724
			row = oSettings.aoData[iRow],
1725
			rowData = row._aData,
1726
			cells = [],
1727
			nTr, nTd, oCol,
1728
			i, iLen;
1729
 
1730
		if ( row.nTr === null )
1731
		{
1732
			nTr = nTrIn || document.createElement('tr');
1733
 
1734
			row.nTr = nTr;
1735
			row.anCells = cells;
1736
 
1737
			/* Use a private property on the node to allow reserve mapping from the node
1738
			 * to the aoData array for fast look up
1739
			 */
1740
			nTr._DT_RowIndex = iRow;
1741
 
1742
			/* Special parameters can be given by the data source to be used on the row */
1743
			_fnRowAttributes( oSettings, row );
1744
 
1745
			/* Process each column */
1746
			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1747
			{
1748
				oCol = oSettings.aoColumns[i];
1749
 
1750
				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1751
				cells.push( nTd );
1752
 
1753
				// Need to create the HTML if new, or if a rendering function is defined
1754
				if ( !nTrIn || oCol.mRender || oCol.mData !== i )
1755
				{
1756
					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
1757
				}
1758
 
1759
				/* Add user defined class */
1760
				if ( oCol.sClass )
1761
				{
1762
					nTd.className += ' '+oCol.sClass;
1763
				}
1764
 
1765
				// Visibility - add or remove as required
1766
				if ( oCol.bVisible && ! nTrIn )
1767
				{
1768
					nTr.appendChild( nTd );
1769
				}
1770
				else if ( ! oCol.bVisible && nTrIn )
1771
				{
1772
					nTd.parentNode.removeChild( nTd );
1773
				}
1774
 
1775
				if ( oCol.fnCreatedCell )
1776
				{
1777
					oCol.fnCreatedCell.call( oSettings.oInstance,
1778
						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
1779
					);
1780
				}
1781
			}
1782
 
1783
			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
1784
		}
1785
 
1786
		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1787
		// and deployed
1788
		row.nTr.setAttribute( 'role', 'row' );
1789
	}
1790
 
1791
 
1792
	/**
1793
	 * Add attributes to a row based on the special `DT_*` parameters in a data
1794
	 * source object.
1795
	 *  @param {object} settings DataTables settings object
1796
	 *  @param {object} DataTables row object for the row to be modified
1797
	 *  @memberof DataTable#oApi
1798
	 */
1799
	function _fnRowAttributes( settings, row )
1800
	{
1801
		var tr = row.nTr;
1802
		var data = row._aData;
1803
 
1804
		if ( tr ) {
1805
			var id = settings.rowIdFn( data );
1806
 
1807
			if ( id ) {
1808
				tr.id = id;
1809
			}
1810
 
1811
			if ( data.DT_RowClass ) {
1812
				// Remove any classes added by DT_RowClass before
1813
				var a = data.DT_RowClass.split(' ');
1814
				row.__rowc = row.__rowc ?
1815
					_unique( row.__rowc.concat( a ) ) :
1816
					a;
1817
 
1818
				$(tr)
1819
					.removeClass( row.__rowc.join(' ') )
1820
					.addClass( data.DT_RowClass );
1821
			}
1822
 
1823
			if ( data.DT_RowAttr ) {
1824
				$(tr).attr( data.DT_RowAttr );
1825
			}
1826
 
1827
			if ( data.DT_RowData ) {
1828
				$(tr).data( data.DT_RowData );
1829
			}
1830
		}
1831
	}
1832
 
1833
 
1834
	/**
1835
	 * Create the HTML header for the table
1836
	 *  @param {object} oSettings dataTables settings object
1837
	 *  @memberof DataTable#oApi
1838
	 */
1839
	function _fnBuildHead( oSettings )
1840
	{
1841
		var i, ien, cell, row, column;
1842
		var thead = oSettings.nTHead;
1843
		var tfoot = oSettings.nTFoot;
1844
		var createHeader = $('th, td', thead).length === 0;
1845
		var classes = oSettings.oClasses;
1846
		var columns = oSettings.aoColumns;
1847
 
1848
		if ( createHeader ) {
1849
			row = $('<tr/>').appendTo( thead );
1850
		}
1851
 
1852
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
1853
			column = columns[i];
1854
			cell = $( column.nTh ).addClass( column.sClass );
1855
 
1856
			if ( createHeader ) {
1857
				cell.appendTo( row );
1858
			}
1859
 
1860
			// 1.11 move into sorting
1861
			if ( oSettings.oFeatures.bSort ) {
1862
				cell.addClass( column.sSortingClass );
1863
 
1864
				if ( column.bSortable !== false ) {
1865
					cell
1866
						.attr( 'tabindex', oSettings.iTabIndex )
1867
						.attr( 'aria-controls', oSettings.sTableId );
1868
 
1869
					_fnSortAttachListener( oSettings, column.nTh, i );
1870
				}
1871
			}
1872
 
1873
			if ( column.sTitle != cell[0].innerHTML ) {
1874
				cell.html( column.sTitle );
1875
			}
1876
 
1877
			_fnRenderer( oSettings, 'header' )(
1878
				oSettings, cell, column, classes
1879
			);
1880
		}
1881
 
1882
		if ( createHeader ) {
1883
			_fnDetectHeader( oSettings.aoHeader, thead );
1884
		}
1885
 
1886
		/* ARIA role for the rows */
1887
	 	$(thead).find('>tr').attr('role', 'row');
1888
 
1889
		/* Deal with the footer - add classes if required */
1890
		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
1891
		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
1892
 
1893
		// Cache the footer cells. Note that we only take the cells from the first
1894
		// row in the footer. If there is more than one row the user wants to
1895
		// interact with, they need to use the table().foot() method. Note also this
1896
		// allows cells to be used for multiple columns using colspan
1897
		if ( tfoot !== null ) {
1898
			var cells = oSettings.aoFooter[0];
1899
 
1900
			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1901
				column = columns[i];
1902
				column.nTf = cells[i].cell;
1903
 
1904
				if ( column.sClass ) {
1905
					$(column.nTf).addClass( column.sClass );
1906
				}
1907
			}
1908
		}
1909
	}
1910
 
1911
 
1912
	/**
1913
	 * Draw the header (or footer) element based on the column visibility states. The
1914
	 * methodology here is to use the layout array from _fnDetectHeader, modified for
1915
	 * the instantaneous column visibility, to construct the new layout. The grid is
1916
	 * traversed over cell at a time in a rows x columns grid fashion, although each
1917
	 * cell insert can cover multiple elements in the grid - which is tracks using the
1918
	 * aApplied array. Cell inserts in the grid will only occur where there isn't
1919
	 * already a cell in that position.
1920
	 *  @param {object} oSettings dataTables settings object
1921
	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
1922
	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1923
	 *  @memberof DataTable#oApi
1924
	 */
1925
	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1926
	{
1927
		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1928
		var aoLocal = [];
1929
		var aApplied = [];
1930
		var iColumns = oSettings.aoColumns.length;
1931
		var iRowspan, iColspan;
1932
 
1933
		if ( ! aoSource )
1934
		{
1935
			return;
1936
		}
1937
 
1938
		if (  bIncludeHidden === undefined )
1939
		{
1940
			bIncludeHidden = false;
1941
		}
1942
 
1943
		/* Make a copy of the master layout array, but without the visible columns in it */
1944
		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1945
		{
1946
			aoLocal[i] = aoSource[i].slice();
1947
			aoLocal[i].nTr = aoSource[i].nTr;
1948
 
1949
			/* Remove any columns which are currently hidden */
1950
			for ( j=iColumns-1 ; j>=0 ; j-- )
1951
			{
1952
				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1953
				{
1954
					aoLocal[i].splice( j, 1 );
1955
				}
1956
			}
1957
 
1958
			/* Prep the applied array - it needs an element for each row */
1959
			aApplied.push( [] );
1960
		}
1961
 
1962
		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1963
		{
1964
			nLocalTr = aoLocal[i].nTr;
1965
 
1966
			/* All cells are going to be replaced, so empty out the row */
1967
			if ( nLocalTr )
1968
			{
1969
				while( (n = nLocalTr.firstChild) )
1970
				{
1971
					nLocalTr.removeChild( n );
1972
				}
1973
			}
1974
 
1975
			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1976
			{
1977
				iRowspan = 1;
1978
				iColspan = 1;
1979
 
1980
				/* Check to see if there is already a cell (row/colspan) covering our target
1981
				 * insert point. If there is, then there is nothing to do.
1982
				 */
1983
				if ( aApplied[i][j] === undefined )
1984
				{
1985
					nLocalTr.appendChild( aoLocal[i][j].cell );
1986
					aApplied[i][j] = 1;
1987
 
1988
					/* Expand the cell to cover as many rows as needed */
1989
					while ( aoLocal[i+iRowspan] !== undefined &&
1990
					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1991
					{
1992
						aApplied[i+iRowspan][j] = 1;
1993
						iRowspan++;
1994
					}
1995
 
1996
					/* Expand the cell to cover as many columns as needed */
1997
					while ( aoLocal[i][j+iColspan] !== undefined &&
1998
					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1999
					{
2000
						/* Must update the applied array over the rows for the columns */
2001
						for ( k=0 ; k<iRowspan ; k++ )
2002
						{
2003
							aApplied[i+k][j+iColspan] = 1;
2004
						}
2005
						iColspan++;
2006
					}
2007
 
2008
					/* Do the actual expansion in the DOM */
2009
					$(aoLocal[i][j].cell)
2010
						.attr('rowspan', iRowspan)
2011
						.attr('colspan', iColspan);
2012
				}
2013
			}
2014
		}
2015
	}
2016
 
2017
 
2018
	/**
2019
	 * Insert the required TR nodes into the table for display
2020
	 *  @param {object} oSettings dataTables settings object
2021
	 *  @memberof DataTable#oApi
2022
	 */
2023
	function _fnDraw( oSettings )
2024
	{
2025
		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
2026
		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
2027
		if ( $.inArray( false, aPreDraw ) !== -1 )
2028
		{
2029
			_fnProcessingDisplay( oSettings, false );
2030
			return;
2031
		}
2032
 
2033
		var i, iLen, n;
2034
		var anRows = [];
2035
		var iRowCount = 0;
2036
		var asStripeClasses = oSettings.asStripeClasses;
2037
		var iStripes = asStripeClasses.length;
2038
		var iOpenRows = oSettings.aoOpenRows.length;
2039
		var oLang = oSettings.oLanguage;
2040
		var iInitDisplayStart = oSettings.iInitDisplayStart;
2041
		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
2042
		var aiDisplay = oSettings.aiDisplay;
2043
 
2044
		oSettings.bDrawing = true;
2045
 
2046
		/* Check and see if we have an initial draw position from state saving */
2047
		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
2048
		{
2049
			oSettings._iDisplayStart = bServerSide ?
2050
				iInitDisplayStart :
2051
				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
2052
 
2053
					iInitDisplayStart;
2054
 
2055
			oSettings.iInitDisplayStart = -1;
2056
		}
2057
 
2058
		var iDisplayStart = oSettings._iDisplayStart;
2059
		var iDisplayEnd = oSettings.fnDisplayEnd();
2060
 
2061
		/* Server-side processing draw intercept */
2062
		if ( oSettings.bDeferLoading )
2063
		{
2064
			oSettings.bDeferLoading = false;
2065
			oSettings.iDraw++;
2066
			_fnProcessingDisplay( oSettings, false );
2067
		}
2068
		else if ( !bServerSide )
2069
		{
2070
			oSettings.iDraw++;
2071
		}
2072
		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
2073
		{
2074
			return;
2075
		}
2076
 
2077
		if ( aiDisplay.length !== 0 )
2078
		{
2079
			var iStart = bServerSide ? 0 : iDisplayStart;
2080
			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
2081
 
2082
			for ( var j=iStart ; j<iEnd ; j++ )
2083
			{
2084
				var iDataIndex = aiDisplay[j];
2085
				var aoData = oSettings.aoData[ iDataIndex ];
2086
				if ( aoData.nTr === null )
2087
				{
2088
					_fnCreateTr( oSettings, iDataIndex );
2089
				}
2090
 
2091
				var nRow = aoData.nTr;
2092
 
2093
				/* Remove the old striping classes and then add the new one */
2094
				if ( iStripes !== 0 )
2095
				{
2096
					var sStripe = asStripeClasses[ iRowCount % iStripes ];
2097
					if ( aoData._sRowStripe != sStripe )
2098
					{
2099
						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
2100
						aoData._sRowStripe = sStripe;
2101
					}
2102
				}
2103
 
2104
				// Row callback functions - might want to manipulate the row
2105
				// iRowCount and j are not currently documented. Are they at all
2106
				// useful?
2107
				_fnCallbackFire( oSettings, 'aoRowCallback', null,
2108
					[nRow, aoData._aData, iRowCount, j] );
2109
 
2110
				anRows.push( nRow );
2111
				iRowCount++;
2112
			}
2113
		}
2114
		else
2115
		{
2116
			/* Table is empty - create a row with an empty message in it */
2117
			var sZero = oLang.sZeroRecords;
2118
			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
2119
			{
2120
				sZero = oLang.sLoadingRecords;
2121
			}
2122
			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
2123
			{
2124
				sZero = oLang.sEmptyTable;
2125
			}
2126
 
2127
			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
2128
				.append( $('<td />', {
2129
					'valign':  'top',
2130
					'colSpan': _fnVisbleColumns( oSettings ),
2131
					'class':   oSettings.oClasses.sRowEmpty
2132
				} ).html( sZero ) )[0];
2133
		}
2134
 
2135
		/* Header and footer callbacks */
2136
		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
2137
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2138
 
2139
		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
2140
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2141
 
2142
		var body = $(oSettings.nTBody);
2143
 
2144
		body.children().detach();
2145
		body.append( $(anRows) );
2146
 
2147
		/* Call all required callback functions for the end of a draw */
2148
		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
2149
 
2150
		/* Draw is complete, sorting and filtering must be as well */
2151
		oSettings.bSorted = false;
2152
		oSettings.bFiltered = false;
2153
		oSettings.bDrawing = false;
2154
	}
2155
 
2156
 
2157
	/**
2158
	 * Redraw the table - taking account of the various features which are enabled
2159
	 *  @param {object} oSettings dataTables settings object
2160
	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
2161
	 *    the paging is reset to the first page
2162
	 *  @memberof DataTable#oApi
2163
	 */
2164
	function _fnReDraw( settings, holdPosition )
2165
	{
2166
		var
2167
			features = settings.oFeatures,
2168
			sort     = features.bSort,
2169
			filter   = features.bFilter;
2170
 
2171
		if ( sort ) {
2172
			_fnSort( settings );
2173
		}
2174
 
2175
		if ( filter ) {
2176
			_fnFilterComplete( settings, settings.oPreviousSearch );
2177
		}
2178
		else {
2179
			// No filtering, so we want to just use the display master
2180
			settings.aiDisplay = settings.aiDisplayMaster.slice();
2181
		}
2182
 
2183
		if ( holdPosition !== true ) {
2184
			settings._iDisplayStart = 0;
2185
		}
2186
 
2187
		// Let any modules know about the draw hold position state (used by
2188
		// scrolling internally)
2189
		settings._drawHold = holdPosition;
2190
 
2191
		_fnDraw( settings );
2192
 
2193
		settings._drawHold = false;
2194
	}
2195
 
2196
 
2197
	/**
2198
	 * Add the options to the page HTML for the table
2199
	 *  @param {object} oSettings dataTables settings object
2200
	 *  @memberof DataTable#oApi
2201
	 */
2202
	function _fnAddOptionsHtml ( oSettings )
2203
	{
2204
		var classes = oSettings.oClasses;
2205
		var table = $(oSettings.nTable);
2206
		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
2207
		var features = oSettings.oFeatures;
2208
 
2209
		// All DataTables are wrapped in a div
2210
		var insert = $('<div/>', {
2211
			id:      oSettings.sTableId+'_wrapper',
2212
			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
2213
		} );
2214
 
2215
		oSettings.nHolding = holding[0];
2216
		oSettings.nTableWrapper = insert[0];
2217
		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
2218
 
2219
		/* Loop over the user set positioning and place the elements as needed */
2220
		var aDom = oSettings.sDom.split('');
2221
		var featureNode, cOption, nNewNode, cNext, sAttr, j;
2222
		for ( var i=0 ; i<aDom.length ; i++ )
2223
		{
2224
			featureNode = null;
2225
			cOption = aDom[i];
2226
 
2227
			if ( cOption == '<' )
2228
			{
2229
				/* New container div */
2230
				nNewNode = $('<div/>')[0];
2231
 
2232
				/* Check to see if we should append an id and/or a class name to the container */
2233
				cNext = aDom[i+1];
2234
				if ( cNext == "'" || cNext == '"' )
2235
				{
2236
					sAttr = "";
2237
					j = 2;
2238
					while ( aDom[i+j] != cNext )
2239
					{
2240
						sAttr += aDom[i+j];
2241
						j++;
2242
					}
2243
 
2244
					/* Replace jQuery UI constants @todo depreciated */
2245
					if ( sAttr == "H" )
2246
					{
2247
						sAttr = classes.sJUIHeader;
2248
					}
2249
					else if ( sAttr == "F" )
2250
					{
2251
						sAttr = classes.sJUIFooter;
2252
					}
2253
 
2254
					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2255
					 * breaks the string into parts and applies them as needed
2256
					 */
2257
					if ( sAttr.indexOf('.') != -1 )
2258
					{
2259
						var aSplit = sAttr.split('.');
2260
						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
2261
						nNewNode.className = aSplit[1];
2262
					}
2263
					else if ( sAttr.charAt(0) == "#" )
2264
					{
2265
						nNewNode.id = sAttr.substr(1, sAttr.length-1);
2266
					}
2267
					else
2268
					{
2269
						nNewNode.className = sAttr;
2270
					}
2271
 
2272
					i += j; /* Move along the position array */
2273
				}
2274
 
2275
				insert.append( nNewNode );
2276
				insert = $(nNewNode);
2277
			}
2278
			else if ( cOption == '>' )
2279
			{
2280
				/* End container div */
2281
				insert = insert.parent();
2282
			}
2283
			// @todo Move options into their own plugins?
2284
			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
2285
			{
2286
				/* Length */
2287
				featureNode = _fnFeatureHtmlLength( oSettings );
2288
			}
2289
			else if ( cOption == 'f' && features.bFilter )
2290
			{
2291
				/* Filter */
2292
				featureNode = _fnFeatureHtmlFilter( oSettings );
2293
			}
2294
			else if ( cOption == 'r' && features.bProcessing )
2295
			{
2296
				/* pRocessing */
2297
				featureNode = _fnFeatureHtmlProcessing( oSettings );
2298
			}
2299
			else if ( cOption == 't' )
2300
			{
2301
				/* Table */
2302
				featureNode = _fnFeatureHtmlTable( oSettings );
2303
			}
2304
			else if ( cOption ==  'i' && features.bInfo )
2305
			{
2306
				/* Info */
2307
				featureNode = _fnFeatureHtmlInfo( oSettings );
2308
			}
2309
			else if ( cOption == 'p' && features.bPaginate )
2310
			{
2311
				/* Pagination */
2312
				featureNode = _fnFeatureHtmlPaginate( oSettings );
2313
			}
2314
			else if ( DataTable.ext.feature.length !== 0 )
2315
			{
2316
				/* Plug-in features */
2317
				var aoFeatures = DataTable.ext.feature;
2318
				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
2319
				{
2320
					if ( cOption == aoFeatures[k].cFeature )
2321
					{
2322
						featureNode = aoFeatures[k].fnInit( oSettings );
2323
						break;
2324
					}
2325
				}
2326
			}
2327
 
2328
			/* Add to the 2D features array */
2329
			if ( featureNode )
2330
			{
2331
				var aanFeatures = oSettings.aanFeatures;
2332
 
2333
				if ( ! aanFeatures[cOption] )
2334
				{
2335
					aanFeatures[cOption] = [];
2336
				}
2337
 
2338
				aanFeatures[cOption].push( featureNode );
2339
				insert.append( featureNode );
2340
			}
2341
		}
2342
 
2343
		/* Built our DOM structure - replace the holding div with what we want */
2344
		holding.replaceWith( insert );
2345
		oSettings.nHolding = null;
2346
	}
2347
 
2348
 
2349
	/**
2350
	 * Use the DOM source to create up an array of header cells. The idea here is to
2351
	 * create a layout grid (array) of rows x columns, which contains a reference
2352
	 * to the cell that that point in the grid (regardless of col/rowspan), such that
2353
	 * any column / row could be removed and the new grid constructed
2354
	 *  @param array {object} aLayout Array to store the calculated layout in
2355
	 *  @param {node} nThead The header/footer element for the table
2356
	 *  @memberof DataTable#oApi
2357
	 */
2358
	function _fnDetectHeader ( aLayout, nThead )
2359
	{
2360
		var nTrs = $(nThead).children('tr');
2361
		var nTr, nCell;
2362
		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
2363
		var bUnique;
2364
		var fnShiftCol = function ( a, i, j ) {
2365
			var k = a[i];
2366
	                while ( k[j] ) {
2367
				j++;
2368
			}
2369
			return j;
2370
		};
2371
 
2372
		aLayout.splice( 0, aLayout.length );
2373
 
2374
		/* We know how many rows there are in the layout - so prep it */
2375
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2376
		{
2377
			aLayout.push( [] );
2378
		}
2379
 
2380
		/* Calculate a layout array */
2381
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2382
		{
2383
			nTr = nTrs[i];
2384
			iColumn = 0;
2385
 
2386
			/* For every cell in the row... */
2387
			nCell = nTr.firstChild;
2388
			while ( nCell ) {
2389
				if ( nCell.nodeName.toUpperCase() == "TD" ||
2390
				     nCell.nodeName.toUpperCase() == "TH" )
2391
				{
2392
					/* Get the col and rowspan attributes from the DOM and sanitise them */
2393
					iColspan = nCell.getAttribute('colspan') * 1;
2394
					iRowspan = nCell.getAttribute('rowspan') * 1;
2395
					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
2396
					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
2397
 
2398
					/* There might be colspan cells already in this row, so shift our target
2399
					 * accordingly
2400
					 */
2401
					iColShifted = fnShiftCol( aLayout, i, iColumn );
2402
 
2403
					/* Cache calculation for unique columns */
2404
					bUnique = iColspan === 1 ? true : false;
2405
 
2406
					/* If there is col / rowspan, copy the information into the layout grid */
2407
					for ( l=0 ; l<iColspan ; l++ )
2408
					{
2409
						for ( k=0 ; k<iRowspan ; k++ )
2410
						{
2411
							aLayout[i+k][iColShifted+l] = {
2412
								"cell": nCell,
2413
								"unique": bUnique
2414
							};
2415
							aLayout[i+k].nTr = nTr;
2416
						}
2417
					}
2418
				}
2419
				nCell = nCell.nextSibling;
2420
			}
2421
		}
2422
	}
2423
 
2424
 
2425
	/**
2426
	 * Get an array of unique th elements, one for each column
2427
	 *  @param {object} oSettings dataTables settings object
2428
	 *  @param {node} nHeader automatically detect the layout from this node - optional
2429
	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2430
	 *  @returns array {node} aReturn list of unique th's
2431
	 *  @memberof DataTable#oApi
2432
	 */
2433
	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
2434
	{
2435
		var aReturn = [];
2436
		if ( !aLayout )
2437
		{
2438
			aLayout = oSettings.aoHeader;
2439
			if ( nHeader )
2440
			{
2441
				aLayout = [];
2442
				_fnDetectHeader( aLayout, nHeader );
2443
			}
2444
		}
2445
 
2446
		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
2447
		{
2448
			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
2449
			{
2450
				if ( aLayout[i][j].unique &&
2451
					 (!aReturn[j] || !oSettings.bSortCellsTop) )
2452
				{
2453
					aReturn[j] = aLayout[i][j].cell;
2454
				}
2455
			}
2456
		}
2457
 
2458
		return aReturn;
2459
	}
2460
 
2461
	/**
2462
	 * Create an Ajax call based on the table's settings, taking into account that
2463
	 * parameters can have multiple forms, and backwards compatibility.
2464
	 *
2465
	 * @param {object} oSettings dataTables settings object
2466
	 * @param {array} data Data to send to the server, required by
2467
	 *     DataTables - may be augmented by developer callbacks
2468
	 * @param {function} fn Callback function to run when data is obtained
2469
	 */
2470
	function _fnBuildAjax( oSettings, data, fn )
2471
	{
2472
		// Compatibility with 1.9-, allow fnServerData and event to manipulate
2473
		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
2474
 
2475
		// Convert to object based for 1.10+ if using the old array scheme which can
2476
		// come from server-side processing or serverParams
2477
		if ( data && $.isArray(data) ) {
2478
			var tmp = {};
2479
			var rbracket = /(.*?)\[\]$/;
2480
 
2481
			$.each( data, function (key, val) {
2482
				var match = val.name.match(rbracket);
2483
 
2484
				if ( match ) {
2485
					// Support for arrays
2486
					var name = match[0];
2487
 
2488
					if ( ! tmp[ name ] ) {
2489
						tmp[ name ] = [];
2490
					}
2491
					tmp[ name ].push( val.value );
2492
				}
2493
				else {
2494
					tmp[val.name] = val.value;
2495
				}
2496
			} );
2497
			data = tmp;
2498
		}
2499
 
2500
		var ajaxData;
2501
		var ajax = oSettings.ajax;
2502
		var instance = oSettings.oInstance;
2503
		var callback = function ( json ) {
2504
			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
2505
			fn( json );
2506
		};
2507
 
2508
		if ( $.isPlainObject( ajax ) && ajax.data )
2509
		{
2510
			ajaxData = ajax.data;
2511
 
2512
			var newData = $.isFunction( ajaxData ) ?
2513
				ajaxData( data, oSettings ) :  // fn can manipulate data or return
2514
				ajaxData;                      // an object object or array to merge
2515
 
2516
			// If the function returned something, use that alone
2517
			data = $.isFunction( ajaxData ) && newData ?
2518
				newData :
2519
				$.extend( true, data, newData );
2520
 
2521
			// Remove the data property as we've resolved it already and don't want
2522
			// jQuery to do it again (it is restored at the end of the function)
2523
			delete ajax.data;
2524
		}
2525
 
2526
		var baseAjax = {
2527
			"data": data,
2528
			"success": function (json) {
2529
				var error = json.error || json.sError;
2530
				if ( error ) {
2531
					_fnLog( oSettings, 0, error );
2532
				}
2533
 
2534
				oSettings.json = json;
2535
				callback( json );
2536
			},
2537
			"dataType": "json",
2538
			"cache": false,
2539
			"type": oSettings.sServerMethod,
2540
			"error": function (xhr, error, thrown) {
2541
				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
2542
 
2543
				if ( $.inArray( true, ret ) === -1 ) {
2544
					if ( error == "parsererror" ) {
2545
						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
2546
					}
2547
					else if ( xhr.readyState === 4 ) {
2548
						_fnLog( oSettings, 0, 'Ajax error', 7 );
2549
					}
2550
				}
2551
 
2552
				_fnProcessingDisplay( oSettings, false );
2553
			}
2554
		};
2555
 
2556
		// Store the data submitted for the API
2557
		oSettings.oAjaxData = data;
2558
 
2559
		// Allow plug-ins and external processes to modify the data
2560
		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
2561
 
2562
		if ( oSettings.fnServerData )
2563
		{
2564
			// DataTables 1.9- compatibility
2565
			oSettings.fnServerData.call( instance,
2566
				oSettings.sAjaxSource,
2567
				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2568
					return { name: key, value: val };
2569
				} ),
2570
				callback,
2571
				oSettings
2572
			);
2573
		}
2574
		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
2575
		{
2576
			// DataTables 1.9- compatibility
2577
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
2578
				url: ajax || oSettings.sAjaxSource
2579
			} ) );
2580
		}
2581
		else if ( $.isFunction( ajax ) )
2582
		{
2583
			// Is a function - let the caller define what needs to be done
2584
			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
2585
		}
2586
		else
2587
		{
2588
			// Object to extend the base settings
2589
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
2590
 
2591
			// Restore for next time around
2592
			ajax.data = ajaxData;
2593
		}
2594
	}
2595
 
2596
 
2597
	/**
2598
	 * Update the table using an Ajax call
2599
	 *  @param {object} settings dataTables settings object
2600
	 *  @returns {boolean} Block the table drawing or not
2601
	 *  @memberof DataTable#oApi
2602
	 */
2603
	function _fnAjaxUpdate( settings )
2604
	{
2605
		if ( settings.bAjaxDataGet ) {
2606
			settings.iDraw++;
2607
			_fnProcessingDisplay( settings, true );
2608
 
2609
			_fnBuildAjax(
2610
				settings,
2611
				_fnAjaxParameters( settings ),
2612
				function(json) {
2613
					_fnAjaxUpdateDraw( settings, json );
2614
				}
2615
			);
2616
 
2617
			return false;
2618
		}
2619
		return true;
2620
	}
2621
 
2622
 
2623
	/**
2624
	 * Build up the parameters in an object needed for a server-side processing
2625
	 * request. Note that this is basically done twice, is different ways - a modern
2626
	 * method which is used by default in DataTables 1.10 which uses objects and
2627
	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2628
	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
2629
	 * option is set.
2630
	 *  @param {object} oSettings dataTables settings object
2631
	 *  @returns {bool} block the table drawing or not
2632
	 *  @memberof DataTable#oApi
2633
	 */
2634
	function _fnAjaxParameters( settings )
2635
	{
2636
		var
2637
			columns = settings.aoColumns,
2638
			columnCount = columns.length,
2639
			features = settings.oFeatures,
2640
			preSearch = settings.oPreviousSearch,
2641
			preColSearch = settings.aoPreSearchCols,
2642
			i, data = [], dataProp, column, columnSearch,
2643
			sort = _fnSortFlatten( settings ),
2644
			displayStart = settings._iDisplayStart,
2645
			displayLength = features.bPaginate !== false ?
2646
				settings._iDisplayLength :
2647
				-1;
2648
 
2649
		var param = function ( name, value ) {
2650
			data.push( { 'name': name, 'value': value } );
2651
		};
2652
 
2653
		// DataTables 1.9- compatible method
2654
		param( 'sEcho',          settings.iDraw );
2655
		param( 'iColumns',       columnCount );
2656
		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
2657
		param( 'iDisplayStart',  displayStart );
2658
		param( 'iDisplayLength', displayLength );
2659
 
2660
		// DataTables 1.10+ method
2661
		var d = {
2662
			draw:    settings.iDraw,
2663
			columns: [],
2664
			order:   [],
2665
			start:   displayStart,
2666
			length:  displayLength,
2667
			search:  {
2668
				value: preSearch.sSearch,
2669
				regex: preSearch.bRegex
2670
			}
2671
		};
2672
 
2673
		for ( i=0 ; i<columnCount ; i++ ) {
2674
			column = columns[i];
2675
			columnSearch = preColSearch[i];
2676
			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
2677
 
2678
			d.columns.push( {
2679
				data:       dataProp,
2680
				name:       column.sName,
2681
				searchable: column.bSearchable,
2682
				orderable:  column.bSortable,
2683
				search:     {
2684
					value: columnSearch.sSearch,
2685
					regex: columnSearch.bRegex
2686
				}
2687
			} );
2688
 
2689
			param( "mDataProp_"+i, dataProp );
2690
 
2691
			if ( features.bFilter ) {
2692
				param( 'sSearch_'+i,     columnSearch.sSearch );
2693
				param( 'bRegex_'+i,      columnSearch.bRegex );
2694
				param( 'bSearchable_'+i, column.bSearchable );
2695
			}
2696
 
2697
			if ( features.bSort ) {
2698
				param( 'bSortable_'+i, column.bSortable );
2699
			}
2700
		}
2701
 
2702
		if ( features.bFilter ) {
2703
			param( 'sSearch', preSearch.sSearch );
2704
			param( 'bRegex', preSearch.bRegex );
2705
		}
2706
 
2707
		if ( features.bSort ) {
2708
			$.each( sort, function ( i, val ) {
2709
				d.order.push( { column: val.col, dir: val.dir } );
2710
 
2711
				param( 'iSortCol_'+i, val.col );
2712
				param( 'sSortDir_'+i, val.dir );
2713
			} );
2714
 
2715
			param( 'iSortingCols', sort.length );
2716
		}
2717
 
2718
		// If the legacy.ajax parameter is null, then we automatically decide which
2719
		// form to use, based on sAjaxSource
2720
		var legacy = DataTable.ext.legacy.ajax;
2721
		if ( legacy === null ) {
2722
			return settings.sAjaxSource ? data : d;
2723
		}
2724
 
2725
		// Otherwise, if legacy has been specified then we use that to decide on the
2726
		// form
2727
		return legacy ? data : d;
2728
	}
2729
 
2730
 
2731
	/**
2732
	 * Data the data from the server (nuking the old) and redraw the table
2733
	 *  @param {object} oSettings dataTables settings object
2734
	 *  @param {object} json json data return from the server.
2735
	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
2736
	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2737
	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2738
	 *  @param {array} json.aaData The data to display on this page
2739
	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
2740
	 *  @memberof DataTable#oApi
2741
	 */
2742
	function _fnAjaxUpdateDraw ( settings, json )
2743
	{
2744
		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2745
		// Support both
2746
		var compat = function ( old, modern ) {
2747
			return json[old] !== undefined ? json[old] : json[modern];
2748
		};
2749
 
2750
		var data = _fnAjaxDataSrc( settings, json );
2751
		var draw            = compat( 'sEcho',                'draw' );
2752
		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
2753
		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2754
 
2755
		if ( draw ) {
2756
			// Protect against out of sequence returns
2757
			if ( draw*1 < settings.iDraw ) {
2758
				return;
2759
			}
2760
			settings.iDraw = draw * 1;
2761
		}
2762
 
2763
		_fnClearTable( settings );
2764
		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
2765
		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
2766
 
2767
		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2768
			_fnAddData( settings, data[i] );
2769
		}
2770
		settings.aiDisplay = settings.aiDisplayMaster.slice();
2771
 
2772
		settings.bAjaxDataGet = false;
2773
		_fnDraw( settings );
2774
 
2775
		if ( ! settings._bInitComplete ) {
2776
			_fnInitComplete( settings, json );
2777
		}
2778
 
2779
		settings.bAjaxDataGet = true;
2780
		_fnProcessingDisplay( settings, false );
2781
	}
2782
 
2783
 
2784
	/**
2785
	 * Get the data from the JSON data source to use for drawing a table. Using
2786
	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2787
	 * source object, or from a processing function.
2788
	 *  @param {object} oSettings dataTables settings object
2789
	 *  @param  {object} json Data source object / array from the server
2790
	 *  @return {array} Array of data to use
2791
	 */
2792
	function _fnAjaxDataSrc ( oSettings, json )
2793
	{
2794
		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
2795
			oSettings.ajax.dataSrc :
2796
			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
2797
 
2798
		// Compatibility with 1.9-. In order to read from aaData, check if the
2799
		// default has been changed, if not, check for aaData
2800
		if ( dataSrc === 'data' ) {
2801
			return json.aaData || json[dataSrc];
2802
		}
2803
 
2804
		return dataSrc !== "" ?
2805
			_fnGetObjectDataFn( dataSrc )( json ) :
2806
			json;
2807
	}
2808
 
2809
	/**
2810
	 * Generate the node required for filtering text
2811
	 *  @returns {node} Filter control element
2812
	 *  @param {object} oSettings dataTables settings object
2813
	 *  @memberof DataTable#oApi
2814
	 */
2815
	function _fnFeatureHtmlFilter ( settings )
2816
	{
2817
		var classes = settings.oClasses;
2818
		var tableId = settings.sTableId;
2819
		var language = settings.oLanguage;
2820
		var previousSearch = settings.oPreviousSearch;
2821
		var features = settings.aanFeatures;
2822
		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
2823
 
2824
		var str = language.sSearch;
2825
		str = str.match(/_INPUT_/) ?
2826
			str.replace('_INPUT_', input) :
2827
			str+input;
2828
 
2829
		var filter = $('<div/>', {
2830
				'id': ! features.f ? tableId+'_filter' : null,
2831
				'class': classes.sFilter
2832
			} )
2833
			.append( $('<label/>' ).append( str ) );
2834
 
2835
		var searchFn = function() {
2836
			/* Update all other filter input elements for the new display */
2837
			var n = features.f;
2838
			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
2839
 
2840
			/* Now do the filter */
2841
			if ( val != previousSearch.sSearch ) {
2842
				_fnFilterComplete( settings, {
2843
					"sSearch": val,
2844
					"bRegex": previousSearch.bRegex,
2845
					"bSmart": previousSearch.bSmart ,
2846
					"bCaseInsensitive": previousSearch.bCaseInsensitive
2847
				} );
2848
 
2849
				// Need to redraw, without resorting
2850
				settings._iDisplayStart = 0;
2851
				_fnDraw( settings );
2852
			}
2853
		};
2854
 
2855
		var searchDelay = settings.searchDelay !== null ?
2856
			settings.searchDelay :
2857
			_fnDataSource( settings ) === 'ssp' ?
2858
				400 :
2859
				0;
2860
 
2861
		var jqFilter = $('input', filter)
2862
			.val( previousSearch.sSearch )
2863
			.attr( 'placeholder', language.sSearchPlaceholder )
2864
			.bind(
2865
				'keyup.DT search.DT input.DT paste.DT cut.DT',
2866
				searchDelay ?
2867
					_fnThrottle( searchFn, searchDelay ) :
2868
					searchFn
2869
			)
2870
			.bind( 'keypress.DT', function(e) {
2871
				/* Prevent form submission */
2872
				if ( e.keyCode == 13 ) {
2873
					return false;
2874
				}
2875
			} )
2876
			.attr('aria-controls', tableId);
2877
 
2878
		// Update the input elements whenever the table is filtered
2879
		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
2880
			if ( settings === s ) {
2881
				// IE9 throws an 'unknown error' if document.activeElement is used
2882
				// inside an iframe or frame...
2883
				try {
2884
					if ( jqFilter[0] !== document.activeElement ) {
2885
						jqFilter.val( previousSearch.sSearch );
2886
					}
2887
				}
2888
				catch ( e ) {}
2889
			}
2890
		} );
2891
 
2892
		return filter[0];
2893
	}
2894
 
2895
 
2896
	/**
2897
	 * Filter the table using both the global filter and column based filtering
2898
	 *  @param {object} oSettings dataTables settings object
2899
	 *  @param {object} oSearch search information
2900
	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2901
	 *  @memberof DataTable#oApi
2902
	 */
2903
	function _fnFilterComplete ( oSettings, oInput, iForce )
2904
	{
2905
		var oPrevSearch = oSettings.oPreviousSearch;
2906
		var aoPrevSearch = oSettings.aoPreSearchCols;
2907
		var fnSaveFilter = function ( oFilter ) {
2908
			/* Save the filtering values */
2909
			oPrevSearch.sSearch = oFilter.sSearch;
2910
			oPrevSearch.bRegex = oFilter.bRegex;
2911
			oPrevSearch.bSmart = oFilter.bSmart;
2912
			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
2913
		};
2914
		var fnRegex = function ( o ) {
2915
			// Backwards compatibility with the bEscapeRegex option
2916
			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
2917
		};
2918
 
2919
		// Resolve any column types that are unknown due to addition or invalidation
2920
		// @todo As per sort - can this be moved into an event handler?
2921
		_fnColumnTypes( oSettings );
2922
 
2923
		/* In server-side processing all filtering is done by the server, so no point hanging around here */
2924
		if ( _fnDataSource( oSettings ) != 'ssp' )
2925
		{
2926
			/* Global filter */
2927
			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
2928
			fnSaveFilter( oInput );
2929
 
2930
			/* Now do the individual column filter */
2931
			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
2932
			{
2933
				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
2934
					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
2935
			}
2936
 
2937
			/* Custom filtering */
2938
			_fnFilterCustom( oSettings );
2939
		}
2940
		else
2941
		{
2942
			fnSaveFilter( oInput );
2943
		}
2944
 
2945
		/* Tell the draw function we have been filtering */
2946
		oSettings.bFiltered = true;
2947
		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
2948
	}
2949
 
2950
 
2951
	/**
2952
	 * Apply custom filtering functions
2953
	 *  @param {object} oSettings dataTables settings object
2954
	 *  @memberof DataTable#oApi
2955
	 */
2956
	function _fnFilterCustom( settings )
2957
	{
2958
		var filters = DataTable.ext.search;
2959
		var displayRows = settings.aiDisplay;
2960
		var row, rowIdx;
2961
 
2962
		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
2963
			var rows = [];
2964
 
2965
			// Loop over each row and see if it should be included
2966
			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
2967
				rowIdx = displayRows[ j ];
2968
				row = settings.aoData[ rowIdx ];
2969
 
2970
				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
2971
					rows.push( rowIdx );
2972
				}
2973
			}
2974
 
2975
			// So the array reference doesn't break set the results into the
2976
			// existing array
2977
			displayRows.length = 0;
2978
			$.merge( displayRows, rows );
2979
		}
2980
	}
2981
 
2982
 
2983
	/**
2984
	 * Filter the table on a per-column basis
2985
	 *  @param {object} oSettings dataTables settings object
2986
	 *  @param {string} sInput string to filter on
2987
	 *  @param {int} iColumn column to filter
2988
	 *  @param {bool} bRegex treat search string as a regular expression or not
2989
	 *  @param {bool} bSmart use smart filtering or not
2990
	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
2991
	 *  @memberof DataTable#oApi
2992
	 */
2993
	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
2994
	{
2995
		if ( searchStr === '' ) {
2996
			return;
2997
		}
2998
 
2999
		var data;
3000
		var display = settings.aiDisplay;
3001
		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
3002
 
3003
		for ( var i=display.length-1 ; i>=0 ; i-- ) {
3004
			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
3005
 
3006
			if ( ! rpSearch.test( data ) ) {
3007
				display.splice( i, 1 );
3008
			}
3009
		}
3010
	}
3011
 
3012
 
3013
	/**
3014
	 * Filter the data table based on user input and draw the table
3015
	 *  @param {object} settings dataTables settings object
3016
	 *  @param {string} input string to filter on
3017
	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
3018
	 *  @param {bool} regex treat as a regular expression or not
3019
	 *  @param {bool} smart perform smart filtering or not
3020
	 *  @param {bool} caseInsensitive Do case insenstive matching or not
3021
	 *  @memberof DataTable#oApi
3022
	 */
3023
	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
3024
	{
3025
		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
3026
		var prevSearch = settings.oPreviousSearch.sSearch;
3027
		var displayMaster = settings.aiDisplayMaster;
3028
		var display, invalidated, i;
3029
 
3030
		// Need to take account of custom filtering functions - always filter
3031
		if ( DataTable.ext.search.length !== 0 ) {
3032
			force = true;
3033
		}
3034
 
3035
		// Check if any of the rows were invalidated
3036
		invalidated = _fnFilterData( settings );
3037
 
3038
		// If the input is blank - we just want the full data set
3039
		if ( input.length <= 0 ) {
3040
			settings.aiDisplay = displayMaster.slice();
3041
		}
3042
		else {
3043
			// New search - start from the master array
3044
			if ( invalidated ||
3045
				 force ||
3046
				 prevSearch.length > input.length ||
3047
				 input.indexOf(prevSearch) !== 0 ||
3048
				 settings.bSorted // On resort, the display master needs to be
3049
				                  // re-filtered since indexes will have changed
3050
			) {
3051
				settings.aiDisplay = displayMaster.slice();
3052
			}
3053
 
3054
			// Search the display array
3055
			display = settings.aiDisplay;
3056
 
3057
			for ( i=display.length-1 ; i>=0 ; i-- ) {
3058
				if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
3059
					display.splice( i, 1 );
3060
				}
3061
			}
3062
		}
3063
	}
3064
 
3065
 
3066
	/**
3067
	 * Build a regular expression object suitable for searching a table
3068
	 *  @param {string} sSearch string to search for
3069
	 *  @param {bool} bRegex treat as a regular expression or not
3070
	 *  @param {bool} bSmart perform smart filtering or not
3071
	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
3072
	 *  @returns {RegExp} constructed object
3073
	 *  @memberof DataTable#oApi
3074
	 */
3075
	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
3076
	{
3077
		search = regex ?
3078
			search :
3079
			_fnEscapeRegex( search );
3080
 
3081
		if ( smart ) {
3082
			/* For smart filtering we want to allow the search to work regardless of
3083
			 * word order. We also want double quoted text to be preserved, so word
3084
			 * order is important - a la google. So this is what we want to
3085
			 * generate:
3086
			 *
3087
			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
3088
			 */
3089
			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
3090
				if ( word.charAt(0) === '"' ) {
3091
					var m = word.match( /^"(.*)"$/ );
3092
					word = m ? m[1] : word;
3093
				}
3094
 
3095
				return word.replace('"', '');
3096
			} );
3097
 
3098
			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
3099
		}
3100
 
3101
		return new RegExp( search, caseInsensitive ? 'i' : '' );
3102
	}
3103
 
3104
 
3105
	/**
3106
	 * Escape a string such that it can be used in a regular expression
3107
	 *  @param {string} sVal string to escape
3108
	 *  @returns {string} escaped string
3109
	 *  @memberof DataTable#oApi
3110
	 */
3111
	function _fnEscapeRegex ( sVal )
3112
	{
3113
		return sVal.replace( _re_escape_regex, '\\$1' );
3114
	}
3115
 
3116
 
3117
 
3118
	var __filter_div = $('<div>')[0];
3119
	var __filter_div_textContent = __filter_div.textContent !== undefined;
3120
 
3121
	// Update the filtering data for each row if needed (by invalidation or first run)
3122
	function _fnFilterData ( settings )
3123
	{
3124
		var columns = settings.aoColumns;
3125
		var column;
3126
		var i, j, ien, jen, filterData, cellData, row;
3127
		var fomatters = DataTable.ext.type.search;
3128
		var wasInvalidated = false;
3129
 
3130
		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
3131
			row = settings.aoData[i];
3132
 
3133
			if ( ! row._aFilterData ) {
3134
				filterData = [];
3135
 
3136
				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
3137
					column = columns[j];
3138
 
3139
					if ( column.bSearchable ) {
3140
						cellData = _fnGetCellData( settings, i, j, 'filter' );
3141
 
3142
						if ( fomatters[ column.sType ] ) {
3143
							cellData = fomatters[ column.sType ]( cellData );
3144
						}
3145
 
3146
						// Search in DataTables 1.10 is string based. In 1.11 this
3147
						// should be altered to also allow strict type checking.
3148
						if ( cellData === null ) {
3149
							cellData = '';
3150
						}
3151
 
3152
						if ( typeof cellData !== 'string' && cellData.toString ) {
3153
							cellData = cellData.toString();
3154
						}
3155
					}
3156
					else {
3157
						cellData = '';
3158
					}
3159
 
3160
					// If it looks like there is an HTML entity in the string,
3161
					// attempt to decode it so sorting works as expected. Note that
3162
					// we could use a single line of jQuery to do this, but the DOM
3163
					// method used here is much faster http://jsperf.com/html-decode
3164
					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
3165
						__filter_div.innerHTML = cellData;
3166
						cellData = __filter_div_textContent ?
3167
							__filter_div.textContent :
3168
							__filter_div.innerText;
3169
					}
3170
 
3171
					if ( cellData.replace ) {
3172
						cellData = cellData.replace(/[\r\n]/g, '');
3173
					}
3174
 
3175
					filterData.push( cellData );
3176
				}
3177
 
3178
				row._aFilterData = filterData;
3179
				row._sFilterRow = filterData.join('  ');
3180
				wasInvalidated = true;
3181
			}
3182
		}
3183
 
3184
		return wasInvalidated;
3185
	}
3186
 
3187
 
3188
	/**
3189
	 * Convert from the internal Hungarian notation to camelCase for external
3190
	 * interaction
3191
	 *  @param {object} obj Object to convert
3192
	 *  @returns {object} Inverted object
3193
	 *  @memberof DataTable#oApi
3194
	 */
3195
	function _fnSearchToCamel ( obj )
3196
	{
3197
		return {
3198
			search:          obj.sSearch,
3199
			smart:           obj.bSmart,
3200
			regex:           obj.bRegex,
3201
			caseInsensitive: obj.bCaseInsensitive
3202
		};
3203
	}
3204
 
3205
 
3206
 
3207
	/**
3208
	 * Convert from camelCase notation to the internal Hungarian. We could use the
3209
	 * Hungarian convert function here, but this is cleaner
3210
	 *  @param {object} obj Object to convert
3211
	 *  @returns {object} Inverted object
3212
	 *  @memberof DataTable#oApi
3213
	 */
3214
	function _fnSearchToHung ( obj )
3215
	{
3216
		return {
3217
			sSearch:          obj.search,
3218
			bSmart:           obj.smart,
3219
			bRegex:           obj.regex,
3220
			bCaseInsensitive: obj.caseInsensitive
3221
		};
3222
	}
3223
 
3224
	/**
3225
	 * Generate the node required for the info display
3226
	 *  @param {object} oSettings dataTables settings object
3227
	 *  @returns {node} Information element
3228
	 *  @memberof DataTable#oApi
3229
	 */
3230
	function _fnFeatureHtmlInfo ( settings )
3231
	{
3232
		var
3233
			tid = settings.sTableId,
3234
			nodes = settings.aanFeatures.i,
3235
			n = $('<div/>', {
3236
				'class': settings.oClasses.sInfo,
3237
				'id': ! nodes ? tid+'_info' : null
3238
			} );
3239
 
3240
		if ( ! nodes ) {
3241
			// Update display on each draw
3242
			settings.aoDrawCallback.push( {
3243
				"fn": _fnUpdateInfo,
3244
				"sName": "information"
3245
			} );
3246
 
3247
			n
3248
				.attr( 'role', 'status' )
3249
				.attr( 'aria-live', 'polite' );
3250
 
3251
			// Table is described by our info div
3252
			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
3253
		}
3254
 
3255
		return n[0];
3256
	}
3257
 
3258
 
3259
	/**
3260
	 * Update the information elements in the display
3261
	 *  @param {object} settings dataTables settings object
3262
	 *  @memberof DataTable#oApi
3263
	 */
3264
	function _fnUpdateInfo ( settings )
3265
	{
3266
		/* Show information about the table */
3267
		var nodes = settings.aanFeatures.i;
3268
		if ( nodes.length === 0 ) {
3269
			return;
3270
		}
3271
 
3272
		var
3273
			lang  = settings.oLanguage,
3274
			start = settings._iDisplayStart+1,
3275
			end   = settings.fnDisplayEnd(),
3276
			max   = settings.fnRecordsTotal(),
3277
			total = settings.fnRecordsDisplay(),
3278
			out   = total ?
3279
				lang.sInfo :
3280
				lang.sInfoEmpty;
3281
 
3282
		if ( total !== max ) {
3283
			/* Record set after filtering */
3284
			out += ' ' + lang.sInfoFiltered;
3285
		}
3286
 
3287
		// Convert the macros
3288
		out += lang.sInfoPostFix;
3289
		out = _fnInfoMacros( settings, out );
3290
 
3291
		var callback = lang.fnInfoCallback;
3292
		if ( callback !== null ) {
3293
			out = callback.call( settings.oInstance,
3294
				settings, start, end, max, total, out
3295
			);
3296
		}
3297
 
3298
		$(nodes).html( out );
3299
	}
3300
 
3301
 
3302
	function _fnInfoMacros ( settings, str )
3303
	{
3304
		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3305
		// internally
3306
		var
3307
			formatter  = settings.fnFormatNumber,
3308
			start      = settings._iDisplayStart+1,
3309
			len        = settings._iDisplayLength,
3310
			vis        = settings.fnRecordsDisplay(),
3311
			all        = len === -1;
3312
 
3313
		return str.
3314
			replace(/_START_/g, formatter.call( settings, start ) ).
3315
			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
3316
			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
3317
			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
3318
			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
3319
			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
3320
	}
3321
 
3322
 
3323
 
3324
	/**
3325
	 * Draw the table for the first time, adding all required features
3326
	 *  @param {object} settings dataTables settings object
3327
	 *  @memberof DataTable#oApi
3328
	 */
3329
	function _fnInitialise ( settings )
3330
	{
3331
		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3332
		var columns = settings.aoColumns, column;
3333
		var features = settings.oFeatures;
3334
		var deferLoading = settings.bDeferLoading; // value modified by the draw
3335
 
3336
		/* Ensure that the table data is fully initialised */
3337
		if ( ! settings.bInitialised ) {
3338
			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
3339
			return;
3340
		}
3341
 
3342
		/* Show the display HTML options */
3343
		_fnAddOptionsHtml( settings );
3344
 
3345
		/* Build and draw the header / footer for the table */
3346
		_fnBuildHead( settings );
3347
		_fnDrawHead( settings, settings.aoHeader );
3348
		_fnDrawHead( settings, settings.aoFooter );
3349
 
3350
		/* Okay to show that something is going on now */
3351
		_fnProcessingDisplay( settings, true );
3352
 
3353
		/* Calculate sizes for columns */
3354
		if ( features.bAutoWidth ) {
3355
			_fnCalculateColumnWidths( settings );
3356
		}
3357
 
3358
		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
3359
			column = columns[i];
3360
 
3361
			if ( column.sWidth ) {
3362
				column.nTh.style.width = _fnStringToCss( column.sWidth );
3363
			}
3364
		}
3365
 
3366
		_fnCallbackFire( settings, null, 'preInit', [settings] );
3367
 
3368
		// If there is default sorting required - let's do it. The sort function
3369
		// will do the drawing for us. Otherwise we draw the table regardless of the
3370
		// Ajax source - this allows the table to look initialised for Ajax sourcing
3371
		// data (show 'loading' message possibly)
3372
		_fnReDraw( settings );
3373
 
3374
		// Server-side processing init complete is done by _fnAjaxUpdateDraw
3375
		var dataSrc = _fnDataSource( settings );
3376
		if ( dataSrc != 'ssp' || deferLoading ) {
3377
			// if there is an ajax source load the data
3378
			if ( dataSrc == 'ajax' ) {
3379
				_fnBuildAjax( settings, [], function(json) {
3380
					var aData = _fnAjaxDataSrc( settings, json );
3381
 
3382
					// Got the data - add it to the table
3383
					for ( i=0 ; i<aData.length ; i++ ) {
3384
						_fnAddData( settings, aData[i] );
3385
					}
3386
 
3387
					// Reset the init display for cookie saving. We've already done
3388
					// a filter, and therefore cleared it before. So we need to make
3389
					// it appear 'fresh'
3390
					settings.iInitDisplayStart = iAjaxStart;
3391
 
3392
					_fnReDraw( settings );
3393
 
3394
					_fnProcessingDisplay( settings, false );
3395
					_fnInitComplete( settings, json );
3396
				}, settings );
3397
			}
3398
			else {
3399
				_fnProcessingDisplay( settings, false );
3400
				_fnInitComplete( settings );
3401
			}
3402
		}
3403
	}
3404
 
3405
 
3406
	/**
3407
	 * Draw the table for the first time, adding all required features
3408
	 *  @param {object} oSettings dataTables settings object
3409
	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
3410
	 *    with client-side processing (optional)
3411
	 *  @memberof DataTable#oApi
3412
	 */
3413
	function _fnInitComplete ( settings, json )
3414
	{
3415
		settings._bInitComplete = true;
3416
 
3417
		// When data was added after the initialisation (data or Ajax) we need to
3418
		// calculate the column sizing
3419
		if ( json || settings.oInit.aaData ) {
3420
			_fnAdjustColumnSizing( settings );
3421
		}
3422
 
3423
		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3424
	}
3425
 
3426
 
3427
	function _fnLengthChange ( settings, val )
3428
	{
3429
		var len = parseInt( val, 10 );
3430
		settings._iDisplayLength = len;
3431
 
3432
		_fnLengthOverflow( settings );
3433
 
3434
		// Fire length change event
3435
		_fnCallbackFire( settings, null, 'length', [settings, len] );
3436
	}
3437
 
3438
 
3439
	/**
3440
	 * Generate the node required for user display length changing
3441
	 *  @param {object} settings dataTables settings object
3442
	 *  @returns {node} Display length feature node
3443
	 *  @memberof DataTable#oApi
3444
	 */
3445
	function _fnFeatureHtmlLength ( settings )
3446
	{
3447
		var
3448
			classes  = settings.oClasses,
3449
			tableId  = settings.sTableId,
3450
			menu     = settings.aLengthMenu,
3451
			d2       = $.isArray( menu[0] ),
3452
			lengths  = d2 ? menu[0] : menu,
3453
			language = d2 ? menu[1] : menu;
3454
 
3455
		var select = $('<select/>', {
3456
			'name':          tableId+'_length',
3457
			'aria-controls': tableId,
3458
			'class':         classes.sLengthSelect
3459
		} );
3460
 
3461
		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
3462
			select[0][ i ] = new Option( language[i], lengths[i] );
3463
		}
3464
 
3465
		var div = $('<div><label/></div>').addClass( classes.sLength );
3466
		if ( ! settings.aanFeatures.l ) {
3467
			div[0].id = tableId+'_length';
3468
		}
3469
 
3470
		div.children().append(
3471
			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
3472
		);
3473
 
3474
		// Can't use `select` variable as user might provide their own and the
3475
		// reference is broken by the use of outerHTML
3476
		$('select', div)
3477
			.val( settings._iDisplayLength )
3478
			.bind( 'change.DT', function(e) {
3479
				_fnLengthChange( settings, $(this).val() );
3480
				_fnDraw( settings );
3481
			} );
3482
 
3483
		// Update node value whenever anything changes the table's length
3484
		$(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
3485
			if ( settings === s ) {
3486
				$('select', div).val( len );
3487
			}
3488
		} );
3489
 
3490
		return div[0];
3491
	}
3492
 
3493
 
3494
 
3495
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3496
	 * Note that most of the paging logic is done in
3497
	 * DataTable.ext.pager
3498
	 */
3499
 
3500
	/**
3501
	 * Generate the node required for default pagination
3502
	 *  @param {object} oSettings dataTables settings object
3503
	 *  @returns {node} Pagination feature node
3504
	 *  @memberof DataTable#oApi
3505
	 */
3506
	function _fnFeatureHtmlPaginate ( settings )
3507
	{
3508
		var
3509
			type   = settings.sPaginationType,
3510
			plugin = DataTable.ext.pager[ type ],
3511
			modern = typeof plugin === 'function',
3512
			redraw = function( settings ) {
3513
				_fnDraw( settings );
3514
			},
3515
			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
3516
			features = settings.aanFeatures;
3517
 
3518
		if ( ! modern ) {
3519
			plugin.fnInit( settings, node, redraw );
3520
		}
3521
 
3522
		/* Add a draw callback for the pagination on first instance, to update the paging display */
3523
		if ( ! features.p )
3524
		{
3525
			node.id = settings.sTableId+'_paginate';
3526
 
3527
			settings.aoDrawCallback.push( {
3528
				"fn": function( settings ) {
3529
					if ( modern ) {
3530
						var
3531
							start      = settings._iDisplayStart,
3532
							len        = settings._iDisplayLength,
3533
							visRecords = settings.fnRecordsDisplay(),
3534
							all        = len === -1,
3535
							page = all ? 0 : Math.ceil( start / len ),
3536
							pages = all ? 1 : Math.ceil( visRecords / len ),
3537
							buttons = plugin(page, pages),
3538
							i, ien;
3539
 
3540
						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
3541
							_fnRenderer( settings, 'pageButton' )(
3542
								settings, features.p[i], i, buttons, page, pages
3543
							);
3544
						}
3545
					}
3546
					else {
3547
						plugin.fnUpdate( settings, redraw );
3548
					}
3549
				},
3550
				"sName": "pagination"
3551
			} );
3552
		}
3553
 
3554
		return node;
3555
	}
3556
 
3557
 
3558
	/**
3559
	 * Alter the display settings to change the page
3560
	 *  @param {object} settings DataTables settings object
3561
	 *  @param {string|int} action Paging action to take: "first", "previous",
3562
	 *    "next" or "last" or page number to jump to (integer)
3563
	 *  @param [bool] redraw Automatically draw the update or not
3564
	 *  @returns {bool} true page has changed, false - no change
3565
	 *  @memberof DataTable#oApi
3566
	 */
3567
	function _fnPageChange ( settings, action, redraw )
3568
	{
3569
		var
3570
			start     = settings._iDisplayStart,
3571
			len       = settings._iDisplayLength,
3572
			records   = settings.fnRecordsDisplay();
3573
 
3574
		if ( records === 0 || len === -1 )
3575
		{
3576
			start = 0;
3577
		}
3578
		else if ( typeof action === "number" )
3579
		{
3580
			start = action * len;
3581
 
3582
			if ( start > records )
3583
			{
3584
				start = 0;
3585
			}
3586
		}
3587
		else if ( action == "first" )
3588
		{
3589
			start = 0;
3590
		}
3591
		else if ( action == "previous" )
3592
		{
3593
			start = len >= 0 ?
3594
				start - len :
3595
				0;
3596
 
3597
			if ( start < 0 )
3598
			{
3599
			  start = 0;
3600
			}
3601
		}
3602
		else if ( action == "next" )
3603
		{
3604
			if ( start + len < records )
3605
			{
3606
				start += len;
3607
			}
3608
		}
3609
		else if ( action == "last" )
3610
		{
3611
			start = Math.floor( (records-1) / len) * len;
3612
		}
3613
		else
3614
		{
3615
			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
3616
		}
3617
 
3618
		var changed = settings._iDisplayStart !== start;
3619
		settings._iDisplayStart = start;
3620
 
3621
		if ( changed ) {
3622
			_fnCallbackFire( settings, null, 'page', [settings] );
3623
 
3624
			if ( redraw ) {
3625
				_fnDraw( settings );
3626
			}
3627
		}
3628
 
3629
		return changed;
3630
	}
3631
 
3632
 
3633
 
3634
	/**
3635
	 * Generate the node required for the processing node
3636
	 *  @param {object} settings dataTables settings object
3637
	 *  @returns {node} Processing element
3638
	 *  @memberof DataTable#oApi
3639
	 */
3640
	function _fnFeatureHtmlProcessing ( settings )
3641
	{
3642
		return $('<div/>', {
3643
				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
3644
				'class': settings.oClasses.sProcessing
3645
			} )
3646
			.html( settings.oLanguage.sProcessing )
3647
			.insertBefore( settings.nTable )[0];
3648
	}
3649
 
3650
 
3651
	/**
3652
	 * Display or hide the processing indicator
3653
	 *  @param {object} settings dataTables settings object
3654
	 *  @param {bool} show Show the processing indicator (true) or not (false)
3655
	 *  @memberof DataTable#oApi
3656
	 */
3657
	function _fnProcessingDisplay ( settings, show )
3658
	{
3659
		if ( settings.oFeatures.bProcessing ) {
3660
			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
3661
		}
3662
 
3663
		_fnCallbackFire( settings, null, 'processing', [settings, show] );
3664
	}
3665
 
3666
	/**
3667
	 * Add any control elements for the table - specifically scrolling
3668
	 *  @param {object} settings dataTables settings object
3669
	 *  @returns {node} Node to add to the DOM
3670
	 *  @memberof DataTable#oApi
3671
	 */
3672
	function _fnFeatureHtmlTable ( settings )
3673
	{
3674
		var table = $(settings.nTable);
3675
 
3676
		// Add the ARIA grid role to the table
3677
		table.attr( 'role', 'grid' );
3678
 
3679
		// Scrolling from here on in
3680
		var scroll = settings.oScroll;
3681
 
3682
		if ( scroll.sX === '' && scroll.sY === '' ) {
3683
			return settings.nTable;
3684
		}
3685
 
3686
		var scrollX = scroll.sX;
3687
		var scrollY = scroll.sY;
3688
		var classes = settings.oClasses;
3689
		var caption = table.children('caption');
3690
		var captionSide = caption.length ? caption[0]._captionSide : null;
3691
		var headerClone = $( table[0].cloneNode(false) );
3692
		var footerClone = $( table[0].cloneNode(false) );
3693
		var footer = table.children('tfoot');
3694
		var _div = '<div/>';
3695
		var size = function ( s ) {
3696
			return !s ? null : _fnStringToCss( s );
3697
		};
3698
 
3699
		// This is fairly messy, but with x scrolling enabled, if the table has a
3700
		// width attribute, regardless of any width applied using the column width
3701
		// options, the browser will shrink or grow the table as needed to fit into
3702
		// that 100%. That would make the width options useless. So we remove it.
3703
		// This is okay, under the assumption that width:100% is applied to the
3704
		// table in CSS (it is in the default stylesheet) which will set the table
3705
		// width as appropriate (the attribute and css behave differently...)
3706
		if ( scroll.sX && table.attr('width') === '100%' ) {
3707
			table.removeAttr('width');
3708
		}
3709
 
3710
		if ( ! footer.length ) {
3711
			footer = null;
3712
		}
3713
 
3714
		/*
3715
		 * The HTML structure that we want to generate in this function is:
3716
		 *  div - scroller
3717
		 *    div - scroll head
3718
		 *      div - scroll head inner
3719
		 *        table - scroll head table
3720
		 *          thead - thead
3721
		 *    div - scroll body
3722
		 *      table - table (master table)
3723
		 *        thead - thead clone for sizing
3724
		 *        tbody - tbody
3725
		 *    div - scroll foot
3726
		 *      div - scroll foot inner
3727
		 *        table - scroll foot table
3728
		 *          tfoot - tfoot
3729
		 */
3730
		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
3731
			.append(
3732
				$(_div, { 'class': classes.sScrollHead } )
3733
					.css( {
3734
						overflow: 'hidden',
3735
						position: 'relative',
3736
						border: 0,
3737
						width: scrollX ? size(scrollX) : '100%'
3738
					} )
3739
					.append(
3740
						$(_div, { 'class': classes.sScrollHeadInner } )
3741
							.css( {
3742
								'box-sizing': 'content-box',
3743
								width: scroll.sXInner || '100%'
3744
							} )
3745
							.append(
3746
								headerClone
3747
									.removeAttr('id')
3748
									.css( 'margin-left', 0 )
3749
									.append( captionSide === 'top' ? caption : null )
3750
									.append(
3751
										table.children('thead')
3752
									)
3753
							)
3754
					)
3755
			)
3756
			.append(
3757
				$(_div, { 'class': classes.sScrollBody } )
3758
					.css( {
3759
						position: 'relative',
3760
						overflow: 'auto',
3761
						width: size( scrollX )
3762
					} )
3763
					.append( table )
3764
			);
3765
 
3766
		if ( footer ) {
3767
			scroller.append(
3768
				$(_div, { 'class': classes.sScrollFoot } )
3769
					.css( {
3770
						overflow: 'hidden',
3771
						border: 0,
3772
						width: scrollX ? size(scrollX) : '100%'
3773
					} )
3774
					.append(
3775
						$(_div, { 'class': classes.sScrollFootInner } )
3776
							.append(
3777
								footerClone
3778
									.removeAttr('id')
3779
									.css( 'margin-left', 0 )
3780
									.append( captionSide === 'bottom' ? caption : null )
3781
									.append(
3782
										table.children('tfoot')
3783
									)
3784
							)
3785
					)
3786
			);
3787
		}
3788
 
3789
		var children = scroller.children();
3790
		var scrollHead = children[0];
3791
		var scrollBody = children[1];
3792
		var scrollFoot = footer ? children[2] : null;
3793
 
3794
		// When the body is scrolled, then we also want to scroll the headers
3795
		if ( scrollX ) {
3796
			$(scrollBody).on( 'scroll.DT', function (e) {
3797
				var scrollLeft = this.scrollLeft;
3798
 
3799
				scrollHead.scrollLeft = scrollLeft;
3800
 
3801
				if ( footer ) {
3802
					scrollFoot.scrollLeft = scrollLeft;
3803
				}
3804
			} );
3805
		}
3806
 
3807
		$(scrollBody).css(
3808
			scrollY && scroll.bCollapse ? 'max-height' : 'height',
3809
			scrollY
3810
		);
3811
 
3812
		settings.nScrollHead = scrollHead;
3813
		settings.nScrollBody = scrollBody;
3814
		settings.nScrollFoot = scrollFoot;
3815
 
3816
		// On redraw - align columns
3817
		settings.aoDrawCallback.push( {
3818
			"fn": _fnScrollDraw,
3819
			"sName": "scrolling"
3820
		} );
3821
 
3822
		return scroller[0];
3823
	}
3824
 
3825
 
3826
 
3827
	/**
3828
	 * Update the header, footer and body tables for resizing - i.e. column
3829
	 * alignment.
3830
	 *
3831
	 * Welcome to the most horrible function DataTables. The process that this
3832
	 * function follows is basically:
3833
	 *   1. Re-create the table inside the scrolling div
3834
	 *   2. Take live measurements from the DOM
3835
	 *   3. Apply the measurements to align the columns
3836
	 *   4. Clean up
3837
	 *
3838
	 *  @param {object} settings dataTables settings object
3839
	 *  @memberof DataTable#oApi
3840
	 */
3841
	function _fnScrollDraw ( settings )
3842
	{
3843
		// Given that this is such a monster function, a lot of variables are use
3844
		// to try and keep the minimised size as small as possible
3845
		var
3846
			scroll         = settings.oScroll,
3847
			scrollX        = scroll.sX,
3848
			scrollXInner   = scroll.sXInner,
3849
			scrollY        = scroll.sY,
3850
			barWidth       = scroll.iBarWidth,
3851
			divHeader      = $(settings.nScrollHead),
3852
			divHeaderStyle = divHeader[0].style,
3853
			divHeaderInner = divHeader.children('div'),
3854
			divHeaderInnerStyle = divHeaderInner[0].style,
3855
			divHeaderTable = divHeaderInner.children('table'),
3856
			divBodyEl      = settings.nScrollBody,
3857
			divBody        = $(divBodyEl),
3858
			divBodyStyle   = divBodyEl.style,
3859
			divFooter      = $(settings.nScrollFoot),
3860
			divFooterInner = divFooter.children('div'),
3861
			divFooterTable = divFooterInner.children('table'),
3862
			header         = $(settings.nTHead),
3863
			table          = $(settings.nTable),
3864
			tableEl        = table[0],
3865
			tableStyle     = tableEl.style,
3866
			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
3867
			browser        = settings.oBrowser,
3868
			ie67           = browser.bScrollOversize,
3869
			headerTrgEls, footerTrgEls,
3870
			headerSrcEls, footerSrcEls,
3871
			headerCopy, footerCopy,
3872
			headerWidths=[], footerWidths=[],
3873
			headerContent=[],
3874
			idx, correction, sanityWidth,
3875
			zeroOut = function(nSizer) {
3876
				var style = nSizer.style;
3877
				style.paddingTop = "0";
3878
				style.paddingBottom = "0";
3879
				style.borderTopWidth = "0";
3880
				style.borderBottomWidth = "0";
3881
				style.height = 0;
3882
			};
3883
 
3884
		/*
3885
		 * 1. Re-create the table inside the scrolling div
3886
		 */
3887
 
3888
		// Remove the old minimised thead and tfoot elements in the inner table
3889
		table.children('thead, tfoot').remove();
3890
 
3891
		// Clone the current header and footer elements and then place it into the inner table
3892
		headerCopy = header.clone().prependTo( table );
3893
		headerTrgEls = header.find('tr'); // original header is in its own table
3894
		headerSrcEls = headerCopy.find('tr');
3895
		headerCopy.find('th, td').removeAttr('tabindex');
3896
 
3897
		if ( footer ) {
3898
			footerCopy = footer.clone().prependTo( table );
3899
			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
3900
			footerSrcEls = footerCopy.find('tr');
3901
		}
3902
 
3903
 
3904
		/*
3905
		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
3906
		 */
3907
 
3908
		// Remove old sizing and apply the calculated column widths
3909
		// Get the unique column headers in the newly created (cloned) header. We want to apply the
3910
		// calculated sizes to this header
3911
		if ( ! scrollX )
3912
		{
3913
			divBodyStyle.width = '100%';
3914
			divHeader[0].style.width = '100%';
3915
		}
3916
 
3917
		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
3918
			idx = _fnVisibleToColumnIndex( settings, i );
3919
			el.style.width = settings.aoColumns[idx].sWidth;
3920
		} );
3921
 
3922
		if ( footer ) {
3923
			_fnApplyToChildren( function(n) {
3924
				n.style.width = "";
3925
			}, footerSrcEls );
3926
		}
3927
 
3928
		// Size the table as a whole
3929
		sanityWidth = table.outerWidth();
3930
		if ( scrollX === "" ) {
3931
			// No x scrolling
3932
			tableStyle.width = "100%";
3933
 
3934
			// IE7 will make the width of the table when 100% include the scrollbar
3935
			// - which is shouldn't. When there is a scrollbar we need to take this
3936
			// into account.
3937
			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
3938
				divBody.css('overflow-y') == "scroll")
3939
			) {
3940
				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3941
			}
3942
 
3943
			// Recalculate the sanity width
3944
			sanityWidth = table.outerWidth();
3945
		}
3946
		else if ( scrollXInner !== "" ) {
3947
			// legacy x scroll inner has been given - use it
3948
			tableStyle.width = _fnStringToCss(scrollXInner);
3949
 
3950
			// Recalculate the sanity width
3951
			sanityWidth = table.outerWidth();
3952
		}
3953
 
3954
		// Hidden header should have zero height, so remove padding and borders. Then
3955
		// set the width based on the real headers
3956
 
3957
		// Apply all styles in one pass
3958
		_fnApplyToChildren( zeroOut, headerSrcEls );
3959
 
3960
		// Read all widths in next pass
3961
		_fnApplyToChildren( function(nSizer) {
3962
			headerContent.push( nSizer.innerHTML );
3963
			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3964
		}, headerSrcEls );
3965
 
3966
		// Apply all widths in final pass
3967
		_fnApplyToChildren( function(nToSize, i) {
3968
			nToSize.style.width = headerWidths[i];
3969
		}, headerTrgEls );
3970
 
3971
		$(headerSrcEls).height(0);
3972
 
3973
		/* Same again with the footer if we have one */
3974
		if ( footer )
3975
		{
3976
			_fnApplyToChildren( zeroOut, footerSrcEls );
3977
 
3978
			_fnApplyToChildren( function(nSizer) {
3979
				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3980
			}, footerSrcEls );
3981
 
3982
			_fnApplyToChildren( function(nToSize, i) {
3983
				nToSize.style.width = footerWidths[i];
3984
			}, footerTrgEls );
3985
 
3986
			$(footerSrcEls).height(0);
3987
		}
3988
 
3989
 
3990
		/*
3991
		 * 3. Apply the measurements
3992
		 */
3993
 
3994
		// "Hide" the header and footer that we used for the sizing. We need to keep
3995
		// the content of the cell so that the width applied to the header and body
3996
		// both match, but we want to hide it completely. We want to also fix their
3997
		// width to what they currently are
3998
		_fnApplyToChildren( function(nSizer, i) {
3999
			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
4000
			nSizer.style.width = headerWidths[i];
4001
		}, headerSrcEls );
4002
 
4003
		if ( footer )
4004
		{
4005
			_fnApplyToChildren( function(nSizer, i) {
4006
				nSizer.innerHTML = "";
4007
				nSizer.style.width = footerWidths[i];
4008
			}, footerSrcEls );
4009
		}
4010
 
4011
		// Sanity check that the table is of a sensible width. If not then we are going to get
4012
		// misalignment - try to prevent this by not allowing the table to shrink below its min width
4013
		if ( table.outerWidth() < sanityWidth )
4014
		{
4015
			// The min width depends upon if we have a vertical scrollbar visible or not */
4016
			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
4017
				divBody.css('overflow-y') == "scroll")) ?
4018
					sanityWidth+barWidth :
4019
					sanityWidth;
4020
 
4021
			// IE6/7 are a law unto themselves...
4022
			if ( ie67 && (divBodyEl.scrollHeight >
4023
				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
4024
			) {
4025
				tableStyle.width = _fnStringToCss( correction-barWidth );
4026
			}
4027
 
4028
			// And give the user a warning that we've stopped the table getting too small
4029
			if ( scrollX === "" || scrollXInner !== "" ) {
4030
				_fnLog( settings, 1, 'Possible column misalignment', 6 );
4031
			}
4032
		}
4033
		else
4034
		{
4035
			correction = '100%';
4036
		}
4037
 
4038
		// Apply to the container elements
4039
		divBodyStyle.width = _fnStringToCss( correction );
4040
		divHeaderStyle.width = _fnStringToCss( correction );
4041
 
4042
		if ( footer ) {
4043
			settings.nScrollFoot.style.width = _fnStringToCss( correction );
4044
		}
4045
 
4046
 
4047
		/*
4048
		 * 4. Clean up
4049
		 */
4050
		if ( ! scrollY ) {
4051
			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
4052
			 * the scrollbar height from the visible display, rather than adding it on. We need to
4053
			 * set the height in order to sort this. Don't want to do it in any other browsers.
4054
			 */
4055
			if ( ie67 ) {
4056
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
4057
			}
4058
		}
4059
 
4060
		/* Finally set the width's of the header and footer tables */
4061
		var iOuterWidth = table.outerWidth();
4062
		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
4063
		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
4064
 
4065
		// Figure out if there are scrollbar present - if so then we need a the header and footer to
4066
		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
4067
		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
4068
		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
4069
		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
4070
 
4071
		if ( footer ) {
4072
			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
4073
			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
4074
			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
4075
		}
4076
 
4077
		/* Adjust the position of the header in case we loose the y-scrollbar */
4078
		divBody.scroll();
4079
 
4080
		// If sorting or filtering has occurred, jump the scrolling back to the top
4081
		// only if we aren't holding the position
4082
		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
4083
			divBodyEl.scrollTop = 0;
4084
		}
4085
	}
4086
 
4087
 
4088
 
4089
	/**
4090
	 * Apply a given function to the display child nodes of an element array (typically
4091
	 * TD children of TR rows
4092
	 *  @param {function} fn Method to apply to the objects
4093
	 *  @param array {nodes} an1 List of elements to look through for display children
4094
	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
4095
	 *  @memberof DataTable#oApi
4096
	 */
4097
	function _fnApplyToChildren( fn, an1, an2 )
4098
	{
4099
		var index=0, i=0, iLen=an1.length;
4100
		var nNode1, nNode2;
4101
 
4102
		while ( i < iLen ) {
4103
			nNode1 = an1[i].firstChild;
4104
			nNode2 = an2 ? an2[i].firstChild : null;
4105
 
4106
			while ( nNode1 ) {
4107
				if ( nNode1.nodeType === 1 ) {
4108
					if ( an2 ) {
4109
						fn( nNode1, nNode2, index );
4110
					}
4111
					else {
4112
						fn( nNode1, index );
4113
					}
4114
 
4115
					index++;
4116
				}
4117
 
4118
				nNode1 = nNode1.nextSibling;
4119
				nNode2 = an2 ? nNode2.nextSibling : null;
4120
			}
4121
 
4122
			i++;
4123
		}
4124
	}
4125
 
4126
 
4127
 
4128
	var __re_html_remove = /<.*?>/g;
4129
 
4130
 
4131
	/**
4132
	 * Calculate the width of columns for the table
4133
	 *  @param {object} oSettings dataTables settings object
4134
	 *  @memberof DataTable#oApi
4135
	 */
4136
	function _fnCalculateColumnWidths ( oSettings )
4137
	{
4138
		var
4139
			table = oSettings.nTable,
4140
			columns = oSettings.aoColumns,
4141
			scroll = oSettings.oScroll,
4142
			scrollY = scroll.sY,
4143
			scrollX = scroll.sX,
4144
			scrollXInner = scroll.sXInner,
4145
			columnCount = columns.length,
4146
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
4147
			headerCells = $('th', oSettings.nTHead),
4148
			tableWidthAttr = table.getAttribute('width'), // from DOM element
4149
			tableContainer = table.parentNode,
4150
			userInputs = false,
4151
			i, column, columnIdx, width, outerWidth,
4152
			browser = oSettings.oBrowser,
4153
			ie67 = browser.bScrollOversize;
4154
 
4155
		var styleWidth = table.style.width;
4156
		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
4157
			tableWidthAttr = styleWidth;
4158
		}
4159
 
4160
		/* Convert any user input sizes into pixel sizes */
4161
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
4162
			column = columns[ visibleColumns[i] ];
4163
 
4164
			if ( column.sWidth !== null ) {
4165
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
4166
 
4167
				userInputs = true;
4168
			}
4169
		}
4170
 
4171
		/* If the number of columns in the DOM equals the number that we have to
4172
		 * process in DataTables, then we can use the offsets that are created by
4173
		 * the web- browser. No custom sizes can be set in order for this to happen,
4174
		 * nor scrolling used
4175
		 */
4176
		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
4177
		     columnCount == _fnVisbleColumns( oSettings ) &&
4178
		     columnCount == headerCells.length
4179
		) {
4180
			for ( i=0 ; i<columnCount ; i++ ) {
4181
				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
4182
 
4183
				if ( colIdx ) {
4184
					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
4185
				}
4186
			}
4187
		}
4188
		else
4189
		{
4190
			// Otherwise construct a single row, worst case, table with the widest
4191
			// node in the data, assign any user defined widths, then insert it into
4192
			// the DOM and allow the browser to do all the hard work of calculating
4193
			// table widths
4194
			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
4195
				.css( 'visibility', 'hidden' )
4196
				.removeAttr( 'id' );
4197
 
4198
			// Clean up the table body
4199
			tmpTable.find('tbody tr').remove();
4200
			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
4201
 
4202
			// Clone the table header and footer - we can't use the header / footer
4203
			// from the cloned table, since if scrolling is active, the table's
4204
			// real header and footer are contained in different table tags
4205
			tmpTable.find('thead, tfoot').remove();
4206
			tmpTable
4207
				.append( $(oSettings.nTHead).clone() )
4208
				.append( $(oSettings.nTFoot).clone() );
4209
 
4210
			// Remove any assigned widths from the footer (from scrolling)
4211
			tmpTable.find('tfoot th, tfoot td').css('width', '');
4212
 
4213
			// Apply custom sizing to the cloned header
4214
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
4215
 
4216
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
4217
				column = columns[ visibleColumns[i] ];
4218
 
4219
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
4220
					_fnStringToCss( column.sWidthOrig ) :
4221
					'';
4222
			}
4223
 
4224
			// Find the widest cell for each column and put it into the table
4225
			if ( oSettings.aoData.length ) {
4226
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
4227
					columnIdx = visibleColumns[i];
4228
					column = columns[ columnIdx ];
4229
 
4230
					$( _fnGetWidestNode( oSettings, columnIdx ) )
4231
						.clone( false )
4232
						.append( column.sContentPadding )
4233
						.appendTo( tr );
4234
				}
4235
			}
4236
 
4237
			// Table has been built, attach to the document so we can work with it.
4238
			// A holding element is used, positioned at the top of the container
4239
			// with minimal height, so it has no effect on if the container scrolls
4240
			// or not. Otherwise it might trigger scrolling when it actually isn't
4241
			// needed
4242
			var holder = $('<div/>').css( scrollX || scrollY ?
4243
					{
4244
						position: 'absolute',
4245
						top: 0,
4246
						left: 0,
4247
						height: 1,
4248
						right: 0,
4249
						overflow: 'hidden'
4250
					} :
4251
					{}
4252
				)
4253
				.append( tmpTable )
4254
				.appendTo( tableContainer );
4255
 
4256
			// When scrolling (X or Y) we want to set the width of the table as
4257
			// appropriate. However, when not scrolling leave the table width as it
4258
			// is. This results in slightly different, but I think correct behaviour
4259
			if ( scrollX && scrollXInner ) {
4260
				tmpTable.width( scrollXInner );
4261
			}
4262
			else if ( scrollX ) {
4263
				tmpTable.css( 'width', 'auto' );
4264
 
4265
				if ( tmpTable.width() < tableContainer.clientWidth ) {
4266
					tmpTable.width( tableContainer.clientWidth );
4267
				}
4268
			}
4269
			else if ( scrollY ) {
4270
				tmpTable.width( tableContainer.clientWidth );
4271
			}
4272
			else if ( tableWidthAttr ) {
4273
				tmpTable.width( tableWidthAttr );
4274
			}
4275
 
4276
			// Browsers need a bit of a hand when a width is assigned to any columns
4277
			// when x-scrolling as they tend to collapse the table to the min-width,
4278
			// even if we sent the column widths. So we need to keep track of what
4279
			// the table width should be by summing the user given values, and the
4280
			// automatic values
4281
			if ( scrollX )
4282
			{
4283
				var total = 0;
4284
 
4285
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
4286
					column = columns[ visibleColumns[i] ];
4287
 
4288
					// Much prefer to use getBoundingClientRect due to its sub-pixel
4289
					// resolution, but IE8- do not support the width property.
4290
					outerWidth = browser.bBounding ?
4291
						headerCells[i].getBoundingClientRect().width :
4292
						$(headerCells[i]).outerWidth();
4293
 
4294
					total += column.sWidthOrig === null ?
4295
						outerWidth :
4296
						parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4297
				}
4298
 
4299
				tmpTable.width( _fnStringToCss( total ) );
4300
				table.style.width = _fnStringToCss( total );
4301
			}
4302
 
4303
			// Get the width of each column in the constructed table
4304
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
4305
				column = columns[ visibleColumns[i] ];
4306
				width = $(headerCells[i]).width();
4307
 
4308
				if ( width ) {
4309
					column.sWidth = _fnStringToCss( width );
4310
				}
4311
			}
4312
 
4313
			table.style.width = _fnStringToCss( tmpTable.css('width') );
4314
 
4315
			// Finished with the table - ditch it
4316
			holder.remove();
4317
		}
4318
 
4319
		// If there is a width attr, we want to attach an event listener which
4320
		// allows the table sizing to automatically adjust when the window is
4321
		// resized. Use the width attr rather than CSS, since we can't know if the
4322
		// CSS is a relative value or absolute - DOM read is always px.
4323
		if ( tableWidthAttr ) {
4324
			table.style.width = _fnStringToCss( tableWidthAttr );
4325
		}
4326
 
4327
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4328
			var bindResize = function () {
4329
				$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4330
					_fnAdjustColumnSizing( oSettings );
4331
				} ) );
4332
			};
4333
 
4334
			// IE6/7 will crash if we bind a resize event handler on page load.
4335
			// To be removed in 1.11 which drops IE6/7 support
4336
			if ( ie67 ) {
4337
				setTimeout( bindResize, 1000 );
4338
			}
4339
			else {
4340
				bindResize();
4341
			}
4342
 
4343
			oSettings._reszEvt = true;
4344
		}
4345
	}
4346
 
4347
 
4348
	/**
4349
	 * Throttle the calls to a function. Arguments and context are maintained for
4350
	 * the throttled function
4351
	 *  @param {function} fn Function to be called
4352
	 *  @param {int} [freq=200] call frequency in mS
4353
	 *  @returns {function} wrapped function
4354
	 *  @memberof DataTable#oApi
4355
	 */
4356
	function _fnThrottle( fn, freq ) {
4357
		var
4358
			frequency = freq !== undefined ? freq : 200,
4359
			last,
4360
			timer;
4361
 
4362
		return function () {
4363
			var
4364
				that = this,
4365
				now  = +new Date(),
4366
				args = arguments;
4367
 
4368
			if ( last && now < last + frequency ) {
4369
				clearTimeout( timer );
4370
 
4371
				timer = setTimeout( function () {
4372
					last = undefined;
4373
					fn.apply( that, args );
4374
				}, frequency );
4375
			}
4376
			else {
4377
				last = now;
4378
				fn.apply( that, args );
4379
			}
4380
		};
4381
	}
4382
 
4383
 
4384
	/**
4385
	 * Convert a CSS unit width to pixels (e.g. 2em)
4386
	 *  @param {string} width width to be converted
4387
	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
4388
	 *  @returns {int} width in pixels
4389
	 *  @memberof DataTable#oApi
4390
	 */
4391
	function _fnConvertToWidth ( width, parent )
4392
	{
4393
		if ( ! width ) {
4394
			return 0;
4395
		}
4396
 
4397
		var n = $('<div/>')
4398
			.css( 'width', _fnStringToCss( width ) )
4399
			.appendTo( parent || document.body );
4400
 
4401
		var val = n[0].offsetWidth;
4402
		n.remove();
4403
 
4404
		return val;
4405
	}
4406
 
4407
 
4408
	/**
4409
	 * Get the widest node
4410
	 *  @param {object} settings dataTables settings object
4411
	 *  @param {int} colIdx column of interest
4412
	 *  @returns {node} widest table node
4413
	 *  @memberof DataTable#oApi
4414
	 */
4415
	function _fnGetWidestNode( settings, colIdx )
4416
	{
4417
		var idx = _fnGetMaxLenString( settings, colIdx );
4418
		if ( idx < 0 ) {
4419
			return null;
4420
		}
4421
 
4422
		var data = settings.aoData[ idx ];
4423
		return ! data.nTr ? // Might not have been created when deferred rendering
4424
			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
4425
			data.anCells[ colIdx ];
4426
	}
4427
 
4428
 
4429
	/**
4430
	 * Get the maximum strlen for each data column
4431
	 *  @param {object} settings dataTables settings object
4432
	 *  @param {int} colIdx column of interest
4433
	 *  @returns {string} max string length for each column
4434
	 *  @memberof DataTable#oApi
4435
	 */
4436
	function _fnGetMaxLenString( settings, colIdx )
4437
	{
4438
		var s, max=-1, maxIdx = -1;
4439
 
4440
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4441
			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4442
			s = s.replace( __re_html_remove, '' );
4443
 
4444
			if ( s.length > max ) {
4445
				max = s.length;
4446
				maxIdx = i;
4447
			}
4448
		}
4449
 
4450
		return maxIdx;
4451
	}
4452
 
4453
 
4454
	/**
4455
	 * Append a CSS unit (only if required) to a string
4456
	 *  @param {string} value to css-ify
4457
	 *  @returns {string} value with css unit
4458
	 *  @memberof DataTable#oApi
4459
	 */
4460
	function _fnStringToCss( s )
4461
	{
4462
		if ( s === null ) {
4463
			return '0px';
4464
		}
4465
 
4466
		if ( typeof s == 'number' ) {
4467
			return s < 0 ?
4468
				'0px' :
4469
				s+'px';
4470
		}
4471
 
4472
		// Check it has a unit character already
4473
		return s.match(/\d$/) ?
4474
			s+'px' :
4475
			s;
4476
	}
4477
 
4478
 
4479
 
4480
	function _fnSortFlatten ( settings )
4481
	{
4482
		var
4483
			i, iLen, k, kLen,
4484
			aSort = [],
4485
			aiOrig = [],
4486
			aoColumns = settings.aoColumns,
4487
			aDataSort, iCol, sType, srcCol,
4488
			fixed = settings.aaSortingFixed,
4489
			fixedObj = $.isPlainObject( fixed ),
4490
			nestedSort = [],
4491
			add = function ( a ) {
4492
				if ( a.length && ! $.isArray( a[0] ) ) {
4493
					// 1D array
4494
					nestedSort.push( a );
4495
				}
4496
				else {
4497
					// 2D array
4498
					$.merge( nestedSort, a );
4499
				}
4500
			};
4501
 
4502
		// Build the sort array, with pre-fix and post-fix options if they have been
4503
		// specified
4504
		if ( $.isArray( fixed ) ) {
4505
			add( fixed );
4506
		}
4507
 
4508
		if ( fixedObj && fixed.pre ) {
4509
			add( fixed.pre );
4510
		}
4511
 
4512
		add( settings.aaSorting );
4513
 
4514
		if (fixedObj && fixed.post ) {
4515
			add( fixed.post );
4516
		}
4517
 
4518
		for ( i=0 ; i<nestedSort.length ; i++ )
4519
		{
4520
			srcCol = nestedSort[i][0];
4521
			aDataSort = aoColumns[ srcCol ].aDataSort;
4522
 
4523
			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
4524
			{
4525
				iCol = aDataSort[k];
4526
				sType = aoColumns[ iCol ].sType || 'string';
4527
 
4528
				if ( nestedSort[i]._idx === undefined ) {
4529
					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
4530
				}
4531
 
4532
				aSort.push( {
4533
					src:       srcCol,
4534
					col:       iCol,
4535
					dir:       nestedSort[i][1],
4536
					index:     nestedSort[i]._idx,
4537
					type:      sType,
4538
					formatter: DataTable.ext.type.order[ sType+"-pre" ]
4539
				} );
4540
			}
4541
		}
4542
 
4543
		return aSort;
4544
	}
4545
 
4546
	/**
4547
	 * Change the order of the table
4548
	 *  @param {object} oSettings dataTables settings object
4549
	 *  @memberof DataTable#oApi
4550
	 *  @todo This really needs split up!
4551
	 */
4552
	function _fnSort ( oSettings )
4553
	{
4554
		var
4555
			i, ien, iLen, j, jLen, k, kLen,
4556
			sDataType, nTh,
4557
			aiOrig = [],
4558
			oExtSort = DataTable.ext.type.order,
4559
			aoData = oSettings.aoData,
4560
			aoColumns = oSettings.aoColumns,
4561
			aDataSort, data, iCol, sType, oSort,
4562
			formatters = 0,
4563
			sortCol,
4564
			displayMaster = oSettings.aiDisplayMaster,
4565
			aSort;
4566
 
4567
		// Resolve any column types that are unknown due to addition or invalidation
4568
		// @todo Can this be moved into a 'data-ready' handler which is called when
4569
		//   data is going to be used in the table?
4570
		_fnColumnTypes( oSettings );
4571
 
4572
		aSort = _fnSortFlatten( oSettings );
4573
 
4574
		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
4575
			sortCol = aSort[i];
4576
 
4577
			// Track if we can use the fast sort algorithm
4578
			if ( sortCol.formatter ) {
4579
				formatters++;
4580
			}
4581
 
4582
			// Load the data needed for the sort, for each cell
4583
			_fnSortData( oSettings, sortCol.col );
4584
		}
4585
 
4586
		/* No sorting required if server-side or no sorting array */
4587
		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
4588
		{
4589
			// Create a value - key array of the current row positions such that we can use their
4590
			// current position during the sort, if values match, in order to perform stable sorting
4591
			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
4592
				aiOrig[ displayMaster[i] ] = i;
4593
			}
4594
 
4595
			/* Do the sort - here we want multi-column sorting based on a given data source (column)
4596
			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4597
			 * follow on it's own, but this is what we want (example two column sorting):
4598
			 *  fnLocalSorting = function(a,b){
4599
			 *    var iTest;
4600
			 *    iTest = oSort['string-asc']('data11', 'data12');
4601
			 *      if (iTest !== 0)
4602
			 *        return iTest;
4603
			 *    iTest = oSort['numeric-desc']('data21', 'data22');
4604
			 *    if (iTest !== 0)
4605
			 *      return iTest;
4606
			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4607
			 *  }
4608
			 * Basically we have a test for each sorting column, if the data in that column is equal,
4609
			 * test the next column. If all columns match, then we use a numeric sort on the row
4610
			 * positions in the original data array to provide a stable sort.
4611
			 *
4612
			 * Note - I know it seems excessive to have two sorting methods, but the first is around
4613
			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
4614
			 * methods which do not have a pre-sort formatting function.
4615
			 */
4616
			if ( formatters === aSort.length ) {
4617
				// All sort types have formatting functions
4618
				displayMaster.sort( function ( a, b ) {
4619
					var
4620
						x, y, k, test, sort,
4621
						len=aSort.length,
4622
						dataA = aoData[a]._aSortData,
4623
						dataB = aoData[b]._aSortData;
4624
 
4625
					for ( k=0 ; k<len ; k++ ) {
4626
						sort = aSort[k];
4627
 
4628
						x = dataA[ sort.col ];
4629
						y = dataB[ sort.col ];
4630
 
4631
						test = x<y ? -1 : x>y ? 1 : 0;
4632
						if ( test !== 0 ) {
4633
							return sort.dir === 'asc' ? test : -test;
4634
						}
4635
					}
4636
 
4637
					x = aiOrig[a];
4638
					y = aiOrig[b];
4639
					return x<y ? -1 : x>y ? 1 : 0;
4640
				} );
4641
			}
4642
			else {
4643
				// Depreciated - remove in 1.11 (providing a plug-in option)
4644
				// Not all sort types have formatting methods, so we have to call their sorting
4645
				// methods.
4646
				displayMaster.sort( function ( a, b ) {
4647
					var
4648
						x, y, k, l, test, sort, fn,
4649
						len=aSort.length,
4650
						dataA = aoData[a]._aSortData,
4651
						dataB = aoData[b]._aSortData;
4652
 
4653
					for ( k=0 ; k<len ; k++ ) {
4654
						sort = aSort[k];
4655
 
4656
						x = dataA[ sort.col ];
4657
						y = dataB[ sort.col ];
4658
 
4659
						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
4660
						test = fn( x, y );
4661
						if ( test !== 0 ) {
4662
							return test;
4663
						}
4664
					}
4665
 
4666
					x = aiOrig[a];
4667
					y = aiOrig[b];
4668
					return x<y ? -1 : x>y ? 1 : 0;
4669
				} );
4670
			}
4671
		}
4672
 
4673
		/* Tell the draw function that we have sorted the data */
4674
		oSettings.bSorted = true;
4675
	}
4676
 
4677
 
4678
	function _fnSortAria ( settings )
4679
	{
4680
		var label;
4681
		var nextSort;
4682
		var columns = settings.aoColumns;
4683
		var aSort = _fnSortFlatten( settings );
4684
		var oAria = settings.oLanguage.oAria;
4685
 
4686
		// ARIA attributes - need to loop all columns, to update all (removing old
4687
		// attributes as needed)
4688
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4689
		{
4690
			var col = columns[i];
4691
			var asSorting = col.asSorting;
4692
			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
4693
			var th = col.nTh;
4694
 
4695
			// IE7 is throwing an error when setting these properties with jQuery's
4696
			// attr() and removeAttr() methods...
4697
			th.removeAttribute('aria-sort');
4698
 
4699
			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4700
			if ( col.bSortable ) {
4701
				if ( aSort.length > 0 && aSort[0].col == i ) {
4702
					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
4703
					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
4704
				}
4705
				else {
4706
					nextSort = asSorting[0];
4707
				}
4708
 
4709
				label = sTitle + ( nextSort === "asc" ?
4710
					oAria.sSortAscending :
4711
					oAria.sSortDescending
4712
				);
4713
			}
4714
			else {
4715
				label = sTitle;
4716
			}
4717
 
4718
			th.setAttribute('aria-label', label);
4719
		}
4720
	}
4721
 
4722
 
4723
	/**
4724
	 * Function to run on user sort request
4725
	 *  @param {object} settings dataTables settings object
4726
	 *  @param {node} attachTo node to attach the handler to
4727
	 *  @param {int} colIdx column sorting index
4728
	 *  @param {boolean} [append=false] Append the requested sort to the existing
4729
	 *    sort if true (i.e. multi-column sort)
4730
	 *  @param {function} [callback] callback function
4731
	 *  @memberof DataTable#oApi
4732
	 */
4733
	function _fnSortListener ( settings, colIdx, append, callback )
4734
	{
4735
		var col = settings.aoColumns[ colIdx ];
4736
		var sorting = settings.aaSorting;
4737
		var asSorting = col.asSorting;
4738
		var nextSortIdx;
4739
		var next = function ( a, overflow ) {
4740
			var idx = a._idx;
4741
			if ( idx === undefined ) {
4742
				idx = $.inArray( a[1], asSorting );
4743
			}
4744
 
4745
			return idx+1 < asSorting.length ?
4746
				idx+1 :
4747
				overflow ?
4748
					null :
4749
					0;
4750
		};
4751
 
4752
		// Convert to 2D array if needed
4753
		if ( typeof sorting[0] === 'number' ) {
4754
			sorting = settings.aaSorting = [ sorting ];
4755
		}
4756
 
4757
		// If appending the sort then we are multi-column sorting
4758
		if ( append && settings.oFeatures.bSortMulti ) {
4759
			// Are we already doing some kind of sort on this column?
4760
			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
4761
 
4762
			if ( sortIdx !== -1 ) {
4763
				// Yes, modify the sort
4764
				nextSortIdx = next( sorting[sortIdx], true );
4765
 
4766
				if ( nextSortIdx === null && sorting.length === 1 ) {
4767
					nextSortIdx = 0; // can't remove sorting completely
4768
				}
4769
 
4770
				if ( nextSortIdx === null ) {
4771
					sorting.splice( sortIdx, 1 );
4772
				}
4773
				else {
4774
					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
4775
					sorting[sortIdx]._idx = nextSortIdx;
4776
				}
4777
			}
4778
			else {
4779
				// No sort on this column yet
4780
				sorting.push( [ colIdx, asSorting[0], 0 ] );
4781
				sorting[sorting.length-1]._idx = 0;
4782
			}
4783
		}
4784
		else if ( sorting.length && sorting[0][0] == colIdx ) {
4785
			// Single column - already sorting on this column, modify the sort
4786
			nextSortIdx = next( sorting[0] );
4787
 
4788
			sorting.length = 1;
4789
			sorting[0][1] = asSorting[ nextSortIdx ];
4790
			sorting[0]._idx = nextSortIdx;
4791
		}
4792
		else {
4793
			// Single column - sort only on this column
4794
			sorting.length = 0;
4795
			sorting.push( [ colIdx, asSorting[0] ] );
4796
			sorting[0]._idx = 0;
4797
		}
4798
 
4799
		// Run the sort by calling a full redraw
4800
		_fnReDraw( settings );
4801
 
4802
		// callback used for async user interaction
4803
		if ( typeof callback == 'function' ) {
4804
			callback( settings );
4805
		}
4806
	}
4807
 
4808
 
4809
	/**
4810
	 * Attach a sort handler (click) to a node
4811
	 *  @param {object} settings dataTables settings object
4812
	 *  @param {node} attachTo node to attach the handler to
4813
	 *  @param {int} colIdx column sorting index
4814
	 *  @param {function} [callback] callback function
4815
	 *  @memberof DataTable#oApi
4816
	 */
4817
	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
4818
	{
4819
		var col = settings.aoColumns[ colIdx ];
4820
 
4821
		_fnBindAction( attachTo, {}, function (e) {
4822
			/* If the column is not sortable - don't to anything */
4823
			if ( col.bSortable === false ) {
4824
				return;
4825
			}
4826
 
4827
			// If processing is enabled use a timeout to allow the processing
4828
			// display to be shown - otherwise to it synchronously
4829
			if ( settings.oFeatures.bProcessing ) {
4830
				_fnProcessingDisplay( settings, true );
4831
 
4832
				setTimeout( function() {
4833
					_fnSortListener( settings, colIdx, e.shiftKey, callback );
4834
 
4835
					// In server-side processing, the draw callback will remove the
4836
					// processing display
4837
					if ( _fnDataSource( settings ) !== 'ssp' ) {
4838
						_fnProcessingDisplay( settings, false );
4839
					}
4840
				}, 0 );
4841
			}
4842
			else {
4843
				_fnSortListener( settings, colIdx, e.shiftKey, callback );
4844
			}
4845
		} );
4846
	}
4847
 
4848
 
4849
	/**
4850
	 * Set the sorting classes on table's body, Note: it is safe to call this function
4851
	 * when bSort and bSortClasses are false
4852
	 *  @param {object} oSettings dataTables settings object
4853
	 *  @memberof DataTable#oApi
4854
	 */
4855
	function _fnSortingClasses( settings )
4856
	{
4857
		var oldSort = settings.aLastSort;
4858
		var sortClass = settings.oClasses.sSortColumn;
4859
		var sort = _fnSortFlatten( settings );
4860
		var features = settings.oFeatures;
4861
		var i, ien, colIdx;
4862
 
4863
		if ( features.bSort && features.bSortClasses ) {
4864
			// Remove old sorting classes
4865
			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
4866
				colIdx = oldSort[i].src;
4867
 
4868
				// Remove column sorting
4869
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4870
					.removeClass( sortClass + (i<2 ? i+1 : 3) );
4871
			}
4872
 
4873
			// Add new column sorting
4874
			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
4875
				colIdx = sort[i].src;
4876
 
4877
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4878
					.addClass( sortClass + (i<2 ? i+1 : 3) );
4879
			}
4880
		}
4881
 
4882
		settings.aLastSort = sort;
4883
	}
4884
 
4885
 
4886
	// Get the data to sort a column, be it from cache, fresh (populating the
4887
	// cache), or from a sort formatter
4888
	function _fnSortData( settings, idx )
4889
	{
4890
		// Custom sorting function - provided by the sort data type
4891
		var column = settings.aoColumns[ idx ];
4892
		var customSort = DataTable.ext.order[ column.sSortDataType ];
4893
		var customData;
4894
 
4895
		if ( customSort ) {
4896
			customData = customSort.call( settings.oInstance, settings, idx,
4897
				_fnColumnIndexToVisible( settings, idx )
4898
			);
4899
		}
4900
 
4901
		// Use / populate cache
4902
		var row, cellData;
4903
		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
4904
 
4905
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4906
			row = settings.aoData[i];
4907
 
4908
			if ( ! row._aSortData ) {
4909
				row._aSortData = [];
4910
			}
4911
 
4912
			if ( ! row._aSortData[idx] || customSort ) {
4913
				cellData = customSort ?
4914
					customData[i] : // If there was a custom sort function, use data from there
4915
					_fnGetCellData( settings, i, idx, 'sort' );
4916
 
4917
				row._aSortData[ idx ] = formatter ?
4918
					formatter( cellData ) :
4919
					cellData;
4920
			}
4921
		}
4922
	}
4923
 
4924
 
4925
 
4926
	/**
4927
	 * Save the state of a table
4928
	 *  @param {object} oSettings dataTables settings object
4929
	 *  @memberof DataTable#oApi
4930
	 */
4931
	function _fnSaveState ( settings )
4932
	{
4933
		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
4934
		{
4935
			return;
4936
		}
4937
 
4938
		/* Store the interesting variables */
4939
		var state = {
4940
			time:    +new Date(),
4941
			start:   settings._iDisplayStart,
4942
			length:  settings._iDisplayLength,
4943
			order:   $.extend( true, [], settings.aaSorting ),
4944
			search:  _fnSearchToCamel( settings.oPreviousSearch ),
4945
			columns: $.map( settings.aoColumns, function ( col, i ) {
4946
				return {
4947
					visible: col.bVisible,
4948
					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
4949
				};
4950
			} )
4951
		};
4952
 
4953
		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
4954
 
4955
		settings.oSavedState = state;
4956
		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
4957
	}
4958
 
4959
 
4960
	/**
4961
	 * Attempt to load a saved table state
4962
	 *  @param {object} oSettings dataTables settings object
4963
	 *  @param {object} oInit DataTables init object so we can override settings
4964
	 *  @memberof DataTable#oApi
4965
	 */
4966
	function _fnLoadState ( settings, oInit )
4967
	{
4968
		var i, ien;
4969
		var columns = settings.aoColumns;
4970
 
4971
		if ( ! settings.oFeatures.bStateSave ) {
4972
			return;
4973
		}
4974
 
4975
		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
4976
		if ( ! state || ! state.time ) {
4977
			return;
4978
		}
4979
 
4980
		/* Allow custom and plug-in manipulation functions to alter the saved data set and
4981
		 * cancelling of loading by returning false
4982
		 */
4983
		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
4984
		if ( $.inArray( false, abStateLoad ) !== -1 ) {
4985
			return;
4986
		}
4987
 
4988
		/* Reject old data */
4989
		var duration = settings.iStateDuration;
4990
		if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
4991
			return;
4992
		}
4993
 
4994
		// Number of columns have changed - all bets are off, no restore of settings
4995
		if ( columns.length !== state.columns.length ) {
4996
			return;
4997
		}
4998
 
4999
		// Store the saved state so it might be accessed at any time
5000
		settings.oLoadedState = $.extend( true, {}, state );
5001
 
5002
		// Restore key features - todo - for 1.11 this needs to be done by
5003
		// subscribed events
5004
		if ( state.start !== undefined ) {
5005
			settings._iDisplayStart    = state.start;
5006
			settings.iInitDisplayStart = state.start;
5007
		}
5008
		if ( state.length !== undefined ) {
5009
			settings._iDisplayLength   = state.length;
5010
		}
5011
 
5012
		// Order
5013
		if ( state.order !== undefined ) {
5014
			settings.aaSorting = [];
5015
			$.each( state.order, function ( i, col ) {
5016
				settings.aaSorting.push( col[0] >= columns.length ?
5017
					[ 0, col[1] ] :
5018
					col
5019
				);
5020
			} );
5021
		}
5022
 
5023
		// Search
5024
		if ( state.search !== undefined ) {
5025
			$.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
5026
		}
5027
 
5028
		// Columns
5029
		for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
5030
			var col = state.columns[i];
5031
 
5032
			// Visibility
5033
			if ( col.visible !== undefined ) {
5034
				columns[i].bVisible = col.visible;
5035
			}
5036
 
5037
			// Search
5038
			if ( col.search !== undefined ) {
5039
				$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
5040
			}
5041
		}
5042
 
5043
		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
5044
	}
5045
 
5046
 
5047
	/**
5048
	 * Return the settings object for a particular table
5049
	 *  @param {node} table table we are using as a dataTable
5050
	 *  @returns {object} Settings object - or null if not found
5051
	 *  @memberof DataTable#oApi
5052
	 */
5053
	function _fnSettingsFromNode ( table )
5054
	{
5055
		var settings = DataTable.settings;
5056
		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
5057
 
5058
		return idx !== -1 ?
5059
			settings[ idx ] :
5060
			null;
5061
	}
5062
 
5063
 
5064
	/**
5065
	 * Log an error message
5066
	 *  @param {object} settings dataTables settings object
5067
	 *  @param {int} level log error messages, or display them to the user
5068
	 *  @param {string} msg error message
5069
	 *  @param {int} tn Technical note id to get more information about the error.
5070
	 *  @memberof DataTable#oApi
5071
	 */
5072
	function _fnLog( settings, level, msg, tn )
5073
	{
5074
		msg = 'DataTables warning: '+
5075
			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
5076
 
5077
		if ( tn ) {
5078
			msg += '. For more information about this error, please see '+
5079
			'http://datatables.net/tn/'+tn;
5080
		}
5081
 
5082
		if ( ! level  ) {
5083
			// Backwards compatibility pre 1.10
5084
			var ext = DataTable.ext;
5085
			var type = ext.sErrMode || ext.errMode;
5086
 
5087
			if ( settings ) {
5088
				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
5089
			}
5090
 
5091
			if ( type == 'alert' ) {
5092
				alert( msg );
5093
			}
5094
			else if ( type == 'throw' ) {
5095
				throw new Error(msg);
5096
			}
5097
			else if ( typeof type == 'function' ) {
5098
				type( settings, tn, msg );
5099
			}
5100
		}
5101
		else if ( window.console && console.log ) {
5102
			console.log( msg );
5103
		}
5104
	}
5105
 
5106
 
5107
	/**
5108
	 * See if a property is defined on one object, if so assign it to the other object
5109
	 *  @param {object} ret target object
5110
	 *  @param {object} src source object
5111
	 *  @param {string} name property
5112
	 *  @param {string} [mappedName] name to map too - optional, name used if not given
5113
	 *  @memberof DataTable#oApi
5114
	 */
5115
	function _fnMap( ret, src, name, mappedName )
5116
	{
5117
		if ( $.isArray( name ) ) {
5118
			$.each( name, function (i, val) {
5119
				if ( $.isArray( val ) ) {
5120
					_fnMap( ret, src, val[0], val[1] );
5121
				}
5122
				else {
5123
					_fnMap( ret, src, val );
5124
				}
5125
			} );
5126
 
5127
			return;
5128
		}
5129
 
5130
		if ( mappedName === undefined ) {
5131
			mappedName = name;
5132
		}
5133
 
5134
		if ( src[name] !== undefined ) {
5135
			ret[mappedName] = src[name];
5136
		}
5137
	}
5138
 
5139
 
5140
	/**
5141
	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
5142
	 * shallow copy arrays. The reason we need to do this, is that we don't want to
5143
	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
5144
	 * able to override them, but we do want to deep copy arrays.
5145
	 *  @param {object} out Object to extend
5146
	 *  @param {object} extender Object from which the properties will be applied to
5147
	 *      out
5148
	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
5149
	 *      independent copy with the exception of the `data` or `aaData` parameters
5150
	 *      if they are present. This is so you can pass in a collection to
5151
	 *      DataTables and have that used as your data source without breaking the
5152
	 *      references
5153
	 *  @returns {object} out Reference, just for convenience - out === the return.
5154
	 *  @memberof DataTable#oApi
5155
	 *  @todo This doesn't take account of arrays inside the deep copied objects.
5156
	 */
5157
	function _fnExtend( out, extender, breakRefs )
5158
	{
5159
		var val;
5160
 
5161
		for ( var prop in extender ) {
5162
			if ( extender.hasOwnProperty(prop) ) {
5163
				val = extender[prop];
5164
 
5165
				if ( $.isPlainObject( val ) ) {
5166
					if ( ! $.isPlainObject( out[prop] ) ) {
5167
						out[prop] = {};
5168
					}
5169
					$.extend( true, out[prop], val );
5170
				}
5171
				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
5172
					out[prop] = val.slice();
5173
				}
5174
				else {
5175
					out[prop] = val;
5176
				}
5177
			}
5178
		}
5179
 
5180
		return out;
5181
	}
5182
 
5183
 
5184
	/**
5185
	 * Bind an event handers to allow a click or return key to activate the callback.
5186
	 * This is good for accessibility since a return on the keyboard will have the
5187
	 * same effect as a click, if the element has focus.
5188
	 *  @param {element} n Element to bind the action to
5189
	 *  @param {object} oData Data object to pass to the triggered function
5190
	 *  @param {function} fn Callback function for when the event is triggered
5191
	 *  @memberof DataTable#oApi
5192
	 */
5193
	function _fnBindAction( n, oData, fn )
5194
	{
5195
		$(n)
5196
			.bind( 'click.DT', oData, function (e) {
5197
					n.blur(); // Remove focus outline for mouse users
5198
					fn(e);
5199
				} )
5200
			.bind( 'keypress.DT', oData, function (e){
5201
					if ( e.which === 13 ) {
5202
						e.preventDefault();
5203
						fn(e);
5204
					}
5205
				} )
5206
			.bind( 'selectstart.DT', function () {
5207
					/* Take the brutal approach to cancelling text selection */
5208
					return false;
5209
				} );
5210
	}
5211
 
5212
 
5213
	/**
5214
	 * Register a callback function. Easily allows a callback function to be added to
5215
	 * an array store of callback functions that can then all be called together.
5216
	 *  @param {object} oSettings dataTables settings object
5217
	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
5218
	 *  @param {function} fn Function to be called back
5219
	 *  @param {string} sName Identifying name for the callback (i.e. a label)
5220
	 *  @memberof DataTable#oApi
5221
	 */
5222
	function _fnCallbackReg( oSettings, sStore, fn, sName )
5223
	{
5224
		if ( fn )
5225
		{
5226
			oSettings[sStore].push( {
5227
				"fn": fn,
5228
				"sName": sName
5229
			} );
5230
		}
5231
	}
5232
 
5233
 
5234
	/**
5235
	 * Fire callback functions and trigger events. Note that the loop over the
5236
	 * callback array store is done backwards! Further note that you do not want to
5237
	 * fire off triggers in time sensitive applications (for example cell creation)
5238
	 * as its slow.
5239
	 *  @param {object} settings dataTables settings object
5240
	 *  @param {string} callbackArr Name of the array storage for the callbacks in
5241
	 *      oSettings
5242
	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
5243
	 *      null no trigger is fired
5244
	 *  @param {array} args Array of arguments to pass to the callback function /
5245
	 *      trigger
5246
	 *  @memberof DataTable#oApi
5247
	 */
5248
	function _fnCallbackFire( settings, callbackArr, eventName, args )
5249
	{
5250
		var ret = [];
5251
 
5252
		if ( callbackArr ) {
5253
			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
5254
				return val.fn.apply( settings.oInstance, args );
5255
			} );
5256
		}
5257
 
5258
		if ( eventName !== null ) {
5259
			var e = $.Event( eventName+'.dt' );
5260
 
5261
			$(settings.nTable).trigger( e, args );
5262
 
5263
			ret.push( e.result );
5264
		}
5265
 
5266
		return ret;
5267
	}
5268
 
5269
 
5270
	function _fnLengthOverflow ( settings )
5271
	{
5272
		var
5273
			start = settings._iDisplayStart,
5274
			end = settings.fnDisplayEnd(),
5275
			len = settings._iDisplayLength;
5276
 
5277
		/* If we have space to show extra rows (backing up from the end point - then do so */
5278
		if ( start >= end )
5279
		{
5280
			start = end - len;
5281
		}
5282
 
5283
		// Keep the start record on the current page
5284
		start -= (start % len);
5285
 
5286
		if ( len === -1 || start < 0 )
5287
		{
5288
			start = 0;
5289
		}
5290
 
5291
		settings._iDisplayStart = start;
5292
	}
5293
 
5294
 
5295
	function _fnRenderer( settings, type )
5296
	{
5297
		var renderer = settings.renderer;
5298
		var host = DataTable.ext.renderer[type];
5299
 
5300
		if ( $.isPlainObject( renderer ) && renderer[type] ) {
5301
			// Specific renderer for this type. If available use it, otherwise use
5302
			// the default.
5303
			return host[renderer[type]] || host._;
5304
		}
5305
		else if ( typeof renderer === 'string' ) {
5306
			// Common renderer - if there is one available for this type use it,
5307
			// otherwise use the default
5308
			return host[renderer] || host._;
5309
		}
5310
 
5311
		// Use the default
5312
		return host._;
5313
	}
5314
 
5315
 
5316
	/**
5317
	 * Detect the data source being used for the table. Used to simplify the code
5318
	 * a little (ajax) and to make it compress a little smaller.
5319
	 *
5320
	 *  @param {object} settings dataTables settings object
5321
	 *  @returns {string} Data source
5322
	 *  @memberof DataTable#oApi
5323
	 */
5324
	function _fnDataSource ( settings )
5325
	{
5326
		if ( settings.oFeatures.bServerSide ) {
5327
			return 'ssp';
5328
		}
5329
		else if ( settings.ajax || settings.sAjaxSource ) {
5330
			return 'ajax';
5331
		}
5332
		return 'dom';
5333
	}
5334
 
5335
 
5336
	DataTable = function( options )
5337
	{
5338
		/**
5339
		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5340
		 * return the resulting jQuery object.
5341
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5342
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5343
		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5344
		 *    criterion ("applied") or all TR elements (i.e. no filter).
5345
		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5346
		 *    Can be either 'current', whereby the current sorting of the table is used, or
5347
		 *    'original' whereby the original order the data was read into the table is used.
5348
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5349
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5350
		 *    'current' and filter is 'applied', regardless of what they might be given as.
5351
		 *  @returns {object} jQuery object, filtered by the given selector.
5352
		 *  @dtopt API
5353
		 *  @deprecated Since v1.10
5354
		 *
5355
		 *  @example
5356
		 *    $(document).ready(function() {
5357
		 *      var oTable = $('#example').dataTable();
5358
		 *
5359
		 *      // Highlight every second row
5360
		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
5361
		 *    } );
5362
		 *
5363
		 *  @example
5364
		 *    $(document).ready(function() {
5365
		 *      var oTable = $('#example').dataTable();
5366
		 *
5367
		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
5368
		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
5369
		 *      oTable.fnFilter('Webkit');
5370
		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5371
		 *      oTable.fnFilter('');
5372
		 *    } );
5373
		 */
5374
		this.$ = function ( sSelector, oOpts )
5375
		{
5376
			return this.api(true).$( sSelector, oOpts );
5377
		};
5378
 
5379
 
5380
		/**
5381
		 * Almost identical to $ in operation, but in this case returns the data for the matched
5382
		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5383
		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
5384
		 * rows are found, the data returned is the original data array/object that was used to
5385
		 * create the row (or a generated array if from a DOM source).
5386
		 *
5387
		 * This method is often useful in-combination with $ where both functions are given the
5388
		 * same parameters and the array indexes will match identically.
5389
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5390
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5391
		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
5392
		 *    criterion ("applied") or all elements (i.e. no filter).
5393
		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
5394
		 *    Can be either 'current', whereby the current sorting of the table is used, or
5395
		 *    'original' whereby the original order the data was read into the table is used.
5396
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5397
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5398
		 *    'current' and filter is 'applied', regardless of what they might be given as.
5399
		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
5400
		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
5401
		 *    entry in the array.
5402
		 *  @dtopt API
5403
		 *  @deprecated Since v1.10
5404
		 *
5405
		 *  @example
5406
		 *    $(document).ready(function() {
5407
		 *      var oTable = $('#example').dataTable();
5408
		 *
5409
		 *      // Get the data from the first row in the table
5410
		 *      var data = oTable._('tr:first');
5411
		 *
5412
		 *      // Do something useful with the data
5413
		 *      alert( "First cell is: "+data[0] );
5414
		 *    } );
5415
		 *
5416
		 *  @example
5417
		 *    $(document).ready(function() {
5418
		 *      var oTable = $('#example').dataTable();
5419
		 *
5420
		 *      // Filter to 'Webkit' and get all data for
5421
		 *      oTable.fnFilter('Webkit');
5422
		 *      var data = oTable._('tr', {"search": "applied"});
5423
		 *
5424
		 *      // Do something with the data
5425
		 *      alert( data.length+" rows matched the search" );
5426
		 *    } );
5427
		 */
5428
		this._ = function ( sSelector, oOpts )
5429
		{
5430
			return this.api(true).rows( sSelector, oOpts ).data();
5431
		};
5432
 
5433
 
5434
		/**
5435
		 * Create a DataTables Api instance, with the currently selected tables for
5436
		 * the Api's context.
5437
		 * @param {boolean} [traditional=false] Set the API instance's context to be
5438
		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5439
		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5440
		 *   or if all tables captured in the jQuery object should be used.
5441
		 * @return {DataTables.Api}
5442
		 */
5443
		this.api = function ( traditional )
5444
		{
5445
			return traditional ?
5446
				new _Api(
5447
					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
5448
				) :
5449
				new _Api( this );
5450
		};
5451
 
5452
 
5453
		/**
5454
		 * Add a single new row or multiple rows of data to the table. Please note
5455
		 * that this is suitable for client-side processing only - if you are using
5456
		 * server-side processing (i.e. "bServerSide": true), then to add data, you
5457
		 * must add it to the data source, i.e. the server-side, through an Ajax call.
5458
		 *  @param {array|object} data The data to be added to the table. This can be:
5459
		 *    <ul>
5460
		 *      <li>1D array of data - add a single row with the data provided</li>
5461
		 *      <li>2D array of arrays - add multiple rows in a single call</li>
5462
		 *      <li>object - data object when using <i>mData</i></li>
5463
		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
5464
		 *    </ul>
5465
		 *  @param {bool} [redraw=true] redraw the table or not
5466
		 *  @returns {array} An array of integers, representing the list of indexes in
5467
		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5468
		 *    the table.
5469
		 *  @dtopt API
5470
		 *  @deprecated Since v1.10
5471
		 *
5472
		 *  @example
5473
		 *    // Global var for counter
5474
		 *    var giCount = 2;
5475
		 *
5476
		 *    $(document).ready(function() {
5477
		 *      $('#example').dataTable();
5478
		 *    } );
5479
		 *
5480
		 *    function fnClickAddRow() {
5481
		 *      $('#example').dataTable().fnAddData( [
5482
		 *        giCount+".1",
5483
		 *        giCount+".2",
5484
		 *        giCount+".3",
5485
		 *        giCount+".4" ]
5486
		 *      );
5487
		 *
5488
		 *      giCount++;
5489
		 *    }
5490
		 */
5491
		this.fnAddData = function( data, redraw )
5492
		{
5493
			var api = this.api( true );
5494
 
5495
			/* Check if we want to add multiple rows or not */
5496
			var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
5497
				api.rows.add( data ) :
5498
				api.row.add( data );
5499
 
5500
			if ( redraw === undefined || redraw ) {
5501
				api.draw();
5502
			}
5503
 
5504
			return rows.flatten().toArray();
5505
		};
5506
 
5507
 
5508
		/**
5509
		 * This function will make DataTables recalculate the column sizes, based on the data
5510
		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5511
		 * through the sWidth parameter). This can be useful when the width of the table's
5512
		 * parent element changes (for example a window resize).
5513
		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5514
		 *  @dtopt API
5515
		 *  @deprecated Since v1.10
5516
		 *
5517
		 *  @example
5518
		 *    $(document).ready(function() {
5519
		 *      var oTable = $('#example').dataTable( {
5520
		 *        "sScrollY": "200px",
5521
		 *        "bPaginate": false
5522
		 *      } );
5523
		 *
5524
		 *      $(window).bind('resize', function () {
5525
		 *        oTable.fnAdjustColumnSizing();
5526
		 *      } );
5527
		 *    } );
5528
		 */
5529
		this.fnAdjustColumnSizing = function ( bRedraw )
5530
		{
5531
			var api = this.api( true ).columns.adjust();
5532
			var settings = api.settings()[0];
5533
			var scroll = settings.oScroll;
5534
 
5535
			if ( bRedraw === undefined || bRedraw ) {
5536
				api.draw( false );
5537
			}
5538
			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
5539
				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5540
				_fnScrollDraw( settings );
5541
			}
5542
		};
5543
 
5544
 
5545
		/**
5546
		 * Quickly and simply clear a table
5547
		 *  @param {bool} [bRedraw=true] redraw the table or not
5548
		 *  @dtopt API
5549
		 *  @deprecated Since v1.10
5550
		 *
5551
		 *  @example
5552
		 *    $(document).ready(function() {
5553
		 *      var oTable = $('#example').dataTable();
5554
		 *
5555
		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5556
		 *      oTable.fnClearTable();
5557
		 *    } );
5558
		 */
5559
		this.fnClearTable = function( bRedraw )
5560
		{
5561
			var api = this.api( true ).clear();
5562
 
5563
			if ( bRedraw === undefined || bRedraw ) {
5564
				api.draw();
5565
			}
5566
		};
5567
 
5568
 
5569
		/**
5570
		 * The exact opposite of 'opening' a row, this function will close any rows which
5571
		 * are currently 'open'.
5572
		 *  @param {node} nTr the table row to 'close'
5573
		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
5574
		 *  @dtopt API
5575
		 *  @deprecated Since v1.10
5576
		 *
5577
		 *  @example
5578
		 *    $(document).ready(function() {
5579
		 *      var oTable;
5580
		 *
5581
		 *      // 'open' an information row when a row is clicked on
5582
		 *      $('#example tbody tr').click( function () {
5583
		 *        if ( oTable.fnIsOpen(this) ) {
5584
		 *          oTable.fnClose( this );
5585
		 *        } else {
5586
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5587
		 *        }
5588
		 *      } );
5589
		 *
5590
		 *      oTable = $('#example').dataTable();
5591
		 *    } );
5592
		 */
5593
		this.fnClose = function( nTr )
5594
		{
5595
			this.api( true ).row( nTr ).child.hide();
5596
		};
5597
 
5598
 
5599
		/**
5600
		 * Remove a row for the table
5601
		 *  @param {mixed} target The index of the row from aoData to be deleted, or
5602
		 *    the TR element you want to delete
5603
		 *  @param {function|null} [callBack] Callback function
5604
		 *  @param {bool} [redraw=true] Redraw the table or not
5605
		 *  @returns {array} The row that was deleted
5606
		 *  @dtopt API
5607
		 *  @deprecated Since v1.10
5608
		 *
5609
		 *  @example
5610
		 *    $(document).ready(function() {
5611
		 *      var oTable = $('#example').dataTable();
5612
		 *
5613
		 *      // Immediately remove the first row
5614
		 *      oTable.fnDeleteRow( 0 );
5615
		 *    } );
5616
		 */
5617
		this.fnDeleteRow = function( target, callback, redraw )
5618
		{
5619
			var api = this.api( true );
5620
			var rows = api.rows( target );
5621
			var settings = rows.settings()[0];
5622
			var data = settings.aoData[ rows[0][0] ];
5623
 
5624
			rows.remove();
5625
 
5626
			if ( callback ) {
5627
				callback.call( this, settings, data );
5628
			}
5629
 
5630
			if ( redraw === undefined || redraw ) {
5631
				api.draw();
5632
			}
5633
 
5634
			return data;
5635
		};
5636
 
5637
 
5638
		/**
5639
		 * Restore the table to it's original state in the DOM by removing all of DataTables
5640
		 * enhancements, alterations to the DOM structure of the table and event listeners.
5641
		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
5642
		 *  @dtopt API
5643
		 *  @deprecated Since v1.10
5644
		 *
5645
		 *  @example
5646
		 *    $(document).ready(function() {
5647
		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
5648
		 *      var oTable = $('#example').dataTable();
5649
		 *      oTable.fnDestroy();
5650
		 *    } );
5651
		 */
5652
		this.fnDestroy = function ( remove )
5653
		{
5654
			this.api( true ).destroy( remove );
5655
		};
5656
 
5657
 
5658
		/**
5659
		 * Redraw the table
5660
		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5661
		 *  @dtopt API
5662
		 *  @deprecated Since v1.10
5663
		 *
5664
		 *  @example
5665
		 *    $(document).ready(function() {
5666
		 *      var oTable = $('#example').dataTable();
5667
		 *
5668
		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5669
		 *      oTable.fnDraw();
5670
		 *    } );
5671
		 */
5672
		this.fnDraw = function( complete )
5673
		{
5674
			// Note that this isn't an exact match to the old call to _fnDraw - it takes
5675
			// into account the new data, but can hold position.
5676
			this.api( true ).draw( complete );
5677
		};
5678
 
5679
 
5680
		/**
5681
		 * Filter the input based on data
5682
		 *  @param {string} sInput String to filter the table on
5683
		 *  @param {int|null} [iColumn] Column to limit filtering to
5684
		 *  @param {bool} [bRegex=false] Treat as regular expression or not
5685
		 *  @param {bool} [bSmart=true] Perform smart filtering or not
5686
		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5687
		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5688
		 *  @dtopt API
5689
		 *  @deprecated Since v1.10
5690
		 *
5691
		 *  @example
5692
		 *    $(document).ready(function() {
5693
		 *      var oTable = $('#example').dataTable();
5694
		 *
5695
		 *      // Sometime later - filter...
5696
		 *      oTable.fnFilter( 'test string' );
5697
		 *    } );
5698
		 */
5699
		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
5700
		{
5701
			var api = this.api( true );
5702
 
5703
			if ( iColumn === null || iColumn === undefined ) {
5704
				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
5705
			}
5706
			else {
5707
				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
5708
			}
5709
 
5710
			api.draw();
5711
		};
5712
 
5713
 
5714
		/**
5715
		 * Get the data for the whole table, an individual row or an individual cell based on the
5716
		 * provided parameters.
5717
		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5718
		 *    a TR node then the data source for the whole row will be returned. If given as a
5719
		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
5720
		 *    cell returned. If given as an integer, then this is treated as the aoData internal
5721
		 *    data index for the row (see fnGetPosition) and the data for that row used.
5722
		 *  @param {int} [col] Optional column index that you want the data of.
5723
		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
5724
		 *    returned. If mRow is defined, just data for that row, and is iCol is
5725
		 *    defined, only data for the designated cell is returned.
5726
		 *  @dtopt API
5727
		 *  @deprecated Since v1.10
5728
		 *
5729
		 *  @example
5730
		 *    // Row data
5731
		 *    $(document).ready(function() {
5732
		 *      oTable = $('#example').dataTable();
5733
		 *
5734
		 *      oTable.$('tr').click( function () {
5735
		 *        var data = oTable.fnGetData( this );
5736
		 *        // ... do something with the array / object of data for the row
5737
		 *      } );
5738
		 *    } );
5739
		 *
5740
		 *  @example
5741
		 *    // Individual cell data
5742
		 *    $(document).ready(function() {
5743
		 *      oTable = $('#example').dataTable();
5744
		 *
5745
		 *      oTable.$('td').click( function () {
5746
		 *        var sData = oTable.fnGetData( this );
5747
		 *        alert( 'The cell clicked on had the value of '+sData );
5748
		 *      } );
5749
		 *    } );
5750
		 */
5751
		this.fnGetData = function( src, col )
5752
		{
5753
			var api = this.api( true );
5754
 
5755
			if ( src !== undefined ) {
5756
				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
5757
 
5758
				return col !== undefined || type == 'td' || type == 'th' ?
5759
					api.cell( src, col ).data() :
5760
					api.row( src ).data() || null;
5761
			}
5762
 
5763
			return api.data().toArray();
5764
		};
5765
 
5766
 
5767
		/**
5768
		 * Get an array of the TR nodes that are used in the table's body. Note that you will
5769
		 * typically want to use the '$' API method in preference to this as it is more
5770
		 * flexible.
5771
		 *  @param {int} [iRow] Optional row index for the TR element you want
5772
		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
5773
		 *    in the table's body, or iRow is defined, just the TR element requested.
5774
		 *  @dtopt API
5775
		 *  @deprecated Since v1.10
5776
		 *
5777
		 *  @example
5778
		 *    $(document).ready(function() {
5779
		 *      var oTable = $('#example').dataTable();
5780
		 *
5781
		 *      // Get the nodes from the table
5782
		 *      var nNodes = oTable.fnGetNodes( );
5783
		 *    } );
5784
		 */
5785
		this.fnGetNodes = function( iRow )
5786
		{
5787
			var api = this.api( true );
5788
 
5789
			return iRow !== undefined ?
5790
				api.row( iRow ).node() :
5791
				api.rows().nodes().flatten().toArray();
5792
		};
5793
 
5794
 
5795
		/**
5796
		 * Get the array indexes of a particular cell from it's DOM element
5797
		 * and column index including hidden columns
5798
		 *  @param {node} node this can either be a TR, TD or TH in the table's body
5799
		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
5800
		 *    if given as a cell, an array of [row index, column index (visible),
5801
		 *    column index (all)] is given.
5802
		 *  @dtopt API
5803
		 *  @deprecated Since v1.10
5804
		 *
5805
		 *  @example
5806
		 *    $(document).ready(function() {
5807
		 *      $('#example tbody td').click( function () {
5808
		 *        // Get the position of the current data from the node
5809
		 *        var aPos = oTable.fnGetPosition( this );
5810
		 *
5811
		 *        // Get the data array for this row
5812
		 *        var aData = oTable.fnGetData( aPos[0] );
5813
		 *
5814
		 *        // Update the data array and return the value
5815
		 *        aData[ aPos[1] ] = 'clicked';
5816
		 *        this.innerHTML = 'clicked';
5817
		 *      } );
5818
		 *
5819
		 *      // Init DataTables
5820
		 *      oTable = $('#example').dataTable();
5821
		 *    } );
5822
		 */
5823
		this.fnGetPosition = function( node )
5824
		{
5825
			var api = this.api( true );
5826
			var nodeName = node.nodeName.toUpperCase();
5827
 
5828
			if ( nodeName == 'TR' ) {
5829
				return api.row( node ).index();
5830
			}
5831
			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
5832
				var cell = api.cell( node ).index();
5833
 
5834
				return [
5835
					cell.row,
5836
					cell.columnVisible,
5837
					cell.column
5838
				];
5839
			}
5840
			return null;
5841
		};
5842
 
5843
 
5844
		/**
5845
		 * Check to see if a row is 'open' or not.
5846
		 *  @param {node} nTr the table row to check
5847
		 *  @returns {boolean} true if the row is currently open, false otherwise
5848
		 *  @dtopt API
5849
		 *  @deprecated Since v1.10
5850
		 *
5851
		 *  @example
5852
		 *    $(document).ready(function() {
5853
		 *      var oTable;
5854
		 *
5855
		 *      // 'open' an information row when a row is clicked on
5856
		 *      $('#example tbody tr').click( function () {
5857
		 *        if ( oTable.fnIsOpen(this) ) {
5858
		 *          oTable.fnClose( this );
5859
		 *        } else {
5860
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5861
		 *        }
5862
		 *      } );
5863
		 *
5864
		 *      oTable = $('#example').dataTable();
5865
		 *    } );
5866
		 */
5867
		this.fnIsOpen = function( nTr )
5868
		{
5869
			return this.api( true ).row( nTr ).child.isShown();
5870
		};
5871
 
5872
 
5873
		/**
5874
		 * This function will place a new row directly after a row which is currently
5875
		 * on display on the page, with the HTML contents that is passed into the
5876
		 * function. This can be used, for example, to ask for confirmation that a
5877
		 * particular record should be deleted.
5878
		 *  @param {node} nTr The table row to 'open'
5879
		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
5880
		 *  @param {string} sClass Class to give the new TD cell
5881
		 *  @returns {node} The row opened. Note that if the table row passed in as the
5882
		 *    first parameter, is not found in the table, this method will silently
5883
		 *    return.
5884
		 *  @dtopt API
5885
		 *  @deprecated Since v1.10
5886
		 *
5887
		 *  @example
5888
		 *    $(document).ready(function() {
5889
		 *      var oTable;
5890
		 *
5891
		 *      // 'open' an information row when a row is clicked on
5892
		 *      $('#example tbody tr').click( function () {
5893
		 *        if ( oTable.fnIsOpen(this) ) {
5894
		 *          oTable.fnClose( this );
5895
		 *        } else {
5896
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5897
		 *        }
5898
		 *      } );
5899
		 *
5900
		 *      oTable = $('#example').dataTable();
5901
		 *    } );
5902
		 */
5903
		this.fnOpen = function( nTr, mHtml, sClass )
5904
		{
5905
			return this.api( true )
5906
				.row( nTr )
5907
				.child( mHtml, sClass )
5908
				.show()
5909
				.child()[0];
5910
		};
5911
 
5912
 
5913
		/**
5914
		 * Change the pagination - provides the internal logic for pagination in a simple API
5915
		 * function. With this function you can have a DataTables table go to the next,
5916
		 * previous, first or last pages.
5917
		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5918
		 *    or page number to jump to (integer), note that page 0 is the first page.
5919
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5920
		 *  @dtopt API
5921
		 *  @deprecated Since v1.10
5922
		 *
5923
		 *  @example
5924
		 *    $(document).ready(function() {
5925
		 *      var oTable = $('#example').dataTable();
5926
		 *      oTable.fnPageChange( 'next' );
5927
		 *    } );
5928
		 */
5929
		this.fnPageChange = function ( mAction, bRedraw )
5930
		{
5931
			var api = this.api( true ).page( mAction );
5932
 
5933
			if ( bRedraw === undefined || bRedraw ) {
5934
				api.draw(false);
5935
			}
5936
		};
5937
 
5938
 
5939
		/**
5940
		 * Show a particular column
5941
		 *  @param {int} iCol The column whose display should be changed
5942
		 *  @param {bool} bShow Show (true) or hide (false) the column
5943
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5944
		 *  @dtopt API
5945
		 *  @deprecated Since v1.10
5946
		 *
5947
		 *  @example
5948
		 *    $(document).ready(function() {
5949
		 *      var oTable = $('#example').dataTable();
5950
		 *
5951
		 *      // Hide the second column after initialisation
5952
		 *      oTable.fnSetColumnVis( 1, false );
5953
		 *    } );
5954
		 */
5955
		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
5956
		{
5957
			var api = this.api( true ).column( iCol ).visible( bShow );
5958
 
5959
			if ( bRedraw === undefined || bRedraw ) {
5960
				api.columns.adjust().draw();
5961
			}
5962
		};
5963
 
5964
 
5965
		/**
5966
		 * Get the settings for a particular table for external manipulation
5967
		 *  @returns {object} DataTables settings object. See
5968
		 *    {@link DataTable.models.oSettings}
5969
		 *  @dtopt API
5970
		 *  @deprecated Since v1.10
5971
		 *
5972
		 *  @example
5973
		 *    $(document).ready(function() {
5974
		 *      var oTable = $('#example').dataTable();
5975
		 *      var oSettings = oTable.fnSettings();
5976
		 *
5977
		 *      // Show an example parameter from the settings
5978
		 *      alert( oSettings._iDisplayStart );
5979
		 *    } );
5980
		 */
5981
		this.fnSettings = function()
5982
		{
5983
			return _fnSettingsFromNode( this[_ext.iApiIndex] );
5984
		};
5985
 
5986
 
5987
		/**
5988
		 * Sort the table by a particular column
5989
		 *  @param {int} iCol the data index to sort on. Note that this will not match the
5990
		 *    'display index' if you have hidden data entries
5991
		 *  @dtopt API
5992
		 *  @deprecated Since v1.10
5993
		 *
5994
		 *  @example
5995
		 *    $(document).ready(function() {
5996
		 *      var oTable = $('#example').dataTable();
5997
		 *
5998
		 *      // Sort immediately with columns 0 and 1
5999
		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
6000
		 *    } );
6001
		 */
6002
		this.fnSort = function( aaSort )
6003
		{
6004
			this.api( true ).order( aaSort ).draw();
6005
		};
6006
 
6007
 
6008
		/**
6009
		 * Attach a sort listener to an element for a given column
6010
		 *  @param {node} nNode the element to attach the sort listener to
6011
		 *  @param {int} iColumn the column that a click on this node will sort on
6012
		 *  @param {function} [fnCallback] callback function when sort is run
6013
		 *  @dtopt API
6014
		 *  @deprecated Since v1.10
6015
		 *
6016
		 *  @example
6017
		 *    $(document).ready(function() {
6018
		 *      var oTable = $('#example').dataTable();
6019
		 *
6020
		 *      // Sort on column 1, when 'sorter' is clicked on
6021
		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
6022
		 *    } );
6023
		 */
6024
		this.fnSortListener = function( nNode, iColumn, fnCallback )
6025
		{
6026
			this.api( true ).order.listener( nNode, iColumn, fnCallback );
6027
		};
6028
 
6029
 
6030
		/**
6031
		 * Update a table cell or row - this method will accept either a single value to
6032
		 * update the cell with, an array of values with one element for each column or
6033
		 * an object in the same format as the original data source. The function is
6034
		 * self-referencing in order to make the multi column updates easier.
6035
		 *  @param {object|array|string} mData Data to update the cell/row with
6036
		 *  @param {node|int} mRow TR element you want to update or the aoData index
6037
		 *  @param {int} [iColumn] The column to update, give as null or undefined to
6038
		 *    update a whole row.
6039
		 *  @param {bool} [bRedraw=true] Redraw the table or not
6040
		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
6041
		 *  @returns {int} 0 on success, 1 on error
6042
		 *  @dtopt API
6043
		 *  @deprecated Since v1.10
6044
		 *
6045
		 *  @example
6046
		 *    $(document).ready(function() {
6047
		 *      var oTable = $('#example').dataTable();
6048
		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
6049
		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
6050
		 *    } );
6051
		 */
6052
		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
6053
		{
6054
			var api = this.api( true );
6055
 
6056
			if ( iColumn === undefined || iColumn === null ) {
6057
				api.row( mRow ).data( mData );
6058
			}
6059
			else {
6060
				api.cell( mRow, iColumn ).data( mData );
6061
			}
6062
 
6063
			if ( bAction === undefined || bAction ) {
6064
				api.columns.adjust();
6065
			}
6066
 
6067
			if ( bRedraw === undefined || bRedraw ) {
6068
				api.draw();
6069
			}
6070
			return 0;
6071
		};
6072
 
6073
 
6074
		/**
6075
		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
6076
		 * to ensure compatibility.
6077
		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
6078
		 *    formats "X" and "X.Y" are also acceptable.
6079
		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
6080
		 *    version, or false if this version of DataTales is not suitable
6081
		 *  @method
6082
		 *  @dtopt API
6083
		 *  @deprecated Since v1.10
6084
		 *
6085
		 *  @example
6086
		 *    $(document).ready(function() {
6087
		 *      var oTable = $('#example').dataTable();
6088
		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
6089
		 *    } );
6090
		 */
6091
		this.fnVersionCheck = _ext.fnVersionCheck;
6092
 
6093
 
6094
		var _that = this;
6095
		var emptyInit = options === undefined;
6096
		var len = this.length;
6097
 
6098
		if ( emptyInit ) {
6099
			options = {};
6100
		}
6101
 
6102
		this.oApi = this.internal = _ext.internal;
6103
 
6104
		// Extend with old style plug-in API methods
6105
		for ( var fn in DataTable.ext.internal ) {
6106
			if ( fn ) {
6107
				this[fn] = _fnExternApiFunc(fn);
6108
			}
6109
		}
6110
 
6111
		this.each(function() {
6112
			// For each initialisation we want to give it a clean initialisation
6113
			// object that can be bashed around
6114
			var o = {};
6115
			var oInit = len > 1 ? // optimisation for single table case
6116
				_fnExtend( o, options, true ) :
6117
				options;
6118
 
6119
			/*global oInit,_that,emptyInit*/
6120
			var i=0, iLen, j, jLen, k, kLen;
6121
			var sId = this.getAttribute( 'id' );
6122
			var bInitHandedOff = false;
6123
			var defaults = DataTable.defaults;
6124
			var $this = $(this);
6125
 
6126
 
6127
			/* Sanity check */
6128
			if ( this.nodeName.toLowerCase() != 'table' )
6129
			{
6130
				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
6131
				return;
6132
			}
6133
 
6134
			/* Backwards compatibility for the defaults */
6135
			_fnCompatOpts( defaults );
6136
			_fnCompatCols( defaults.column );
6137
 
6138
			/* Convert the camel-case defaults to Hungarian */
6139
			_fnCamelToHungarian( defaults, defaults, true );
6140
			_fnCamelToHungarian( defaults.column, defaults.column, true );
6141
 
6142
			/* Setting up the initialisation object */
6143
			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
6144
 
6145
 
6146
 
6147
			/* Check to see if we are re-initialising a table */
6148
			var allSettings = DataTable.settings;
6149
			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
6150
			{
6151
				var s = allSettings[i];
6152
 
6153
				/* Base check on table node */
6154
				if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
6155
				{
6156
					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
6157
					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
6158
 
6159
					if ( emptyInit || bRetrieve )
6160
					{
6161
						return s.oInstance;
6162
					}
6163
					else if ( bDestroy )
6164
					{
6165
						s.oInstance.fnDestroy();
6166
						break;
6167
					}
6168
					else
6169
					{
6170
						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
6171
						return;
6172
					}
6173
				}
6174
 
6175
				/* If the element we are initialising has the same ID as a table which was previously
6176
				 * initialised, but the table nodes don't match (from before) then we destroy the old
6177
				 * instance by simply deleting it. This is under the assumption that the table has been
6178
				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6179
				 */
6180
				if ( s.sTableId == this.id )
6181
				{
6182
					allSettings.splice( i, 1 );
6183
					break;
6184
				}
6185
			}
6186
 
6187
			/* Ensure the table has an ID - required for accessibility */
6188
			if ( sId === null || sId === "" )
6189
			{
6190
				sId = "DataTables_Table_"+(DataTable.ext._unique++);
6191
				this.id = sId;
6192
			}
6193
 
6194
			/* Create the settings object for this table and set some of the default parameters */
6195
			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
6196
				"sDestroyWidth": $this[0].style.width,
6197
				"sInstance":     sId,
6198
				"sTableId":      sId
6199
			} );
6200
			oSettings.nTable = this;
6201
			oSettings.oApi   = _that.internal;
6202
			oSettings.oInit  = oInit;
6203
 
6204
			allSettings.push( oSettings );
6205
 
6206
			// Need to add the instance after the instance after the settings object has been added
6207
			// to the settings array, so we can self reference the table instance if more than one
6208
			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
6209
 
6210
			// Backwards compatibility, before we apply all the defaults
6211
			_fnCompatOpts( oInit );
6212
 
6213
			if ( oInit.oLanguage )
6214
			{
6215
				_fnLanguageCompat( oInit.oLanguage );
6216
			}
6217
 
6218
			// If the length menu is given, but the init display length is not, use the length menu
6219
			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
6220
			{
6221
				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
6222
					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
6223
			}
6224
 
6225
			// Apply the defaults and init options to make a single init object will all
6226
			// options defined from defaults and instance options.
6227
			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
6228
 
6229
 
6230
			// Map the initialisation options onto the settings object
6231
			_fnMap( oSettings.oFeatures, oInit, [
6232
				"bPaginate",
6233
				"bLengthChange",
6234
				"bFilter",
6235
				"bSort",
6236
				"bSortMulti",
6237
				"bInfo",
6238
				"bProcessing",
6239
				"bAutoWidth",
6240
				"bSortClasses",
6241
				"bServerSide",
6242
				"bDeferRender"
6243
			] );
6244
			_fnMap( oSettings, oInit, [
6245
				"asStripeClasses",
6246
				"ajax",
6247
				"fnServerData",
6248
				"fnFormatNumber",
6249
				"sServerMethod",
6250
				"aaSorting",
6251
				"aaSortingFixed",
6252
				"aLengthMenu",
6253
				"sPaginationType",
6254
				"sAjaxSource",
6255
				"sAjaxDataProp",
6256
				"iStateDuration",
6257
				"sDom",
6258
				"bSortCellsTop",
6259
				"iTabIndex",
6260
				"fnStateLoadCallback",
6261
				"fnStateSaveCallback",
6262
				"renderer",
6263
				"searchDelay",
6264
				"rowId",
6265
				[ "iCookieDuration", "iStateDuration" ], // backwards compat
6266
				[ "oSearch", "oPreviousSearch" ],
6267
				[ "aoSearchCols", "aoPreSearchCols" ],
6268
				[ "iDisplayLength", "_iDisplayLength" ],
6269
				[ "bJQueryUI", "bJUI" ]
6270
			] );
6271
			_fnMap( oSettings.oScroll, oInit, [
6272
				[ "sScrollX", "sX" ],
6273
				[ "sScrollXInner", "sXInner" ],
6274
				[ "sScrollY", "sY" ],
6275
				[ "bScrollCollapse", "bCollapse" ]
6276
			] );
6277
			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
6278
 
6279
			/* Callback functions which are array driven */
6280
			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
6281
			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
6282
			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
6283
			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
6284
			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
6285
			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
6286
			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
6287
			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
6288
			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
6289
			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
6290
			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
6291
 
6292
			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
6293
 
6294
			/* Browser support detection */
6295
			_fnBrowserDetect( oSettings );
6296
 
6297
			var oClasses = oSettings.oClasses;
6298
 
6299
			// @todo Remove in 1.11
6300
			if ( oInit.bJQueryUI )
6301
			{
6302
				/* Use the JUI classes object for display. You could clone the oStdClasses object if
6303
				 * you want to have multiple tables with multiple independent classes
6304
				 */
6305
				$.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
6306
 
6307
				if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
6308
				{
6309
					/* Set the DOM to use a layout suitable for jQuery UI's theming */
6310
					oSettings.sDom = '<"H"lfr>t<"F"ip>';
6311
				}
6312
 
6313
				if ( ! oSettings.renderer ) {
6314
					oSettings.renderer = 'jqueryui';
6315
				}
6316
				else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
6317
					oSettings.renderer.header = 'jqueryui';
6318
				}
6319
			}
6320
			else
6321
			{
6322
				$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6323
			}
6324
			$this.addClass( oClasses.sTable );
6325
 
6326
 
6327
			if ( oSettings.iInitDisplayStart === undefined )
6328
			{
6329
				/* Display start point, taking into account the save saving */
6330
				oSettings.iInitDisplayStart = oInit.iDisplayStart;
6331
				oSettings._iDisplayStart = oInit.iDisplayStart;
6332
			}
6333
 
6334
			if ( oInit.iDeferLoading !== null )
6335
			{
6336
				oSettings.bDeferLoading = true;
6337
				var tmp = $.isArray( oInit.iDeferLoading );
6338
				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
6339
				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
6340
			}
6341
 
6342
			/* Language definitions */
6343
			var oLanguage = oSettings.oLanguage;
6344
			$.extend( true, oLanguage, oInit.oLanguage );
6345
 
6346
			if ( oLanguage.sUrl !== "" )
6347
			{
6348
				/* Get the language definitions from a file - because this Ajax call makes the language
6349
				 * get async to the remainder of this function we use bInitHandedOff to indicate that
6350
				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6351
				 */
6352
				$.ajax( {
6353
					dataType: 'json',
6354
					url: oLanguage.sUrl,
6355
					success: function ( json ) {
6356
						_fnLanguageCompat( json );
6357
						_fnCamelToHungarian( defaults.oLanguage, json );
6358
						$.extend( true, oLanguage, json );
6359
						_fnInitialise( oSettings );
6360
					},
6361
					error: function () {
6362
						// Error occurred loading language file, continue on as best we can
6363
						_fnInitialise( oSettings );
6364
					}
6365
				} );
6366
				bInitHandedOff = true;
6367
			}
6368
 
6369
			/*
6370
			 * Stripes
6371
			 */
6372
			if ( oInit.asStripeClasses === null )
6373
			{
6374
				oSettings.asStripeClasses =[
6375
					oClasses.sStripeOdd,
6376
					oClasses.sStripeEven
6377
				];
6378
			}
6379
 
6380
			/* Remove row stripe classes if they are already on the table row */
6381
			var stripeClasses = oSettings.asStripeClasses;
6382
			var rowOne = $this.children('tbody').find('tr').eq(0);
6383
			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6384
				return rowOne.hasClass(el);
6385
			} ) ) !== -1 ) {
6386
				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
6387
				oSettings.asDestroyStripes = stripeClasses.slice();
6388
			}
6389
 
6390
			/*
6391
			 * Columns
6392
			 * See if we should load columns automatically or use defined ones
6393
			 */
6394
			var anThs = [];
6395
			var aoColumnsInit;
6396
			var nThead = this.getElementsByTagName('thead');
6397
			if ( nThead.length !== 0 )
6398
			{
6399
				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
6400
				anThs = _fnGetUniqueThs( oSettings );
6401
			}
6402
 
6403
			/* If not given a column array, generate one with nulls */
6404
			if ( oInit.aoColumns === null )
6405
			{
6406
				aoColumnsInit = [];
6407
				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6408
				{
6409
					aoColumnsInit.push( null );
6410
				}
6411
			}
6412
			else
6413
			{
6414
				aoColumnsInit = oInit.aoColumns;
6415
			}
6416
 
6417
			/* Add the columns */
6418
			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6419
			{
6420
				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
6421
			}
6422
 
6423
			/* Apply the column definitions */
6424
			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
6425
				_fnColumnOptions( oSettings, iCol, oDef );
6426
			} );
6427
 
6428
			/* HTML5 attribute detection - build an mData object automatically if the
6429
			 * attributes are found
6430
			 */
6431
			if ( rowOne.length ) {
6432
				var a = function ( cell, name ) {
6433
					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
6434
				};
6435
 
6436
				$( rowOne[0] ).children('th, td').each( function (i, cell) {
6437
					var col = oSettings.aoColumns[i];
6438
 
6439
					if ( col.mData === i ) {
6440
						var sort = a( cell, 'sort' ) || a( cell, 'order' );
6441
						var filter = a( cell, 'filter' ) || a( cell, 'search' );
6442
 
6443
						if ( sort !== null || filter !== null ) {
6444
							col.mData = {
6445
								_:      i+'.display',
6446
								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
6447
								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
6448
								filter: filter !== null ? i+'.@data-'+filter : undefined
6449
							};
6450
 
6451
							_fnColumnOptions( oSettings, i );
6452
						}
6453
					}
6454
				} );
6455
			}
6456
 
6457
			var features = oSettings.oFeatures;
6458
 
6459
			/* Must be done after everything which can be overridden by the state saving! */
6460
			if ( oInit.bStateSave )
6461
			{
6462
				features.bStateSave = true;
6463
				_fnLoadState( oSettings, oInit );
6464
				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
6465
			}
6466
 
6467
 
6468
			/*
6469
			 * Sorting
6470
			 * @todo For modularisation (1.11) this needs to do into a sort start up handler
6471
			 */
6472
 
6473
			// If aaSorting is not defined, then we use the first indicator in asSorting
6474
			// in case that has been altered, so the default sort reflects that option
6475
			if ( oInit.aaSorting === undefined )
6476
			{
6477
				var sorting = oSettings.aaSorting;
6478
				for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
6479
				{
6480
					sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
6481
				}
6482
			}
6483
 
6484
			/* Do a first pass on the sorting classes (allows any size changes to be taken into
6485
			 * account, and also will apply sorting disabled classes if disabled
6486
			 */
6487
			_fnSortingClasses( oSettings );
6488
 
6489
			if ( features.bSort )
6490
			{
6491
				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6492
					if ( oSettings.bSorted ) {
6493
						var aSort = _fnSortFlatten( oSettings );
6494
						var sortedColumns = {};
6495
 
6496
						$.each( aSort, function (i, val) {
6497
							sortedColumns[ val.src ] = val.dir;
6498
						} );
6499
 
6500
						_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
6501
						_fnSortAria( oSettings );
6502
					}
6503
				} );
6504
			}
6505
 
6506
			_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6507
				if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
6508
					_fnSortingClasses( oSettings );
6509
				}
6510
			}, 'sc' );
6511
 
6512
 
6513
			/*
6514
			 * Final init
6515
			 * Cache the header, body and footer as required, creating them if needed
6516
			 */
6517
 
6518
			// Work around for Webkit bug 83867 - store the caption-side before removing from doc
6519
			var captions = $this.children('caption').each( function () {
6520
				this._captionSide = $this.css('caption-side');
6521
			} );
6522
 
6523
			var thead = $this.children('thead');
6524
			if ( thead.length === 0 )
6525
			{
6526
				thead = $('<thead/>').appendTo(this);
6527
			}
6528
			oSettings.nTHead = thead[0];
6529
 
6530
			var tbody = $this.children('tbody');
6531
			if ( tbody.length === 0 )
6532
			{
6533
				tbody = $('<tbody/>').appendTo(this);
6534
			}
6535
			oSettings.nTBody = tbody[0];
6536
 
6537
			var tfoot = $this.children('tfoot');
6538
			if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6539
			{
6540
				// If we are a scrolling table, and no footer has been given, then we need to create
6541
				// a tfoot element for the caption element to be appended to
6542
				tfoot = $('<tfoot/>').appendTo(this);
6543
			}
6544
 
6545
			if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6546
				$this.addClass( oClasses.sNoFooter );
6547
			}
6548
			else if ( tfoot.length > 0 ) {
6549
				oSettings.nTFoot = tfoot[0];
6550
				_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
6551
			}
6552
 
6553
			/* Check if there is data passing into the constructor */
6554
			if ( oInit.aaData )
6555
			{
6556
				for ( i=0 ; i<oInit.aaData.length ; i++ )
6557
				{
6558
					_fnAddData( oSettings, oInit.aaData[ i ] );
6559
				}
6560
			}
6561
			else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
6562
			{
6563
				/* Grab the data from the page - only do this when deferred loading or no Ajax
6564
				 * source since there is no point in reading the DOM data if we are then going
6565
				 * to replace it with Ajax data
6566
				 */
6567
				_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
6568
			}
6569
 
6570
			/* Copy the data index array */
6571
			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6572
 
6573
			/* Initialisation complete - table can be drawn */
6574
			oSettings.bInitialised = true;
6575
 
6576
			/* Check if we need to initialise the table (it might not have been handed off to the
6577
			 * language processor)
6578
			 */
6579
			if ( bInitHandedOff === false )
6580
			{
6581
				_fnInitialise( oSettings );
6582
			}
6583
		} );
6584
		_that = null;
6585
		return this;
6586
	};
6587
 
6588
 
6589
 
6590
	/**
6591
	 * Computed structure of the DataTables API, defined by the options passed to
6592
	 * `DataTable.Api.register()` when building the API.
6593
	 *
6594
	 * The structure is built in order to speed creation and extension of the Api
6595
	 * objects since the extensions are effectively pre-parsed.
6596
	 *
6597
	 * The array is an array of objects with the following structure, where this
6598
	 * base array represents the Api prototype base:
6599
	 *
6600
	 *     [
6601
	 *       {
6602
	 *         name:      'data'                -- string   - Property name
6603
	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6604
	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6605
	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6606
	 *       },
6607
	 *       {
6608
	 *         name:     'row'
6609
	 *         val:       {},
6610
	 *         methodExt: [ ... ],
6611
	 *         propExt:   [
6612
	 *           {
6613
	 *             name:      'data'
6614
	 *             val:       function () {},
6615
	 *             methodExt: [ ... ],
6616
	 *             propExt:   [ ... ]
6617
	 *           },
6618
	 *           ...
6619
	 *         ]
6620
	 *       }
6621
	 *     ]
6622
	 *
6623
	 * @type {Array}
6624
	 * @ignore
6625
	 */
6626
	var __apiStruct = [];
6627
 
6628
 
6629
	/**
6630
	 * `Array.prototype` reference.
6631
	 *
6632
	 * @type object
6633
	 * @ignore
6634
	 */
6635
	var __arrayProto = Array.prototype;
6636
 
6637
 
6638
	/**
6639
	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6640
	 * take several different forms for ease of use.
6641
	 *
6642
	 * Each of the input parameter types will be converted to a DataTables settings
6643
	 * object where possible.
6644
	 *
6645
	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6646
	 *   of:
6647
	 *
6648
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6649
	 *     with be found and used.
6650
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6651
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6652
	 *   * `object` - DataTables settings object
6653
	 *   * `DataTables.Api` - API instance
6654
	 * @return {array|null} Matching DataTables settings objects. `null` or
6655
	 *   `undefined` is returned if no matching DataTable is found.
6656
	 * @ignore
6657
	 */
6658
	var _toSettings = function ( mixed )
6659
	{
6660
		var idx, jq;
6661
		var settings = DataTable.settings;
6662
		var tables = $.map( settings, function (el, i) {
6663
			return el.nTable;
6664
		} );
6665
 
6666
		if ( ! mixed ) {
6667
			return [];
6668
		}
6669
		else if ( mixed.nTable && mixed.oApi ) {
6670
			// DataTables settings object
6671
			return [ mixed ];
6672
		}
6673
		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6674
			// Table node
6675
			idx = $.inArray( mixed, tables );
6676
			return idx !== -1 ? [ settings[idx] ] : null;
6677
		}
6678
		else if ( mixed && typeof mixed.settings === 'function' ) {
6679
			return mixed.settings().toArray();
6680
		}
6681
		else if ( typeof mixed === 'string' ) {
6682
			// jQuery selector
6683
			jq = $(mixed);
6684
		}
6685
		else if ( mixed instanceof $ ) {
6686
			// jQuery object (also DataTables instance)
6687
			jq = mixed;
6688
		}
6689
 
6690
		if ( jq ) {
6691
			return jq.map( function(i) {
6692
				idx = $.inArray( this, tables );
6693
				return idx !== -1 ? settings[idx] : null;
6694
			} ).toArray();
6695
		}
6696
	};
6697
 
6698
 
6699
	/**
6700
	 * DataTables API class - used to control and interface with  one or more
6701
	 * DataTables enhanced tables.
6702
	 *
6703
	 * The API class is heavily based on jQuery, presenting a chainable interface
6704
	 * that you can use to interact with tables. Each instance of the API class has
6705
	 * a "context" - i.e. the tables that it will operate on. This could be a single
6706
	 * table, all tables on a page or a sub-set thereof.
6707
	 *
6708
	 * Additionally the API is designed to allow you to easily work with the data in
6709
	 * the tables, retrieving and manipulating it as required. This is done by
6710
	 * presenting the API class as an array like interface. The contents of the
6711
	 * array depend upon the actions requested by each method (for example
6712
	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6713
	 * return an array of objects or arrays depending upon your table's
6714
	 * configuration). The API object has a number of array like methods (`push`,
6715
	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6716
	 * `unique` etc) to assist your working with the data held in a table.
6717
	 *
6718
	 * Most methods (those which return an Api instance) are chainable, which means
6719
	 * the return from a method call also has all of the methods available that the
6720
	 * top level object had. For example, these two calls are equivalent:
6721
	 *
6722
	 *     // Not chained
6723
	 *     api.row.add( {...} );
6724
	 *     api.draw();
6725
	 *
6726
	 *     // Chained
6727
	 *     api.row.add( {...} ).draw();
6728
	 *
6729
	 * @class DataTable.Api
6730
	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6731
	 *   used to define which DataTables enhanced tables this API will operate on.
6732
	 *   Can be one of:
6733
	 *
6734
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6735
	 *     with be found and used.
6736
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6737
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6738
	 *   * `object` - DataTables settings object
6739
	 * @param {array} [data] Data to initialise the Api instance with.
6740
	 *
6741
	 * @example
6742
	 *   // Direct initialisation during DataTables construction
6743
	 *   var api = $('#example').DataTable();
6744
	 *
6745
	 * @example
6746
	 *   // Initialisation using a DataTables jQuery object
6747
	 *   var api = $('#example').dataTable().api();
6748
	 *
6749
	 * @example
6750
	 *   // Initialisation as a constructor
6751
	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6752
	 */
6753
	_Api = function ( context, data )
6754
	{
6755
		if ( ! (this instanceof _Api) ) {
6756
			return new _Api( context, data );
6757
		}
6758
 
6759
		var settings = [];
6760
		var ctxSettings = function ( o ) {
6761
			var a = _toSettings( o );
6762
			if ( a ) {
6763
				settings = settings.concat( a );
6764
			}
6765
		};
6766
 
6767
		if ( $.isArray( context ) ) {
6768
			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6769
				ctxSettings( context[i] );
6770
			}
6771
		}
6772
		else {
6773
			ctxSettings( context );
6774
		}
6775
 
6776
		// Remove duplicates
6777
		this.context = _unique( settings );
6778
 
6779
		// Initial data
6780
		if ( data ) {
6781
			$.merge( this, data );
6782
		}
6783
 
6784
		// selector
6785
		this.selector = {
6786
			rows: null,
6787
			cols: null,
6788
			opts: null
6789
		};
6790
 
6791
		_Api.extend( this, this, __apiStruct );
6792
	};
6793
 
6794
	DataTable.Api = _Api;
6795
 
6796
	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6797
	// isPlainObject.
6798
	$.extend( _Api.prototype, {
6799
		any: function ()
6800
		{
6801
			return this.count() !== 0;
6802
		},
6803
 
6804
 
6805
		concat:  __arrayProto.concat,
6806
 
6807
 
6808
		context: [], // array of table settings objects
6809
 
6810
 
6811
		count: function ()
6812
		{
6813
			return this.flatten().length;
6814
		},
6815
 
6816
 
6817
		each: function ( fn )
6818
		{
6819
			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6820
				fn.call( this, this[i], i, this );
6821
			}
6822
 
6823
			return this;
6824
		},
6825
 
6826
 
6827
		eq: function ( idx )
6828
		{
6829
			var ctx = this.context;
6830
 
6831
			return ctx.length > idx ?
6832
				new _Api( ctx[idx], this[idx] ) :
6833
				null;
6834
		},
6835
 
6836
 
6837
		filter: function ( fn )
6838
		{
6839
			var a = [];
6840
 
6841
			if ( __arrayProto.filter ) {
6842
				a = __arrayProto.filter.call( this, fn, this );
6843
			}
6844
			else {
6845
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6846
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6847
					if ( fn.call( this, this[i], i, this ) ) {
6848
						a.push( this[i] );
6849
					}
6850
				}
6851
			}
6852
 
6853
			return new _Api( this.context, a );
6854
		},
6855
 
6856
 
6857
		flatten: function ()
6858
		{
6859
			var a = [];
6860
			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6861
		},
6862
 
6863
 
6864
		join:    __arrayProto.join,
6865
 
6866
 
6867
		indexOf: __arrayProto.indexOf || function (obj, start)
6868
		{
6869
			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6870
				if ( this[i] === obj ) {
6871
					return i;
6872
				}
6873
			}
6874
			return -1;
6875
		},
6876
 
6877
		iterator: function ( flatten, type, fn, alwaysNew ) {
6878
			var
6879
				a = [], ret,
6880
				i, ien, j, jen,
6881
				context = this.context,
6882
				rows, items, item,
6883
				selector = this.selector;
6884
 
6885
			// Argument shifting
6886
			if ( typeof flatten === 'string' ) {
6887
				alwaysNew = fn;
6888
				fn = type;
6889
				type = flatten;
6890
				flatten = false;
6891
			}
6892
 
6893
			for ( i=0, ien=context.length ; i<ien ; i++ ) {
6894
				var apiInst = new _Api( context[i] );
6895
 
6896
				if ( type === 'table' ) {
6897
					ret = fn.call( apiInst, context[i], i );
6898
 
6899
					if ( ret !== undefined ) {
6900
						a.push( ret );
6901
					}
6902
				}
6903
				else if ( type === 'columns' || type === 'rows' ) {
6904
					// this has same length as context - one entry for each table
6905
					ret = fn.call( apiInst, context[i], this[i], i );
6906
 
6907
					if ( ret !== undefined ) {
6908
						a.push( ret );
6909
					}
6910
				}
6911
				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6912
					// columns and rows share the same structure.
6913
					// 'this' is an array of column indexes for each context
6914
					items = this[i];
6915
 
6916
					if ( type === 'column-rows' ) {
6917
						rows = _selector_row_indexes( context[i], selector.opts );
6918
					}
6919
 
6920
					for ( j=0, jen=items.length ; j<jen ; j++ ) {
6921
						item = items[j];
6922
 
6923
						if ( type === 'cell' ) {
6924
							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
6925
						}
6926
						else {
6927
							ret = fn.call( apiInst, context[i], item, i, j, rows );
6928
						}
6929
 
6930
						if ( ret !== undefined ) {
6931
							a.push( ret );
6932
						}
6933
					}
6934
				}
6935
			}
6936
 
6937
			if ( a.length || alwaysNew ) {
6938
				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6939
				var apiSelector = api.selector;
6940
				apiSelector.rows = selector.rows;
6941
				apiSelector.cols = selector.cols;
6942
				apiSelector.opts = selector.opts;
6943
				return api;
6944
			}
6945
			return this;
6946
		},
6947
 
6948
 
6949
		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
6950
		{
6951
			// Bit cheeky...
6952
			return this.indexOf.apply( this.toArray.reverse(), arguments );
6953
		},
6954
 
6955
 
6956
		length:  0,
6957
 
6958
 
6959
		map: function ( fn )
6960
		{
6961
			var a = [];
6962
 
6963
			if ( __arrayProto.map ) {
6964
				a = __arrayProto.map.call( this, fn, this );
6965
			}
6966
			else {
6967
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6968
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6969
					a.push( fn.call( this, this[i], i ) );
6970
				}
6971
			}
6972
 
6973
			return new _Api( this.context, a );
6974
		},
6975
 
6976
 
6977
		pluck: function ( prop )
6978
		{
6979
			return this.map( function ( el ) {
6980
				return el[ prop ];
6981
			} );
6982
		},
6983
 
6984
		pop:     __arrayProto.pop,
6985
 
6986
 
6987
		push:    __arrayProto.push,
6988
 
6989
 
6990
		// Does not return an API instance
6991
		reduce: __arrayProto.reduce || function ( fn, init )
6992
		{
6993
			return _fnReduce( this, fn, init, 0, this.length, 1 );
6994
		},
6995
 
6996
 
6997
		reduceRight: __arrayProto.reduceRight || function ( fn, init )
6998
		{
6999
			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7000
		},
7001
 
7002
 
7003
		reverse: __arrayProto.reverse,
7004
 
7005
 
7006
		// Object with rows, columns and opts
7007
		selector: null,
7008
 
7009
 
7010
		shift:   __arrayProto.shift,
7011
 
7012
 
7013
		sort:    __arrayProto.sort, // ? name - order?
7014
 
7015
 
7016
		splice:  __arrayProto.splice,
7017
 
7018
 
7019
		toArray: function ()
7020
		{
7021
			return __arrayProto.slice.call( this );
7022
		},
7023
 
7024
 
7025
		to$: function ()
7026
		{
7027
			return $( this );
7028
		},
7029
 
7030
 
7031
		toJQuery: function ()
7032
		{
7033
			return $( this );
7034
		},
7035
 
7036
 
7037
		unique: function ()
7038
		{
7039
			return new _Api( this.context, _unique(this) );
7040
		},
7041
 
7042
 
7043
		unshift: __arrayProto.unshift
7044
	} );
7045
 
7046
 
7047
	_Api.extend = function ( scope, obj, ext )
7048
	{
7049
		// Only extend API instances and static properties of the API
7050
		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7051
			return;
7052
		}
7053
 
7054
		var
7055
			i, ien,
7056
			j, jen,
7057
			struct, inner,
7058
			methodScoping = function ( scope, fn, struc ) {
7059
				return function () {
7060
					var ret = fn.apply( scope, arguments );
7061
 
7062
					// Method extension
7063
					_Api.extend( ret, ret, struc.methodExt );
7064
					return ret;
7065
				};
7066
			};
7067
 
7068
		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7069
			struct = ext[i];
7070
 
7071
			// Value
7072
			obj[ struct.name ] = typeof struct.val === 'function' ?
7073
				methodScoping( scope, struct.val, struct ) :
7074
				$.isPlainObject( struct.val ) ?
7075
					{} :
7076
					struct.val;
7077
 
7078
			obj[ struct.name ].__dt_wrapper = true;
7079
 
7080
			// Property extension
7081
			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7082
		}
7083
	};
7084
 
7085
 
7086
	// @todo - Is there need for an augment function?
7087
	// _Api.augment = function ( inst, name )
7088
	// {
7089
	// 	// Find src object in the structure from the name
7090
	// 	var parts = name.split('.');
7091
 
7092
	// 	_Api.extend( inst, obj );
7093
	// };
7094
 
7095
 
7096
	//     [
7097
	//       {
7098
	//         name:      'data'                -- string   - Property name
7099
	//         val:       function () {},       -- function - Api method (or undefined if just an object
7100
	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7101
	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7102
	//       },
7103
	//       {
7104
	//         name:     'row'
7105
	//         val:       {},
7106
	//         methodExt: [ ... ],
7107
	//         propExt:   [
7108
	//           {
7109
	//             name:      'data'
7110
	//             val:       function () {},
7111
	//             methodExt: [ ... ],
7112
	//             propExt:   [ ... ]
7113
	//           },
7114
	//           ...
7115
	//         ]
7116
	//       }
7117
	//     ]
7118
 
7119
	_Api.register = _api_register = function ( name, val )
7120
	{
7121
		if ( $.isArray( name ) ) {
7122
			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7123
				_Api.register( name[j], val );
7124
			}
7125
			return;
7126
		}
7127
 
7128
		var
7129
			i, ien,
7130
			heir = name.split('.'),
7131
			struct = __apiStruct,
7132
			key, method;
7133
 
7134
		var find = function ( src, name ) {
7135
			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7136
				if ( src[i].name === name ) {
7137
					return src[i];
7138
				}
7139
			}
7140
			return null;
7141
		};
7142
 
7143
		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7144
			method = heir[i].indexOf('()') !== -1;
7145
			key = method ?
7146
				heir[i].replace('()', '') :
7147
				heir[i];
7148
 
7149
			var src = find( struct, key );
7150
			if ( ! src ) {
7151
				src = {
7152
					name:      key,
7153
					val:       {},
7154
					methodExt: [],
7155
					propExt:   []
7156
				};
7157
				struct.push( src );
7158
			}
7159
 
7160
			if ( i === ien-1 ) {
7161
				src.val = val;
7162
			}
7163
			else {
7164
				struct = method ?
7165
					src.methodExt :
7166
					src.propExt;
7167
			}
7168
		}
7169
	};
7170
 
7171
 
7172
	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7173
		_Api.register( pluralName, val );
7174
 
7175
		_Api.register( singularName, function () {
7176
			var ret = val.apply( this, arguments );
7177
 
7178
			if ( ret === this ) {
7179
				// Returned item is the API instance that was passed in, return it
7180
				return this;
7181
			}
7182
			else if ( ret instanceof _Api ) {
7183
				// New API instance returned, want the value from the first item
7184
				// in the returned array for the singular result.
7185
				return ret.length ?
7186
					$.isArray( ret[0] ) ?
7187
						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7188
						ret[0] :
7189
					undefined;
7190
			}
7191
 
7192
			// Non-API return - just fire it back
7193
			return ret;
7194
		} );
7195
	};
7196
 
7197
 
7198
	/**
7199
	 * Selector for HTML tables. Apply the given selector to the give array of
7200
	 * DataTables settings objects.
7201
	 *
7202
	 * @param {string|integer} [selector] jQuery selector string or integer
7203
	 * @param  {array} Array of DataTables settings objects to be filtered
7204
	 * @return {array}
7205
	 * @ignore
7206
	 */
7207
	var __table_selector = function ( selector, a )
7208
	{
7209
		// Integer is used to pick out a table by index
7210
		if ( typeof selector === 'number' ) {
7211
			return [ a[ selector ] ];
7212
		}
7213
 
7214
		// Perform a jQuery selector on the table nodes
7215
		var nodes = $.map( a, function (el, i) {
7216
			return el.nTable;
7217
		} );
7218
 
7219
		return $(nodes)
7220
			.filter( selector )
7221
			.map( function (i) {
7222
				// Need to translate back from the table node to the settings
7223
				var idx = $.inArray( this, nodes );
7224
				return a[ idx ];
7225
			} )
7226
			.toArray();
7227
	};
7228
 
7229
 
7230
 
7231
	/**
7232
	 * Context selector for the API's context (i.e. the tables the API instance
7233
	 * refers to.
7234
	 *
7235
	 * @name    DataTable.Api#tables
7236
	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7237
	 *   should operate on. If not given, all tables in the current context are
7238
	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7239
	 *   select multiple tables or as an integer to select a single table.
7240
	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7241
	 */
7242
	_api_register( 'tables()', function ( selector ) {
7243
		// A new instance is created if there was a selector specified
7244
		return selector ?
7245
			new _Api( __table_selector( selector, this.context ) ) :
7246
			this;
7247
	} );
7248
 
7249
 
7250
	_api_register( 'table()', function ( selector ) {
7251
		var tables = this.tables( selector );
7252
		var ctx = tables.context;
7253
 
7254
		// Truncate to the first matched table
7255
		return ctx.length ?
7256
			new _Api( ctx[0] ) :
7257
			tables;
7258
	} );
7259
 
7260
 
7261
	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7262
		return this.iterator( 'table', function ( ctx ) {
7263
			return ctx.nTable;
7264
		}, 1 );
7265
	} );
7266
 
7267
 
7268
	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7269
		return this.iterator( 'table', function ( ctx ) {
7270
			return ctx.nTBody;
7271
		}, 1 );
7272
	} );
7273
 
7274
 
7275
	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7276
		return this.iterator( 'table', function ( ctx ) {
7277
			return ctx.nTHead;
7278
		}, 1 );
7279
	} );
7280
 
7281
 
7282
	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7283
		return this.iterator( 'table', function ( ctx ) {
7284
			return ctx.nTFoot;
7285
		}, 1 );
7286
	} );
7287
 
7288
 
7289
	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7290
		return this.iterator( 'table', function ( ctx ) {
7291
			return ctx.nTableWrapper;
7292
		}, 1 );
7293
	} );
7294
 
7295
 
7296
 
7297
	/**
7298
	 * Redraw the tables in the current context.
7299
	 */
7300
	_api_register( 'draw()', function ( paging ) {
7301
		return this.iterator( 'table', function ( settings ) {
7302
			if ( paging === 'page' ) {
7303
				_fnDraw( settings );
7304
			}
7305
			else {
7306
				if ( typeof paging === 'string' ) {
7307
					paging = paging === 'full-hold' ?
7308
						false :
7309
						true;
7310
				}
7311
 
7312
				_fnReDraw( settings, paging===false );
7313
			}
7314
		} );
7315
	} );
7316
 
7317
 
7318
 
7319
	/**
7320
	 * Get the current page index.
7321
	 *
7322
	 * @return {integer} Current page index (zero based)
7323
	 *//**
7324
	 * Set the current page.
7325
	 *
7326
	 * Note that if you attempt to show a page which does not exist, DataTables will
7327
	 * not throw an error, but rather reset the paging.
7328
	 *
7329
	 * @param {integer|string} action The paging action to take. This can be one of:
7330
	 *  * `integer` - The page index to jump to
7331
	 *  * `string` - An action to take:
7332
	 *    * `first` - Jump to first page.
7333
	 *    * `next` - Jump to the next page
7334
	 *    * `previous` - Jump to previous page
7335
	 *    * `last` - Jump to the last page.
7336
	 * @returns {DataTables.Api} this
7337
	 */
7338
	_api_register( 'page()', function ( action ) {
7339
		if ( action === undefined ) {
7340
			return this.page.info().page; // not an expensive call
7341
		}
7342
 
7343
		// else, have an action to take on all tables
7344
		return this.iterator( 'table', function ( settings ) {
7345
			_fnPageChange( settings, action );
7346
		} );
7347
	} );
7348
 
7349
 
7350
	/**
7351
	 * Paging information for the first table in the current context.
7352
	 *
7353
	 * If you require paging information for another table, use the `table()` method
7354
	 * with a suitable selector.
7355
	 *
7356
	 * @return {object} Object with the following properties set:
7357
	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7358
	 *  * `pages` - Total number of pages
7359
	 *  * `start` - Display index for the first record shown on the current page
7360
	 *  * `end` - Display index for the last record shown on the current page
7361
	 *  * `length` - Display length (number of records). Note that generally `start
7362
	 *    + length = end`, but this is not always true, for example if there are
7363
	 *    only 2 records to show on the final page, with a length of 10.
7364
	 *  * `recordsTotal` - Full data set length
7365
	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7366
	 *    are applied.
7367
	 */
7368
	_api_register( 'page.info()', function ( action ) {
7369
		if ( this.context.length === 0 ) {
7370
			return undefined;
7371
		}
7372
 
7373
		var
7374
			settings   = this.context[0],
7375
			start      = settings._iDisplayStart,
7376
			len        = settings._iDisplayLength,
7377
			visRecords = settings.fnRecordsDisplay(),
7378
			all        = len === -1;
7379
 
7380
		return {
7381
			"page":           all ? 0 : Math.floor( start / len ),
7382
			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7383
			"start":          start,
7384
			"end":            settings.fnDisplayEnd(),
7385
			"length":         len,
7386
			"recordsTotal":   settings.fnRecordsTotal(),
7387
			"recordsDisplay": visRecords,
7388
			"serverSide":     _fnDataSource( settings ) === 'ssp'
7389
		};
7390
	} );
7391
 
7392
 
7393
	/**
7394
	 * Get the current page length.
7395
	 *
7396
	 * @return {integer} Current page length. Note `-1` indicates that all records
7397
	 *   are to be shown.
7398
	 *//**
7399
	 * Set the current page length.
7400
	 *
7401
	 * @param {integer} Page length to set. Use `-1` to show all records.
7402
	 * @returns {DataTables.Api} this
7403
	 */
7404
	_api_register( 'page.len()', function ( len ) {
7405
		// Note that we can't call this function 'length()' because `length`
7406
		// is a Javascript property of functions which defines how many arguments
7407
		// the function expects.
7408
		if ( len === undefined ) {
7409
			return this.context.length !== 0 ?
7410
				this.context[0]._iDisplayLength :
7411
				undefined;
7412
		}
7413
 
7414
		// else, set the page length
7415
		return this.iterator( 'table', function ( settings ) {
7416
			_fnLengthChange( settings, len );
7417
		} );
7418
	} );
7419
 
7420
 
7421
 
7422
	var __reload = function ( settings, holdPosition, callback ) {
7423
		// Use the draw event to trigger a callback
7424
		if ( callback ) {
7425
			var api = new _Api( settings );
7426
 
7427
			api.one( 'draw', function () {
7428
				callback( api.ajax.json() );
7429
			} );
7430
		}
7431
 
7432
		if ( _fnDataSource( settings ) == 'ssp' ) {
7433
			_fnReDraw( settings, holdPosition );
7434
		}
7435
		else {
7436
			_fnProcessingDisplay( settings, true );
7437
 
7438
			// Cancel an existing request
7439
			var xhr = settings.jqXHR;
7440
			if ( xhr && xhr.readyState !== 4 ) {
7441
				xhr.abort();
7442
			}
7443
 
7444
			// Trigger xhr
7445
			_fnBuildAjax( settings, [], function( json ) {
7446
				_fnClearTable( settings );
7447
 
7448
				var data = _fnAjaxDataSrc( settings, json );
7449
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7450
					_fnAddData( settings, data[i] );
7451
				}
7452
 
7453
				_fnReDraw( settings, holdPosition );
7454
				_fnProcessingDisplay( settings, false );
7455
			} );
7456
		}
7457
	};
7458
 
7459
 
7460
	/**
7461
	 * Get the JSON response from the last Ajax request that DataTables made to the
7462
	 * server. Note that this returns the JSON from the first table in the current
7463
	 * context.
7464
	 *
7465
	 * @return {object} JSON received from the server.
7466
	 */
7467
	_api_register( 'ajax.json()', function () {
7468
		var ctx = this.context;
7469
 
7470
		if ( ctx.length > 0 ) {
7471
			return ctx[0].json;
7472
		}
7473
 
7474
		// else return undefined;
7475
	} );
7476
 
7477
 
7478
	/**
7479
	 * Get the data submitted in the last Ajax request
7480
	 */
7481
	_api_register( 'ajax.params()', function () {
7482
		var ctx = this.context;
7483
 
7484
		if ( ctx.length > 0 ) {
7485
			return ctx[0].oAjaxData;
7486
		}
7487
 
7488
		// else return undefined;
7489
	} );
7490
 
7491
 
7492
	/**
7493
	 * Reload tables from the Ajax data source. Note that this function will
7494
	 * automatically re-draw the table when the remote data has been loaded.
7495
	 *
7496
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7497
	 *   position. A full re-sort and re-filter is performed when this method is
7498
	 *   called, which is why the pagination reset is the default action.
7499
	 * @returns {DataTables.Api} this
7500
	 */
7501
	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7502
		return this.iterator( 'table', function (settings) {
7503
			__reload( settings, resetPaging===false, callback );
7504
		} );
7505
	} );
7506
 
7507
 
7508
	/**
7509
	 * Get the current Ajax URL. Note that this returns the URL from the first
7510
	 * table in the current context.
7511
	 *
7512
	 * @return {string} Current Ajax source URL
7513
	 *//**
7514
	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7515
	 * current context.
7516
	 *
7517
	 * @param {string} url URL to set.
7518
	 * @returns {DataTables.Api} this
7519
	 */
7520
	_api_register( 'ajax.url()', function ( url ) {
7521
		var ctx = this.context;
7522
 
7523
		if ( url === undefined ) {
7524
			// get
7525
			if ( ctx.length === 0 ) {
7526
				return undefined;
7527
			}
7528
			ctx = ctx[0];
7529
 
7530
			return ctx.ajax ?
7531
				$.isPlainObject( ctx.ajax ) ?
7532
					ctx.ajax.url :
7533
					ctx.ajax :
7534
				ctx.sAjaxSource;
7535
		}
7536
 
7537
		// set
7538
		return this.iterator( 'table', function ( settings ) {
7539
			if ( $.isPlainObject( settings.ajax ) ) {
7540
				settings.ajax.url = url;
7541
			}
7542
			else {
7543
				settings.ajax = url;
7544
			}
7545
			// No need to consider sAjaxSource here since DataTables gives priority
7546
			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7547
			// value of `sAjaxSource` redundant.
7548
		} );
7549
	} );
7550
 
7551
 
7552
	/**
7553
	 * Load data from the newly set Ajax URL. Note that this method is only
7554
	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7555
	 * has the same effect as calling `ajax.reload()` but is provided for
7556
	 * convenience when setting a new URL. Like `ajax.reload()` it will
7557
	 * automatically redraw the table once the remote data has been loaded.
7558
	 *
7559
	 * @returns {DataTables.Api} this
7560
	 */
7561
	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7562
		// Same as a reload, but makes sense to present it for easy access after a
7563
		// url change
7564
		return this.iterator( 'table', function ( ctx ) {
7565
			__reload( ctx, resetPaging===false, callback );
7566
		} );
7567
	} );
7568
 
7569
 
7570
 
7571
 
7572
	var _selector_run = function ( type, selector, selectFn, settings, opts )
7573
	{
7574
		var
7575
			out = [], res,
7576
			a, i, ien, j, jen,
7577
			selectorType = typeof selector;
7578
 
7579
		// Can't just check for isArray here, as an API or jQuery instance might be
7580
		// given with their array like look
7581
		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7582
			selector = [ selector ];
7583
		}
7584
 
7585
		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7586
			a = selector[i] && selector[i].split ?
7587
				selector[i].split(',') :
7588
				[ selector[i] ];
7589
 
7590
			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7591
				res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7592
 
7593
				if ( res && res.length ) {
7594
					out = out.concat( res );
7595
				}
7596
			}
7597
		}
7598
 
7599
		// selector extensions
7600
		var ext = _ext.selector[ type ];
7601
		if ( ext.length ) {
7602
			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7603
				out = ext[i]( settings, opts, out );
7604
			}
7605
		}
7606
 
7607
		return _unique( out );
7608
	};
7609
 
7610
 
7611
	var _selector_opts = function ( opts )
7612
	{
7613
		if ( ! opts ) {
7614
			opts = {};
7615
		}
7616
 
7617
		// Backwards compatibility for 1.9- which used the terminology filter rather
7618
		// than search
7619
		if ( opts.filter && opts.search === undefined ) {
7620
			opts.search = opts.filter;
7621
		}
7622
 
7623
		return $.extend( {
7624
			search: 'none',
7625
			order: 'current',
7626
			page: 'all'
7627
		}, opts );
7628
	};
7629
 
7630
 
7631
	var _selector_first = function ( inst )
7632
	{
7633
		// Reduce the API instance to the first item found
7634
		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7635
			if ( inst[i].length > 0 ) {
7636
				// Assign the first element to the first item in the instance
7637
				// and truncate the instance and context
7638
				inst[0] = inst[i];
7639
				inst[0].length = 1;
7640
				inst.length = 1;
7641
				inst.context = [ inst.context[i] ];
7642
 
7643
				return inst;
7644
			}
7645
		}
7646
 
7647
		// Not found - return an empty instance
7648
		inst.length = 0;
7649
		return inst;
7650
	};
7651
 
7652
 
7653
	var _selector_row_indexes = function ( settings, opts )
7654
	{
7655
		var
7656
			i, ien, tmp, a=[],
7657
			displayFiltered = settings.aiDisplay,
7658
			displayMaster = settings.aiDisplayMaster;
7659
 
7660
		var
7661
			search = opts.search,  // none, applied, removed
7662
			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7663
			page   = opts.page;    // all, current
7664
 
7665
		if ( _fnDataSource( settings ) == 'ssp' ) {
7666
			// In server-side processing mode, most options are irrelevant since
7667
			// rows not shown don't exist and the index order is the applied order
7668
			// Removed is a special case - for consistency just return an empty
7669
			// array
7670
			return search === 'removed' ?
7671
				[] :
7672
				_range( 0, displayMaster.length );
7673
		}
7674
		else if ( page == 'current' ) {
7675
			// Current page implies that order=current and fitler=applied, since it is
7676
			// fairly senseless otherwise, regardless of what order and search actually
7677
			// are
7678
			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7679
				a.push( displayFiltered[i] );
7680
			}
7681
		}
7682
		else if ( order == 'current' || order == 'applied' ) {
7683
			a = search == 'none' ?
7684
				displayMaster.slice() :                      // no search
7685
				search == 'applied' ?
7686
					displayFiltered.slice() :                // applied search
7687
					$.map( displayMaster, function (el, i) { // removed search
7688
						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7689
					} );
7690
		}
7691
		else if ( order == 'index' || order == 'original' ) {
7692
			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7693
				if ( search == 'none' ) {
7694
					a.push( i );
7695
				}
7696
				else { // applied | removed
7697
					tmp = $.inArray( i, displayFiltered );
7698
 
7699
					if ((tmp === -1 && search == 'removed') ||
7700
						(tmp >= 0   && search == 'applied') )
7701
					{
7702
						a.push( i );
7703
					}
7704
				}
7705
			}
7706
		}
7707
 
7708
		return a;
7709
	};
7710
 
7711
 
7712
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7713
	 * Rows
7714
	 *
7715
	 * {}          - no selector - use all available rows
7716
	 * {integer}   - row aoData index
7717
	 * {node}      - TR node
7718
	 * {string}    - jQuery selector to apply to the TR elements
7719
	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7720
	 *
7721
	 */
7722
 
7723
 
7724
	var __row_selector = function ( settings, selector, opts )
7725
	{
7726
		var run = function ( sel ) {
7727
			var selInt = _intVal( sel );
7728
			var i, ien;
7729
 
7730
			// Short cut - selector is a number and no options provided (default is
7731
			// all records, so no need to check if the index is in there, since it
7732
			// must be - dev error if the index doesn't exist).
7733
			if ( selInt !== null && ! opts ) {
7734
				return [ selInt ];
7735
			}
7736
 
7737
			var rows = _selector_row_indexes( settings, opts );
7738
 
7739
			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7740
				// Selector - integer
7741
				return [ selInt ];
7742
			}
7743
			else if ( ! sel ) {
7744
				// Selector - none
7745
				return rows;
7746
			}
7747
 
7748
			// Selector - function
7749
			if ( typeof sel === 'function' ) {
7750
				return $.map( rows, function (idx) {
7751
					var row = settings.aoData[ idx ];
7752
					return sel( idx, row._aData, row.nTr ) ? idx : null;
7753
				} );
7754
			}
7755
 
7756
			// Get nodes in the order from the `rows` array with null values removed
7757
			var nodes = _removeEmpty(
7758
				_pluck_order( settings.aoData, rows, 'nTr' )
7759
			);
7760
 
7761
			// Selector - node
7762
			if ( sel.nodeName ) {
7763
				if ( $.inArray( sel, nodes ) !== -1 ) {
7764
					return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table
7765
					                             // and DataTables adds a prop for fast lookup
7766
				}
7767
			}
7768
 
7769
			// ID selector. Want to always be able to select rows by id, regardless
7770
			// of if the tr element has been created or not, so can't rely upon
7771
			// jQuery here - hence a custom implementation. This does not match
7772
			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7773
			// but to select it using a CSS selector engine (like Sizzle or
7774
			// querySelect) it would need to need to be escaped for some characters.
7775
			// DataTables simplifies this for row selectors since you can select
7776
			// only a row. A # indicates an id any anything that follows is the id -
7777
			// unescaped.
7778
			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7779
				// get row index from id
7780
				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7781
				if ( rowObj !== undefined ) {
7782
					return [ rowObj.idx ];
7783
				}
7784
 
7785
				// need to fall through to jQuery in case there is DOM id that
7786
				// matches
7787
			}
7788
 
7789
			// Selector - jQuery selector string, array of nodes or jQuery object/
7790
			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7791
			// it also allows arrays, so this will cope with all three options
7792
			return $(nodes)
7793
				.filter( sel )
7794
				.map( function () {
7795
					return this._DT_RowIndex;
7796
				} )
7797
				.toArray();
7798
		};
7799
 
7800
		return _selector_run( 'row', selector, run, settings, opts );
7801
	};
7802
 
7803
 
7804
	_api_register( 'rows()', function ( selector, opts ) {
7805
		// argument shifting
7806
		if ( selector === undefined ) {
7807
			selector = '';
7808
		}
7809
		else if ( $.isPlainObject( selector ) ) {
7810
			opts = selector;
7811
			selector = '';
7812
		}
7813
 
7814
		opts = _selector_opts( opts );
7815
 
7816
		var inst = this.iterator( 'table', function ( settings ) {
7817
			return __row_selector( settings, selector, opts );
7818
		}, 1 );
7819
 
7820
		// Want argument shifting here and in __row_selector?
7821
		inst.selector.rows = selector;
7822
		inst.selector.opts = opts;
7823
 
7824
		return inst;
7825
	} );
7826
 
7827
	_api_register( 'rows().nodes()', function () {
7828
		return this.iterator( 'row', function ( settings, row ) {
7829
			return settings.aoData[ row ].nTr || undefined;
7830
		}, 1 );
7831
	} );
7832
 
7833
	_api_register( 'rows().data()', function () {
7834
		return this.iterator( true, 'rows', function ( settings, rows ) {
7835
			return _pluck_order( settings.aoData, rows, '_aData' );
7836
		}, 1 );
7837
	} );
7838
 
7839
	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7840
		return this.iterator( 'row', function ( settings, row ) {
7841
			var r = settings.aoData[ row ];
7842
			return type === 'search' ? r._aFilterData : r._aSortData;
7843
		}, 1 );
7844
	} );
7845
 
7846
	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7847
		return this.iterator( 'row', function ( settings, row ) {
7848
			_fnInvalidate( settings, row, src );
7849
		} );
7850
	} );
7851
 
7852
	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7853
		return this.iterator( 'row', function ( settings, row ) {
7854
			return row;
7855
		}, 1 );
7856
	} );
7857
 
7858
	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
7859
		var a = [];
7860
		var context = this.context;
7861
 
7862
		// `iterator` will drop undefined values, but in this case we want them
7863
		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7864
			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
7865
				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
7866
				a.push( (hash === true ? '#' : '' )+ id );
7867
			}
7868
		}
7869
 
7870
		return new _Api( context, a );
7871
	} );
7872
 
7873
	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7874
		var that = this;
7875
 
7876
		this.iterator( 'row', function ( settings, row, thatIdx ) {
7877
			var data = settings.aoData;
7878
			var rowData = data[ row ];
7879
 
7880
			data.splice( row, 1 );
7881
 
7882
			// Update the _DT_RowIndex parameter on all rows in the table
7883
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7884
				if ( data[i].nTr !== null ) {
7885
					data[i].nTr._DT_RowIndex = i;
7886
				}
7887
			}
7888
 
7889
			// Delete from the display arrays
7890
			_fnDeleteIndex( settings.aiDisplayMaster, row );
7891
			_fnDeleteIndex( settings.aiDisplay, row );
7892
			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7893
 
7894
			// Check for an 'overflow' they case for displaying the table
7895
			_fnLengthOverflow( settings );
7896
 
7897
			// Remove the row's ID reference if there is one
7898
			var id = settings.rowIdFn( rowData._aData );
7899
			if ( id !== undefined ) {
7900
				delete settings.aIds[ id ];
7901
			}
7902
		} );
7903
 
7904
		this.iterator( 'table', function ( settings ) {
7905
			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7906
				settings.aoData[i].idx = i;
7907
			}
7908
		} );
7909
 
7910
		return this;
7911
	} );
7912
 
7913
 
7914
	_api_register( 'rows.add()', function ( rows ) {
7915
		var newRows = this.iterator( 'table', function ( settings ) {
7916
				var row, i, ien;
7917
				var out = [];
7918
 
7919
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
7920
					row = rows[i];
7921
 
7922
					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7923
						out.push( _fnAddTr( settings, row )[0] );
7924
					}
7925
					else {
7926
						out.push( _fnAddData( settings, row ) );
7927
					}
7928
				}
7929
 
7930
				return out;
7931
			}, 1 );
7932
 
7933
		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
7934
		var modRows = this.rows( -1 );
7935
		modRows.pop();
7936
		$.merge( modRows, newRows );
7937
 
7938
		return modRows;
7939
	} );
7940
 
7941
 
7942
 
7943
 
7944
 
7945
	/**
7946
	 *
7947
	 */
7948
	_api_register( 'row()', function ( selector, opts ) {
7949
		return _selector_first( this.rows( selector, opts ) );
7950
	} );
7951
 
7952
 
7953
	_api_register( 'row().data()', function ( data ) {
7954
		var ctx = this.context;
7955
 
7956
		if ( data === undefined ) {
7957
			// Get
7958
			return ctx.length && this.length ?
7959
				ctx[0].aoData[ this[0] ]._aData :
7960
				undefined;
7961
		}
7962
 
7963
		// Set
7964
		ctx[0].aoData[ this[0] ]._aData = data;
7965
 
7966
		// Automatically invalidate
7967
		_fnInvalidate( ctx[0], this[0], 'data' );
7968
 
7969
		return this;
7970
	} );
7971
 
7972
 
7973
	_api_register( 'row().node()', function () {
7974
		var ctx = this.context;
7975
 
7976
		return ctx.length && this.length ?
7977
			ctx[0].aoData[ this[0] ].nTr || null :
7978
			null;
7979
	} );
7980
 
7981
 
7982
	_api_register( 'row.add()', function ( row ) {
7983
		// Allow a jQuery object to be passed in - only a single row is added from
7984
		// it though - the first element in the set
7985
		if ( row instanceof $ && row.length ) {
7986
			row = row[0];
7987
		}
7988
 
7989
		var rows = this.iterator( 'table', function ( settings ) {
7990
			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7991
				return _fnAddTr( settings, row )[0];
7992
			}
7993
			return _fnAddData( settings, row );
7994
		} );
7995
 
7996
		// Return an Api.rows() extended instance, with the newly added row selected
7997
		return this.row( rows[0] );
7998
	} );
7999
 
8000
 
8001
 
8002
	var __details_add = function ( ctx, row, data, klass )
8003
	{
8004
		// Convert to array of TR elements
8005
		var rows = [];
8006
		var addRow = function ( r, k ) {
8007
			// Recursion to allow for arrays of jQuery objects
8008
			if ( $.isArray( r ) || r instanceof $ ) {
8009
				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8010
					addRow( r[i], k );
8011
				}
8012
				return;
8013
			}
8014
 
8015
			// If we get a TR element, then just add it directly - up to the dev
8016
			// to add the correct number of columns etc
8017
			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8018
				rows.push( r );
8019
			}
8020
			else {
8021
				// Otherwise create a row with a wrapper
8022
				var created = $('<tr><td/></tr>').addClass( k );
8023
				$('td', created)
8024
					.addClass( k )
8025
					.html( r )
8026
					[0].colSpan = _fnVisbleColumns( ctx );
8027
 
8028
				rows.push( created[0] );
8029
			}
8030
		};
8031
 
8032
		addRow( data, klass );
8033
 
8034
		if ( row._details ) {
8035
			row._details.remove();
8036
		}
8037
 
8038
		row._details = $(rows);
8039
 
8040
		// If the children were already shown, that state should be retained
8041
		if ( row._detailsShow ) {
8042
			row._details.insertAfter( row.nTr );
8043
		}
8044
	};
8045
 
8046
 
8047
	var __details_remove = function ( api, idx )
8048
	{
8049
		var ctx = api.context;
8050
 
8051
		if ( ctx.length ) {
8052
			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8053
 
8054
			if ( row && row._details ) {
8055
				row._details.remove();
8056
 
8057
				row._detailsShow = undefined;
8058
				row._details = undefined;
8059
			}
8060
		}
8061
	};
8062
 
8063
 
8064
	var __details_display = function ( api, show ) {
8065
		var ctx = api.context;
8066
 
8067
		if ( ctx.length && api.length ) {
8068
			var row = ctx[0].aoData[ api[0] ];
8069
 
8070
			if ( row._details ) {
8071
				row._detailsShow = show;
8072
 
8073
				if ( show ) {
8074
					row._details.insertAfter( row.nTr );
8075
				}
8076
				else {
8077
					row._details.detach();
8078
				}
8079
 
8080
				__details_events( ctx[0] );
8081
			}
8082
		}
8083
	};
8084
 
8085
 
8086
	var __details_events = function ( settings )
8087
	{
8088
		var api = new _Api( settings );
8089
		var namespace = '.dt.DT_details';
8090
		var drawEvent = 'draw'+namespace;
8091
		var colvisEvent = 'column-visibility'+namespace;
8092
		var destroyEvent = 'destroy'+namespace;
8093
		var data = settings.aoData;
8094
 
8095
		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8096
 
8097
		if ( _pluck( data, '_details' ).length > 0 ) {
8098
			// On each draw, insert the required elements into the document
8099
			api.on( drawEvent, function ( e, ctx ) {
8100
				if ( settings !== ctx ) {
8101
					return;
8102
				}
8103
 
8104
				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8105
					// Internal data grab
8106
					var row = data[ idx ];
8107
 
8108
					if ( row._detailsShow ) {
8109
						row._details.insertAfter( row.nTr );
8110
					}
8111
				} );
8112
			} );
8113
 
8114
			// Column visibility change - update the colspan
8115
			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8116
				if ( settings !== ctx ) {
8117
					return;
8118
				}
8119
 
8120
				// Update the colspan for the details rows (note, only if it already has
8121
				// a colspan)
8122
				var row, visible = _fnVisbleColumns( ctx );
8123
 
8124
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8125
					row = data[i];
8126
 
8127
					if ( row._details ) {
8128
						row._details.children('td[colspan]').attr('colspan', visible );
8129
					}
8130
				}
8131
			} );
8132
 
8133
			// Table destroyed - nuke any child rows
8134
			api.on( destroyEvent, function ( e, ctx ) {
8135
				if ( settings !== ctx ) {
8136
					return;
8137
				}
8138
 
8139
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8140
					if ( data[i]._details ) {
8141
						__details_remove( api, i );
8142
					}
8143
				}
8144
			} );
8145
		}
8146
	};
8147
 
8148
	// Strings for the method names to help minification
8149
	var _emp = '';
8150
	var _child_obj = _emp+'row().child';
8151
	var _child_mth = _child_obj+'()';
8152
 
8153
	// data can be:
8154
	//  tr
8155
	//  string
8156
	//  jQuery or array of any of the above
8157
	_api_register( _child_mth, function ( data, klass ) {
8158
		var ctx = this.context;
8159
 
8160
		if ( data === undefined ) {
8161
			// get
8162
			return ctx.length && this.length ?
8163
				ctx[0].aoData[ this[0] ]._details :
8164
				undefined;
8165
		}
8166
		else if ( data === true ) {
8167
			// show
8168
			this.child.show();
8169
		}
8170
		else if ( data === false ) {
8171
			// remove
8172
			__details_remove( this );
8173
		}
8174
		else if ( ctx.length && this.length ) {
8175
			// set
8176
			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8177
		}
8178
 
8179
		return this;
8180
	} );
8181
 
8182
 
8183
	_api_register( [
8184
		_child_obj+'.show()',
8185
		_child_mth+'.show()' // only when `child()` was called with parameters (without
8186
	], function ( show ) {   // it returns an object and this method is not executed)
8187
		__details_display( this, true );
8188
		return this;
8189
	} );
8190
 
8191
 
8192
	_api_register( [
8193
		_child_obj+'.hide()',
8194
		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8195
	], function () {         // it returns an object and this method is not executed)
8196
		__details_display( this, false );
8197
		return this;
8198
	} );
8199
 
8200
 
8201
	_api_register( [
8202
		_child_obj+'.remove()',
8203
		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8204
	], function () {           // it returns an object and this method is not executed)
8205
		__details_remove( this );
8206
		return this;
8207
	} );
8208
 
8209
 
8210
	_api_register( _child_obj+'.isShown()', function () {
8211
		var ctx = this.context;
8212
 
8213
		if ( ctx.length && this.length ) {
8214
			// _detailsShown as false or undefined will fall through to return false
8215
			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8216
		}
8217
		return false;
8218
	} );
8219
 
8220
 
8221
 
8222
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8223
	 * Columns
8224
	 *
8225
	 * {integer}           - column index (>=0 count from left, <0 count from right)
8226
	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8227
	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8228
	 * "{string}:name"     - column name
8229
	 * "{string}"          - jQuery selector on column header nodes
8230
	 *
8231
	 */
8232
 
8233
	// can be an array of these items, comma separated list, or an array of comma
8234
	// separated lists
8235
 
8236
	var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
8237
 
8238
 
8239
	// r1 and r2 are redundant - but it means that the parameters match for the
8240
	// iterator callback in columns().data()
8241
	var __columnData = function ( settings, column, r1, r2, rows ) {
8242
		var a = [];
8243
		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8244
			a.push( _fnGetCellData( settings, rows[row], column ) );
8245
		}
8246
		return a;
8247
	};
8248
 
8249
 
8250
	var __column_selector = function ( settings, selector, opts )
8251
	{
8252
		var
8253
			columns = settings.aoColumns,
8254
			names = _pluck( columns, 'sName' ),
8255
			nodes = _pluck( columns, 'nTh' );
8256
 
8257
		var run = function ( s ) {
8258
			var selInt = _intVal( s );
8259
 
8260
			// Selector - all
8261
			if ( s === '' ) {
8262
				return _range( columns.length );
8263
			}
8264
 
8265
			// Selector - index
8266
			if ( selInt !== null ) {
8267
				return [ selInt >= 0 ?
8268
					selInt : // Count from left
8269
					columns.length + selInt // Count from right (+ because its a negative value)
8270
				];
8271
			}
8272
 
8273
			// Selector = function
8274
			if ( typeof s === 'function' ) {
8275
				var rows = _selector_row_indexes( settings, opts );
8276
 
8277
				return $.map( columns, function (col, idx) {
8278
					return s(
8279
							idx,
8280
							__columnData( settings, idx, 0, 0, rows ),
8281
							nodes[ idx ]
8282
						) ? idx : null;
8283
				} );
8284
			}
8285
 
8286
			// jQuery or string selector
8287
			var match = typeof s === 'string' ?
8288
				s.match( __re_column_selector ) :
8289
				'';
8290
 
8291
			if ( match ) {
8292
				switch( match[2] ) {
8293
					case 'visIdx':
8294
					case 'visible':
8295
						var idx = parseInt( match[1], 10 );
8296
						// Visible index given, convert to column index
8297
						if ( idx < 0 ) {
8298
							// Counting from the right
8299
							var visColumns = $.map( columns, function (col,i) {
8300
								return col.bVisible ? i : null;
8301
							} );
8302
							return [ visColumns[ visColumns.length + idx ] ];
8303
						}
8304
						// Counting from the left
8305
						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8306
 
8307
					case 'name':
8308
						// match by name. `names` is column index complete and in order
8309
						return $.map( names, function (name, i) {
8310
							return name === match[1] ? i : null;
8311
						} );
8312
				}
8313
			}
8314
			else {
8315
				// jQuery selector on the TH elements for the columns
8316
				return $( nodes )
8317
					.filter( s )
8318
					.map( function () {
8319
						return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8320
					} )
8321
					.toArray();
8322
			}
8323
		};
8324
 
8325
		return _selector_run( 'column', selector, run, settings, opts );
8326
	};
8327
 
8328
 
8329
	var __setColumnVis = function ( settings, column, vis, recalc ) {
8330
		var
8331
			cols = settings.aoColumns,
8332
			col  = cols[ column ],
8333
			data = settings.aoData,
8334
			row, cells, i, ien, tr;
8335
 
8336
		// Get
8337
		if ( vis === undefined ) {
8338
			return col.bVisible;
8339
		}
8340
 
8341
		// Set
8342
		// No change
8343
		if ( col.bVisible === vis ) {
8344
			return;
8345
		}
8346
 
8347
		if ( vis ) {
8348
			// Insert column
8349
			// Need to decide if we should use appendChild or insertBefore
8350
			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8351
 
8352
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8353
				tr = data[i].nTr;
8354
				cells = data[i].anCells;
8355
 
8356
				if ( tr ) {
8357
					// insertBefore can act like appendChild if 2nd arg is null
8358
					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8359
				}
8360
			}
8361
		}
8362
		else {
8363
			// Remove column
8364
			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8365
		}
8366
 
8367
		// Common actions
8368
		col.bVisible = vis;
8369
		_fnDrawHead( settings, settings.aoHeader );
8370
		_fnDrawHead( settings, settings.aoFooter );
8371
 
8372
		if ( recalc === undefined || recalc ) {
8373
			// Automatically adjust column sizing
8374
			_fnAdjustColumnSizing( settings );
8375
 
8376
			// Realign columns for scrolling
8377
			if ( settings.oScroll.sX || settings.oScroll.sY ) {
8378
				_fnScrollDraw( settings );
8379
			}
8380
		}
8381
 
8382
		_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
8383
 
8384
		_fnSaveState( settings );
8385
	};
8386
 
8387
 
8388
	_api_register( 'columns()', function ( selector, opts ) {
8389
		// argument shifting
8390
		if ( selector === undefined ) {
8391
			selector = '';
8392
		}
8393
		else if ( $.isPlainObject( selector ) ) {
8394
			opts = selector;
8395
			selector = '';
8396
		}
8397
 
8398
		opts = _selector_opts( opts );
8399
 
8400
		var inst = this.iterator( 'table', function ( settings ) {
8401
			return __column_selector( settings, selector, opts );
8402
		}, 1 );
8403
 
8404
		// Want argument shifting here and in _row_selector?
8405
		inst.selector.cols = selector;
8406
		inst.selector.opts = opts;
8407
 
8408
		return inst;
8409
	} );
8410
 
8411
	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8412
		return this.iterator( 'column', function ( settings, column ) {
8413
			return settings.aoColumns[column].nTh;
8414
		}, 1 );
8415
	} );
8416
 
8417
	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8418
		return this.iterator( 'column', function ( settings, column ) {
8419
			return settings.aoColumns[column].nTf;
8420
		}, 1 );
8421
	} );
8422
 
8423
	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8424
		return this.iterator( 'column-rows', __columnData, 1 );
8425
	} );
8426
 
8427
	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8428
		return this.iterator( 'column', function ( settings, column ) {
8429
			return settings.aoColumns[column].mData;
8430
		}, 1 );
8431
	} );
8432
 
8433
	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8434
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8435
			return _pluck_order( settings.aoData, rows,
8436
				type === 'search' ? '_aFilterData' : '_aSortData', column
8437
			);
8438
		}, 1 );
8439
	} );
8440
 
8441
	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8442
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8443
			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8444
		}, 1 );
8445
	} );
8446
 
8447
	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8448
		return this.iterator( 'column', function ( settings, column ) {
8449
			if ( vis === undefined ) {
8450
				return settings.aoColumns[ column ].bVisible;
8451
			} // else
8452
			__setColumnVis( settings, column, vis, calc );
8453
		} );
8454
	} );
8455
 
8456
	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8457
		return this.iterator( 'column', function ( settings, column ) {
8458
			return type === 'visible' ?
8459
				_fnColumnIndexToVisible( settings, column ) :
8460
				column;
8461
		}, 1 );
8462
	} );
8463
 
8464
	_api_register( 'columns.adjust()', function () {
8465
		return this.iterator( 'table', function ( settings ) {
8466
			_fnAdjustColumnSizing( settings );
8467
		}, 1 );
8468
	} );
8469
 
8470
	_api_register( 'column.index()', function ( type, idx ) {
8471
		if ( this.context.length !== 0 ) {
8472
			var ctx = this.context[0];
8473
 
8474
			if ( type === 'fromVisible' || type === 'toData' ) {
8475
				return _fnVisibleToColumnIndex( ctx, idx );
8476
			}
8477
			else if ( type === 'fromData' || type === 'toVisible' ) {
8478
				return _fnColumnIndexToVisible( ctx, idx );
8479
			}
8480
		}
8481
	} );
8482
 
8483
	_api_register( 'column()', function ( selector, opts ) {
8484
		return _selector_first( this.columns( selector, opts ) );
8485
	} );
8486
 
8487
 
8488
 
8489
 
8490
	var __cell_selector = function ( settings, selector, opts )
8491
	{
8492
		var data = settings.aoData;
8493
		var rows = _selector_row_indexes( settings, opts );
8494
		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8495
		var allCells = $( [].concat.apply([], cells) );
8496
		var row;
8497
		var columns = settings.aoColumns.length;
8498
		var a, i, ien, j, o, host;
8499
 
8500
		var run = function ( s ) {
8501
			var fnSelector = typeof s === 'function';
8502
 
8503
			if ( s === null || s === undefined || fnSelector ) {
8504
				// All cells and function selectors
8505
				a = [];
8506
 
8507
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8508
					row = rows[i];
8509
 
8510
					for ( j=0 ; j<columns ; j++ ) {
8511
						o = {
8512
							row: row,
8513
							column: j
8514
						};
8515
 
8516
						if ( fnSelector ) {
8517
							// Selector - function
8518
							host = data[ row ];
8519
 
8520
							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8521
								a.push( o );
8522
							}
8523
						}
8524
						else {
8525
							// Selector - all
8526
							a.push( o );
8527
						}
8528
					}
8529
				}
8530
 
8531
				return a;
8532
			}
8533
 
8534
			// Selector - index
8535
			if ( $.isPlainObject( s ) ) {
8536
				return [s];
8537
			}
8538
 
8539
			// Selector - jQuery filtered cells
8540
			return allCells
8541
				.filter( s )
8542
				.map( function (i, el) {
8543
					if ( el.parentNode ) {
8544
						row = el.parentNode._DT_RowIndex;
8545
					}
8546
					else {
8547
						// If no parent node, then the cell is hidden and we'll need
8548
						// to traverse the array to find it
8549
						for ( i=0, ien=data.length ; i<ien ; i++ ) {
8550
							if ( $.inArray( el, data[i].anCells ) !== -1 ) {
8551
								row = i;
8552
								break;
8553
							}
8554
						}
8555
					}
8556
 
8557
					return {
8558
						row: row,
8559
						column: $.inArray( el, data[ row ].anCells )
8560
					};
8561
				} )
8562
				.toArray();
8563
		};
8564
 
8565
		return _selector_run( 'cell', selector, run, settings, opts );
8566
	};
8567
 
8568
 
8569
 
8570
 
8571
	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8572
		// Argument shifting
8573
		if ( $.isPlainObject( rowSelector ) ) {
8574
			// Indexes
8575
			if ( rowSelector.row === undefined ) {
8576
				// Selector options in first parameter
8577
				opts = rowSelector;
8578
				rowSelector = null;
8579
			}
8580
			else {
8581
				// Cell index objects in first parameter
8582
				opts = columnSelector;
8583
				columnSelector = null;
8584
			}
8585
		}
8586
		if ( $.isPlainObject( columnSelector ) ) {
8587
			opts = columnSelector;
8588
			columnSelector = null;
8589
		}
8590
 
8591
		// Cell selector
8592
		if ( columnSelector === null || columnSelector === undefined ) {
8593
			return this.iterator( 'table', function ( settings ) {
8594
				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8595
			} );
8596
		}
8597
 
8598
		// Row + column selector
8599
		var columns = this.columns( columnSelector, opts );
8600
		var rows = this.rows( rowSelector, opts );
8601
		var a, i, ien, j, jen;
8602
 
8603
		var cells = this.iterator( 'table', function ( settings, idx ) {
8604
			a = [];
8605
 
8606
			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8607
				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8608
					a.push( {
8609
						row:    rows[idx][i],
8610
						column: columns[idx][j]
8611
					} );
8612
				}
8613
			}
8614
 
8615
			return a;
8616
		}, 1 );
8617
 
8618
		$.extend( cells.selector, {
8619
			cols: columnSelector,
8620
			rows: rowSelector,
8621
			opts: opts
8622
		} );
8623
 
8624
		return cells;
8625
	} );
8626
 
8627
 
8628
	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8629
		return this.iterator( 'cell', function ( settings, row, column ) {
8630
			var cells = settings.aoData[ row ].anCells;
8631
			return cells ?
8632
				cells[ column ] :
8633
				undefined;
8634
		}, 1 );
8635
	} );
8636
 
8637
 
8638
	_api_register( 'cells().data()', function () {
8639
		return this.iterator( 'cell', function ( settings, row, column ) {
8640
			return _fnGetCellData( settings, row, column );
8641
		}, 1 );
8642
	} );
8643
 
8644
 
8645
	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8646
		type = type === 'search' ? '_aFilterData' : '_aSortData';
8647
 
8648
		return this.iterator( 'cell', function ( settings, row, column ) {
8649
			return settings.aoData[ row ][ type ][ column ];
8650
		}, 1 );
8651
	} );
8652
 
8653
 
8654
	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8655
		return this.iterator( 'cell', function ( settings, row, column ) {
8656
			return _fnGetCellData( settings, row, column, type );
8657
		}, 1 );
8658
	} );
8659
 
8660
 
8661
	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8662
		return this.iterator( 'cell', function ( settings, row, column ) {
8663
			return {
8664
				row: row,
8665
				column: column,
8666
				columnVisible: _fnColumnIndexToVisible( settings, column )
8667
			};
8668
		}, 1 );
8669
	} );
8670
 
8671
 
8672
	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8673
		return this.iterator( 'cell', function ( settings, row, column ) {
8674
			_fnInvalidate( settings, row, src, column );
8675
		} );
8676
	} );
8677
 
8678
 
8679
 
8680
	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8681
		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8682
	} );
8683
 
8684
 
8685
	_api_register( 'cell().data()', function ( data ) {
8686
		var ctx = this.context;
8687
		var cell = this[0];
8688
 
8689
		if ( data === undefined ) {
8690
			// Get
8691
			return ctx.length && cell.length ?
8692
				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8693
				undefined;
8694
		}
8695
 
8696
		// Set
8697
		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8698
		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8699
 
8700
		return this;
8701
	} );
8702
 
8703
 
8704
 
8705
	/**
8706
	 * Get current ordering (sorting) that has been applied to the table.
8707
	 *
8708
	 * @returns {array} 2D array containing the sorting information for the first
8709
	 *   table in the current context. Each element in the parent array represents
8710
	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8711
	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8712
	 *   the column index that the sorting condition applies to, the second is the
8713
	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8714
	 *   index of the sorting order from the `column.sorting` initialisation array.
8715
	 *//**
8716
	 * Set the ordering for the table.
8717
	 *
8718
	 * @param {integer} order Column index to sort upon.
8719
	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8720
	 * @returns {DataTables.Api} this
8721
	 *//**
8722
	 * Set the ordering for the table.
8723
	 *
8724
	 * @param {array} order 1D array of sorting information to be applied.
8725
	 * @param {array} [...] Optional additional sorting conditions
8726
	 * @returns {DataTables.Api} this
8727
	 *//**
8728
	 * Set the ordering for the table.
8729
	 *
8730
	 * @param {array} order 2D array of sorting information to be applied.
8731
	 * @returns {DataTables.Api} this
8732
	 */
8733
	_api_register( 'order()', function ( order, dir ) {
8734
		var ctx = this.context;
8735
 
8736
		if ( order === undefined ) {
8737
			// get
8738
			return ctx.length !== 0 ?
8739
				ctx[0].aaSorting :
8740
				undefined;
8741
		}
8742
 
8743
		// set
8744
		if ( typeof order === 'number' ) {
8745
			// Simple column / direction passed in
8746
			order = [ [ order, dir ] ];
8747
		}
8748
		else if ( ! $.isArray( order[0] ) ) {
8749
			// Arguments passed in (list of 1D arrays)
8750
			order = Array.prototype.slice.call( arguments );
8751
		}
8752
		// otherwise a 2D array was passed in
8753
 
8754
		return this.iterator( 'table', function ( settings ) {
8755
			settings.aaSorting = order.slice();
8756
		} );
8757
	} );
8758
 
8759
 
8760
	/**
8761
	 * Attach a sort listener to an element for a given column
8762
	 *
8763
	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8764
	 *   listener to. This can take the form of a single DOM node, a jQuery
8765
	 *   collection of nodes or a jQuery selector which will identify the node(s).
8766
	 * @param {integer} column the column that a click on this node will sort on
8767
	 * @param {function} [callback] callback function when sort is run
8768
	 * @returns {DataTables.Api} this
8769
	 */
8770
	_api_register( 'order.listener()', function ( node, column, callback ) {
8771
		return this.iterator( 'table', function ( settings ) {
8772
			_fnSortAttachListener( settings, node, column, callback );
8773
		} );
8774
	} );
8775
 
8776
 
8777
	// Order by the selected column(s)
8778
	_api_register( [
8779
		'columns().order()',
8780
		'column().order()'
8781
	], function ( dir ) {
8782
		var that = this;
8783
 
8784
		return this.iterator( 'table', function ( settings, i ) {
8785
			var sort = [];
8786
 
8787
			$.each( that[i], function (j, col) {
8788
				sort.push( [ col, dir ] );
8789
			} );
8790
 
8791
			settings.aaSorting = sort;
8792
		} );
8793
	} );
8794
 
8795
 
8796
 
8797
	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8798
		var ctx = this.context;
8799
 
8800
		if ( input === undefined ) {
8801
			// get
8802
			return ctx.length !== 0 ?
8803
				ctx[0].oPreviousSearch.sSearch :
8804
				undefined;
8805
		}
8806
 
8807
		// set
8808
		return this.iterator( 'table', function ( settings ) {
8809
			if ( ! settings.oFeatures.bFilter ) {
8810
				return;
8811
			}
8812
 
8813
			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8814
				"sSearch": input+"",
8815
				"bRegex":  regex === null ? false : regex,
8816
				"bSmart":  smart === null ? true  : smart,
8817
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
8818
			} ), 1 );
8819
		} );
8820
	} );
8821
 
8822
 
8823
	_api_registerPlural(
8824
		'columns().search()',
8825
		'column().search()',
8826
		function ( input, regex, smart, caseInsen ) {
8827
			return this.iterator( 'column', function ( settings, column ) {
8828
				var preSearch = settings.aoPreSearchCols;
8829
 
8830
				if ( input === undefined ) {
8831
					// get
8832
					return preSearch[ column ].sSearch;
8833
				}
8834
 
8835
				// set
8836
				if ( ! settings.oFeatures.bFilter ) {
8837
					return;
8838
				}
8839
 
8840
				$.extend( preSearch[ column ], {
8841
					"sSearch": input+"",
8842
					"bRegex":  regex === null ? false : regex,
8843
					"bSmart":  smart === null ? true  : smart,
8844
					"bCaseInsensitive": caseInsen === null ? true : caseInsen
8845
				} );
8846
 
8847
				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8848
			} );
8849
		}
8850
	);
8851
 
8852
	/*
8853
	 * State API methods
8854
	 */
8855
 
8856
	_api_register( 'state()', function () {
8857
		return this.context.length ?
8858
			this.context[0].oSavedState :
8859
			null;
8860
	} );
8861
 
8862
 
8863
	_api_register( 'state.clear()', function () {
8864
		return this.iterator( 'table', function ( settings ) {
8865
			// Save an empty object
8866
			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
8867
		} );
8868
	} );
8869
 
8870
 
8871
	_api_register( 'state.loaded()', function () {
8872
		return this.context.length ?
8873
			this.context[0].oLoadedState :
8874
			null;
8875
	} );
8876
 
8877
 
8878
	_api_register( 'state.save()', function () {
8879
		return this.iterator( 'table', function ( settings ) {
8880
			_fnSaveState( settings );
8881
		} );
8882
	} );
8883
 
8884
 
8885
 
8886
	/**
8887
	 * Provide a common method for plug-ins to check the version of DataTables being
8888
	 * used, in order to ensure compatibility.
8889
	 *
8890
	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
8891
	 *    Note that the formats "X" and "X.Y" are also acceptable.
8892
	 *  @returns {boolean} true if this version of DataTables is greater or equal to
8893
	 *    the required version, or false if this version of DataTales is not
8894
	 *    suitable
8895
	 *  @static
8896
	 *  @dtopt API-Static
8897
	 *
8898
	 *  @example
8899
	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8900
	 */
8901
	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
8902
	{
8903
		var aThis = DataTable.version.split('.');
8904
		var aThat = version.split('.');
8905
		var iThis, iThat;
8906
 
8907
		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
8908
			iThis = parseInt( aThis[i], 10 ) || 0;
8909
			iThat = parseInt( aThat[i], 10 ) || 0;
8910
 
8911
			// Parts are the same, keep comparing
8912
			if (iThis === iThat) {
8913
				continue;
8914
			}
8915
 
8916
			// Parts are different, return immediately
8917
			return iThis > iThat;
8918
		}
8919
 
8920
		return true;
8921
	};
8922
 
8923
 
8924
	/**
8925
	 * Check if a `<table>` node is a DataTable table already or not.
8926
	 *
8927
	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
8928
	 *      selector for the table to test. Note that if more than more than one
8929
	 *      table is passed on, only the first will be checked
8930
	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
8931
	 *  @static
8932
	 *  @dtopt API-Static
8933
	 *
8934
	 *  @example
8935
	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8936
	 *      $('#example').dataTable();
8937
	 *    }
8938
	 */
8939
	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
8940
	{
8941
		var t = $(table).get(0);
8942
		var is = false;
8943
 
8944
		$.each( DataTable.settings, function (i, o) {
8945
			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
8946
			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
8947
 
8948
			if ( o.nTable === t || head === t || foot === t ) {
8949
				is = true;
8950
			}
8951
		} );
8952
 
8953
		return is;
8954
	};
8955
 
8956
 
8957
	/**
8958
	 * Get all DataTable tables that have been initialised - optionally you can
8959
	 * select to get only currently visible tables.
8960
	 *
8961
	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
8962
	 *    or visible tables only.
8963
	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
8964
	 *    DataTables
8965
	 *  @static
8966
	 *  @dtopt API-Static
8967
	 *
8968
	 *  @example
8969
	 *    $.each( $.fn.dataTable.tables(true), function () {
8970
	 *      $(table).DataTable().columns.adjust();
8971
	 *    } );
8972
	 */
8973
	DataTable.tables = DataTable.fnTables = function ( visible )
8974
	{
8975
		var api = false;
8976
 
8977
		if ( $.isPlainObject( visible ) ) {
8978
			api = visible.api;
8979
			visible = visible.visible;
8980
		}
8981
 
8982
		var a = $.map( DataTable.settings, function (o) {
8983
			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8984
				return o.nTable;
8985
			}
8986
		} );
8987
 
8988
		return api ?
8989
			new _Api( a ) :
8990
			a;
8991
	};
8992
 
8993
 
8994
	/**
8995
	 * DataTables utility methods
8996
	 *
8997
	 * This namespace provides helper methods that DataTables uses internally to
8998
	 * create a DataTable, but which are not exclusively used only for DataTables.
8999
	 * These methods can be used by extension authors to save the duplication of
9000
	 * code.
9001
	 *
9002
	 *  @namespace
9003
	 */
9004
	DataTable.util = {
9005
		/**
9006
		 * Throttle the calls to a function. Arguments and context are maintained
9007
		 * for the throttled function.
9008
		 *
9009
		 * @param {function} fn Function to be called
9010
		 * @param {integer} freq Call frequency in mS
9011
		 * @return {function} Wrapped function
9012
		 */
9013
		throttle: _fnThrottle,
9014
 
9015
 
9016
		/**
9017
		 * Escape a string such that it can be used in a regular expression
9018
		 *
9019
		 *  @param {string} sVal string to escape
9020
		 *  @returns {string} escaped string
9021
		 */
9022
		escapeRegex: _fnEscapeRegex
9023
	};
9024
 
9025
 
9026
	/**
9027
	 * Convert from camel case parameters to Hungarian notation. This is made public
9028
	 * for the extensions to provide the same ability as DataTables core to accept
9029
	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9030
	 * parameters.
9031
	 *
9032
	 *  @param {object} src The model object which holds all parameters that can be
9033
	 *    mapped.
9034
	 *  @param {object} user The object to convert from camel case to Hungarian.
9035
	 *  @param {boolean} force When set to `true`, properties which already have a
9036
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9037
	 *    won't be.
9038
	 */
9039
	DataTable.camelToHungarian = _fnCamelToHungarian;
9040
 
9041
 
9042
 
9043
	/**
9044
	 *
9045
	 */
9046
	_api_register( '$()', function ( selector, opts ) {
9047
		var
9048
			rows   = this.rows( opts ).nodes(), // Get all rows
9049
			jqRows = $(rows);
9050
 
9051
		return $( [].concat(
9052
			jqRows.filter( selector ).toArray(),
9053
			jqRows.find( selector ).toArray()
9054
		) );
9055
	} );
9056
 
9057
 
9058
	// jQuery functions to operate on the tables
9059
	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9060
		_api_register( key+'()', function ( /* event, handler */ ) {
9061
			var args = Array.prototype.slice.call(arguments);
9062
 
9063
			// Add the `dt` namespace automatically if it isn't already present
9064
			if ( ! args[0].match(/\.dt\b/) ) {
9065
				args[0] += '.dt';
9066
			}
9067
 
9068
			var inst = $( this.tables().nodes() );
9069
			inst[key].apply( inst, args );
9070
			return this;
9071
		} );
9072
	} );
9073
 
9074
 
9075
	_api_register( 'clear()', function () {
9076
		return this.iterator( 'table', function ( settings ) {
9077
			_fnClearTable( settings );
9078
		} );
9079
	} );
9080
 
9081
 
9082
	_api_register( 'settings()', function () {
9083
		return new _Api( this.context, this.context );
9084
	} );
9085
 
9086
 
9087
	_api_register( 'init()', function () {
9088
		var ctx = this.context;
9089
		return ctx.length ? ctx[0].oInit : null;
9090
	} );
9091
 
9092
 
9093
	_api_register( 'data()', function () {
9094
		return this.iterator( 'table', function ( settings ) {
9095
			return _pluck( settings.aoData, '_aData' );
9096
		} ).flatten();
9097
	} );
9098
 
9099
 
9100
	_api_register( 'destroy()', function ( remove ) {
9101
		remove = remove || false;
9102
 
9103
		return this.iterator( 'table', function ( settings ) {
9104
			var orig      = settings.nTableWrapper.parentNode;
9105
			var classes   = settings.oClasses;
9106
			var table     = settings.nTable;
9107
			var tbody     = settings.nTBody;
9108
			var thead     = settings.nTHead;
9109
			var tfoot     = settings.nTFoot;
9110
			var jqTable   = $(table);
9111
			var jqTbody   = $(tbody);
9112
			var jqWrapper = $(settings.nTableWrapper);
9113
			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9114
			var i, ien;
9115
 
9116
			// Flag to note that the table is currently being destroyed - no action
9117
			// should be taken
9118
			settings.bDestroying = true;
9119
 
9120
			// Fire off the destroy callbacks for plug-ins etc
9121
			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9122
 
9123
			// If not being removed from the document, make all columns visible
9124
			if ( ! remove ) {
9125
				new _Api( settings ).columns().visible( true );
9126
			}
9127
 
9128
			// Blitz all `DT` namespaced events (these are internal events, the
9129
			// lowercase, `dt` events are user subscribed and they are responsible
9130
			// for removing them
9131
			jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
9132
			$(window).unbind('.DT-'+settings.sInstance);
9133
 
9134
			// When scrolling we had to break the table up - restore it
9135
			if ( table != thead.parentNode ) {
9136
				jqTable.children('thead').detach();
9137
				jqTable.append( thead );
9138
			}
9139
 
9140
			if ( tfoot && table != tfoot.parentNode ) {
9141
				jqTable.children('tfoot').detach();
9142
				jqTable.append( tfoot );
9143
			}
9144
 
9145
			settings.aaSorting = [];
9146
			settings.aaSortingFixed = [];
9147
			_fnSortingClasses( settings );
9148
 
9149
			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9150
 
9151
			$('th, td', thead).removeClass( classes.sSortable+' '+
9152
				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9153
			);
9154
 
9155
			if ( settings.bJUI ) {
9156
				$('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
9157
				$('th, td', thead).each( function () {
9158
					var wrapper = $('div.'+classes.sSortJUIWrapper, this);
9159
					$(this).append( wrapper.contents() );
9160
					wrapper.detach();
9161
				} );
9162
			}
9163
 
9164
			// Add the TR elements back into the table in their original order
9165
			jqTbody.children().detach();
9166
			jqTbody.append( rows );
9167
 
9168
			// Remove the DataTables generated nodes, events and classes
9169
			var removedMethod = remove ? 'remove' : 'detach';
9170
			jqTable[ removedMethod ]();
9171
			jqWrapper[ removedMethod ]();
9172
 
9173
			// If we need to reattach the table to the document
9174
			if ( ! remove && orig ) {
9175
				// insertBefore acts like appendChild if !arg[1]
9176
				orig.insertBefore( table, settings.nTableReinsertBefore );
9177
 
9178
				// Restore the width of the original table - was read from the style property,
9179
				// so we can restore directly to that
9180
				jqTable
9181
					.css( 'width', settings.sDestroyWidth )
9182
					.removeClass( classes.sTable );
9183
 
9184
				// If the were originally stripe classes - then we add them back here.
9185
				// Note this is not fool proof (for example if not all rows had stripe
9186
				// classes - but it's a good effort without getting carried away
9187
				ien = settings.asDestroyStripes.length;
9188
 
9189
				if ( ien ) {
9190
					jqTbody.children().each( function (i) {
9191
						$(this).addClass( settings.asDestroyStripes[i % ien] );
9192
					} );
9193
				}
9194
			}
9195
 
9196
			/* Remove the settings object from the settings array */
9197
			var idx = $.inArray( settings, DataTable.settings );
9198
			if ( idx !== -1 ) {
9199
				DataTable.settings.splice( idx, 1 );
9200
			}
9201
		} );
9202
	} );
9203
 
9204
 
9205
	// Add the `every()` method for rows, columns and cells in a compact form
9206
	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9207
		_api_register( type+'s().every()', function ( fn ) {
9208
			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9209
				// Rows and columns:
9210
				//  arg1 - index
9211
				//  arg2 - table counter
9212
				//  arg3 - loop counter
9213
				//  arg4 - undefined
9214
				// Cells:
9215
				//  arg1 - row index
9216
				//  arg2 - column index
9217
				//  arg3 - table counter
9218
				//  arg4 - loop counter
9219
				fn.call(
9220
					new _Api( settings )[ type ]( arg1, type==='cell' ? arg2 : undefined ),
9221
					arg1, arg2, arg3, arg4
9222
				);
9223
			} );
9224
		} );
9225
	} );
9226
 
9227
 
9228
	// i18n method for extensions to be able to use the language object from the
9229
	// DataTable
9230
	_api_register( 'i18n()', function ( token, def, plural ) {
9231
		var ctx = this.context[0];
9232
		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9233
 
9234
		if ( resolved === undefined ) {
9235
			resolved = def;
9236
		}
9237
 
9238
		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9239
			resolved = resolved[ plural ] !== undefined ?
9240
				resolved[ plural ] :
9241
				resolved._;
9242
		}
9243
 
9244
		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9245
	} );
9246
 
9247
	/**
9248
	 * Version string for plug-ins to check compatibility. Allowed format is
9249
	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9250
	 * only for non-release builds. See http://semver.org/ for more information.
9251
	 *  @member
9252
	 *  @type string
9253
	 *  @default Version number
9254
	 */
9255
	DataTable.version = "1.10.9";
9256
 
9257
	/**
9258
	 * Private data store, containing all of the settings objects that are
9259
	 * created for the tables on a given page.
9260
	 *
9261
	 * Note that the `DataTable.settings` object is aliased to
9262
	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9263
	 * manipulated, or `jQuery.fn.dataTable.settings`.
9264
	 *  @member
9265
	 *  @type array
9266
	 *  @default []
9267
	 *  @private
9268
	 */
9269
	DataTable.settings = [];
9270
 
9271
	/**
9272
	 * Object models container, for the various models that DataTables has
9273
	 * available to it. These models define the objects that are used to hold
9274
	 * the active state and configuration of the table.
9275
	 *  @namespace
9276
	 */
9277
	DataTable.models = {};
9278
 
9279
 
9280
 
9281
	/**
9282
	 * Template object for the way in which DataTables holds information about
9283
	 * search information for the global filter and individual column filters.
9284
	 *  @namespace
9285
	 */
9286
	DataTable.models.oSearch = {
9287
		/**
9288
		 * Flag to indicate if the filtering should be case insensitive or not
9289
		 *  @type boolean
9290
		 *  @default true
9291
		 */
9292
		"bCaseInsensitive": true,
9293
 
9294
		/**
9295
		 * Applied search term
9296
		 *  @type string
9297
		 *  @default <i>Empty string</i>
9298
		 */
9299
		"sSearch": "",
9300
 
9301
		/**
9302
		 * Flag to indicate if the search term should be interpreted as a
9303
		 * regular expression (true) or not (false) and therefore and special
9304
		 * regex characters escaped.
9305
		 *  @type boolean
9306
		 *  @default false
9307
		 */
9308
		"bRegex": false,
9309
 
9310
		/**
9311
		 * Flag to indicate if DataTables is to use its smart filtering or not.
9312
		 *  @type boolean
9313
		 *  @default true
9314
		 */
9315
		"bSmart": true
9316
	};
9317
 
9318
 
9319
 
9320
 
9321
	/**
9322
	 * Template object for the way in which DataTables holds information about
9323
	 * each individual row. This is the object format used for the settings
9324
	 * aoData array.
9325
	 *  @namespace
9326
	 */
9327
	DataTable.models.oRow = {
9328
		/**
9329
		 * TR element for the row
9330
		 *  @type node
9331
		 *  @default null
9332
		 */
9333
		"nTr": null,
9334
 
9335
		/**
9336
		 * Array of TD elements for each row. This is null until the row has been
9337
		 * created.
9338
		 *  @type array nodes
9339
		 *  @default []
9340
		 */
9341
		"anCells": null,
9342
 
9343
		/**
9344
		 * Data object from the original data source for the row. This is either
9345
		 * an array if using the traditional form of DataTables, or an object if
9346
		 * using mData options. The exact type will depend on the passed in
9347
		 * data from the data source, or will be an array if using DOM a data
9348
		 * source.
9349
		 *  @type array|object
9350
		 *  @default []
9351
		 */
9352
		"_aData": [],
9353
 
9354
		/**
9355
		 * Sorting data cache - this array is ostensibly the same length as the
9356
		 * number of columns (although each index is generated only as it is
9357
		 * needed), and holds the data that is used for sorting each column in the
9358
		 * row. We do this cache generation at the start of the sort in order that
9359
		 * the formatting of the sort data need be done only once for each cell
9360
		 * per sort. This array should not be read from or written to by anything
9361
		 * other than the master sorting methods.
9362
		 *  @type array
9363
		 *  @default null
9364
		 *  @private
9365
		 */
9366
		"_aSortData": null,
9367
 
9368
		/**
9369
		 * Per cell filtering data cache. As per the sort data cache, used to
9370
		 * increase the performance of the filtering in DataTables
9371
		 *  @type array
9372
		 *  @default null
9373
		 *  @private
9374
		 */
9375
		"_aFilterData": null,
9376
 
9377
		/**
9378
		 * Filtering data cache. This is the same as the cell filtering cache, but
9379
		 * in this case a string rather than an array. This is easily computed with
9380
		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9381
		 * needed on every search (memory traded for performance)
9382
		 *  @type array
9383
		 *  @default null
9384
		 *  @private
9385
		 */
9386
		"_sFilterRow": null,
9387
 
9388
		/**
9389
		 * Cache of the class name that DataTables has applied to the row, so we
9390
		 * can quickly look at this variable rather than needing to do a DOM check
9391
		 * on className for the nTr property.
9392
		 *  @type string
9393
		 *  @default <i>Empty string</i>
9394
		 *  @private
9395
		 */
9396
		"_sRowStripe": "",
9397
 
9398
		/**
9399
		 * Denote if the original data source was from the DOM, or the data source
9400
		 * object. This is used for invalidating data, so DataTables can
9401
		 * automatically read data from the original source, unless uninstructed
9402
		 * otherwise.
9403
		 *  @type string
9404
		 *  @default null
9405
		 *  @private
9406
		 */
9407
		"src": null,
9408
 
9409
		/**
9410
		 * Index in the aoData array. This saves an indexOf lookup when we have the
9411
		 * object, but want to know the index
9412
		 *  @type integer
9413
		 *  @default -1
9414
		 *  @private
9415
		 */
9416
		"idx": -1
9417
	};
9418
 
9419
 
9420
	/**
9421
	 * Template object for the column information object in DataTables. This object
9422
	 * is held in the settings aoColumns array and contains all the information that
9423
	 * DataTables needs about each individual column.
9424
	 *
9425
	 * Note that this object is related to {@link DataTable.defaults.column}
9426
	 * but this one is the internal data store for DataTables's cache of columns.
9427
	 * It should NOT be manipulated outside of DataTables. Any configuration should
9428
	 * be done through the initialisation options.
9429
	 *  @namespace
9430
	 */
9431
	DataTable.models.oColumn = {
9432
		/**
9433
		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9434
		 * is faster to just hold it as a variable
9435
		 *  @type integer
9436
		 *  @default null
9437
		 */
9438
		"idx": null,
9439
 
9440
		/**
9441
		 * A list of the columns that sorting should occur on when this column
9442
		 * is sorted. That this property is an array allows multi-column sorting
9443
		 * to be defined for a column (for example first name / last name columns
9444
		 * would benefit from this). The values are integers pointing to the
9445
		 * columns to be sorted on (typically it will be a single integer pointing
9446
		 * at itself, but that doesn't need to be the case).
9447
		 *  @type array
9448
		 */
9449
		"aDataSort": null,
9450
 
9451
		/**
9452
		 * Define the sorting directions that are applied to the column, in sequence
9453
		 * as the column is repeatedly sorted upon - i.e. the first value is used
9454
		 * as the sorting direction when the column if first sorted (clicked on).
9455
		 * Sort it again (click again) and it will move on to the next index.
9456
		 * Repeat until loop.
9457
		 *  @type array
9458
		 */
9459
		"asSorting": null,
9460
 
9461
		/**
9462
		 * Flag to indicate if the column is searchable, and thus should be included
9463
		 * in the filtering or not.
9464
		 *  @type boolean
9465
		 */
9466
		"bSearchable": null,
9467
 
9468
		/**
9469
		 * Flag to indicate if the column is sortable or not.
9470
		 *  @type boolean
9471
		 */
9472
		"bSortable": null,
9473
 
9474
		/**
9475
		 * Flag to indicate if the column is currently visible in the table or not
9476
		 *  @type boolean
9477
		 */
9478
		"bVisible": null,
9479
 
9480
		/**
9481
		 * Store for manual type assignment using the `column.type` option. This
9482
		 * is held in store so we can manipulate the column's `sType` property.
9483
		 *  @type string
9484
		 *  @default null
9485
		 *  @private
9486
		 */
9487
		"_sManualType": null,
9488
 
9489
		/**
9490
		 * Flag to indicate if HTML5 data attributes should be used as the data
9491
		 * source for filtering or sorting. True is either are.
9492
		 *  @type boolean
9493
		 *  @default false
9494
		 *  @private
9495
		 */
9496
		"_bAttrSrc": false,
9497
 
9498
		/**
9499
		 * Developer definable function that is called whenever a cell is created (Ajax source,
9500
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9501
		 * allowing you to modify the DOM element (add background colour for example) when the
9502
		 * element is available.
9503
		 *  @type function
9504
		 *  @param {element} nTd The TD node that has been created
9505
		 *  @param {*} sData The Data for the cell
9506
		 *  @param {array|object} oData The data for the whole row
9507
		 *  @param {int} iRow The row index for the aoData data store
9508
		 *  @default null
9509
		 */
9510
		"fnCreatedCell": null,
9511
 
9512
		/**
9513
		 * Function to get data from a cell in a column. You should <b>never</b>
9514
		 * access data directly through _aData internally in DataTables - always use
9515
		 * the method attached to this property. It allows mData to function as
9516
		 * required. This function is automatically assigned by the column
9517
		 * initialisation method
9518
		 *  @type function
9519
		 *  @param {array|object} oData The data array/object for the array
9520
		 *    (i.e. aoData[]._aData)
9521
		 *  @param {string} sSpecific The specific data type you want to get -
9522
		 *    'display', 'type' 'filter' 'sort'
9523
		 *  @returns {*} The data for the cell from the given row's data
9524
		 *  @default null
9525
		 */
9526
		"fnGetData": null,
9527
 
9528
		/**
9529
		 * Function to set data for a cell in the column. You should <b>never</b>
9530
		 * set the data directly to _aData internally in DataTables - always use
9531
		 * this method. It allows mData to function as required. This function
9532
		 * is automatically assigned by the column initialisation method
9533
		 *  @type function
9534
		 *  @param {array|object} oData The data array/object for the array
9535
		 *    (i.e. aoData[]._aData)
9536
		 *  @param {*} sValue Value to set
9537
		 *  @default null
9538
		 */
9539
		"fnSetData": null,
9540
 
9541
		/**
9542
		 * Property to read the value for the cells in the column from the data
9543
		 * source array / object. If null, then the default content is used, if a
9544
		 * function is given then the return from the function is used.
9545
		 *  @type function|int|string|null
9546
		 *  @default null
9547
		 */
9548
		"mData": null,
9549
 
9550
		/**
9551
		 * Partner property to mData which is used (only when defined) to get
9552
		 * the data - i.e. it is basically the same as mData, but without the
9553
		 * 'set' option, and also the data fed to it is the result from mData.
9554
		 * This is the rendering method to match the data method of mData.
9555
		 *  @type function|int|string|null
9556
		 *  @default null
9557
		 */
9558
		"mRender": null,
9559
 
9560
		/**
9561
		 * Unique header TH/TD element for this column - this is what the sorting
9562
		 * listener is attached to (if sorting is enabled.)
9563
		 *  @type node
9564
		 *  @default null
9565
		 */
9566
		"nTh": null,
9567
 
9568
		/**
9569
		 * Unique footer TH/TD element for this column (if there is one). Not used
9570
		 * in DataTables as such, but can be used for plug-ins to reference the
9571
		 * footer for each column.
9572
		 *  @type node
9573
		 *  @default null
9574
		 */
9575
		"nTf": null,
9576
 
9577
		/**
9578
		 * The class to apply to all TD elements in the table's TBODY for the column
9579
		 *  @type string
9580
		 *  @default null
9581
		 */
9582
		"sClass": null,
9583
 
9584
		/**
9585
		 * When DataTables calculates the column widths to assign to each column,
9586
		 * it finds the longest string in each column and then constructs a
9587
		 * temporary table and reads the widths from that. The problem with this
9588
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9589
		 * string - thus the calculation can go wrong (doing it properly and putting
9590
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9591
		 * a "work around" we provide this option. It will append its value to the
9592
		 * text that is found to be the longest string for the column - i.e. padding.
9593
		 *  @type string
9594
		 */
9595
		"sContentPadding": null,
9596
 
9597
		/**
9598
		 * Allows a default value to be given for a column's data, and will be used
9599
		 * whenever a null data source is encountered (this can be because mData
9600
		 * is set to null, or because the data source itself is null).
9601
		 *  @type string
9602
		 *  @default null
9603
		 */
9604
		"sDefaultContent": null,
9605
 
9606
		/**
9607
		 * Name for the column, allowing reference to the column by name as well as
9608
		 * by index (needs a lookup to work by name).
9609
		 *  @type string
9610
		 */
9611
		"sName": null,
9612
 
9613
		/**
9614
		 * Custom sorting data type - defines which of the available plug-ins in
9615
		 * afnSortData the custom sorting will use - if any is defined.
9616
		 *  @type string
9617
		 *  @default std
9618
		 */
9619
		"sSortDataType": 'std',
9620
 
9621
		/**
9622
		 * Class to be applied to the header element when sorting on this column
9623
		 *  @type string
9624
		 *  @default null
9625
		 */
9626
		"sSortingClass": null,
9627
 
9628
		/**
9629
		 * Class to be applied to the header element when sorting on this column -
9630
		 * when jQuery UI theming is used.
9631
		 *  @type string
9632
		 *  @default null
9633
		 */
9634
		"sSortingClassJUI": null,
9635
 
9636
		/**
9637
		 * Title of the column - what is seen in the TH element (nTh).
9638
		 *  @type string
9639
		 */
9640
		"sTitle": null,
9641
 
9642
		/**
9643
		 * Column sorting and filtering type
9644
		 *  @type string
9645
		 *  @default null
9646
		 */
9647
		"sType": null,
9648
 
9649
		/**
9650
		 * Width of the column
9651
		 *  @type string
9652
		 *  @default null
9653
		 */
9654
		"sWidth": null,
9655
 
9656
		/**
9657
		 * Width of the column when it was first "encountered"
9658
		 *  @type string
9659
		 *  @default null
9660
		 */
9661
		"sWidthOrig": null
9662
	};
9663
 
9664
 
9665
	/*
9666
	 * Developer note: The properties of the object below are given in Hungarian
9667
	 * notation, that was used as the interface for DataTables prior to v1.10, however
9668
	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9669
	 * breaking backwards compatibility utterly with this change, the Hungarian
9670
	 * version is still, internally the primary interface, but is is not documented
9671
	 * - hence the @name tags in each doc comment. This allows a Javascript function
9672
	 * to create a map from Hungarian notation to camel case (going the other direction
9673
	 * would require each property to be listed, which would at around 3K to the size
9674
	 * of DataTables, while this method is about a 0.5K hit.
9675
	 *
9676
	 * Ultimately this does pave the way for Hungarian notation to be dropped
9677
	 * completely, but that is a massive amount of work and will break current
9678
	 * installs (therefore is on-hold until v2).
9679
	 */
9680
 
9681
	/**
9682
	 * Initialisation options that can be given to DataTables at initialisation
9683
	 * time.
9684
	 *  @namespace
9685
	 */
9686
	DataTable.defaults = {
9687
		/**
9688
		 * An array of data to use for the table, passed in at initialisation which
9689
		 * will be used in preference to any data which is already in the DOM. This is
9690
		 * particularly useful for constructing tables purely in Javascript, for
9691
		 * example with a custom Ajax call.
9692
		 *  @type array
9693
		 *  @default null
9694
		 *
9695
		 *  @dtopt Option
9696
		 *  @name DataTable.defaults.data
9697
		 *
9698
		 *  @example
9699
		 *    // Using a 2D array data source
9700
		 *    $(document).ready( function () {
9701
		 *      $('#example').dataTable( {
9702
		 *        "data": [
9703
		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9704
		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9705
		 *        ],
9706
		 *        "columns": [
9707
		 *          { "title": "Engine" },
9708
		 *          { "title": "Browser" },
9709
		 *          { "title": "Platform" },
9710
		 *          { "title": "Version" },
9711
		 *          { "title": "Grade" }
9712
		 *        ]
9713
		 *      } );
9714
		 *    } );
9715
		 *
9716
		 *  @example
9717
		 *    // Using an array of objects as a data source (`data`)
9718
		 *    $(document).ready( function () {
9719
		 *      $('#example').dataTable( {
9720
		 *        "data": [
9721
		 *          {
9722
		 *            "engine":   "Trident",
9723
		 *            "browser":  "Internet Explorer 4.0",
9724
		 *            "platform": "Win 95+",
9725
		 *            "version":  4,
9726
		 *            "grade":    "X"
9727
		 *          },
9728
		 *          {
9729
		 *            "engine":   "Trident",
9730
		 *            "browser":  "Internet Explorer 5.0",
9731
		 *            "platform": "Win 95+",
9732
		 *            "version":  5,
9733
		 *            "grade":    "C"
9734
		 *          }
9735
		 *        ],
9736
		 *        "columns": [
9737
		 *          { "title": "Engine",   "data": "engine" },
9738
		 *          { "title": "Browser",  "data": "browser" },
9739
		 *          { "title": "Platform", "data": "platform" },
9740
		 *          { "title": "Version",  "data": "version" },
9741
		 *          { "title": "Grade",    "data": "grade" }
9742
		 *        ]
9743
		 *      } );
9744
		 *    } );
9745
		 */
9746
		"aaData": null,
9747
 
9748
 
9749
		/**
9750
		 * If ordering is enabled, then DataTables will perform a first pass sort on
9751
		 * initialisation. You can define which column(s) the sort is performed
9752
		 * upon, and the sorting direction, with this variable. The `sorting` array
9753
		 * should contain an array for each column to be sorted initially containing
9754
		 * the column's index and a direction string ('asc' or 'desc').
9755
		 *  @type array
9756
		 *  @default [[0,'asc']]
9757
		 *
9758
		 *  @dtopt Option
9759
		 *  @name DataTable.defaults.order
9760
		 *
9761
		 *  @example
9762
		 *    // Sort by 3rd column first, and then 4th column
9763
		 *    $(document).ready( function() {
9764
		 *      $('#example').dataTable( {
9765
		 *        "order": [[2,'asc'], [3,'desc']]
9766
		 *      } );
9767
		 *    } );
9768
		 *
9769
		 *    // No initial sorting
9770
		 *    $(document).ready( function() {
9771
		 *      $('#example').dataTable( {
9772
		 *        "order": []
9773
		 *      } );
9774
		 *    } );
9775
		 */
9776
		"aaSorting": [[0,'asc']],
9777
 
9778
 
9779
		/**
9780
		 * This parameter is basically identical to the `sorting` parameter, but
9781
		 * cannot be overridden by user interaction with the table. What this means
9782
		 * is that you could have a column (visible or hidden) which the sorting
9783
		 * will always be forced on first - any sorting after that (from the user)
9784
		 * will then be performed as required. This can be useful for grouping rows
9785
		 * together.
9786
		 *  @type array
9787
		 *  @default null
9788
		 *
9789
		 *  @dtopt Option
9790
		 *  @name DataTable.defaults.orderFixed
9791
		 *
9792
		 *  @example
9793
		 *    $(document).ready( function() {
9794
		 *      $('#example').dataTable( {
9795
		 *        "orderFixed": [[0,'asc']]
9796
		 *      } );
9797
		 *    } )
9798
		 */
9799
		"aaSortingFixed": [],
9800
 
9801
 
9802
		/**
9803
		 * DataTables can be instructed to load data to display in the table from a
9804
		 * Ajax source. This option defines how that Ajax call is made and where to.
9805
		 *
9806
		 * The `ajax` property has three different modes of operation, depending on
9807
		 * how it is defined. These are:
9808
		 *
9809
		 * * `string` - Set the URL from where the data should be loaded from.
9810
		 * * `object` - Define properties for `jQuery.ajax`.
9811
		 * * `function` - Custom data get function
9812
		 *
9813
		 * `string`
9814
		 * --------
9815
		 *
9816
		 * As a string, the `ajax` property simply defines the URL from which
9817
		 * DataTables will load data.
9818
		 *
9819
		 * `object`
9820
		 * --------
9821
		 *
9822
		 * As an object, the parameters in the object are passed to
9823
		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9824
		 * of the Ajax request. DataTables has a number of default parameters which
9825
		 * you can override using this option. Please refer to the jQuery
9826
		 * documentation for a full description of the options available, although
9827
		 * the following parameters provide additional options in DataTables or
9828
		 * require special consideration:
9829
		 *
9830
		 * * `data` - As with jQuery, `data` can be provided as an object, but it
9831
		 *   can also be used as a function to manipulate the data DataTables sends
9832
		 *   to the server. The function takes a single parameter, an object of
9833
		 *   parameters with the values that DataTables has readied for sending. An
9834
		 *   object may be returned which will be merged into the DataTables
9835
		 *   defaults, or you can add the items to the object that was passed in and
9836
		 *   not return anything from the function. This supersedes `fnServerParams`
9837
		 *   from DataTables 1.9-.
9838
		 *
9839
		 * * `dataSrc` - By default DataTables will look for the property `data` (or
9840
		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9841
		 *   from an Ajax source or for server-side processing - this parameter
9842
		 *   allows that property to be changed. You can use Javascript dotted
9843
		 *   object notation to get a data source for multiple levels of nesting, or
9844
		 *   it my be used as a function. As a function it takes a single parameter,
9845
		 *   the JSON returned from the server, which can be manipulated as
9846
		 *   required, with the returned value being that used by DataTables as the
9847
		 *   data source for the table. This supersedes `sAjaxDataProp` from
9848
		 *   DataTables 1.9-.
9849
		 *
9850
		 * * `success` - Should not be overridden it is used internally in
9851
		 *   DataTables. To manipulate / transform the data returned by the server
9852
		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9853
		 *
9854
		 * `function`
9855
		 * ----------
9856
		 *
9857
		 * As a function, making the Ajax call is left up to yourself allowing
9858
		 * complete control of the Ajax request. Indeed, if desired, a method other
9859
		 * than Ajax could be used to obtain the required data, such as Web storage
9860
		 * or an AIR database.
9861
		 *
9862
		 * The function is given four parameters and no return is required. The
9863
		 * parameters are:
9864
		 *
9865
		 * 1. _object_ - Data to send to the server
9866
		 * 2. _function_ - Callback function that must be executed when the required
9867
		 *    data has been obtained. That data should be passed into the callback
9868
		 *    as the only parameter
9869
		 * 3. _object_ - DataTables settings object for the table
9870
		 *
9871
		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
9872
		 *
9873
		 *  @type string|object|function
9874
		 *  @default null
9875
		 *
9876
		 *  @dtopt Option
9877
		 *  @name DataTable.defaults.ajax
9878
		 *  @since 1.10.0
9879
		 *
9880
		 * @example
9881
		 *   // Get JSON data from a file via Ajax.
9882
		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9883
		 *   $('#example').dataTable( {
9884
		 *     "ajax": "data.json"
9885
		 *   } );
9886
		 *
9887
		 * @example
9888
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
9889
		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9890
		 *   $('#example').dataTable( {
9891
		 *     "ajax": {
9892
		 *       "url": "data.json",
9893
		 *       "dataSrc": "tableData"
9894
		 *     }
9895
		 *   } );
9896
		 *
9897
		 * @example
9898
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
9899
		 *   // from a plain array rather than an array in an object
9900
		 *   $('#example').dataTable( {
9901
		 *     "ajax": {
9902
		 *       "url": "data.json",
9903
		 *       "dataSrc": ""
9904
		 *     }
9905
		 *   } );
9906
		 *
9907
		 * @example
9908
		 *   // Manipulate the data returned from the server - add a link to data
9909
		 *   // (note this can, should, be done using `render` for the column - this
9910
		 *   // is just a simple example of how the data can be manipulated).
9911
		 *   $('#example').dataTable( {
9912
		 *     "ajax": {
9913
		 *       "url": "data.json",
9914
		 *       "dataSrc": function ( json ) {
9915
		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9916
		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9917
		 *         }
9918
		 *         return json;
9919
		 *       }
9920
		 *     }
9921
		 *   } );
9922
		 *
9923
		 * @example
9924
		 *   // Add data to the request
9925
		 *   $('#example').dataTable( {
9926
		 *     "ajax": {
9927
		 *       "url": "data.json",
9928
		 *       "data": function ( d ) {
9929
		 *         return {
9930
		 *           "extra_search": $('#extra').val()
9931
		 *         };
9932
		 *       }
9933
		 *     }
9934
		 *   } );
9935
		 *
9936
		 * @example
9937
		 *   // Send request as POST
9938
		 *   $('#example').dataTable( {
9939
		 *     "ajax": {
9940
		 *       "url": "data.json",
9941
		 *       "type": "POST"
9942
		 *     }
9943
		 *   } );
9944
		 *
9945
		 * @example
9946
		 *   // Get the data from localStorage (could interface with a form for
9947
		 *   // adding, editing and removing rows).
9948
		 *   $('#example').dataTable( {
9949
		 *     "ajax": function (data, callback, settings) {
9950
		 *       callback(
9951
		 *         JSON.parse( localStorage.getItem('dataTablesData') )
9952
		 *       );
9953
		 *     }
9954
		 *   } );
9955
		 */
9956
		"ajax": null,
9957
 
9958
 
9959
		/**
9960
		 * This parameter allows you to readily specify the entries in the length drop
9961
		 * down menu that DataTables shows when pagination is enabled. It can be
9962
		 * either a 1D array of options which will be used for both the displayed
9963
		 * option and the value, or a 2D array which will use the array in the first
9964
		 * position as the value, and the array in the second position as the
9965
		 * displayed options (useful for language strings such as 'All').
9966
		 *
9967
		 * Note that the `pageLength` property will be automatically set to the
9968
		 * first value given in this array, unless `pageLength` is also provided.
9969
		 *  @type array
9970
		 *  @default [ 10, 25, 50, 100 ]
9971
		 *
9972
		 *  @dtopt Option
9973
		 *  @name DataTable.defaults.lengthMenu
9974
		 *
9975
		 *  @example
9976
		 *    $(document).ready( function() {
9977
		 *      $('#example').dataTable( {
9978
		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9979
		 *      } );
9980
		 *    } );
9981
		 */
9982
		"aLengthMenu": [ 10, 25, 50, 100 ],
9983
 
9984
 
9985
		/**
9986
		 * The `columns` option in the initialisation parameter allows you to define
9987
		 * details about the way individual columns behave. For a full list of
9988
		 * column options that can be set, please see
9989
		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
9990
		 * define your columns, you must have an entry in the array for every single
9991
		 * column that you have in your table (these can be null if you don't which
9992
		 * to specify any options).
9993
		 *  @member
9994
		 *
9995
		 *  @name DataTable.defaults.column
9996
		 */
9997
		"aoColumns": null,
9998
 
9999
		/**
10000
		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10001
		 * column, multiple columns, or all columns, using the `targets` property of
10002
		 * each object in the array. This allows great flexibility when creating
10003
		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10004
		 * columns you specifically want. `columnDefs` may use any of the column
10005
		 * options available: {@link DataTable.defaults.column}, but it _must_
10006
		 * have `targets` defined in each object in the array. Values in the `targets`
10007
		 * array may be:
10008
		 *   <ul>
10009
		 *     <li>a string - class name will be matched on the TH for the column</li>
10010
		 *     <li>0 or a positive integer - column index counting from the left</li>
10011
		 *     <li>a negative integer - column index counting from the right</li>
10012
		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10013
		 *   </ul>
10014
		 *  @member
10015
		 *
10016
		 *  @name DataTable.defaults.columnDefs
10017
		 */
10018
		"aoColumnDefs": null,
10019
 
10020
 
10021
		/**
10022
		 * Basically the same as `search`, this parameter defines the individual column
10023
		 * filtering state at initialisation time. The array must be of the same size
10024
		 * as the number of columns, and each element be an object with the parameters
10025
		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10026
		 * accepted and the default will be used.
10027
		 *  @type array
10028
		 *  @default []
10029
		 *
10030
		 *  @dtopt Option
10031
		 *  @name DataTable.defaults.searchCols
10032
		 *
10033
		 *  @example
10034
		 *    $(document).ready( function() {
10035
		 *      $('#example').dataTable( {
10036
		 *        "searchCols": [
10037
		 *          null,
10038
		 *          { "search": "My filter" },
10039
		 *          null,
10040
		 *          { "search": "^[0-9]", "escapeRegex": false }
10041
		 *        ]
10042
		 *      } );
10043
		 *    } )
10044
		 */
10045
		"aoSearchCols": [],
10046
 
10047
 
10048
		/**
10049
		 * An array of CSS classes that should be applied to displayed rows. This
10050
		 * array may be of any length, and DataTables will apply each class
10051
		 * sequentially, looping when required.
10052
		 *  @type array
10053
		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10054
		 *    options</i>
10055
		 *
10056
		 *  @dtopt Option
10057
		 *  @name DataTable.defaults.stripeClasses
10058
		 *
10059
		 *  @example
10060
		 *    $(document).ready( function() {
10061
		 *      $('#example').dataTable( {
10062
		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10063
		 *      } );
10064
		 *    } )
10065
		 */
10066
		"asStripeClasses": null,
10067
 
10068
 
10069
		/**
10070
		 * Enable or disable automatic column width calculation. This can be disabled
10071
		 * as an optimisation (it takes some time to calculate the widths) if the
10072
		 * tables widths are passed in using `columns`.
10073
		 *  @type boolean
10074
		 *  @default true
10075
		 *
10076
		 *  @dtopt Features
10077
		 *  @name DataTable.defaults.autoWidth
10078
		 *
10079
		 *  @example
10080
		 *    $(document).ready( function () {
10081
		 *      $('#example').dataTable( {
10082
		 *        "autoWidth": false
10083
		 *      } );
10084
		 *    } );
10085
		 */
10086
		"bAutoWidth": true,
10087
 
10088
 
10089
		/**
10090
		 * Deferred rendering can provide DataTables with a huge speed boost when you
10091
		 * are using an Ajax or JS data source for the table. This option, when set to
10092
		 * true, will cause DataTables to defer the creation of the table elements for
10093
		 * each row until they are needed for a draw - saving a significant amount of
10094
		 * time.
10095
		 *  @type boolean
10096
		 *  @default false
10097
		 *
10098
		 *  @dtopt Features
10099
		 *  @name DataTable.defaults.deferRender
10100
		 *
10101
		 *  @example
10102
		 *    $(document).ready( function() {
10103
		 *      $('#example').dataTable( {
10104
		 *        "ajax": "sources/arrays.txt",
10105
		 *        "deferRender": true
10106
		 *      } );
10107
		 *    } );
10108
		 */
10109
		"bDeferRender": false,
10110
 
10111
 
10112
		/**
10113
		 * Replace a DataTable which matches the given selector and replace it with
10114
		 * one which has the properties of the new initialisation object passed. If no
10115
		 * table matches the selector, then the new DataTable will be constructed as
10116
		 * per normal.
10117
		 *  @type boolean
10118
		 *  @default false
10119
		 *
10120
		 *  @dtopt Options
10121
		 *  @name DataTable.defaults.destroy
10122
		 *
10123
		 *  @example
10124
		 *    $(document).ready( function() {
10125
		 *      $('#example').dataTable( {
10126
		 *        "srollY": "200px",
10127
		 *        "paginate": false
10128
		 *      } );
10129
		 *
10130
		 *      // Some time later....
10131
		 *      $('#example').dataTable( {
10132
		 *        "filter": false,
10133
		 *        "destroy": true
10134
		 *      } );
10135
		 *    } );
10136
		 */
10137
		"bDestroy": false,
10138
 
10139
 
10140
		/**
10141
		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10142
		 * that it allows the end user to input multiple words (space separated) and
10143
		 * will match a row containing those words, even if not in the order that was
10144
		 * specified (this allow matching across multiple columns). Note that if you
10145
		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10146
		 * default filtering input box and retain filtering abilities, please use
10147
		 * {@link DataTable.defaults.dom}.
10148
		 *  @type boolean
10149
		 *  @default true
10150
		 *
10151
		 *  @dtopt Features
10152
		 *  @name DataTable.defaults.searching
10153
		 *
10154
		 *  @example
10155
		 *    $(document).ready( function () {
10156
		 *      $('#example').dataTable( {
10157
		 *        "searching": false
10158
		 *      } );
10159
		 *    } );
10160
		 */
10161
		"bFilter": true,
10162
 
10163
 
10164
		/**
10165
		 * Enable or disable the table information display. This shows information
10166
		 * about the data that is currently visible on the page, including information
10167
		 * about filtered data if that action is being performed.
10168
		 *  @type boolean
10169
		 *  @default true
10170
		 *
10171
		 *  @dtopt Features
10172
		 *  @name DataTable.defaults.info
10173
		 *
10174
		 *  @example
10175
		 *    $(document).ready( function () {
10176
		 *      $('#example').dataTable( {
10177
		 *        "info": false
10178
		 *      } );
10179
		 *    } );
10180
		 */
10181
		"bInfo": true,
10182
 
10183
 
10184
		/**
10185
		 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
10186
		 * slightly different and additional mark-up from what DataTables has
10187
		 * traditionally used).
10188
		 *  @type boolean
10189
		 *  @default false
10190
		 *
10191
		 *  @dtopt Features
10192
		 *  @name DataTable.defaults.jQueryUI
10193
		 *
10194
		 *  @example
10195
		 *    $(document).ready( function() {
10196
		 *      $('#example').dataTable( {
10197
		 *        "jQueryUI": true
10198
		 *      } );
10199
		 *    } );
10200
		 */
10201
		"bJQueryUI": false,
10202
 
10203
 
10204
		/**
10205
		 * Allows the end user to select the size of a formatted page from a select
10206
		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10207
		 *  @type boolean
10208
		 *  @default true
10209
		 *
10210
		 *  @dtopt Features
10211
		 *  @name DataTable.defaults.lengthChange
10212
		 *
10213
		 *  @example
10214
		 *    $(document).ready( function () {
10215
		 *      $('#example').dataTable( {
10216
		 *        "lengthChange": false
10217
		 *      } );
10218
		 *    } );
10219
		 */
10220
		"bLengthChange": true,
10221
 
10222
 
10223
		/**
10224
		 * Enable or disable pagination.
10225
		 *  @type boolean
10226
		 *  @default true
10227
		 *
10228
		 *  @dtopt Features
10229
		 *  @name DataTable.defaults.paging
10230
		 *
10231
		 *  @example
10232
		 *    $(document).ready( function () {
10233
		 *      $('#example').dataTable( {
10234
		 *        "paging": false
10235
		 *      } );
10236
		 *    } );
10237
		 */
10238
		"bPaginate": true,
10239
 
10240
 
10241
		/**
10242
		 * Enable or disable the display of a 'processing' indicator when the table is
10243
		 * being processed (e.g. a sort). This is particularly useful for tables with
10244
		 * large amounts of data where it can take a noticeable amount of time to sort
10245
		 * the entries.
10246
		 *  @type boolean
10247
		 *  @default false
10248
		 *
10249
		 *  @dtopt Features
10250
		 *  @name DataTable.defaults.processing
10251
		 *
10252
		 *  @example
10253
		 *    $(document).ready( function () {
10254
		 *      $('#example').dataTable( {
10255
		 *        "processing": true
10256
		 *      } );
10257
		 *    } );
10258
		 */
10259
		"bProcessing": false,
10260
 
10261
 
10262
		/**
10263
		 * Retrieve the DataTables object for the given selector. Note that if the
10264
		 * table has already been initialised, this parameter will cause DataTables
10265
		 * to simply return the object that has already been set up - it will not take
10266
		 * account of any changes you might have made to the initialisation object
10267
		 * passed to DataTables (setting this parameter to true is an acknowledgement
10268
		 * that you understand this). `destroy` can be used to reinitialise a table if
10269
		 * you need.
10270
		 *  @type boolean
10271
		 *  @default false
10272
		 *
10273
		 *  @dtopt Options
10274
		 *  @name DataTable.defaults.retrieve
10275
		 *
10276
		 *  @example
10277
		 *    $(document).ready( function() {
10278
		 *      initTable();
10279
		 *      tableActions();
10280
		 *    } );
10281
		 *
10282
		 *    function initTable ()
10283
		 *    {
10284
		 *      return $('#example').dataTable( {
10285
		 *        "scrollY": "200px",
10286
		 *        "paginate": false,
10287
		 *        "retrieve": true
10288
		 *      } );
10289
		 *    }
10290
		 *
10291
		 *    function tableActions ()
10292
		 *    {
10293
		 *      var table = initTable();
10294
		 *      // perform API operations with oTable
10295
		 *    }
10296
		 */
10297
		"bRetrieve": false,
10298
 
10299
 
10300
		/**
10301
		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10302
		 * the table's viewport to the given height at all times (useful for layout).
10303
		 * However, this can look odd when filtering data down to a small data set,
10304
		 * and the footer is left "floating" further down. This parameter (when
10305
		 * enabled) will cause DataTables to collapse the table's viewport down when
10306
		 * the result set will fit within the given Y height.
10307
		 *  @type boolean
10308
		 *  @default false
10309
		 *
10310
		 *  @dtopt Options
10311
		 *  @name DataTable.defaults.scrollCollapse
10312
		 *
10313
		 *  @example
10314
		 *    $(document).ready( function() {
10315
		 *      $('#example').dataTable( {
10316
		 *        "scrollY": "200",
10317
		 *        "scrollCollapse": true
10318
		 *      } );
10319
		 *    } );
10320
		 */
10321
		"bScrollCollapse": false,
10322
 
10323
 
10324
		/**
10325
		 * Configure DataTables to use server-side processing. Note that the
10326
		 * `ajax` parameter must also be given in order to give DataTables a
10327
		 * source to obtain the required data for each draw.
10328
		 *  @type boolean
10329
		 *  @default false
10330
		 *
10331
		 *  @dtopt Features
10332
		 *  @dtopt Server-side
10333
		 *  @name DataTable.defaults.serverSide
10334
		 *
10335
		 *  @example
10336
		 *    $(document).ready( function () {
10337
		 *      $('#example').dataTable( {
10338
		 *        "serverSide": true,
10339
		 *        "ajax": "xhr.php"
10340
		 *      } );
10341
		 *    } );
10342
		 */
10343
		"bServerSide": false,
10344
 
10345
 
10346
		/**
10347
		 * Enable or disable sorting of columns. Sorting of individual columns can be
10348
		 * disabled by the `sortable` option for each column.
10349
		 *  @type boolean
10350
		 *  @default true
10351
		 *
10352
		 *  @dtopt Features
10353
		 *  @name DataTable.defaults.ordering
10354
		 *
10355
		 *  @example
10356
		 *    $(document).ready( function () {
10357
		 *      $('#example').dataTable( {
10358
		 *        "ordering": false
10359
		 *      } );
10360
		 *    } );
10361
		 */
10362
		"bSort": true,
10363
 
10364
 
10365
		/**
10366
		 * Enable or display DataTables' ability to sort multiple columns at the
10367
		 * same time (activated by shift-click by the user).
10368
		 *  @type boolean
10369
		 *  @default true
10370
		 *
10371
		 *  @dtopt Options
10372
		 *  @name DataTable.defaults.orderMulti
10373
		 *
10374
		 *  @example
10375
		 *    // Disable multiple column sorting ability
10376
		 *    $(document).ready( function () {
10377
		 *      $('#example').dataTable( {
10378
		 *        "orderMulti": false
10379
		 *      } );
10380
		 *    } );
10381
		 */
10382
		"bSortMulti": true,
10383
 
10384
 
10385
		/**
10386
		 * Allows control over whether DataTables should use the top (true) unique
10387
		 * cell that is found for a single column, or the bottom (false - default).
10388
		 * This is useful when using complex headers.
10389
		 *  @type boolean
10390
		 *  @default false
10391
		 *
10392
		 *  @dtopt Options
10393
		 *  @name DataTable.defaults.orderCellsTop
10394
		 *
10395
		 *  @example
10396
		 *    $(document).ready( function() {
10397
		 *      $('#example').dataTable( {
10398
		 *        "orderCellsTop": true
10399
		 *      } );
10400
		 *    } );
10401
		 */
10402
		"bSortCellsTop": false,
10403
 
10404
 
10405
		/**
10406
		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10407
		 * `sorting\_3` to the columns which are currently being sorted on. This is
10408
		 * presented as a feature switch as it can increase processing time (while
10409
		 * classes are removed and added) so for large data sets you might want to
10410
		 * turn this off.
10411
		 *  @type boolean
10412
		 *  @default true
10413
		 *
10414
		 *  @dtopt Features
10415
		 *  @name DataTable.defaults.orderClasses
10416
		 *
10417
		 *  @example
10418
		 *    $(document).ready( function () {
10419
		 *      $('#example').dataTable( {
10420
		 *        "orderClasses": false
10421
		 *      } );
10422
		 *    } );
10423
		 */
10424
		"bSortClasses": true,
10425
 
10426
 
10427
		/**
10428
		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10429
		 * used to save table display information such as pagination information,
10430
		 * display length, filtering and sorting. As such when the end user reloads
10431
		 * the page the display display will match what thy had previously set up.
10432
		 *
10433
		 * Due to the use of `localStorage` the default state saving is not supported
10434
		 * in IE6 or 7. If state saving is required in those browsers, use
10435
		 * `stateSaveCallback` to provide a storage solution such as cookies.
10436
		 *  @type boolean
10437
		 *  @default false
10438
		 *
10439
		 *  @dtopt Features
10440
		 *  @name DataTable.defaults.stateSave
10441
		 *
10442
		 *  @example
10443
		 *    $(document).ready( function () {
10444
		 *      $('#example').dataTable( {
10445
		 *        "stateSave": true
10446
		 *      } );
10447
		 *    } );
10448
		 */
10449
		"bStateSave": false,
10450
 
10451
 
10452
		/**
10453
		 * This function is called when a TR element is created (and all TD child
10454
		 * elements have been inserted), or registered if using a DOM source, allowing
10455
		 * manipulation of the TR element (adding classes etc).
10456
		 *  @type function
10457
		 *  @param {node} row "TR" element for the current row
10458
		 *  @param {array} data Raw data array for this row
10459
		 *  @param {int} dataIndex The index of this row in the internal aoData array
10460
		 *
10461
		 *  @dtopt Callbacks
10462
		 *  @name DataTable.defaults.createdRow
10463
		 *
10464
		 *  @example
10465
		 *    $(document).ready( function() {
10466
		 *      $('#example').dataTable( {
10467
		 *        "createdRow": function( row, data, dataIndex ) {
10468
		 *          // Bold the grade for all 'A' grade browsers
10469
		 *          if ( data[4] == "A" )
10470
		 *          {
10471
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10472
		 *          }
10473
		 *        }
10474
		 *      } );
10475
		 *    } );
10476
		 */
10477
		"fnCreatedRow": null,
10478
 
10479
 
10480
		/**
10481
		 * This function is called on every 'draw' event, and allows you to
10482
		 * dynamically modify any aspect you want about the created DOM.
10483
		 *  @type function
10484
		 *  @param {object} settings DataTables settings object
10485
		 *
10486
		 *  @dtopt Callbacks
10487
		 *  @name DataTable.defaults.drawCallback
10488
		 *
10489
		 *  @example
10490
		 *    $(document).ready( function() {
10491
		 *      $('#example').dataTable( {
10492
		 *        "drawCallback": function( settings ) {
10493
		 *          alert( 'DataTables has redrawn the table' );
10494
		 *        }
10495
		 *      } );
10496
		 *    } );
10497
		 */
10498
		"fnDrawCallback": null,
10499
 
10500
 
10501
		/**
10502
		 * Identical to fnHeaderCallback() but for the table footer this function
10503
		 * allows you to modify the table footer on every 'draw' event.
10504
		 *  @type function
10505
		 *  @param {node} foot "TR" element for the footer
10506
		 *  @param {array} data Full table data (as derived from the original HTML)
10507
		 *  @param {int} start Index for the current display starting point in the
10508
		 *    display array
10509
		 *  @param {int} end Index for the current display ending point in the
10510
		 *    display array
10511
		 *  @param {array int} display Index array to translate the visual position
10512
		 *    to the full data array
10513
		 *
10514
		 *  @dtopt Callbacks
10515
		 *  @name DataTable.defaults.footerCallback
10516
		 *
10517
		 *  @example
10518
		 *    $(document).ready( function() {
10519
		 *      $('#example').dataTable( {
10520
		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10521
		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10522
		 *        }
10523
		 *      } );
10524
		 *    } )
10525
		 */
10526
		"fnFooterCallback": null,
10527
 
10528
 
10529
		/**
10530
		 * When rendering large numbers in the information element for the table
10531
		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10532
		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10533
		 * rendered as "1,000,000") to help readability for the end user. This
10534
		 * function will override the default method DataTables uses.
10535
		 *  @type function
10536
		 *  @member
10537
		 *  @param {int} toFormat number to be formatted
10538
		 *  @returns {string} formatted string for DataTables to show the number
10539
		 *
10540
		 *  @dtopt Callbacks
10541
		 *  @name DataTable.defaults.formatNumber
10542
		 *
10543
		 *  @example
10544
		 *    // Format a number using a single quote for the separator (note that
10545
		 *    // this can also be done with the language.thousands option)
10546
		 *    $(document).ready( function() {
10547
		 *      $('#example').dataTable( {
10548
		 *        "formatNumber": function ( toFormat ) {
10549
		 *          return toFormat.toString().replace(
10550
		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10551
		 *          );
10552
		 *        };
10553
		 *      } );
10554
		 *    } );
10555
		 */
10556
		"fnFormatNumber": function ( toFormat ) {
10557
			return toFormat.toString().replace(
10558
				/\B(?=(\d{3})+(?!\d))/g,
10559
				this.oLanguage.sThousands
10560
			);
10561
		},
10562
 
10563
 
10564
		/**
10565
		 * This function is called on every 'draw' event, and allows you to
10566
		 * dynamically modify the header row. This can be used to calculate and
10567
		 * display useful information about the table.
10568
		 *  @type function
10569
		 *  @param {node} head "TR" element for the header
10570
		 *  @param {array} data Full table data (as derived from the original HTML)
10571
		 *  @param {int} start Index for the current display starting point in the
10572
		 *    display array
10573
		 *  @param {int} end Index for the current display ending point in the
10574
		 *    display array
10575
		 *  @param {array int} display Index array to translate the visual position
10576
		 *    to the full data array
10577
		 *
10578
		 *  @dtopt Callbacks
10579
		 *  @name DataTable.defaults.headerCallback
10580
		 *
10581
		 *  @example
10582
		 *    $(document).ready( function() {
10583
		 *      $('#example').dataTable( {
10584
		 *        "fheaderCallback": function( head, data, start, end, display ) {
10585
		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10586
		 *        }
10587
		 *      } );
10588
		 *    } )
10589
		 */
10590
		"fnHeaderCallback": null,
10591
 
10592
 
10593
		/**
10594
		 * The information element can be used to convey information about the current
10595
		 * state of the table. Although the internationalisation options presented by
10596
		 * DataTables are quite capable of dealing with most customisations, there may
10597
		 * be times where you wish to customise the string further. This callback
10598
		 * allows you to do exactly that.
10599
		 *  @type function
10600
		 *  @param {object} oSettings DataTables settings object
10601
		 *  @param {int} start Starting position in data for the draw
10602
		 *  @param {int} end End position in data for the draw
10603
		 *  @param {int} max Total number of rows in the table (regardless of
10604
		 *    filtering)
10605
		 *  @param {int} total Total number of rows in the data set, after filtering
10606
		 *  @param {string} pre The string that DataTables has formatted using it's
10607
		 *    own rules
10608
		 *  @returns {string} The string to be displayed in the information element.
10609
		 *
10610
		 *  @dtopt Callbacks
10611
		 *  @name DataTable.defaults.infoCallback
10612
		 *
10613
		 *  @example
10614
		 *    $('#example').dataTable( {
10615
		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10616
		 *        return start +" to "+ end;
10617
		 *      }
10618
		 *    } );
10619
		 */
10620
		"fnInfoCallback": null,
10621
 
10622
 
10623
		/**
10624
		 * Called when the table has been initialised. Normally DataTables will
10625
		 * initialise sequentially and there will be no need for this function,
10626
		 * however, this does not hold true when using external language information
10627
		 * since that is obtained using an async XHR call.
10628
		 *  @type function
10629
		 *  @param {object} settings DataTables settings object
10630
		 *  @param {object} json The JSON object request from the server - only
10631
		 *    present if client-side Ajax sourced data is used
10632
		 *
10633
		 *  @dtopt Callbacks
10634
		 *  @name DataTable.defaults.initComplete
10635
		 *
10636
		 *  @example
10637
		 *    $(document).ready( function() {
10638
		 *      $('#example').dataTable( {
10639
		 *        "initComplete": function(settings, json) {
10640
		 *          alert( 'DataTables has finished its initialisation.' );
10641
		 *        }
10642
		 *      } );
10643
		 *    } )
10644
		 */
10645
		"fnInitComplete": null,
10646
 
10647
 
10648
		/**
10649
		 * Called at the very start of each table draw and can be used to cancel the
10650
		 * draw by returning false, any other return (including undefined) results in
10651
		 * the full draw occurring).
10652
		 *  @type function
10653
		 *  @param {object} settings DataTables settings object
10654
		 *  @returns {boolean} False will cancel the draw, anything else (including no
10655
		 *    return) will allow it to complete.
10656
		 *
10657
		 *  @dtopt Callbacks
10658
		 *  @name DataTable.defaults.preDrawCallback
10659
		 *
10660
		 *  @example
10661
		 *    $(document).ready( function() {
10662
		 *      $('#example').dataTable( {
10663
		 *        "preDrawCallback": function( settings ) {
10664
		 *          if ( $('#test').val() == 1 ) {
10665
		 *            return false;
10666
		 *          }
10667
		 *        }
10668
		 *      } );
10669
		 *    } );
10670
		 */
10671
		"fnPreDrawCallback": null,
10672
 
10673
 
10674
		/**
10675
		 * This function allows you to 'post process' each row after it have been
10676
		 * generated for each table draw, but before it is rendered on screen. This
10677
		 * function might be used for setting the row class name etc.
10678
		 *  @type function
10679
		 *  @param {node} row "TR" element for the current row
10680
		 *  @param {array} data Raw data array for this row
10681
		 *  @param {int} displayIndex The display index for the current table draw
10682
		 *  @param {int} displayIndexFull The index of the data in the full list of
10683
		 *    rows (after filtering)
10684
		 *
10685
		 *  @dtopt Callbacks
10686
		 *  @name DataTable.defaults.rowCallback
10687
		 *
10688
		 *  @example
10689
		 *    $(document).ready( function() {
10690
		 *      $('#example').dataTable( {
10691
		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10692
		 *          // Bold the grade for all 'A' grade browsers
10693
		 *          if ( data[4] == "A" ) {
10694
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10695
		 *          }
10696
		 *        }
10697
		 *      } );
10698
		 *    } );
10699
		 */
10700
		"fnRowCallback": null,
10701
 
10702
 
10703
		/**
10704
		 * __Deprecated__ The functionality provided by this parameter has now been
10705
		 * superseded by that provided through `ajax`, which should be used instead.
10706
		 *
10707
		 * This parameter allows you to override the default function which obtains
10708
		 * the data from the server so something more suitable for your application.
10709
		 * For example you could use POST data, or pull information from a Gears or
10710
		 * AIR database.
10711
		 *  @type function
10712
		 *  @member
10713
		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10714
		 *  @param {array} data A key/value pair object containing the data to send
10715
		 *    to the server
10716
		 *  @param {function} callback to be called on completion of the data get
10717
		 *    process that will draw the data on the page.
10718
		 *  @param {object} settings DataTables settings object
10719
		 *
10720
		 *  @dtopt Callbacks
10721
		 *  @dtopt Server-side
10722
		 *  @name DataTable.defaults.serverData
10723
		 *
10724
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10725
		 */
10726
		"fnServerData": null,
10727
 
10728
 
10729
		/**
10730
		 * __Deprecated__ The functionality provided by this parameter has now been
10731
		 * superseded by that provided through `ajax`, which should be used instead.
10732
		 *
10733
		 *  It is often useful to send extra data to the server when making an Ajax
10734
		 * request - for example custom filtering information, and this callback
10735
		 * function makes it trivial to send extra information to the server. The
10736
		 * passed in parameter is the data set that has been constructed by
10737
		 * DataTables, and you can add to this or modify it as you require.
10738
		 *  @type function
10739
		 *  @param {array} data Data array (array of objects which are name/value
10740
		 *    pairs) that has been constructed by DataTables and will be sent to the
10741
		 *    server. In the case of Ajax sourced data with server-side processing
10742
		 *    this will be an empty array, for server-side processing there will be a
10743
		 *    significant number of parameters!
10744
		 *  @returns {undefined} Ensure that you modify the data array passed in,
10745
		 *    as this is passed by reference.
10746
		 *
10747
		 *  @dtopt Callbacks
10748
		 *  @dtopt Server-side
10749
		 *  @name DataTable.defaults.serverParams
10750
		 *
10751
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10752
		 */
10753
		"fnServerParams": null,
10754
 
10755
 
10756
		/**
10757
		 * Load the table state. With this function you can define from where, and how, the
10758
		 * state of a table is loaded. By default DataTables will load from `localStorage`
10759
		 * but you might wish to use a server-side database or cookies.
10760
		 *  @type function
10761
		 *  @member
10762
		 *  @param {object} settings DataTables settings object
10763
		 *  @return {object} The DataTables state object to be loaded
10764
		 *
10765
		 *  @dtopt Callbacks
10766
		 *  @name DataTable.defaults.stateLoadCallback
10767
		 *
10768
		 *  @example
10769
		 *    $(document).ready( function() {
10770
		 *      $('#example').dataTable( {
10771
		 *        "stateSave": true,
10772
		 *        "stateLoadCallback": function (settings) {
10773
		 *          var o;
10774
		 *
10775
		 *          // Send an Ajax request to the server to get the data. Note that
10776
		 *          // this is a synchronous request.
10777
		 *          $.ajax( {
10778
		 *            "url": "/state_load",
10779
		 *            "async": false,
10780
		 *            "dataType": "json",
10781
		 *            "success": function (json) {
10782
		 *              o = json;
10783
		 *            }
10784
		 *          } );
10785
		 *
10786
		 *          return o;
10787
		 *        }
10788
		 *      } );
10789
		 *    } );
10790
		 */
10791
		"fnStateLoadCallback": function ( settings ) {
10792
			try {
10793
				return JSON.parse(
10794
					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10795
						'DataTables_'+settings.sInstance+'_'+location.pathname
10796
					)
10797
				);
10798
			} catch (e) {}
10799
		},
10800
 
10801
 
10802
		/**
10803
		 * Callback which allows modification of the saved state prior to loading that state.
10804
		 * This callback is called when the table is loading state from the stored data, but
10805
		 * prior to the settings object being modified by the saved state. Note that for
10806
		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10807
		 * a plug-in.
10808
		 *  @type function
10809
		 *  @param {object} settings DataTables settings object
10810
		 *  @param {object} data The state object that is to be loaded
10811
		 *
10812
		 *  @dtopt Callbacks
10813
		 *  @name DataTable.defaults.stateLoadParams
10814
		 *
10815
		 *  @example
10816
		 *    // Remove a saved filter, so filtering is never loaded
10817
		 *    $(document).ready( function() {
10818
		 *      $('#example').dataTable( {
10819
		 *        "stateSave": true,
10820
		 *        "stateLoadParams": function (settings, data) {
10821
		 *          data.oSearch.sSearch = "";
10822
		 *        }
10823
		 *      } );
10824
		 *    } );
10825
		 *
10826
		 *  @example
10827
		 *    // Disallow state loading by returning false
10828
		 *    $(document).ready( function() {
10829
		 *      $('#example').dataTable( {
10830
		 *        "stateSave": true,
10831
		 *        "stateLoadParams": function (settings, data) {
10832
		 *          return false;
10833
		 *        }
10834
		 *      } );
10835
		 *    } );
10836
		 */
10837
		"fnStateLoadParams": null,
10838
 
10839
 
10840
		/**
10841
		 * Callback that is called when the state has been loaded from the state saving method
10842
		 * and the DataTables settings object has been modified as a result of the loaded state.
10843
		 *  @type function
10844
		 *  @param {object} settings DataTables settings object
10845
		 *  @param {object} data The state object that was loaded
10846
		 *
10847
		 *  @dtopt Callbacks
10848
		 *  @name DataTable.defaults.stateLoaded
10849
		 *
10850
		 *  @example
10851
		 *    // Show an alert with the filtering value that was saved
10852
		 *    $(document).ready( function() {
10853
		 *      $('#example').dataTable( {
10854
		 *        "stateSave": true,
10855
		 *        "stateLoaded": function (settings, data) {
10856
		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10857
		 *        }
10858
		 *      } );
10859
		 *    } );
10860
		 */
10861
		"fnStateLoaded": null,
10862
 
10863
 
10864
		/**
10865
		 * Save the table state. This function allows you to define where and how the state
10866
		 * information for the table is stored By default DataTables will use `localStorage`
10867
		 * but you might wish to use a server-side database or cookies.
10868
		 *  @type function
10869
		 *  @member
10870
		 *  @param {object} settings DataTables settings object
10871
		 *  @param {object} data The state object to be saved
10872
		 *
10873
		 *  @dtopt Callbacks
10874
		 *  @name DataTable.defaults.stateSaveCallback
10875
		 *
10876
		 *  @example
10877
		 *    $(document).ready( function() {
10878
		 *      $('#example').dataTable( {
10879
		 *        "stateSave": true,
10880
		 *        "stateSaveCallback": function (settings, data) {
10881
		 *          // Send an Ajax request to the server with the state object
10882
		 *          $.ajax( {
10883
		 *            "url": "/state_save",
10884
		 *            "data": data,
10885
		 *            "dataType": "json",
10886
		 *            "method": "POST"
10887
		 *            "success": function () {}
10888
		 *          } );
10889
		 *        }
10890
		 *      } );
10891
		 *    } );
10892
		 */
10893
		"fnStateSaveCallback": function ( settings, data ) {
10894
			try {
10895
				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
10896
					'DataTables_'+settings.sInstance+'_'+location.pathname,
10897
					JSON.stringify( data )
10898
				);
10899
			} catch (e) {}
10900
		},
10901
 
10902
 
10903
		/**
10904
		 * Callback which allows modification of the state to be saved. Called when the table
10905
		 * has changed state a new state save is required. This method allows modification of
10906
		 * the state saving object prior to actually doing the save, including addition or
10907
		 * other state properties or modification. Note that for plug-in authors, you should
10908
		 * use the `stateSaveParams` event to save parameters for a plug-in.
10909
		 *  @type function
10910
		 *  @param {object} settings DataTables settings object
10911
		 *  @param {object} data The state object to be saved
10912
		 *
10913
		 *  @dtopt Callbacks
10914
		 *  @name DataTable.defaults.stateSaveParams
10915
		 *
10916
		 *  @example
10917
		 *    // Remove a saved filter, so filtering is never saved
10918
		 *    $(document).ready( function() {
10919
		 *      $('#example').dataTable( {
10920
		 *        "stateSave": true,
10921
		 *        "stateSaveParams": function (settings, data) {
10922
		 *          data.oSearch.sSearch = "";
10923
		 *        }
10924
		 *      } );
10925
		 *    } );
10926
		 */
10927
		"fnStateSaveParams": null,
10928
 
10929
 
10930
		/**
10931
		 * Duration for which the saved state information is considered valid. After this period
10932
		 * has elapsed the state will be returned to the default.
10933
		 * Value is given in seconds.
10934
		 *  @type int
10935
		 *  @default 7200 <i>(2 hours)</i>
10936
		 *
10937
		 *  @dtopt Options
10938
		 *  @name DataTable.defaults.stateDuration
10939
		 *
10940
		 *  @example
10941
		 *    $(document).ready( function() {
10942
		 *      $('#example').dataTable( {
10943
		 *        "stateDuration": 60*60*24; // 1 day
10944
		 *      } );
10945
		 *    } )
10946
		 */
10947
		"iStateDuration": 7200,
10948
 
10949
 
10950
		/**
10951
		 * When enabled DataTables will not make a request to the server for the first
10952
		 * page draw - rather it will use the data already on the page (no sorting etc
10953
		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10954
		 * is used to indicate that deferred loading is required, but it is also used
10955
		 * to tell DataTables how many records there are in the full table (allowing
10956
		 * the information element and pagination to be displayed correctly). In the case
10957
		 * where a filtering is applied to the table on initial load, this can be
10958
		 * indicated by giving the parameter as an array, where the first element is
10959
		 * the number of records available after filtering and the second element is the
10960
		 * number of records without filtering (allowing the table information element
10961
		 * to be shown correctly).
10962
		 *  @type int | array
10963
		 *  @default null
10964
		 *
10965
		 *  @dtopt Options
10966
		 *  @name DataTable.defaults.deferLoading
10967
		 *
10968
		 *  @example
10969
		 *    // 57 records available in the table, no filtering applied
10970
		 *    $(document).ready( function() {
10971
		 *      $('#example').dataTable( {
10972
		 *        "serverSide": true,
10973
		 *        "ajax": "scripts/server_processing.php",
10974
		 *        "deferLoading": 57
10975
		 *      } );
10976
		 *    } );
10977
		 *
10978
		 *  @example
10979
		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
10980
		 *    $(document).ready( function() {
10981
		 *      $('#example').dataTable( {
10982
		 *        "serverSide": true,
10983
		 *        "ajax": "scripts/server_processing.php",
10984
		 *        "deferLoading": [ 57, 100 ],
10985
		 *        "search": {
10986
		 *          "search": "my_filter"
10987
		 *        }
10988
		 *      } );
10989
		 *    } );
10990
		 */
10991
		"iDeferLoading": null,
10992
 
10993
 
10994
		/**
10995
		 * Number of rows to display on a single page when using pagination. If
10996
		 * feature enabled (`lengthChange`) then the end user will be able to override
10997
		 * this to a custom setting using a pop-up menu.
10998
		 *  @type int
10999
		 *  @default 10
11000
		 *
11001
		 *  @dtopt Options
11002
		 *  @name DataTable.defaults.pageLength
11003
		 *
11004
		 *  @example
11005
		 *    $(document).ready( function() {
11006
		 *      $('#example').dataTable( {
11007
		 *        "pageLength": 50
11008
		 *      } );
11009
		 *    } )
11010
		 */
11011
		"iDisplayLength": 10,
11012
 
11013
 
11014
		/**
11015
		 * Define the starting point for data display when using DataTables with
11016
		 * pagination. Note that this parameter is the number of records, rather than
11017
		 * the page number, so if you have 10 records per page and want to start on
11018
		 * the third page, it should be "20".
11019
		 *  @type int
11020
		 *  @default 0
11021
		 *
11022
		 *  @dtopt Options
11023
		 *  @name DataTable.defaults.displayStart
11024
		 *
11025
		 *  @example
11026
		 *    $(document).ready( function() {
11027
		 *      $('#example').dataTable( {
11028
		 *        "displayStart": 20
11029
		 *      } );
11030
		 *    } )
11031
		 */
11032
		"iDisplayStart": 0,
11033
 
11034
 
11035
		/**
11036
		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11037
		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11038
		 * allows you to tab through the controls and press the enter key to activate them.
11039
		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11040
		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11041
		 * disable built-in keyboard navigation.
11042
		 *  @type int
11043
		 *  @default 0
11044
		 *
11045
		 *  @dtopt Options
11046
		 *  @name DataTable.defaults.tabIndex
11047
		 *
11048
		 *  @example
11049
		 *    $(document).ready( function() {
11050
		 *      $('#example').dataTable( {
11051
		 *        "tabIndex": 1
11052
		 *      } );
11053
		 *    } );
11054
		 */
11055
		"iTabIndex": 0,
11056
 
11057
 
11058
		/**
11059
		 * Classes that DataTables assigns to the various components and features
11060
		 * that it adds to the HTML table. This allows classes to be configured
11061
		 * during initialisation in addition to through the static
11062
		 * {@link DataTable.ext.oStdClasses} object).
11063
		 *  @namespace
11064
		 *  @name DataTable.defaults.classes
11065
		 */
11066
		"oClasses": {},
11067
 
11068
 
11069
		/**
11070
		 * All strings that DataTables uses in the user interface that it creates
11071
		 * are defined in this object, allowing you to modified them individually or
11072
		 * completely replace them all as required.
11073
		 *  @namespace
11074
		 *  @name DataTable.defaults.language
11075
		 */
11076
		"oLanguage": {
11077
			/**
11078
			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11079
			 * actually visible on the page, but will be read by screenreaders, and thus
11080
			 * must be internationalised as well).
11081
			 *  @namespace
11082
			 *  @name DataTable.defaults.language.aria
11083
			 */
11084
			"oAria": {
11085
				/**
11086
				 * ARIA label that is added to the table headers when the column may be
11087
				 * sorted ascending by activing the column (click or return when focused).
11088
				 * Note that the column header is prefixed to this string.
11089
				 *  @type string
11090
				 *  @default : activate to sort column ascending
11091
				 *
11092
				 *  @dtopt Language
11093
				 *  @name DataTable.defaults.language.aria.sortAscending
11094
				 *
11095
				 *  @example
11096
				 *    $(document).ready( function() {
11097
				 *      $('#example').dataTable( {
11098
				 *        "language": {
11099
				 *          "aria": {
11100
				 *            "sortAscending": " - click/return to sort ascending"
11101
				 *          }
11102
				 *        }
11103
				 *      } );
11104
				 *    } );
11105
				 */
11106
				"sSortAscending": ": activate to sort column ascending",
11107
 
11108
				/**
11109
				 * ARIA label that is added to the table headers when the column may be
11110
				 * sorted descending by activing the column (click or return when focused).
11111
				 * Note that the column header is prefixed to this string.
11112
				 *  @type string
11113
				 *  @default : activate to sort column ascending
11114
				 *
11115
				 *  @dtopt Language
11116
				 *  @name DataTable.defaults.language.aria.sortDescending
11117
				 *
11118
				 *  @example
11119
				 *    $(document).ready( function() {
11120
				 *      $('#example').dataTable( {
11121
				 *        "language": {
11122
				 *          "aria": {
11123
				 *            "sortDescending": " - click/return to sort descending"
11124
				 *          }
11125
				 *        }
11126
				 *      } );
11127
				 *    } );
11128
				 */
11129
				"sSortDescending": ": activate to sort column descending"
11130
			},
11131
 
11132
			/**
11133
			 * Pagination string used by DataTables for the built-in pagination
11134
			 * control types.
11135
			 *  @namespace
11136
			 *  @name DataTable.defaults.language.paginate
11137
			 */
11138
			"oPaginate": {
11139
				/**
11140
				 * Text to use when using the 'full_numbers' type of pagination for the
11141
				 * button to take the user to the first page.
11142
				 *  @type string
11143
				 *  @default First
11144
				 *
11145
				 *  @dtopt Language
11146
				 *  @name DataTable.defaults.language.paginate.first
11147
				 *
11148
				 *  @example
11149
				 *    $(document).ready( function() {
11150
				 *      $('#example').dataTable( {
11151
				 *        "language": {
11152
				 *          "paginate": {
11153
				 *            "first": "First page"
11154
				 *          }
11155
				 *        }
11156
				 *      } );
11157
				 *    } );
11158
				 */
11159
				"sFirst": "First",
11160
 
11161
 
11162
				/**
11163
				 * Text to use when using the 'full_numbers' type of pagination for the
11164
				 * button to take the user to the last page.
11165
				 *  @type string
11166
				 *  @default Last
11167
				 *
11168
				 *  @dtopt Language
11169
				 *  @name DataTable.defaults.language.paginate.last
11170
				 *
11171
				 *  @example
11172
				 *    $(document).ready( function() {
11173
				 *      $('#example').dataTable( {
11174
				 *        "language": {
11175
				 *          "paginate": {
11176
				 *            "last": "Last page"
11177
				 *          }
11178
				 *        }
11179
				 *      } );
11180
				 *    } );
11181
				 */
11182
				"sLast": "Last",
11183
 
11184
 
11185
				/**
11186
				 * Text to use for the 'next' pagination button (to take the user to the
11187
				 * next page).
11188
				 *  @type string
11189
				 *  @default Next
11190
				 *
11191
				 *  @dtopt Language
11192
				 *  @name DataTable.defaults.language.paginate.next
11193
				 *
11194
				 *  @example
11195
				 *    $(document).ready( function() {
11196
				 *      $('#example').dataTable( {
11197
				 *        "language": {
11198
				 *          "paginate": {
11199
				 *            "next": "Next page"
11200
				 *          }
11201
				 *        }
11202
				 *      } );
11203
				 *    } );
11204
				 */
11205
				"sNext": "Next",
11206
 
11207
 
11208
				/**
11209
				 * Text to use for the 'previous' pagination button (to take the user to
11210
				 * the previous page).
11211
				 *  @type string
11212
				 *  @default Previous
11213
				 *
11214
				 *  @dtopt Language
11215
				 *  @name DataTable.defaults.language.paginate.previous
11216
				 *
11217
				 *  @example
11218
				 *    $(document).ready( function() {
11219
				 *      $('#example').dataTable( {
11220
				 *        "language": {
11221
				 *          "paginate": {
11222
				 *            "previous": "Previous page"
11223
				 *          }
11224
				 *        }
11225
				 *      } );
11226
				 *    } );
11227
				 */
11228
				"sPrevious": "Previous"
11229
			},
11230
 
11231
			/**
11232
			 * This string is shown in preference to `zeroRecords` when the table is
11233
			 * empty of data (regardless of filtering). Note that this is an optional
11234
			 * parameter - if it is not given, the value of `zeroRecords` will be used
11235
			 * instead (either the default or given value).
11236
			 *  @type string
11237
			 *  @default No data available in table
11238
			 *
11239
			 *  @dtopt Language
11240
			 *  @name DataTable.defaults.language.emptyTable
11241
			 *
11242
			 *  @example
11243
			 *    $(document).ready( function() {
11244
			 *      $('#example').dataTable( {
11245
			 *        "language": {
11246
			 *          "emptyTable": "No data available in table"
11247
			 *        }
11248
			 *      } );
11249
			 *    } );
11250
			 */
11251
			"sEmptyTable": "No data available in table",
11252
 
11253
 
11254
			/**
11255
			 * This string gives information to the end user about the information
11256
			 * that is current on display on the page. The following tokens can be
11257
			 * used in the string and will be dynamically replaced as the table
11258
			 * display updates. This tokens can be placed anywhere in the string, or
11259
			 * removed as needed by the language requires:
11260
			 *
11261
			 * * `\_START\_` - Display index of the first record on the current page
11262
			 * * `\_END\_` - Display index of the last record on the current page
11263
			 * * `\_TOTAL\_` - Number of records in the table after filtering
11264
			 * * `\_MAX\_` - Number of records in the table without filtering
11265
			 * * `\_PAGE\_` - Current page number
11266
			 * * `\_PAGES\_` - Total number of pages of data in the table
11267
			 *
11268
			 *  @type string
11269
			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11270
			 *
11271
			 *  @dtopt Language
11272
			 *  @name DataTable.defaults.language.info
11273
			 *
11274
			 *  @example
11275
			 *    $(document).ready( function() {
11276
			 *      $('#example').dataTable( {
11277
			 *        "language": {
11278
			 *          "info": "Showing page _PAGE_ of _PAGES_"
11279
			 *        }
11280
			 *      } );
11281
			 *    } );
11282
			 */
11283
			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11284
 
11285
 
11286
			/**
11287
			 * Display information string for when the table is empty. Typically the
11288
			 * format of this string should match `info`.
11289
			 *  @type string
11290
			 *  @default Showing 0 to 0 of 0 entries
11291
			 *
11292
			 *  @dtopt Language
11293
			 *  @name DataTable.defaults.language.infoEmpty
11294
			 *
11295
			 *  @example
11296
			 *    $(document).ready( function() {
11297
			 *      $('#example').dataTable( {
11298
			 *        "language": {
11299
			 *          "infoEmpty": "No entries to show"
11300
			 *        }
11301
			 *      } );
11302
			 *    } );
11303
			 */
11304
			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11305
 
11306
 
11307
			/**
11308
			 * When a user filters the information in a table, this string is appended
11309
			 * to the information (`info`) to give an idea of how strong the filtering
11310
			 * is. The variable _MAX_ is dynamically updated.
11311
			 *  @type string
11312
			 *  @default (filtered from _MAX_ total entries)
11313
			 *
11314
			 *  @dtopt Language
11315
			 *  @name DataTable.defaults.language.infoFiltered
11316
			 *
11317
			 *  @example
11318
			 *    $(document).ready( function() {
11319
			 *      $('#example').dataTable( {
11320
			 *        "language": {
11321
			 *          "infoFiltered": " - filtering from _MAX_ records"
11322
			 *        }
11323
			 *      } );
11324
			 *    } );
11325
			 */
11326
			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11327
 
11328
 
11329
			/**
11330
			 * If can be useful to append extra information to the info string at times,
11331
			 * and this variable does exactly that. This information will be appended to
11332
			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11333
			 * being used) at all times.
11334
			 *  @type string
11335
			 *  @default <i>Empty string</i>
11336
			 *
11337
			 *  @dtopt Language
11338
			 *  @name DataTable.defaults.language.infoPostFix
11339
			 *
11340
			 *  @example
11341
			 *    $(document).ready( function() {
11342
			 *      $('#example').dataTable( {
11343
			 *        "language": {
11344
			 *          "infoPostFix": "All records shown are derived from real information."
11345
			 *        }
11346
			 *      } );
11347
			 *    } );
11348
			 */
11349
			"sInfoPostFix": "",
11350
 
11351
 
11352
			/**
11353
			 * This decimal place operator is a little different from the other
11354
			 * language options since DataTables doesn't output floating point
11355
			 * numbers, so it won't ever use this for display of a number. Rather,
11356
			 * what this parameter does is modify the sort methods of the table so
11357
			 * that numbers which are in a format which has a character other than
11358
			 * a period (`.`) as a decimal place will be sorted numerically.
11359
			 *
11360
			 * Note that numbers with different decimal places cannot be shown in
11361
			 * the same table and still be sortable, the table must be consistent.
11362
			 * However, multiple different tables on the page can use different
11363
			 * decimal place characters.
11364
			 *  @type string
11365
			 *  @default
11366
			 *
11367
			 *  @dtopt Language
11368
			 *  @name DataTable.defaults.language.decimal
11369
			 *
11370
			 *  @example
11371
			 *    $(document).ready( function() {
11372
			 *      $('#example').dataTable( {
11373
			 *        "language": {
11374
			 *          "decimal": ","
11375
			 *          "thousands": "."
11376
			 *        }
11377
			 *      } );
11378
			 *    } );
11379
			 */
11380
			"sDecimal": "",
11381
 
11382
 
11383
			/**
11384
			 * DataTables has a build in number formatter (`formatNumber`) which is
11385
			 * used to format large numbers that are used in the table information.
11386
			 * By default a comma is used, but this can be trivially changed to any
11387
			 * character you wish with this parameter.
11388
			 *  @type string
11389
			 *  @default ,
11390
			 *
11391
			 *  @dtopt Language
11392
			 *  @name DataTable.defaults.language.thousands
11393
			 *
11394
			 *  @example
11395
			 *    $(document).ready( function() {
11396
			 *      $('#example').dataTable( {
11397
			 *        "language": {
11398
			 *          "thousands": "'"
11399
			 *        }
11400
			 *      } );
11401
			 *    } );
11402
			 */
11403
			"sThousands": ",",
11404
 
11405
 
11406
			/**
11407
			 * Detail the action that will be taken when the drop down menu for the
11408
			 * pagination length option is changed. The '_MENU_' variable is replaced
11409
			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11410
			 * with a custom select box if required.
11411
			 *  @type string
11412
			 *  @default Show _MENU_ entries
11413
			 *
11414
			 *  @dtopt Language
11415
			 *  @name DataTable.defaults.language.lengthMenu
11416
			 *
11417
			 *  @example
11418
			 *    // Language change only
11419
			 *    $(document).ready( function() {
11420
			 *      $('#example').dataTable( {
11421
			 *        "language": {
11422
			 *          "lengthMenu": "Display _MENU_ records"
11423
			 *        }
11424
			 *      } );
11425
			 *    } );
11426
			 *
11427
			 *  @example
11428
			 *    // Language and options change
11429
			 *    $(document).ready( function() {
11430
			 *      $('#example').dataTable( {
11431
			 *        "language": {
11432
			 *          "lengthMenu": 'Display <select>'+
11433
			 *            '<option value="10">10</option>'+
11434
			 *            '<option value="20">20</option>'+
11435
			 *            '<option value="30">30</option>'+
11436
			 *            '<option value="40">40</option>'+
11437
			 *            '<option value="50">50</option>'+
11438
			 *            '<option value="-1">All</option>'+
11439
			 *            '</select> records'
11440
			 *        }
11441
			 *      } );
11442
			 *    } );
11443
			 */
11444
			"sLengthMenu": "Show _MENU_ entries",
11445
 
11446
 
11447
			/**
11448
			 * When using Ajax sourced data and during the first draw when DataTables is
11449
			 * gathering the data, this message is shown in an empty row in the table to
11450
			 * indicate to the end user the the data is being loaded. Note that this
11451
			 * parameter is not used when loading data by server-side processing, just
11452
			 * Ajax sourced data with client-side processing.
11453
			 *  @type string
11454
			 *  @default Loading...
11455
			 *
11456
			 *  @dtopt Language
11457
			 *  @name DataTable.defaults.language.loadingRecords
11458
			 *
11459
			 *  @example
11460
			 *    $(document).ready( function() {
11461
			 *      $('#example').dataTable( {
11462
			 *        "language": {
11463
			 *          "loadingRecords": "Please wait - loading..."
11464
			 *        }
11465
			 *      } );
11466
			 *    } );
11467
			 */
11468
			"sLoadingRecords": "Loading...",
11469
 
11470
 
11471
			/**
11472
			 * Text which is displayed when the table is processing a user action
11473
			 * (usually a sort command or similar).
11474
			 *  @type string
11475
			 *  @default Processing...
11476
			 *
11477
			 *  @dtopt Language
11478
			 *  @name DataTable.defaults.language.processing
11479
			 *
11480
			 *  @example
11481
			 *    $(document).ready( function() {
11482
			 *      $('#example').dataTable( {
11483
			 *        "language": {
11484
			 *          "processing": "DataTables is currently busy"
11485
			 *        }
11486
			 *      } );
11487
			 *    } );
11488
			 */
11489
			"sProcessing": "Processing...",
11490
 
11491
 
11492
			/**
11493
			 * Details the actions that will be taken when the user types into the
11494
			 * filtering input text box. The variable "_INPUT_", if used in the string,
11495
			 * is replaced with the HTML text box for the filtering input allowing
11496
			 * control over where it appears in the string. If "_INPUT_" is not given
11497
			 * then the input box is appended to the string automatically.
11498
			 *  @type string
11499
			 *  @default Search:
11500
			 *
11501
			 *  @dtopt Language
11502
			 *  @name DataTable.defaults.language.search
11503
			 *
11504
			 *  @example
11505
			 *    // Input text box will be appended at the end automatically
11506
			 *    $(document).ready( function() {
11507
			 *      $('#example').dataTable( {
11508
			 *        "language": {
11509
			 *          "search": "Filter records:"
11510
			 *        }
11511
			 *      } );
11512
			 *    } );
11513
			 *
11514
			 *  @example
11515
			 *    // Specify where the filter should appear
11516
			 *    $(document).ready( function() {
11517
			 *      $('#example').dataTable( {
11518
			 *        "language": {
11519
			 *          "search": "Apply filter _INPUT_ to table"
11520
			 *        }
11521
			 *      } );
11522
			 *    } );
11523
			 */
11524
			"sSearch": "Search:",
11525
 
11526
 
11527
			/**
11528
			 * Assign a `placeholder` attribute to the search `input` element
11529
			 *  @type string
11530
			 *  @default
11531
			 *
11532
			 *  @dtopt Language
11533
			 *  @name DataTable.defaults.language.searchPlaceholder
11534
			 */
11535
			"sSearchPlaceholder": "",
11536
 
11537
 
11538
			/**
11539
			 * All of the language information can be stored in a file on the
11540
			 * server-side, which DataTables will look up if this parameter is passed.
11541
			 * It must store the URL of the language file, which is in a JSON format,
11542
			 * and the object has the same properties as the oLanguage object in the
11543
			 * initialiser object (i.e. the above parameters). Please refer to one of
11544
			 * the example language files to see how this works in action.
11545
			 *  @type string
11546
			 *  @default <i>Empty string - i.e. disabled</i>
11547
			 *
11548
			 *  @dtopt Language
11549
			 *  @name DataTable.defaults.language.url
11550
			 *
11551
			 *  @example
11552
			 *    $(document).ready( function() {
11553
			 *      $('#example').dataTable( {
11554
			 *        "language": {
11555
			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11556
			 *        }
11557
			 *      } );
11558
			 *    } );
11559
			 */
11560
			"sUrl": "",
11561
 
11562
 
11563
			/**
11564
			 * Text shown inside the table records when the is no information to be
11565
			 * displayed after filtering. `emptyTable` is shown when there is simply no
11566
			 * information in the table at all (regardless of filtering).
11567
			 *  @type string
11568
			 *  @default No matching records found
11569
			 *
11570
			 *  @dtopt Language
11571
			 *  @name DataTable.defaults.language.zeroRecords
11572
			 *
11573
			 *  @example
11574
			 *    $(document).ready( function() {
11575
			 *      $('#example').dataTable( {
11576
			 *        "language": {
11577
			 *          "zeroRecords": "No records to display"
11578
			 *        }
11579
			 *      } );
11580
			 *    } );
11581
			 */
11582
			"sZeroRecords": "No matching records found"
11583
		},
11584
 
11585
 
11586
		/**
11587
		 * This parameter allows you to have define the global filtering state at
11588
		 * initialisation time. As an object the `search` parameter must be
11589
		 * defined, but all other parameters are optional. When `regex` is true,
11590
		 * the search string will be treated as a regular expression, when false
11591
		 * (default) it will be treated as a straight string. When `smart`
11592
		 * DataTables will use it's smart filtering methods (to word match at
11593
		 * any point in the data), when false this will not be done.
11594
		 *  @namespace
11595
		 *  @extends DataTable.models.oSearch
11596
		 *
11597
		 *  @dtopt Options
11598
		 *  @name DataTable.defaults.search
11599
		 *
11600
		 *  @example
11601
		 *    $(document).ready( function() {
11602
		 *      $('#example').dataTable( {
11603
		 *        "search": {"search": "Initial search"}
11604
		 *      } );
11605
		 *    } )
11606
		 */
11607
		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11608
 
11609
 
11610
		/**
11611
		 * __Deprecated__ The functionality provided by this parameter has now been
11612
		 * superseded by that provided through `ajax`, which should be used instead.
11613
		 *
11614
		 * By default DataTables will look for the property `data` (or `aaData` for
11615
		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11616
		 * source or for server-side processing - this parameter allows that
11617
		 * property to be changed. You can use Javascript dotted object notation to
11618
		 * get a data source for multiple levels of nesting.
11619
		 *  @type string
11620
		 *  @default data
11621
		 *
11622
		 *  @dtopt Options
11623
		 *  @dtopt Server-side
11624
		 *  @name DataTable.defaults.ajaxDataProp
11625
		 *
11626
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11627
		 */
11628
		"sAjaxDataProp": "data",
11629
 
11630
 
11631
		/**
11632
		 * __Deprecated__ The functionality provided by this parameter has now been
11633
		 * superseded by that provided through `ajax`, which should be used instead.
11634
		 *
11635
		 * You can instruct DataTables to load data from an external
11636
		 * source using this parameter (use aData if you want to pass data in you
11637
		 * already have). Simply provide a url a JSON object can be obtained from.
11638
		 *  @type string
11639
		 *  @default null
11640
		 *
11641
		 *  @dtopt Options
11642
		 *  @dtopt Server-side
11643
		 *  @name DataTable.defaults.ajaxSource
11644
		 *
11645
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11646
		 */
11647
		"sAjaxSource": null,
11648
 
11649
 
11650
		/**
11651
		 * This initialisation variable allows you to specify exactly where in the
11652
		 * DOM you want DataTables to inject the various controls it adds to the page
11653
		 * (for example you might want the pagination controls at the top of the
11654
		 * table). DIV elements (with or without a custom class) can also be added to
11655
		 * aid styling. The follow syntax is used:
11656
		 *   <ul>
11657
		 *     <li>The following options are allowed:
11658
		 *       <ul>
11659
		 *         <li>'l' - Length changing</li>
11660
		 *         <li>'f' - Filtering input</li>
11661
		 *         <li>'t' - The table!</li>
11662
		 *         <li>'i' - Information</li>
11663
		 *         <li>'p' - Pagination</li>
11664
		 *         <li>'r' - pRocessing</li>
11665
		 *       </ul>
11666
		 *     </li>
11667
		 *     <li>The following constants are allowed:
11668
		 *       <ul>
11669
		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11670
		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11671
		 *       </ul>
11672
		 *     </li>
11673
		 *     <li>The following syntax is expected:
11674
		 *       <ul>
11675
		 *         <li>'&lt;' and '&gt;' - div elements</li>
11676
		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11677
		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11678
		 *       </ul>
11679
		 *     </li>
11680
		 *     <li>Examples:
11681
		 *       <ul>
11682
		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11683
		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11684
		 *       </ul>
11685
		 *     </li>
11686
		 *   </ul>
11687
		 *  @type string
11688
		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11689
		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11690
		 *
11691
		 *  @dtopt Options
11692
		 *  @name DataTable.defaults.dom
11693
		 *
11694
		 *  @example
11695
		 *    $(document).ready( function() {
11696
		 *      $('#example').dataTable( {
11697
		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11698
		 *      } );
11699
		 *    } );
11700
		 */
11701
		"sDom": "lfrtip",
11702
 
11703
 
11704
		/**
11705
		 * Search delay option. This will throttle full table searches that use the
11706
		 * DataTables provided search input element (it does not effect calls to
11707
		 * `dt-api search()`, providing a delay before the search is made.
11708
		 *  @type integer
11709
		 *  @default 0
11710
		 *
11711
		 *  @dtopt Options
11712
		 *  @name DataTable.defaults.searchDelay
11713
		 *
11714
		 *  @example
11715
		 *    $(document).ready( function() {
11716
		 *      $('#example').dataTable( {
11717
		 *        "searchDelay": 200
11718
		 *      } );
11719
		 *    } )
11720
		 */
11721
		"searchDelay": null,
11722
 
11723
 
11724
		/**
11725
		 * DataTables features four different built-in options for the buttons to
11726
		 * display for pagination control:
11727
		 *
11728
		 * * `simple` - 'Previous' and 'Next' buttons only
11729
		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11730
		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11731
		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11732
		 *   page numbers
11733
		 *
11734
		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11735
		 *  @type string
11736
		 *  @default simple_numbers
11737
		 *
11738
		 *  @dtopt Options
11739
		 *  @name DataTable.defaults.pagingType
11740
		 *
11741
		 *  @example
11742
		 *    $(document).ready( function() {
11743
		 *      $('#example').dataTable( {
11744
		 *        "pagingType": "full_numbers"
11745
		 *      } );
11746
		 *    } )
11747
		 */
11748
		"sPaginationType": "simple_numbers",
11749
 
11750
 
11751
		/**
11752
		 * Enable horizontal scrolling. When a table is too wide to fit into a
11753
		 * certain layout, or you have a large number of columns in the table, you
11754
		 * can enable x-scrolling to show the table in a viewport, which can be
11755
		 * scrolled. This property can be `true` which will allow the table to
11756
		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11757
		 * case it will be treated as a pixel measurement). Setting as simply `true`
11758
		 * is recommended.
11759
		 *  @type boolean|string
11760
		 *  @default <i>blank string - i.e. disabled</i>
11761
		 *
11762
		 *  @dtopt Features
11763
		 *  @name DataTable.defaults.scrollX
11764
		 *
11765
		 *  @example
11766
		 *    $(document).ready( function() {
11767
		 *      $('#example').dataTable( {
11768
		 *        "scrollX": true,
11769
		 *        "scrollCollapse": true
11770
		 *      } );
11771
		 *    } );
11772
		 */
11773
		"sScrollX": "",
11774
 
11775
 
11776
		/**
11777
		 * This property can be used to force a DataTable to use more width than it
11778
		 * might otherwise do when x-scrolling is enabled. For example if you have a
11779
		 * table which requires to be well spaced, this parameter is useful for
11780
		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11781
		 * any CSS unit, or a number (in which case it will be treated as a pixel
11782
		 * measurement).
11783
		 *  @type string
11784
		 *  @default <i>blank string - i.e. disabled</i>
11785
		 *
11786
		 *  @dtopt Options
11787
		 *  @name DataTable.defaults.scrollXInner
11788
		 *
11789
		 *  @example
11790
		 *    $(document).ready( function() {
11791
		 *      $('#example').dataTable( {
11792
		 *        "scrollX": "100%",
11793
		 *        "scrollXInner": "110%"
11794
		 *      } );
11795
		 *    } );
11796
		 */
11797
		"sScrollXInner": "",
11798
 
11799
 
11800
		/**
11801
		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11802
		 * to the given height, and enable scrolling for any data which overflows the
11803
		 * current viewport. This can be used as an alternative to paging to display
11804
		 * a lot of data in a small area (although paging and scrolling can both be
11805
		 * enabled at the same time). This property can be any CSS unit, or a number
11806
		 * (in which case it will be treated as a pixel measurement).
11807
		 *  @type string
11808
		 *  @default <i>blank string - i.e. disabled</i>
11809
		 *
11810
		 *  @dtopt Features
11811
		 *  @name DataTable.defaults.scrollY
11812
		 *
11813
		 *  @example
11814
		 *    $(document).ready( function() {
11815
		 *      $('#example').dataTable( {
11816
		 *        "scrollY": "200px",
11817
		 *        "paginate": false
11818
		 *      } );
11819
		 *    } );
11820
		 */
11821
		"sScrollY": "",
11822
 
11823
 
11824
		/**
11825
		 * __Deprecated__ The functionality provided by this parameter has now been
11826
		 * superseded by that provided through `ajax`, which should be used instead.
11827
		 *
11828
		 * Set the HTTP method that is used to make the Ajax call for server-side
11829
		 * processing or Ajax sourced data.
11830
		 *  @type string
11831
		 *  @default GET
11832
		 *
11833
		 *  @dtopt Options
11834
		 *  @dtopt Server-side
11835
		 *  @name DataTable.defaults.serverMethod
11836
		 *
11837
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11838
		 */
11839
		"sServerMethod": "GET",
11840
 
11841
 
11842
		/**
11843
		 * DataTables makes use of renderers when displaying HTML elements for
11844
		 * a table. These renderers can be added or modified by plug-ins to
11845
		 * generate suitable mark-up for a site. For example the Bootstrap
11846
		 * integration plug-in for DataTables uses a paging button renderer to
11847
		 * display pagination buttons in the mark-up required by Bootstrap.
11848
		 *
11849
		 * For further information about the renderers available see
11850
		 * DataTable.ext.renderer
11851
		 *  @type string|object
11852
		 *  @default null
11853
		 *
11854
		 *  @name DataTable.defaults.renderer
11855
		 *
11856
		 */
11857
		"renderer": null,
11858
 
11859
 
11860
		/**
11861
		 * Set the data property name that DataTables should use to get a row's id
11862
		 * to set as the `id` property in the node.
11863
		 *  @type string
11864
		 *  @default DT_RowId
11865
		 *
11866
		 *  @name DataTable.defaults.rowId
11867
		 */
11868
		"rowId": "DT_RowId"
11869
	};
11870
 
11871
	_fnHungarianMap( DataTable.defaults );
11872
 
11873
 
11874
 
11875
	/*
11876
	 * Developer note - See note in model.defaults.js about the use of Hungarian
11877
	 * notation and camel case.
11878
	 */
11879
 
11880
	/**
11881
	 * Column options that can be given to DataTables at initialisation time.
11882
	 *  @namespace
11883
	 */
11884
	DataTable.defaults.column = {
11885
		/**
11886
		 * Define which column(s) an order will occur on for this column. This
11887
		 * allows a column's ordering to take multiple columns into account when
11888
		 * doing a sort or use the data from a different column. For example first
11889
		 * name / last name columns make sense to do a multi-column sort over the
11890
		 * two columns.
11891
		 *  @type array|int
11892
		 *  @default null <i>Takes the value of the column index automatically</i>
11893
		 *
11894
		 *  @name DataTable.defaults.column.orderData
11895
		 *  @dtopt Columns
11896
		 *
11897
		 *  @example
11898
		 *    // Using `columnDefs`
11899
		 *    $(document).ready( function() {
11900
		 *      $('#example').dataTable( {
11901
		 *        "columnDefs": [
11902
		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11903
		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11904
		 *          { "orderData": 2, "targets": [ 2 ] }
11905
		 *        ]
11906
		 *      } );
11907
		 *    } );
11908
		 *
11909
		 *  @example
11910
		 *    // Using `columns`
11911
		 *    $(document).ready( function() {
11912
		 *      $('#example').dataTable( {
11913
		 *        "columns": [
11914
		 *          { "orderData": [ 0, 1 ] },
11915
		 *          { "orderData": [ 1, 0 ] },
11916
		 *          { "orderData": 2 },
11917
		 *          null,
11918
		 *          null
11919
		 *        ]
11920
		 *      } );
11921
		 *    } );
11922
		 */
11923
		"aDataSort": null,
11924
		"iDataSort": -1,
11925
 
11926
 
11927
		/**
11928
		 * You can control the default ordering direction, and even alter the
11929
		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11930
		 * using this parameter.
11931
		 *  @type array
11932
		 *  @default [ 'asc', 'desc' ]
11933
		 *
11934
		 *  @name DataTable.defaults.column.orderSequence
11935
		 *  @dtopt Columns
11936
		 *
11937
		 *  @example
11938
		 *    // Using `columnDefs`
11939
		 *    $(document).ready( function() {
11940
		 *      $('#example').dataTable( {
11941
		 *        "columnDefs": [
11942
		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11943
		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11944
		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11945
		 *        ]
11946
		 *      } );
11947
		 *    } );
11948
		 *
11949
		 *  @example
11950
		 *    // Using `columns`
11951
		 *    $(document).ready( function() {
11952
		 *      $('#example').dataTable( {
11953
		 *        "columns": [
11954
		 *          null,
11955
		 *          { "orderSequence": [ "asc" ] },
11956
		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
11957
		 *          { "orderSequence": [ "desc" ] },
11958
		 *          null
11959
		 *        ]
11960
		 *      } );
11961
		 *    } );
11962
		 */
11963
		"asSorting": [ 'asc', 'desc' ],
11964
 
11965
 
11966
		/**
11967
		 * Enable or disable filtering on the data in this column.
11968
		 *  @type boolean
11969
		 *  @default true
11970
		 *
11971
		 *  @name DataTable.defaults.column.searchable
11972
		 *  @dtopt Columns
11973
		 *
11974
		 *  @example
11975
		 *    // Using `columnDefs`
11976
		 *    $(document).ready( function() {
11977
		 *      $('#example').dataTable( {
11978
		 *        "columnDefs": [
11979
		 *          { "searchable": false, "targets": [ 0 ] }
11980
		 *        ] } );
11981
		 *    } );
11982
		 *
11983
		 *  @example
11984
		 *    // Using `columns`
11985
		 *    $(document).ready( function() {
11986
		 *      $('#example').dataTable( {
11987
		 *        "columns": [
11988
		 *          { "searchable": false },
11989
		 *          null,
11990
		 *          null,
11991
		 *          null,
11992
		 *          null
11993
		 *        ] } );
11994
		 *    } );
11995
		 */
11996
		"bSearchable": true,
11997
 
11998
 
11999
		/**
12000
		 * Enable or disable ordering on this column.
12001
		 *  @type boolean
12002
		 *  @default true
12003
		 *
12004
		 *  @name DataTable.defaults.column.orderable
12005
		 *  @dtopt Columns
12006
		 *
12007
		 *  @example
12008
		 *    // Using `columnDefs`
12009
		 *    $(document).ready( function() {
12010
		 *      $('#example').dataTable( {
12011
		 *        "columnDefs": [
12012
		 *          { "orderable": false, "targets": [ 0 ] }
12013
		 *        ] } );
12014
		 *    } );
12015
		 *
12016
		 *  @example
12017
		 *    // Using `columns`
12018
		 *    $(document).ready( function() {
12019
		 *      $('#example').dataTable( {
12020
		 *        "columns": [
12021
		 *          { "orderable": false },
12022
		 *          null,
12023
		 *          null,
12024
		 *          null,
12025
		 *          null
12026
		 *        ] } );
12027
		 *    } );
12028
		 */
12029
		"bSortable": true,
12030
 
12031
 
12032
		/**
12033
		 * Enable or disable the display of this column.
12034
		 *  @type boolean
12035
		 *  @default true
12036
		 *
12037
		 *  @name DataTable.defaults.column.visible
12038
		 *  @dtopt Columns
12039
		 *
12040
		 *  @example
12041
		 *    // Using `columnDefs`
12042
		 *    $(document).ready( function() {
12043
		 *      $('#example').dataTable( {
12044
		 *        "columnDefs": [
12045
		 *          { "visible": false, "targets": [ 0 ] }
12046
		 *        ] } );
12047
		 *    } );
12048
		 *
12049
		 *  @example
12050
		 *    // Using `columns`
12051
		 *    $(document).ready( function() {
12052
		 *      $('#example').dataTable( {
12053
		 *        "columns": [
12054
		 *          { "visible": false },
12055
		 *          null,
12056
		 *          null,
12057
		 *          null,
12058
		 *          null
12059
		 *        ] } );
12060
		 *    } );
12061
		 */
12062
		"bVisible": true,
12063
 
12064
 
12065
		/**
12066
		 * Developer definable function that is called whenever a cell is created (Ajax source,
12067
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12068
		 * allowing you to modify the DOM element (add background colour for example) when the
12069
		 * element is available.
12070
		 *  @type function
12071
		 *  @param {element} td The TD node that has been created
12072
		 *  @param {*} cellData The Data for the cell
12073
		 *  @param {array|object} rowData The data for the whole row
12074
		 *  @param {int} row The row index for the aoData data store
12075
		 *  @param {int} col The column index for aoColumns
12076
		 *
12077
		 *  @name DataTable.defaults.column.createdCell
12078
		 *  @dtopt Columns
12079
		 *
12080
		 *  @example
12081
		 *    $(document).ready( function() {
12082
		 *      $('#example').dataTable( {
12083
		 *        "columnDefs": [ {
12084
		 *          "targets": [3],
12085
		 *          "createdCell": function (td, cellData, rowData, row, col) {
12086
		 *            if ( cellData == "1.7" ) {
12087
		 *              $(td).css('color', 'blue')
12088
		 *            }
12089
		 *          }
12090
		 *        } ]
12091
		 *      });
12092
		 *    } );
12093
		 */
12094
		"fnCreatedCell": null,
12095
 
12096
 
12097
		/**
12098
		 * This parameter has been replaced by `data` in DataTables to ensure naming
12099
		 * consistency. `dataProp` can still be used, as there is backwards
12100
		 * compatibility in DataTables for this option, but it is strongly
12101
		 * recommended that you use `data` in preference to `dataProp`.
12102
		 *  @name DataTable.defaults.column.dataProp
12103
		 */
12104
 
12105
 
12106
		/**
12107
		 * This property can be used to read data from any data source property,
12108
		 * including deeply nested objects / properties. `data` can be given in a
12109
		 * number of different ways which effect its behaviour:
12110
		 *
12111
		 * * `integer` - treated as an array index for the data source. This is the
12112
		 *   default that DataTables uses (incrementally increased for each column).
12113
		 * * `string` - read an object property from the data source. There are
12114
		 *   three 'special' options that can be used in the string to alter how
12115
		 *   DataTables reads the data from the source object:
12116
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12117
		 *      Javascript to read from nested objects, so to can the options
12118
		 *      specified in `data`. For example: `browser.version` or
12119
		 *      `browser.name`. If your object parameter name contains a period, use
12120
		 *      `\\` to escape it - i.e. `first\\.name`.
12121
		 *    * `[]` - Array notation. DataTables can automatically combine data
12122
		 *      from and array source, joining the data with the characters provided
12123
		 *      between the two brackets. For example: `name[, ]` would provide a
12124
		 *      comma-space separated list from the source array. If no characters
12125
		 *      are provided between the brackets, the original array source is
12126
		 *      returned.
12127
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12128
		 *      execute a function of the name given. For example: `browser()` for a
12129
		 *      simple function on the data source, `browser.version()` for a
12130
		 *      function in a nested property or even `browser().version` to get an
12131
		 *      object property if the function called returns an object. Note that
12132
		 *      function notation is recommended for use in `render` rather than
12133
		 *      `data` as it is much simpler to use as a renderer.
12134
		 * * `null` - use the original data source for the row rather than plucking
12135
		 *   data directly from it. This action has effects on two other
12136
		 *   initialisation options:
12137
		 *    * `defaultContent` - When null is given as the `data` option and
12138
		 *      `defaultContent` is specified for the column, the value defined by
12139
		 *      `defaultContent` will be used for the cell.
12140
		 *    * `render` - When null is used for the `data` option and the `render`
12141
		 *      option is specified for the column, the whole data source for the
12142
		 *      row is used for the renderer.
12143
		 * * `function` - the function given will be executed whenever DataTables
12144
		 *   needs to set or get the data for a cell in the column. The function
12145
		 *   takes three parameters:
12146
		 *    * Parameters:
12147
		 *      * `{array|object}` The data source for the row
12148
		 *      * `{string}` The type call data requested - this will be 'set' when
12149
		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12150
		 *        when gathering data. Note that when `undefined` is given for the
12151
		 *        type DataTables expects to get the raw data for the object back<
12152
		 *      * `{*}` Data to set when the second parameter is 'set'.
12153
		 *    * Return:
12154
		 *      * The return value from the function is not required when 'set' is
12155
		 *        the type of call, but otherwise the return is what will be used
12156
		 *        for the data requested.
12157
		 *
12158
		 * Note that `data` is a getter and setter option. If you just require
12159
		 * formatting of data for output, you will likely want to use `render` which
12160
		 * is simply a getter and thus simpler to use.
12161
		 *
12162
		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12163
		 * name change reflects the flexibility of this property and is consistent
12164
		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12165
		 * be used by DataTables, as it automatically maps the old name to the new
12166
		 * if required.
12167
		 *
12168
		 *  @type string|int|function|null
12169
		 *  @default null <i>Use automatically calculated column index</i>
12170
		 *
12171
		 *  @name DataTable.defaults.column.data
12172
		 *  @dtopt Columns
12173
		 *
12174
		 *  @example
12175
		 *    // Read table data from objects
12176
		 *    // JSON structure for each row:
12177
		 *    //   {
12178
		 *    //      "engine": {value},
12179
		 *    //      "browser": {value},
12180
		 *    //      "platform": {value},
12181
		 *    //      "version": {value},
12182
		 *    //      "grade": {value}
12183
		 *    //   }
12184
		 *    $(document).ready( function() {
12185
		 *      $('#example').dataTable( {
12186
		 *        "ajaxSource": "sources/objects.txt",
12187
		 *        "columns": [
12188
		 *          { "data": "engine" },
12189
		 *          { "data": "browser" },
12190
		 *          { "data": "platform" },
12191
		 *          { "data": "version" },
12192
		 *          { "data": "grade" }
12193
		 *        ]
12194
		 *      } );
12195
		 *    } );
12196
		 *
12197
		 *  @example
12198
		 *    // Read information from deeply nested objects
12199
		 *    // JSON structure for each row:
12200
		 *    //   {
12201
		 *    //      "engine": {value},
12202
		 *    //      "browser": {value},
12203
		 *    //      "platform": {
12204
		 *    //         "inner": {value}
12205
		 *    //      },
12206
		 *    //      "details": [
12207
		 *    //         {value}, {value}
12208
		 *    //      ]
12209
		 *    //   }
12210
		 *    $(document).ready( function() {
12211
		 *      $('#example').dataTable( {
12212
		 *        "ajaxSource": "sources/deep.txt",
12213
		 *        "columns": [
12214
		 *          { "data": "engine" },
12215
		 *          { "data": "browser" },
12216
		 *          { "data": "platform.inner" },
12217
		 *          { "data": "platform.details.0" },
12218
		 *          { "data": "platform.details.1" }
12219
		 *        ]
12220
		 *      } );
12221
		 *    } );
12222
		 *
12223
		 *  @example
12224
		 *    // Using `data` as a function to provide different information for
12225
		 *    // sorting, filtering and display. In this case, currency (price)
12226
		 *    $(document).ready( function() {
12227
		 *      $('#example').dataTable( {
12228
		 *        "columnDefs": [ {
12229
		 *          "targets": [ 0 ],
12230
		 *          "data": function ( source, type, val ) {
12231
		 *            if (type === 'set') {
12232
		 *              source.price = val;
12233
		 *              // Store the computed dislay and filter values for efficiency
12234
		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12235
		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12236
		 *              return;
12237
		 *            }
12238
		 *            else if (type === 'display') {
12239
		 *              return source.price_display;
12240
		 *            }
12241
		 *            else if (type === 'filter') {
12242
		 *              return source.price_filter;
12243
		 *            }
12244
		 *            // 'sort', 'type' and undefined all just use the integer
12245
		 *            return source.price;
12246
		 *          }
12247
		 *        } ]
12248
		 *      } );
12249
		 *    } );
12250
		 *
12251
		 *  @example
12252
		 *    // Using default content
12253
		 *    $(document).ready( function() {
12254
		 *      $('#example').dataTable( {
12255
		 *        "columnDefs": [ {
12256
		 *          "targets": [ 0 ],
12257
		 *          "data": null,
12258
		 *          "defaultContent": "Click to edit"
12259
		 *        } ]
12260
		 *      } );
12261
		 *    } );
12262
		 *
12263
		 *  @example
12264
		 *    // Using array notation - outputting a list from an array
12265
		 *    $(document).ready( function() {
12266
		 *      $('#example').dataTable( {
12267
		 *        "columnDefs": [ {
12268
		 *          "targets": [ 0 ],
12269
		 *          "data": "name[, ]"
12270
		 *        } ]
12271
		 *      } );
12272
		 *    } );
12273
		 *
12274
		 */
12275
		"mData": null,
12276
 
12277
 
12278
		/**
12279
		 * This property is the rendering partner to `data` and it is suggested that
12280
		 * when you want to manipulate data for display (including filtering,
12281
		 * sorting etc) without altering the underlying data for the table, use this
12282
		 * property. `render` can be considered to be the the read only companion to
12283
		 * `data` which is read / write (then as such more complex). Like `data`
12284
		 * this option can be given in a number of different ways to effect its
12285
		 * behaviour:
12286
		 *
12287
		 * * `integer` - treated as an array index for the data source. This is the
12288
		 *   default that DataTables uses (incrementally increased for each column).
12289
		 * * `string` - read an object property from the data source. There are
12290
		 *   three 'special' options that can be used in the string to alter how
12291
		 *   DataTables reads the data from the source object:
12292
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12293
		 *      Javascript to read from nested objects, so to can the options
12294
		 *      specified in `data`. For example: `browser.version` or
12295
		 *      `browser.name`. If your object parameter name contains a period, use
12296
		 *      `\\` to escape it - i.e. `first\\.name`.
12297
		 *    * `[]` - Array notation. DataTables can automatically combine data
12298
		 *      from and array source, joining the data with the characters provided
12299
		 *      between the two brackets. For example: `name[, ]` would provide a
12300
		 *      comma-space separated list from the source array. If no characters
12301
		 *      are provided between the brackets, the original array source is
12302
		 *      returned.
12303
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12304
		 *      execute a function of the name given. For example: `browser()` for a
12305
		 *      simple function on the data source, `browser.version()` for a
12306
		 *      function in a nested property or even `browser().version` to get an
12307
		 *      object property if the function called returns an object.
12308
		 * * `object` - use different data for the different data types requested by
12309
		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12310
		 *   of the object is the data type the property refers to and the value can
12311
		 *   defined using an integer, string or function using the same rules as
12312
		 *   `render` normally does. Note that an `_` option _must_ be specified.
12313
		 *   This is the default value to use if you haven't specified a value for
12314
		 *   the data type requested by DataTables.
12315
		 * * `function` - the function given will be executed whenever DataTables
12316
		 *   needs to set or get the data for a cell in the column. The function
12317
		 *   takes three parameters:
12318
		 *    * Parameters:
12319
		 *      * {array|object} The data source for the row (based on `data`)
12320
		 *      * {string} The type call data requested - this will be 'filter',
12321
		 *        'display', 'type' or 'sort'.
12322
		 *      * {array|object} The full data source for the row (not based on
12323
		 *        `data`)
12324
		 *    * Return:
12325
		 *      * The return value from the function is what will be used for the
12326
		 *        data requested.
12327
		 *
12328
		 *  @type string|int|function|object|null
12329
		 *  @default null Use the data source value.
12330
		 *
12331
		 *  @name DataTable.defaults.column.render
12332
		 *  @dtopt Columns
12333
		 *
12334
		 *  @example
12335
		 *    // Create a comma separated list from an array of objects
12336
		 *    $(document).ready( function() {
12337
		 *      $('#example').dataTable( {
12338
		 *        "ajaxSource": "sources/deep.txt",
12339
		 *        "columns": [
12340
		 *          { "data": "engine" },
12341
		 *          { "data": "browser" },
12342
		 *          {
12343
		 *            "data": "platform",
12344
		 *            "render": "[, ].name"
12345
		 *          }
12346
		 *        ]
12347
		 *      } );
12348
		 *    } );
12349
		 *
12350
		 *  @example
12351
		 *    // Execute a function to obtain data
12352
		 *    $(document).ready( function() {
12353
		 *      $('#example').dataTable( {
12354
		 *        "columnDefs": [ {
12355
		 *          "targets": [ 0 ],
12356
		 *          "data": null, // Use the full data source object for the renderer's source
12357
		 *          "render": "browserName()"
12358
		 *        } ]
12359
		 *      } );
12360
		 *    } );
12361
		 *
12362
		 *  @example
12363
		 *    // As an object, extracting different data for the different types
12364
		 *    // This would be used with a data source such as:
12365
		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12366
		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12367
		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12368
		 *    // the formatted phone number is the one that is shown in the table.
12369
		 *    $(document).ready( function() {
12370
		 *      $('#example').dataTable( {
12371
		 *        "columnDefs": [ {
12372
		 *          "targets": [ 0 ],
12373
		 *          "data": null, // Use the full data source object for the renderer's source
12374
		 *          "render": {
12375
		 *            "_": "phone",
12376
		 *            "filter": "phone_filter",
12377
		 *            "display": "phone_display"
12378
		 *          }
12379
		 *        } ]
12380
		 *      } );
12381
		 *    } );
12382
		 *
12383
		 *  @example
12384
		 *    // Use as a function to create a link from the data source
12385
		 *    $(document).ready( function() {
12386
		 *      $('#example').dataTable( {
12387
		 *        "columnDefs": [ {
12388
		 *          "targets": [ 0 ],
12389
		 *          "data": "download_link",
12390
		 *          "render": function ( data, type, full ) {
12391
		 *            return '<a href="'+data+'">Download</a>';
12392
		 *          }
12393
		 *        } ]
12394
		 *      } );
12395
		 *    } );
12396
		 */
12397
		"mRender": null,
12398
 
12399
 
12400
		/**
12401
		 * Change the cell type created for the column - either TD cells or TH cells. This
12402
		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12403
		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12404
		 *  @type string
12405
		 *  @default td
12406
		 *
12407
		 *  @name DataTable.defaults.column.cellType
12408
		 *  @dtopt Columns
12409
		 *
12410
		 *  @example
12411
		 *    // Make the first column use TH cells
12412
		 *    $(document).ready( function() {
12413
		 *      $('#example').dataTable( {
12414
		 *        "columnDefs": [ {
12415
		 *          "targets": [ 0 ],
12416
		 *          "cellType": "th"
12417
		 *        } ]
12418
		 *      } );
12419
		 *    } );
12420
		 */
12421
		"sCellType": "td",
12422
 
12423
 
12424
		/**
12425
		 * Class to give to each cell in this column.
12426
		 *  @type string
12427
		 *  @default <i>Empty string</i>
12428
		 *
12429
		 *  @name DataTable.defaults.column.class
12430
		 *  @dtopt Columns
12431
		 *
12432
		 *  @example
12433
		 *    // Using `columnDefs`
12434
		 *    $(document).ready( function() {
12435
		 *      $('#example').dataTable( {
12436
		 *        "columnDefs": [
12437
		 *          { "class": "my_class", "targets": [ 0 ] }
12438
		 *        ]
12439
		 *      } );
12440
		 *    } );
12441
		 *
12442
		 *  @example
12443
		 *    // Using `columns`
12444
		 *    $(document).ready( function() {
12445
		 *      $('#example').dataTable( {
12446
		 *        "columns": [
12447
		 *          { "class": "my_class" },
12448
		 *          null,
12449
		 *          null,
12450
		 *          null,
12451
		 *          null
12452
		 *        ]
12453
		 *      } );
12454
		 *    } );
12455
		 */
12456
		"sClass": "",
12457
 
12458
		/**
12459
		 * When DataTables calculates the column widths to assign to each column,
12460
		 * it finds the longest string in each column and then constructs a
12461
		 * temporary table and reads the widths from that. The problem with this
12462
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12463
		 * string - thus the calculation can go wrong (doing it properly and putting
12464
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12465
		 * a "work around" we provide this option. It will append its value to the
12466
		 * text that is found to be the longest string for the column - i.e. padding.
12467
		 * Generally you shouldn't need this!
12468
		 *  @type string
12469
		 *  @default <i>Empty string<i>
12470
		 *
12471
		 *  @name DataTable.defaults.column.contentPadding
12472
		 *  @dtopt Columns
12473
		 *
12474
		 *  @example
12475
		 *    // Using `columns`
12476
		 *    $(document).ready( function() {
12477
		 *      $('#example').dataTable( {
12478
		 *        "columns": [
12479
		 *          null,
12480
		 *          null,
12481
		 *          null,
12482
		 *          {
12483
		 *            "contentPadding": "mmm"
12484
		 *          }
12485
		 *        ]
12486
		 *      } );
12487
		 *    } );
12488
		 */
12489
		"sContentPadding": "",
12490
 
12491
 
12492
		/**
12493
		 * Allows a default value to be given for a column's data, and will be used
12494
		 * whenever a null data source is encountered (this can be because `data`
12495
		 * is set to null, or because the data source itself is null).
12496
		 *  @type string
12497
		 *  @default null
12498
		 *
12499
		 *  @name DataTable.defaults.column.defaultContent
12500
		 *  @dtopt Columns
12501
		 *
12502
		 *  @example
12503
		 *    // Using `columnDefs`
12504
		 *    $(document).ready( function() {
12505
		 *      $('#example').dataTable( {
12506
		 *        "columnDefs": [
12507
		 *          {
12508
		 *            "data": null,
12509
		 *            "defaultContent": "Edit",
12510
		 *            "targets": [ -1 ]
12511
		 *          }
12512
		 *        ]
12513
		 *      } );
12514
		 *    } );
12515
		 *
12516
		 *  @example
12517
		 *    // Using `columns`
12518
		 *    $(document).ready( function() {
12519
		 *      $('#example').dataTable( {
12520
		 *        "columns": [
12521
		 *          null,
12522
		 *          null,
12523
		 *          null,
12524
		 *          {
12525
		 *            "data": null,
12526
		 *            "defaultContent": "Edit"
12527
		 *          }
12528
		 *        ]
12529
		 *      } );
12530
		 *    } );
12531
		 */
12532
		"sDefaultContent": null,
12533
 
12534
 
12535
		/**
12536
		 * This parameter is only used in DataTables' server-side processing. It can
12537
		 * be exceptionally useful to know what columns are being displayed on the
12538
		 * client side, and to map these to database fields. When defined, the names
12539
		 * also allow DataTables to reorder information from the server if it comes
12540
		 * back in an unexpected order (i.e. if you switch your columns around on the
12541
		 * client-side, your server-side code does not also need updating).
12542
		 *  @type string
12543
		 *  @default <i>Empty string</i>
12544
		 *
12545
		 *  @name DataTable.defaults.column.name
12546
		 *  @dtopt Columns
12547
		 *
12548
		 *  @example
12549
		 *    // Using `columnDefs`
12550
		 *    $(document).ready( function() {
12551
		 *      $('#example').dataTable( {
12552
		 *        "columnDefs": [
12553
		 *          { "name": "engine", "targets": [ 0 ] },
12554
		 *          { "name": "browser", "targets": [ 1 ] },
12555
		 *          { "name": "platform", "targets": [ 2 ] },
12556
		 *          { "name": "version", "targets": [ 3 ] },
12557
		 *          { "name": "grade", "targets": [ 4 ] }
12558
		 *        ]
12559
		 *      } );
12560
		 *    } );
12561
		 *
12562
		 *  @example
12563
		 *    // Using `columns`
12564
		 *    $(document).ready( function() {
12565
		 *      $('#example').dataTable( {
12566
		 *        "columns": [
12567
		 *          { "name": "engine" },
12568
		 *          { "name": "browser" },
12569
		 *          { "name": "platform" },
12570
		 *          { "name": "version" },
12571
		 *          { "name": "grade" }
12572
		 *        ]
12573
		 *      } );
12574
		 *    } );
12575
		 */
12576
		"sName": "",
12577
 
12578
 
12579
		/**
12580
		 * Defines a data source type for the ordering which can be used to read
12581
		 * real-time information from the table (updating the internally cached
12582
		 * version) prior to ordering. This allows ordering to occur on user
12583
		 * editable elements such as form inputs.
12584
		 *  @type string
12585
		 *  @default std
12586
		 *
12587
		 *  @name DataTable.defaults.column.orderDataType
12588
		 *  @dtopt Columns
12589
		 *
12590
		 *  @example
12591
		 *    // Using `columnDefs`
12592
		 *    $(document).ready( function() {
12593
		 *      $('#example').dataTable( {
12594
		 *        "columnDefs": [
12595
		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12596
		 *          { "type": "numeric", "targets": [ 3 ] },
12597
		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12598
		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12599
		 *        ]
12600
		 *      } );
12601
		 *    } );
12602
		 *
12603
		 *  @example
12604
		 *    // Using `columns`
12605
		 *    $(document).ready( function() {
12606
		 *      $('#example').dataTable( {
12607
		 *        "columns": [
12608
		 *          null,
12609
		 *          null,
12610
		 *          { "orderDataType": "dom-text" },
12611
		 *          { "orderDataType": "dom-text", "type": "numeric" },
12612
		 *          { "orderDataType": "dom-select" },
12613
		 *          { "orderDataType": "dom-checkbox" }
12614
		 *        ]
12615
		 *      } );
12616
		 *    } );
12617
		 */
12618
		"sSortDataType": "std",
12619
 
12620
 
12621
		/**
12622
		 * The title of this column.
12623
		 *  @type string
12624
		 *  @default null <i>Derived from the 'TH' value for this column in the
12625
		 *    original HTML table.</i>
12626
		 *
12627
		 *  @name DataTable.defaults.column.title
12628
		 *  @dtopt Columns
12629
		 *
12630
		 *  @example
12631
		 *    // Using `columnDefs`
12632
		 *    $(document).ready( function() {
12633
		 *      $('#example').dataTable( {
12634
		 *        "columnDefs": [
12635
		 *          { "title": "My column title", "targets": [ 0 ] }
12636
		 *        ]
12637
		 *      } );
12638
		 *    } );
12639
		 *
12640
		 *  @example
12641
		 *    // Using `columns`
12642
		 *    $(document).ready( function() {
12643
		 *      $('#example').dataTable( {
12644
		 *        "columns": [
12645
		 *          { "title": "My column title" },
12646
		 *          null,
12647
		 *          null,
12648
		 *          null,
12649
		 *          null
12650
		 *        ]
12651
		 *      } );
12652
		 *    } );
12653
		 */
12654
		"sTitle": null,
12655
 
12656
 
12657
		/**
12658
		 * The type allows you to specify how the data for this column will be
12659
		 * ordered. Four types (string, numeric, date and html (which will strip
12660
		 * HTML tags before ordering)) are currently available. Note that only date
12661
		 * formats understood by Javascript's Date() object will be accepted as type
12662
		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12663
		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12664
		 * through plug-ins.
12665
		 *  @type string
12666
		 *  @default null <i>Auto-detected from raw data</i>
12667
		 *
12668
		 *  @name DataTable.defaults.column.type
12669
		 *  @dtopt Columns
12670
		 *
12671
		 *  @example
12672
		 *    // Using `columnDefs`
12673
		 *    $(document).ready( function() {
12674
		 *      $('#example').dataTable( {
12675
		 *        "columnDefs": [
12676
		 *          { "type": "html", "targets": [ 0 ] }
12677
		 *        ]
12678
		 *      } );
12679
		 *    } );
12680
		 *
12681
		 *  @example
12682
		 *    // Using `columns`
12683
		 *    $(document).ready( function() {
12684
		 *      $('#example').dataTable( {
12685
		 *        "columns": [
12686
		 *          { "type": "html" },
12687
		 *          null,
12688
		 *          null,
12689
		 *          null,
12690
		 *          null
12691
		 *        ]
12692
		 *      } );
12693
		 *    } );
12694
		 */
12695
		"sType": null,
12696
 
12697
 
12698
		/**
12699
		 * Defining the width of the column, this parameter may take any CSS value
12700
		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12701
		 * been given a specific width through this interface ensuring that the table
12702
		 * remains readable.
12703
		 *  @type string
12704
		 *  @default null <i>Automatic</i>
12705
		 *
12706
		 *  @name DataTable.defaults.column.width
12707
		 *  @dtopt Columns
12708
		 *
12709
		 *  @example
12710
		 *    // Using `columnDefs`
12711
		 *    $(document).ready( function() {
12712
		 *      $('#example').dataTable( {
12713
		 *        "columnDefs": [
12714
		 *          { "width": "20%", "targets": [ 0 ] }
12715
		 *        ]
12716
		 *      } );
12717
		 *    } );
12718
		 *
12719
		 *  @example
12720
		 *    // Using `columns`
12721
		 *    $(document).ready( function() {
12722
		 *      $('#example').dataTable( {
12723
		 *        "columns": [
12724
		 *          { "width": "20%" },
12725
		 *          null,
12726
		 *          null,
12727
		 *          null,
12728
		 *          null
12729
		 *        ]
12730
		 *      } );
12731
		 *    } );
12732
		 */
12733
		"sWidth": null
12734
	};
12735
 
12736
	_fnHungarianMap( DataTable.defaults.column );
12737
 
12738
 
12739
 
12740
	/**
12741
	 * DataTables settings object - this holds all the information needed for a
12742
	 * given table, including configuration, data and current application of the
12743
	 * table options. DataTables does not have a single instance for each DataTable
12744
	 * with the settings attached to that instance, but rather instances of the
12745
	 * DataTable "class" are created on-the-fly as needed (typically by a
12746
	 * $().dataTable() call) and the settings object is then applied to that
12747
	 * instance.
12748
	 *
12749
	 * Note that this object is related to {@link DataTable.defaults} but this
12750
	 * one is the internal data store for DataTables's cache of columns. It should
12751
	 * NOT be manipulated outside of DataTables. Any configuration should be done
12752
	 * through the initialisation options.
12753
	 *  @namespace
12754
	 *  @todo Really should attach the settings object to individual instances so we
12755
	 *    don't need to create new instances on each $().dataTable() call (if the
12756
	 *    table already exists). It would also save passing oSettings around and
12757
	 *    into every single function. However, this is a very significant
12758
	 *    architecture change for DataTables and will almost certainly break
12759
	 *    backwards compatibility with older installations. This is something that
12760
	 *    will be done in 2.0.
12761
	 */
12762
	DataTable.models.oSettings = {
12763
		/**
12764
		 * Primary features of DataTables and their enablement state.
12765
		 *  @namespace
12766
		 */
12767
		"oFeatures": {
12768
 
12769
			/**
12770
			 * Flag to say if DataTables should automatically try to calculate the
12771
			 * optimum table and columns widths (true) or not (false).
12772
			 * Note that this parameter will be set by the initialisation routine. To
12773
			 * set a default use {@link DataTable.defaults}.
12774
			 *  @type boolean
12775
			 */
12776
			"bAutoWidth": null,
12777
 
12778
			/**
12779
			 * Delay the creation of TR and TD elements until they are actually
12780
			 * needed by a driven page draw. This can give a significant speed
12781
			 * increase for Ajax source and Javascript source data, but makes no
12782
			 * difference at all fro DOM and server-side processing tables.
12783
			 * Note that this parameter will be set by the initialisation routine. To
12784
			 * set a default use {@link DataTable.defaults}.
12785
			 *  @type boolean
12786
			 */
12787
			"bDeferRender": null,
12788
 
12789
			/**
12790
			 * Enable filtering on the table or not. Note that if this is disabled
12791
			 * then there is no filtering at all on the table, including fnFilter.
12792
			 * To just remove the filtering input use sDom and remove the 'f' option.
12793
			 * Note that this parameter will be set by the initialisation routine. To
12794
			 * set a default use {@link DataTable.defaults}.
12795
			 *  @type boolean
12796
			 */
12797
			"bFilter": null,
12798
 
12799
			/**
12800
			 * Table information element (the 'Showing x of y records' div) enable
12801
			 * flag.
12802
			 * Note that this parameter will be set by the initialisation routine. To
12803
			 * set a default use {@link DataTable.defaults}.
12804
			 *  @type boolean
12805
			 */
12806
			"bInfo": null,
12807
 
12808
			/**
12809
			 * Present a user control allowing the end user to change the page size
12810
			 * when pagination is enabled.
12811
			 * Note that this parameter will be set by the initialisation routine. To
12812
			 * set a default use {@link DataTable.defaults}.
12813
			 *  @type boolean
12814
			 */
12815
			"bLengthChange": null,
12816
 
12817
			/**
12818
			 * Pagination enabled or not. Note that if this is disabled then length
12819
			 * changing must also be disabled.
12820
			 * Note that this parameter will be set by the initialisation routine. To
12821
			 * set a default use {@link DataTable.defaults}.
12822
			 *  @type boolean
12823
			 */
12824
			"bPaginate": null,
12825
 
12826
			/**
12827
			 * Processing indicator enable flag whenever DataTables is enacting a
12828
			 * user request - typically an Ajax request for server-side processing.
12829
			 * Note that this parameter will be set by the initialisation routine. To
12830
			 * set a default use {@link DataTable.defaults}.
12831
			 *  @type boolean
12832
			 */
12833
			"bProcessing": null,
12834
 
12835
			/**
12836
			 * Server-side processing enabled flag - when enabled DataTables will
12837
			 * get all data from the server for every draw - there is no filtering,
12838
			 * sorting or paging done on the client-side.
12839
			 * Note that this parameter will be set by the initialisation routine. To
12840
			 * set a default use {@link DataTable.defaults}.
12841
			 *  @type boolean
12842
			 */
12843
			"bServerSide": null,
12844
 
12845
			/**
12846
			 * Sorting enablement flag.
12847
			 * Note that this parameter will be set by the initialisation routine. To
12848
			 * set a default use {@link DataTable.defaults}.
12849
			 *  @type boolean
12850
			 */
12851
			"bSort": null,
12852
 
12853
			/**
12854
			 * Multi-column sorting
12855
			 * Note that this parameter will be set by the initialisation routine. To
12856
			 * set a default use {@link DataTable.defaults}.
12857
			 *  @type boolean
12858
			 */
12859
			"bSortMulti": null,
12860
 
12861
			/**
12862
			 * Apply a class to the columns which are being sorted to provide a
12863
			 * visual highlight or not. This can slow things down when enabled since
12864
			 * there is a lot of DOM interaction.
12865
			 * Note that this parameter will be set by the initialisation routine. To
12866
			 * set a default use {@link DataTable.defaults}.
12867
			 *  @type boolean
12868
			 */
12869
			"bSortClasses": null,
12870
 
12871
			/**
12872
			 * State saving enablement flag.
12873
			 * Note that this parameter will be set by the initialisation routine. To
12874
			 * set a default use {@link DataTable.defaults}.
12875
			 *  @type boolean
12876
			 */
12877
			"bStateSave": null
12878
		},
12879
 
12880
 
12881
		/**
12882
		 * Scrolling settings for a table.
12883
		 *  @namespace
12884
		 */
12885
		"oScroll": {
12886
			/**
12887
			 * When the table is shorter in height than sScrollY, collapse the
12888
			 * table container down to the height of the table (when true).
12889
			 * Note that this parameter will be set by the initialisation routine. To
12890
			 * set a default use {@link DataTable.defaults}.
12891
			 *  @type boolean
12892
			 */
12893
			"bCollapse": null,
12894
 
12895
			/**
12896
			 * Width of the scrollbar for the web-browser's platform. Calculated
12897
			 * during table initialisation.
12898
			 *  @type int
12899
			 *  @default 0
12900
			 */
12901
			"iBarWidth": 0,
12902
 
12903
			/**
12904
			 * Viewport width for horizontal scrolling. Horizontal scrolling is
12905
			 * disabled if an empty string.
12906
			 * Note that this parameter will be set by the initialisation routine. To
12907
			 * set a default use {@link DataTable.defaults}.
12908
			 *  @type string
12909
			 */
12910
			"sX": null,
12911
 
12912
			/**
12913
			 * Width to expand the table to when using x-scrolling. Typically you
12914
			 * should not need to use this.
12915
			 * Note that this parameter will be set by the initialisation routine. To
12916
			 * set a default use {@link DataTable.defaults}.
12917
			 *  @type string
12918
			 *  @deprecated
12919
			 */
12920
			"sXInner": null,
12921
 
12922
			/**
12923
			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
12924
			 * if an empty string.
12925
			 * Note that this parameter will be set by the initialisation routine. To
12926
			 * set a default use {@link DataTable.defaults}.
12927
			 *  @type string
12928
			 */
12929
			"sY": null
12930
		},
12931
 
12932
		/**
12933
		 * Language information for the table.
12934
		 *  @namespace
12935
		 *  @extends DataTable.defaults.oLanguage
12936
		 */
12937
		"oLanguage": {
12938
			/**
12939
			 * Information callback function. See
12940
			 * {@link DataTable.defaults.fnInfoCallback}
12941
			 *  @type function
12942
			 *  @default null
12943
			 */
12944
			"fnInfoCallback": null
12945
		},
12946
 
12947
		/**
12948
		 * Browser support parameters
12949
		 *  @namespace
12950
		 */
12951
		"oBrowser": {
12952
			/**
12953
			 * Indicate if the browser incorrectly calculates width:100% inside a
12954
			 * scrolling element (IE6/7)
12955
			 *  @type boolean
12956
			 *  @default false
12957
			 */
12958
			"bScrollOversize": false,
12959
 
12960
			/**
12961
			 * Determine if the vertical scrollbar is on the right or left of the
12962
			 * scrolling container - needed for rtl language layout, although not
12963
			 * all browsers move the scrollbar (Safari).
12964
			 *  @type boolean
12965
			 *  @default false
12966
			 */
12967
			"bScrollbarLeft": false,
12968
 
12969
			/**
12970
			 * Flag for if `getBoundingClientRect` is fully supported or not
12971
			 *  @type boolean
12972
			 *  @default false
12973
			 */
12974
			"bBounding": false,
12975
 
12976
			/**
12977
			 * Browser scrollbar width
12978
			 *  @type integer
12979
			 *  @default 0
12980
			 */
12981
			"barWidth": 0
12982
		},
12983
 
12984
 
12985
		"ajax": null,
12986
 
12987
 
12988
		/**
12989
		 * Array referencing the nodes which are used for the features. The
12990
		 * parameters of this object match what is allowed by sDom - i.e.
12991
		 *   <ul>
12992
		 *     <li>'l' - Length changing</li>
12993
		 *     <li>'f' - Filtering input</li>
12994
		 *     <li>'t' - The table!</li>
12995
		 *     <li>'i' - Information</li>
12996
		 *     <li>'p' - Pagination</li>
12997
		 *     <li>'r' - pRocessing</li>
12998
		 *   </ul>
12999
		 *  @type array
13000
		 *  @default []
13001
		 */
13002
		"aanFeatures": [],
13003
 
13004
		/**
13005
		 * Store data information - see {@link DataTable.models.oRow} for detailed
13006
		 * information.
13007
		 *  @type array
13008
		 *  @default []
13009
		 */
13010
		"aoData": [],
13011
 
13012
		/**
13013
		 * Array of indexes which are in the current display (after filtering etc)
13014
		 *  @type array
13015
		 *  @default []
13016
		 */
13017
		"aiDisplay": [],
13018
 
13019
		/**
13020
		 * Array of indexes for display - no filtering
13021
		 *  @type array
13022
		 *  @default []
13023
		 */
13024
		"aiDisplayMaster": [],
13025
 
13026
		/**
13027
		 * Map of row ids to data indexes
13028
		 *  @type object
13029
		 *  @default {}
13030
		 */
13031
		"aIds": {},
13032
 
13033
		/**
13034
		 * Store information about each column that is in use
13035
		 *  @type array
13036
		 *  @default []
13037
		 */
13038
		"aoColumns": [],
13039
 
13040
		/**
13041
		 * Store information about the table's header
13042
		 *  @type array
13043
		 *  @default []
13044
		 */
13045
		"aoHeader": [],
13046
 
13047
		/**
13048
		 * Store information about the table's footer
13049
		 *  @type array
13050
		 *  @default []
13051
		 */
13052
		"aoFooter": [],
13053
 
13054
		/**
13055
		 * Store the applied global search information in case we want to force a
13056
		 * research or compare the old search to a new one.
13057
		 * Note that this parameter will be set by the initialisation routine. To
13058
		 * set a default use {@link DataTable.defaults}.
13059
		 *  @namespace
13060
		 *  @extends DataTable.models.oSearch
13061
		 */
13062
		"oPreviousSearch": {},
13063
 
13064
		/**
13065
		 * Store the applied search for each column - see
13066
		 * {@link DataTable.models.oSearch} for the format that is used for the
13067
		 * filtering information for each column.
13068
		 *  @type array
13069
		 *  @default []
13070
		 */
13071
		"aoPreSearchCols": [],
13072
 
13073
		/**
13074
		 * Sorting that is applied to the table. Note that the inner arrays are
13075
		 * used in the following manner:
13076
		 * <ul>
13077
		 *   <li>Index 0 - column number</li>
13078
		 *   <li>Index 1 - current sorting direction</li>
13079
		 * </ul>
13080
		 * Note that this parameter will be set by the initialisation routine. To
13081
		 * set a default use {@link DataTable.defaults}.
13082
		 *  @type array
13083
		 *  @todo These inner arrays should really be objects
13084
		 */
13085
		"aaSorting": null,
13086
 
13087
		/**
13088
		 * Sorting that is always applied to the table (i.e. prefixed in front of
13089
		 * aaSorting).
13090
		 * Note that this parameter will be set by the initialisation routine. To
13091
		 * set a default use {@link DataTable.defaults}.
13092
		 *  @type array
13093
		 *  @default []
13094
		 */
13095
		"aaSortingFixed": [],
13096
 
13097
		/**
13098
		 * Classes to use for the striping of a table.
13099
		 * Note that this parameter will be set by the initialisation routine. To
13100
		 * set a default use {@link DataTable.defaults}.
13101
		 *  @type array
13102
		 *  @default []
13103
		 */
13104
		"asStripeClasses": null,
13105
 
13106
		/**
13107
		 * If restoring a table - we should restore its striping classes as well
13108
		 *  @type array
13109
		 *  @default []
13110
		 */
13111
		"asDestroyStripes": [],
13112
 
13113
		/**
13114
		 * If restoring a table - we should restore its width
13115
		 *  @type int
13116
		 *  @default 0
13117
		 */
13118
		"sDestroyWidth": 0,
13119
 
13120
		/**
13121
		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13122
		 *  @type array
13123
		 *  @default []
13124
		 */
13125
		"aoRowCallback": [],
13126
 
13127
		/**
13128
		 * Callback functions for the header on each draw.
13129
		 *  @type array
13130
		 *  @default []
13131
		 */
13132
		"aoHeaderCallback": [],
13133
 
13134
		/**
13135
		 * Callback function for the footer on each draw.
13136
		 *  @type array
13137
		 *  @default []
13138
		 */
13139
		"aoFooterCallback": [],
13140
 
13141
		/**
13142
		 * Array of callback functions for draw callback functions
13143
		 *  @type array
13144
		 *  @default []
13145
		 */
13146
		"aoDrawCallback": [],
13147
 
13148
		/**
13149
		 * Array of callback functions for row created function
13150
		 *  @type array
13151
		 *  @default []
13152
		 */
13153
		"aoRowCreatedCallback": [],
13154
 
13155
		/**
13156
		 * Callback functions for just before the table is redrawn. A return of
13157
		 * false will be used to cancel the draw.
13158
		 *  @type array
13159
		 *  @default []
13160
		 */
13161
		"aoPreDrawCallback": [],
13162
 
13163
		/**
13164
		 * Callback functions for when the table has been initialised.
13165
		 *  @type array
13166
		 *  @default []
13167
		 */
13168
		"aoInitComplete": [],
13169
 
13170
 
13171
		/**
13172
		 * Callbacks for modifying the settings to be stored for state saving, prior to
13173
		 * saving state.
13174
		 *  @type array
13175
		 *  @default []
13176
		 */
13177
		"aoStateSaveParams": [],
13178
 
13179
		/**
13180
		 * Callbacks for modifying the settings that have been stored for state saving
13181
		 * prior to using the stored values to restore the state.
13182
		 *  @type array
13183
		 *  @default []
13184
		 */
13185
		"aoStateLoadParams": [],
13186
 
13187
		/**
13188
		 * Callbacks for operating on the settings object once the saved state has been
13189
		 * loaded
13190
		 *  @type array
13191
		 *  @default []
13192
		 */
13193
		"aoStateLoaded": [],
13194
 
13195
		/**
13196
		 * Cache the table ID for quick access
13197
		 *  @type string
13198
		 *  @default <i>Empty string</i>
13199
		 */
13200
		"sTableId": "",
13201
 
13202
		/**
13203
		 * The TABLE node for the main table
13204
		 *  @type node
13205
		 *  @default null
13206
		 */
13207
		"nTable": null,
13208
 
13209
		/**
13210
		 * Permanent ref to the thead element
13211
		 *  @type node
13212
		 *  @default null
13213
		 */
13214
		"nTHead": null,
13215
 
13216
		/**
13217
		 * Permanent ref to the tfoot element - if it exists
13218
		 *  @type node
13219
		 *  @default null
13220
		 */
13221
		"nTFoot": null,
13222
 
13223
		/**
13224
		 * Permanent ref to the tbody element
13225
		 *  @type node
13226
		 *  @default null
13227
		 */
13228
		"nTBody": null,
13229
 
13230
		/**
13231
		 * Cache the wrapper node (contains all DataTables controlled elements)
13232
		 *  @type node
13233
		 *  @default null
13234
		 */
13235
		"nTableWrapper": null,
13236
 
13237
		/**
13238
		 * Indicate if when using server-side processing the loading of data
13239
		 * should be deferred until the second draw.
13240
		 * Note that this parameter will be set by the initialisation routine. To
13241
		 * set a default use {@link DataTable.defaults}.
13242
		 *  @type boolean
13243
		 *  @default false
13244
		 */
13245
		"bDeferLoading": false,
13246
 
13247
		/**
13248
		 * Indicate if all required information has been read in
13249
		 *  @type boolean
13250
		 *  @default false
13251
		 */
13252
		"bInitialised": false,
13253
 
13254
		/**
13255
		 * Information about open rows. Each object in the array has the parameters
13256
		 * 'nTr' and 'nParent'
13257
		 *  @type array
13258
		 *  @default []
13259
		 */
13260
		"aoOpenRows": [],
13261
 
13262
		/**
13263
		 * Dictate the positioning of DataTables' control elements - see
13264
		 * {@link DataTable.model.oInit.sDom}.
13265
		 * Note that this parameter will be set by the initialisation routine. To
13266
		 * set a default use {@link DataTable.defaults}.
13267
		 *  @type string
13268
		 *  @default null
13269
		 */
13270
		"sDom": null,
13271
 
13272
		/**
13273
		 * Search delay (in mS)
13274
		 *  @type integer
13275
		 *  @default null
13276
		 */
13277
		"searchDelay": null,
13278
 
13279
		/**
13280
		 * Which type of pagination should be used.
13281
		 * Note that this parameter will be set by the initialisation routine. To
13282
		 * set a default use {@link DataTable.defaults}.
13283
		 *  @type string
13284
		 *  @default two_button
13285
		 */
13286
		"sPaginationType": "two_button",
13287
 
13288
		/**
13289
		 * The state duration (for `stateSave`) in seconds.
13290
		 * Note that this parameter will be set by the initialisation routine. To
13291
		 * set a default use {@link DataTable.defaults}.
13292
		 *  @type int
13293
		 *  @default 0
13294
		 */
13295
		"iStateDuration": 0,
13296
 
13297
		/**
13298
		 * Array of callback functions for state saving. Each array element is an
13299
		 * object with the following parameters:
13300
		 *   <ul>
13301
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13302
		 *       and the JSON string to save that has been thus far created. Returns
13303
		 *       a JSON string to be inserted into a json object
13304
		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13305
		 *     <li>string:sName - name of callback</li>
13306
		 *   </ul>
13307
		 *  @type array
13308
		 *  @default []
13309
		 */
13310
		"aoStateSave": [],
13311
 
13312
		/**
13313
		 * Array of callback functions for state loading. Each array element is an
13314
		 * object with the following parameters:
13315
		 *   <ul>
13316
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13317
		 *       and the object stored. May return false to cancel state loading</li>
13318
		 *     <li>string:sName - name of callback</li>
13319
		 *   </ul>
13320
		 *  @type array
13321
		 *  @default []
13322
		 */
13323
		"aoStateLoad": [],
13324
 
13325
		/**
13326
		 * State that was saved. Useful for back reference
13327
		 *  @type object
13328
		 *  @default null
13329
		 */
13330
		"oSavedState": null,
13331
 
13332
		/**
13333
		 * State that was loaded. Useful for back reference
13334
		 *  @type object
13335
		 *  @default null
13336
		 */
13337
		"oLoadedState": null,
13338
 
13339
		/**
13340
		 * Source url for AJAX data for the table.
13341
		 * Note that this parameter will be set by the initialisation routine. To
13342
		 * set a default use {@link DataTable.defaults}.
13343
		 *  @type string
13344
		 *  @default null
13345
		 */
13346
		"sAjaxSource": null,
13347
 
13348
		/**
13349
		 * Property from a given object from which to read the table data from. This
13350
		 * can be an empty string (when not server-side processing), in which case
13351
		 * it is  assumed an an array is given directly.
13352
		 * Note that this parameter will be set by the initialisation routine. To
13353
		 * set a default use {@link DataTable.defaults}.
13354
		 *  @type string
13355
		 */
13356
		"sAjaxDataProp": null,
13357
 
13358
		/**
13359
		 * Note if draw should be blocked while getting data
13360
		 *  @type boolean
13361
		 *  @default true
13362
		 */
13363
		"bAjaxDataGet": true,
13364
 
13365
		/**
13366
		 * The last jQuery XHR object that was used for server-side data gathering.
13367
		 * This can be used for working with the XHR information in one of the
13368
		 * callbacks
13369
		 *  @type object
13370
		 *  @default null
13371
		 */
13372
		"jqXHR": null,
13373
 
13374
		/**
13375
		 * JSON returned from the server in the last Ajax request
13376
		 *  @type object
13377
		 *  @default undefined
13378
		 */
13379
		"json": undefined,
13380
 
13381
		/**
13382
		 * Data submitted as part of the last Ajax request
13383
		 *  @type object
13384
		 *  @default undefined
13385
		 */
13386
		"oAjaxData": undefined,
13387
 
13388
		/**
13389
		 * Function to get the server-side data.
13390
		 * Note that this parameter will be set by the initialisation routine. To
13391
		 * set a default use {@link DataTable.defaults}.
13392
		 *  @type function
13393
		 */
13394
		"fnServerData": null,
13395
 
13396
		/**
13397
		 * Functions which are called prior to sending an Ajax request so extra
13398
		 * parameters can easily be sent to the server
13399
		 *  @type array
13400
		 *  @default []
13401
		 */
13402
		"aoServerParams": [],
13403
 
13404
		/**
13405
		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13406
		 * required).
13407
		 * Note that this parameter will be set by the initialisation routine. To
13408
		 * set a default use {@link DataTable.defaults}.
13409
		 *  @type string
13410
		 */
13411
		"sServerMethod": null,
13412
 
13413
		/**
13414
		 * Format numbers for display.
13415
		 * Note that this parameter will be set by the initialisation routine. To
13416
		 * set a default use {@link DataTable.defaults}.
13417
		 *  @type function
13418
		 */
13419
		"fnFormatNumber": null,
13420
 
13421
		/**
13422
		 * List of options that can be used for the user selectable length menu.
13423
		 * Note that this parameter will be set by the initialisation routine. To
13424
		 * set a default use {@link DataTable.defaults}.
13425
		 *  @type array
13426
		 *  @default []
13427
		 */
13428
		"aLengthMenu": null,
13429
 
13430
		/**
13431
		 * Counter for the draws that the table does. Also used as a tracker for
13432
		 * server-side processing
13433
		 *  @type int
13434
		 *  @default 0
13435
		 */
13436
		"iDraw": 0,
13437
 
13438
		/**
13439
		 * Indicate if a redraw is being done - useful for Ajax
13440
		 *  @type boolean
13441
		 *  @default false
13442
		 */
13443
		"bDrawing": false,
13444
 
13445
		/**
13446
		 * Draw index (iDraw) of the last error when parsing the returned data
13447
		 *  @type int
13448
		 *  @default -1
13449
		 */
13450
		"iDrawError": -1,
13451
 
13452
		/**
13453
		 * Paging display length
13454
		 *  @type int
13455
		 *  @default 10
13456
		 */
13457
		"_iDisplayLength": 10,
13458
 
13459
		/**
13460
		 * Paging start point - aiDisplay index
13461
		 *  @type int
13462
		 *  @default 0
13463
		 */
13464
		"_iDisplayStart": 0,
13465
 
13466
		/**
13467
		 * Server-side processing - number of records in the result set
13468
		 * (i.e. before filtering), Use fnRecordsTotal rather than
13469
		 * this property to get the value of the number of records, regardless of
13470
		 * the server-side processing setting.
13471
		 *  @type int
13472
		 *  @default 0
13473
		 *  @private
13474
		 */
13475
		"_iRecordsTotal": 0,
13476
 
13477
		/**
13478
		 * Server-side processing - number of records in the current display set
13479
		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13480
		 * this property to get the value of the number of records, regardless of
13481
		 * the server-side processing setting.
13482
		 *  @type boolean
13483
		 *  @default 0
13484
		 *  @private
13485
		 */
13486
		"_iRecordsDisplay": 0,
13487
 
13488
		/**
13489
		 * Flag to indicate if jQuery UI marking and classes should be used.
13490
		 * Note that this parameter will be set by the initialisation routine. To
13491
		 * set a default use {@link DataTable.defaults}.
13492
		 *  @type boolean
13493
		 */
13494
		"bJUI": null,
13495
 
13496
		/**
13497
		 * The classes to use for the table
13498
		 *  @type object
13499
		 *  @default {}
13500
		 */
13501
		"oClasses": {},
13502
 
13503
		/**
13504
		 * Flag attached to the settings object so you can check in the draw
13505
		 * callback if filtering has been done in the draw. Deprecated in favour of
13506
		 * events.
13507
		 *  @type boolean
13508
		 *  @default false
13509
		 *  @deprecated
13510
		 */
13511
		"bFiltered": false,
13512
 
13513
		/**
13514
		 * Flag attached to the settings object so you can check in the draw
13515
		 * callback if sorting has been done in the draw. Deprecated in favour of
13516
		 * events.
13517
		 *  @type boolean
13518
		 *  @default false
13519
		 *  @deprecated
13520
		 */
13521
		"bSorted": false,
13522
 
13523
		/**
13524
		 * Indicate that if multiple rows are in the header and there is more than
13525
		 * one unique cell per column, if the top one (true) or bottom one (false)
13526
		 * should be used for sorting / title by DataTables.
13527
		 * Note that this parameter will be set by the initialisation routine. To
13528
		 * set a default use {@link DataTable.defaults}.
13529
		 *  @type boolean
13530
		 */
13531
		"bSortCellsTop": null,
13532
 
13533
		/**
13534
		 * Initialisation object that is used for the table
13535
		 *  @type object
13536
		 *  @default null
13537
		 */
13538
		"oInit": null,
13539
 
13540
		/**
13541
		 * Destroy callback functions - for plug-ins to attach themselves to the
13542
		 * destroy so they can clean up markup and events.
13543
		 *  @type array
13544
		 *  @default []
13545
		 */
13546
		"aoDestroyCallback": [],
13547
 
13548
 
13549
		/**
13550
		 * Get the number of records in the current record set, before filtering
13551
		 *  @type function
13552
		 */
13553
		"fnRecordsTotal": function ()
13554
		{
13555
			return _fnDataSource( this ) == 'ssp' ?
13556
				this._iRecordsTotal * 1 :
13557
				this.aiDisplayMaster.length;
13558
		},
13559
 
13560
		/**
13561
		 * Get the number of records in the current record set, after filtering
13562
		 *  @type function
13563
		 */
13564
		"fnRecordsDisplay": function ()
13565
		{
13566
			return _fnDataSource( this ) == 'ssp' ?
13567
				this._iRecordsDisplay * 1 :
13568
				this.aiDisplay.length;
13569
		},
13570
 
13571
		/**
13572
		 * Get the display end point - aiDisplay index
13573
		 *  @type function
13574
		 */
13575
		"fnDisplayEnd": function ()
13576
		{
13577
			var
13578
				len      = this._iDisplayLength,
13579
				start    = this._iDisplayStart,
13580
				calc     = start + len,
13581
				records  = this.aiDisplay.length,
13582
				features = this.oFeatures,
13583
				paginate = features.bPaginate;
13584
 
13585
			if ( features.bServerSide ) {
13586
				return paginate === false || len === -1 ?
13587
					start + records :
13588
					Math.min( start+len, this._iRecordsDisplay );
13589
			}
13590
			else {
13591
				return ! paginate || calc>records || len===-1 ?
13592
					records :
13593
					calc;
13594
			}
13595
		},
13596
 
13597
		/**
13598
		 * The DataTables object for this table
13599
		 *  @type object
13600
		 *  @default null
13601
		 */
13602
		"oInstance": null,
13603
 
13604
		/**
13605
		 * Unique identifier for each instance of the DataTables object. If there
13606
		 * is an ID on the table node, then it takes that value, otherwise an
13607
		 * incrementing internal counter is used.
13608
		 *  @type string
13609
		 *  @default null
13610
		 */
13611
		"sInstance": null,
13612
 
13613
		/**
13614
		 * tabindex attribute value that is added to DataTables control elements, allowing
13615
		 * keyboard navigation of the table and its controls.
13616
		 */
13617
		"iTabIndex": 0,
13618
 
13619
		/**
13620
		 * DIV container for the footer scrolling table if scrolling
13621
		 */
13622
		"nScrollHead": null,
13623
 
13624
		/**
13625
		 * DIV container for the footer scrolling table if scrolling
13626
		 */
13627
		"nScrollFoot": null,
13628
 
13629
		/**
13630
		 * Last applied sort
13631
		 *  @type array
13632
		 *  @default []
13633
		 */
13634
		"aLastSort": [],
13635
 
13636
		/**
13637
		 * Stored plug-in instances
13638
		 *  @type object
13639
		 *  @default {}
13640
		 */
13641
		"oPlugins": {},
13642
 
13643
		/**
13644
		 * Function used to get a row's id from the row's data
13645
		 *  @type function
13646
		 *  @default null
13647
		 */
13648
		"rowIdFn": null,
13649
 
13650
		/**
13651
		 * Data location where to store a row's id
13652
		 *  @type string
13653
		 *  @default null
13654
		 */
13655
		"rowId": null
13656
	};
13657
 
13658
	/**
13659
	 * Extension object for DataTables that is used to provide all extension
13660
	 * options.
13661
	 *
13662
	 * Note that the `DataTable.ext` object is available through
13663
	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13664
	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13665
	 *  @namespace
13666
	 *  @extends DataTable.models.ext
13667
	 */
13668
 
13669
 
13670
	/**
13671
	 * DataTables extensions
13672
	 *
13673
	 * This namespace acts as a collection area for plug-ins that can be used to
13674
	 * extend DataTables capabilities. Indeed many of the build in methods
13675
	 * use this method to provide their own capabilities (sorting methods for
13676
	 * example).
13677
	 *
13678
	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13679
	 * reasons
13680
	 *
13681
	 *  @namespace
13682
	 */
13683
	DataTable.ext = _ext = {
13684
		/**
13685
		 * Buttons. For use with the Buttons extension for DataTables. This is
13686
		 * defined here so other extensions can define buttons regardless of load
13687
		 * order. It is _not_ used by DataTables core.
13688
		 *
13689
		 *  @type object
13690
		 *  @default {}
13691
		 */
13692
		buttons: {},
13693
 
13694
 
13695
		/**
13696
		 * Element class names
13697
		 *
13698
		 *  @type object
13699
		 *  @default {}
13700
		 */
13701
		classes: {},
13702
 
13703
 
13704
		/**
13705
		 * Error reporting.
13706
		 *
13707
		 * How should DataTables report an error. Can take the value 'alert',
13708
		 * 'throw', 'none' or a function.
13709
		 *
13710
		 *  @type string|function
13711
		 *  @default alert
13712
		 */
13713
		errMode: "alert",
13714
 
13715
 
13716
		/**
13717
		 * Feature plug-ins.
13718
		 *
13719
		 * This is an array of objects which describe the feature plug-ins that are
13720
		 * available to DataTables. These feature plug-ins are then available for
13721
		 * use through the `dom` initialisation option.
13722
		 *
13723
		 * Each feature plug-in is described by an object which must have the
13724
		 * following properties:
13725
		 *
13726
		 * * `fnInit` - function that is used to initialise the plug-in,
13727
		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13728
		 *   instillation option. This is case sensitive.
13729
		 *
13730
		 * The `fnInit` function has the following input parameters:
13731
		 *
13732
		 * 1. `{object}` DataTables settings object: see
13733
		 *    {@link DataTable.models.oSettings}
13734
		 *
13735
		 * And the following return is expected:
13736
		 *
13737
		 * * {node|null} The element which contains your feature. Note that the
13738
		 *   return may also be void if your plug-in does not require to inject any
13739
		 *   DOM elements into DataTables control (`dom`) - for example this might
13740
		 *   be useful when developing a plug-in which allows table control via
13741
		 *   keyboard entry
13742
		 *
13743
		 *  @type array
13744
		 *
13745
		 *  @example
13746
		 *    $.fn.dataTable.ext.features.push( {
13747
		 *      "fnInit": function( oSettings ) {
13748
		 *        return new TableTools( { "oDTSettings": oSettings } );
13749
		 *      },
13750
		 *      "cFeature": "T"
13751
		 *    } );
13752
		 */
13753
		feature: [],
13754
 
13755
 
13756
		/**
13757
		 * Row searching.
13758
		 *
13759
		 * This method of searching is complimentary to the default type based
13760
		 * searching, and a lot more comprehensive as it allows you complete control
13761
		 * over the searching logic. Each element in this array is a function
13762
		 * (parameters described below) that is called for every row in the table,
13763
		 * and your logic decides if it should be included in the searching data set
13764
		 * or not.
13765
		 *
13766
		 * Searching functions have the following input parameters:
13767
		 *
13768
		 * 1. `{object}` DataTables settings object: see
13769
		 *    {@link DataTable.models.oSettings}
13770
		 * 2. `{array|object}` Data for the row to be processed (same as the
13771
		 *    original format that was passed in as the data source, or an array
13772
		 *    from a DOM data source
13773
		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13774
		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13775
		 *
13776
		 * And the following return is expected:
13777
		 *
13778
		 * * {boolean} Include the row in the searched result set (true) or not
13779
		 *   (false)
13780
		 *
13781
		 * Note that as with the main search ability in DataTables, technically this
13782
		 * is "filtering", since it is subtractive. However, for consistency in
13783
		 * naming we call it searching here.
13784
		 *
13785
		 *  @type array
13786
		 *  @default []
13787
		 *
13788
		 *  @example
13789
		 *    // The following example shows custom search being applied to the
13790
		 *    // fourth column (i.e. the data[3] index) based on two input values
13791
		 *    // from the end-user, matching the data in a certain range.
13792
		 *    $.fn.dataTable.ext.search.push(
13793
		 *      function( settings, data, dataIndex ) {
13794
		 *        var min = document.getElementById('min').value * 1;
13795
		 *        var max = document.getElementById('max').value * 1;
13796
		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13797
		 *
13798
		 *        if ( min == "" && max == "" ) {
13799
		 *          return true;
13800
		 *        }
13801
		 *        else if ( min == "" && version < max ) {
13802
		 *          return true;
13803
		 *        }
13804
		 *        else if ( min < version && "" == max ) {
13805
		 *          return true;
13806
		 *        }
13807
		 *        else if ( min < version && version < max ) {
13808
		 *          return true;
13809
		 *        }
13810
		 *        return false;
13811
		 *      }
13812
		 *    );
13813
		 */
13814
		search: [],
13815
 
13816
 
13817
		/**
13818
		 * Selector extensions
13819
		 *
13820
		 * The `selector` option can be used to extend the options available for the
13821
		 * selector modifier options (`selector-modifier` object data type) that
13822
		 * each of the three built in selector types offer (row, column and cell +
13823
		 * their plural counterparts). For example the Select extension uses this
13824
		 * mechanism to provide an option to select only rows, columns and cells
13825
		 * that have been marked as selected by the end user (`{selected: true}`),
13826
		 * which can be used in conjunction with the existing built in selector
13827
		 * options.
13828
		 *
13829
		 * Each property is an array to which functions can be pushed. The functions
13830
		 * take three attributes:
13831
		 *
13832
		 * * Settings object for the host table
13833
		 * * Options object (`selector-modifier` object type)
13834
		 * * Array of selected item indexes
13835
		 *
13836
		 * The return is an array of the resulting item indexes after the custom
13837
		 * selector has been applied.
13838
		 *
13839
		 *  @type object
13840
		 */
13841
		selector: {
13842
			cell: [],
13843
			column: [],
13844
			row: []
13845
		},
13846
 
13847
 
13848
		/**
13849
		 * Internal functions, exposed for used in plug-ins.
13850
		 *
13851
		 * Please note that you should not need to use the internal methods for
13852
		 * anything other than a plug-in (and even then, try to avoid if possible).
13853
		 * The internal function may change between releases.
13854
		 *
13855
		 *  @type object
13856
		 *  @default {}
13857
		 */
13858
		internal: {},
13859
 
13860
 
13861
		/**
13862
		 * Legacy configuration options. Enable and disable legacy options that
13863
		 * are available in DataTables.
13864
		 *
13865
		 *  @type object
13866
		 */
13867
		legacy: {
13868
			/**
13869
			 * Enable / disable DataTables 1.9 compatible server-side processing
13870
			 * requests
13871
			 *
13872
			 *  @type boolean
13873
			 *  @default null
13874
			 */
13875
			ajax: null
13876
		},
13877
 
13878
 
13879
		/**
13880
		 * Pagination plug-in methods.
13881
		 *
13882
		 * Each entry in this object is a function and defines which buttons should
13883
		 * be shown by the pagination rendering method that is used for the table:
13884
		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13885
		 * buttons are displayed in the document, while the functions here tell it
13886
		 * what buttons to display. This is done by returning an array of button
13887
		 * descriptions (what each button will do).
13888
		 *
13889
		 * Pagination types (the four built in options and any additional plug-in
13890
		 * options defined here) can be used through the `paginationType`
13891
		 * initialisation parameter.
13892
		 *
13893
		 * The functions defined take two parameters:
13894
		 *
13895
		 * 1. `{int} page` The current page index
13896
		 * 2. `{int} pages` The number of pages in the table
13897
		 *
13898
		 * Each function is expected to return an array where each element of the
13899
		 * array can be one of:
13900
		 *
13901
		 * * `first` - Jump to first page when activated
13902
		 * * `last` - Jump to last page when activated
13903
		 * * `previous` - Show previous page when activated
13904
		 * * `next` - Show next page when activated
13905
		 * * `{int}` - Show page of the index given
13906
		 * * `{array}` - A nested array containing the above elements to add a
13907
		 *   containing 'DIV' element (might be useful for styling).
13908
		 *
13909
		 * Note that DataTables v1.9- used this object slightly differently whereby
13910
		 * an object with two functions would be defined for each plug-in. That
13911
		 * ability is still supported by DataTables 1.10+ to provide backwards
13912
		 * compatibility, but this option of use is now decremented and no longer
13913
		 * documented in DataTables 1.10+.
13914
		 *
13915
		 *  @type object
13916
		 *  @default {}
13917
		 *
13918
		 *  @example
13919
		 *    // Show previous, next and current page buttons only
13920
		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13921
		 *      return [ 'previous', page, 'next' ];
13922
		 *    };
13923
		 */
13924
		pager: {},
13925
 
13926
 
13927
		renderer: {
13928
			pageButton: {},
13929
			header: {}
13930
		},
13931
 
13932
 
13933
		/**
13934
		 * Ordering plug-ins - custom data source
13935
		 *
13936
		 * The extension options for ordering of data available here is complimentary
13937
		 * to the default type based ordering that DataTables typically uses. It
13938
		 * allows much greater control over the the data that is being used to
13939
		 * order a column, but is necessarily therefore more complex.
13940
		 *
13941
		 * This type of ordering is useful if you want to do ordering based on data
13942
		 * live from the DOM (for example the contents of an 'input' element) rather
13943
		 * than just the static string that DataTables knows of.
13944
		 *
13945
		 * The way these plug-ins work is that you create an array of the values you
13946
		 * wish to be ordering for the column in question and then return that
13947
		 * array. The data in the array much be in the index order of the rows in
13948
		 * the table (not the currently ordering order!). Which order data gathering
13949
		 * function is run here depends on the `dt-init columns.orderDataType`
13950
		 * parameter that is used for the column (if any).
13951
		 *
13952
		 * The functions defined take two parameters:
13953
		 *
13954
		 * 1. `{object}` DataTables settings object: see
13955
		 *    {@link DataTable.models.oSettings}
13956
		 * 2. `{int}` Target column index
13957
		 *
13958
		 * Each function is expected to return an array:
13959
		 *
13960
		 * * `{array}` Data for the column to be ordering upon
13961
		 *
13962
		 *  @type array
13963
		 *
13964
		 *  @example
13965
		 *    // Ordering using `input` node values
13966
		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
13967
		 *    {
13968
		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13969
		 *        return $('input', td).val();
13970
		 *      } );
13971
		 *    }
13972
		 */
13973
		order: {},
13974
 
13975
 
13976
		/**
13977
		 * Type based plug-ins.
13978
		 *
13979
		 * Each column in DataTables has a type assigned to it, either by automatic
13980
		 * detection or by direct assignment using the `type` option for the column.
13981
		 * The type of a column will effect how it is ordering and search (plug-ins
13982
		 * can also make use of the column type if required).
13983
		 *
13984
		 * @namespace
13985
		 */
13986
		type: {
13987
			/**
13988
			 * Type detection functions.
13989
			 *
13990
			 * The functions defined in this object are used to automatically detect
13991
			 * a column's type, making initialisation of DataTables super easy, even
13992
			 * when complex data is in the table.
13993
			 *
13994
			 * The functions defined take two parameters:
13995
			 *
13996
		     *  1. `{*}` Data from the column cell to be analysed
13997
		     *  2. `{settings}` DataTables settings object. This can be used to
13998
		     *     perform context specific type detection - for example detection
13999
		     *     based on language settings such as using a comma for a decimal
14000
		     *     place. Generally speaking the options from the settings will not
14001
		     *     be required
14002
			 *
14003
			 * Each function is expected to return:
14004
			 *
14005
			 * * `{string|null}` Data type detected, or null if unknown (and thus
14006
			 *   pass it on to the other type detection functions.
14007
			 *
14008
			 *  @type array
14009
			 *
14010
			 *  @example
14011
			 *    // Currency type detection plug-in:
14012
			 *    $.fn.dataTable.ext.type.detect.push(
14013
			 *      function ( data, settings ) {
14014
			 *        // Check the numeric part
14015
			 *        if ( ! $.isNumeric( data.substring(1) ) ) {
14016
			 *          return null;
14017
			 *        }
14018
			 *
14019
			 *        // Check prefixed by currency
14020
			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14021
			 *          return 'currency';
14022
			 *        }
14023
			 *        return null;
14024
			 *      }
14025
			 *    );
14026
			 */
14027
			detect: [],
14028
 
14029
 
14030
			/**
14031
			 * Type based search formatting.
14032
			 *
14033
			 * The type based searching functions can be used to pre-format the
14034
			 * data to be search on. For example, it can be used to strip HTML
14035
			 * tags or to de-format telephone numbers for numeric only searching.
14036
			 *
14037
			 * Note that is a search is not defined for a column of a given type,
14038
			 * no search formatting will be performed.
14039
			 *
14040
			 * Pre-processing of searching data plug-ins - When you assign the sType
14041
			 * for a column (or have it automatically detected for you by DataTables
14042
			 * or a type detection plug-in), you will typically be using this for
14043
			 * custom sorting, but it can also be used to provide custom searching
14044
			 * by allowing you to pre-processing the data and returning the data in
14045
			 * the format that should be searched upon. This is done by adding
14046
			 * functions this object with a parameter name which matches the sType
14047
			 * for that target column. This is the corollary of <i>afnSortData</i>
14048
			 * for searching data.
14049
			 *
14050
			 * The functions defined take a single parameter:
14051
			 *
14052
		     *  1. `{*}` Data from the column cell to be prepared for searching
14053
			 *
14054
			 * Each function is expected to return:
14055
			 *
14056
			 * * `{string|null}` Formatted string that will be used for the searching.
14057
			 *
14058
			 *  @type object
14059
			 *  @default {}
14060
			 *
14061
			 *  @example
14062
			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14063
			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14064
			 *    }
14065
			 */
14066
			search: {},
14067
 
14068
 
14069
			/**
14070
			 * Type based ordering.
14071
			 *
14072
			 * The column type tells DataTables what ordering to apply to the table
14073
			 * when a column is sorted upon. The order for each type that is defined,
14074
			 * is defined by the functions available in this object.
14075
			 *
14076
			 * Each ordering option can be described by three properties added to
14077
			 * this object:
14078
			 *
14079
			 * * `{type}-pre` - Pre-formatting function
14080
			 * * `{type}-asc` - Ascending order function
14081
			 * * `{type}-desc` - Descending order function
14082
			 *
14083
			 * All three can be used together, only `{type}-pre` or only
14084
			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14085
			 * that only `{type}-pre` is used, as this provides the optimal
14086
			 * implementation in terms of speed, although the others are provided
14087
			 * for compatibility with existing Javascript sort functions.
14088
			 *
14089
			 * `{type}-pre`: Functions defined take a single parameter:
14090
			 *
14091
		     *  1. `{*}` Data from the column cell to be prepared for ordering
14092
			 *
14093
			 * And return:
14094
			 *
14095
			 * * `{*}` Data to be sorted upon
14096
			 *
14097
			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14098
			 * functions, taking two parameters:
14099
			 *
14100
		     *  1. `{*}` Data to compare to the second parameter
14101
		     *  2. `{*}` Data to compare to the first parameter
14102
			 *
14103
			 * And returning:
14104
			 *
14105
			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14106
			 *   than the second parameter, ===0 if the two parameters are equal and
14107
			 *   >0 if the first parameter should be sorted height than the second
14108
			 *   parameter.
14109
			 *
14110
			 *  @type object
14111
			 *  @default {}
14112
			 *
14113
			 *  @example
14114
			 *    // Numeric ordering of formatted numbers with a pre-formatter
14115
			 *    $.extend( $.fn.dataTable.ext.type.order, {
14116
			 *      "string-pre": function(x) {
14117
			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14118
			 *        return parseFloat( a );
14119
			 *      }
14120
			 *    } );
14121
			 *
14122
			 *  @example
14123
			 *    // Case-sensitive string ordering, with no pre-formatting method
14124
			 *    $.extend( $.fn.dataTable.ext.order, {
14125
			 *      "string-case-asc": function(x,y) {
14126
			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14127
			 *      },
14128
			 *      "string-case-desc": function(x,y) {
14129
			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14130
			 *      }
14131
			 *    } );
14132
			 */
14133
			order: {}
14134
		},
14135
 
14136
		/**
14137
		 * Unique DataTables instance counter
14138
		 *
14139
		 * @type int
14140
		 * @private
14141
		 */
14142
		_unique: 0,
14143
 
14144
 
14145
		//
14146
		// Depreciated
14147
		// The following properties are retained for backwards compatiblity only.
14148
		// The should not be used in new projects and will be removed in a future
14149
		// version
14150
		//
14151
 
14152
		/**
14153
		 * Version check function.
14154
		 *  @type function
14155
		 *  @depreciated Since 1.10
14156
		 */
14157
		fnVersionCheck: DataTable.fnVersionCheck,
14158
 
14159
 
14160
		/**
14161
		 * Index for what 'this' index API functions should use
14162
		 *  @type int
14163
		 *  @deprecated Since v1.10
14164
		 */
14165
		iApiIndex: 0,
14166
 
14167
 
14168
		/**
14169
		 * jQuery UI class container
14170
		 *  @type object
14171
		 *  @deprecated Since v1.10
14172
		 */
14173
		oJUIClasses: {},
14174
 
14175
 
14176
		/**
14177
		 * Software version
14178
		 *  @type string
14179
		 *  @deprecated Since v1.10
14180
		 */
14181
		sVersion: DataTable.version
14182
	};
14183
 
14184
 
14185
	//
14186
	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14187
	//
14188
	$.extend( _ext, {
14189
		afnFiltering: _ext.search,
14190
		aTypes:       _ext.type.detect,
14191
		ofnSearch:    _ext.type.search,
14192
		oSort:        _ext.type.order,
14193
		afnSortData:  _ext.order,
14194
		aoFeatures:   _ext.feature,
14195
		oApi:         _ext.internal,
14196
		oStdClasses:  _ext.classes,
14197
		oPagination:  _ext.pager
14198
	} );
14199
 
14200
 
14201
	$.extend( DataTable.ext.classes, {
14202
		"sTable": "dataTable",
14203
		"sNoFooter": "no-footer",
14204
 
14205
		/* Paging buttons */
14206
		"sPageButton": "paginate_button",
14207
		"sPageButtonActive": "current",
14208
		"sPageButtonDisabled": "disabled",
14209
 
14210
		/* Striping classes */
14211
		"sStripeOdd": "odd",
14212
		"sStripeEven": "even",
14213
 
14214
		/* Empty row */
14215
		"sRowEmpty": "dataTables_empty",
14216
 
14217
		/* Features */
14218
		"sWrapper": "dataTables_wrapper",
14219
		"sFilter": "dataTables_filter",
14220
		"sInfo": "dataTables_info",
14221
		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14222
		"sLength": "dataTables_length",
14223
		"sProcessing": "dataTables_processing",
14224
 
14225
		/* Sorting */
14226
		"sSortAsc": "sorting_asc",
14227
		"sSortDesc": "sorting_desc",
14228
		"sSortable": "sorting", /* Sortable in both directions */
14229
		"sSortableAsc": "sorting_asc_disabled",
14230
		"sSortableDesc": "sorting_desc_disabled",
14231
		"sSortableNone": "sorting_disabled",
14232
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14233
 
14234
		/* Filtering */
14235
		"sFilterInput": "",
14236
 
14237
		/* Page length */
14238
		"sLengthSelect": "",
14239
 
14240
		/* Scrolling */
14241
		"sScrollWrapper": "dataTables_scroll",
14242
		"sScrollHead": "dataTables_scrollHead",
14243
		"sScrollHeadInner": "dataTables_scrollHeadInner",
14244
		"sScrollBody": "dataTables_scrollBody",
14245
		"sScrollFoot": "dataTables_scrollFoot",
14246
		"sScrollFootInner": "dataTables_scrollFootInner",
14247
 
14248
		/* Misc */
14249
		"sHeaderTH": "",
14250
		"sFooterTH": "",
14251
 
14252
		// Deprecated
14253
		"sSortJUIAsc": "",
14254
		"sSortJUIDesc": "",
14255
		"sSortJUI": "",
14256
		"sSortJUIAscAllowed": "",
14257
		"sSortJUIDescAllowed": "",
14258
		"sSortJUIWrapper": "",
14259
		"sSortIcon": "",
14260
		"sJUIHeader": "",
14261
		"sJUIFooter": ""
14262
	} );
14263
 
14264
 
14265
	(function() {
14266
 
14267
	// Reused strings for better compression. Closure compiler appears to have a
14268
	// weird edge case where it is trying to expand strings rather than use the
14269
	// variable version. This results in about 200 bytes being added, for very
14270
	// little preference benefit since it this run on script load only.
14271
	var _empty = '';
14272
	_empty = '';
14273
 
14274
	var _stateDefault = _empty + 'ui-state-default';
14275
	var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
14276
	var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
14277
 
14278
	$.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
14279
		/* Full numbers paging buttons */
14280
		"sPageButton":         "fg-button ui-button "+_stateDefault,
14281
		"sPageButtonActive":   "ui-state-disabled",
14282
		"sPageButtonDisabled": "ui-state-disabled",
14283
 
14284
		/* Features */
14285
		"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
14286
			"ui-buttonset-multi paging_", /* Note that the type is postfixed */
14287
 
14288
		/* Sorting */
14289
		"sSortAsc":            _stateDefault+" sorting_asc",
14290
		"sSortDesc":           _stateDefault+" sorting_desc",
14291
		"sSortable":           _stateDefault+" sorting",
14292
		"sSortableAsc":        _stateDefault+" sorting_asc_disabled",
14293
		"sSortableDesc":       _stateDefault+" sorting_desc_disabled",
14294
		"sSortableNone":       _stateDefault+" sorting_disabled",
14295
		"sSortJUIAsc":         _sortIcon+"triangle-1-n",
14296
		"sSortJUIDesc":        _sortIcon+"triangle-1-s",
14297
		"sSortJUI":            _sortIcon+"carat-2-n-s",
14298
		"sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
14299
		"sSortJUIDescAllowed": _sortIcon+"carat-1-s",
14300
		"sSortJUIWrapper":     "DataTables_sort_wrapper",
14301
		"sSortIcon":           "DataTables_sort_icon",
14302
 
14303
		/* Scrolling */
14304
		"sScrollHead": "dataTables_scrollHead "+_stateDefault,
14305
		"sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
14306
 
14307
		/* Misc */
14308
		"sHeaderTH":  _stateDefault,
14309
		"sFooterTH":  _stateDefault,
14310
		"sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
14311
		"sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
14312
	} );
14313
 
14314
	}());
14315
 
14316
 
14317
 
14318
	var extPagination = DataTable.ext.pager;
14319
 
14320
	function _numbers ( page, pages ) {
14321
		var
14322
			numbers = [],
14323
			buttons = extPagination.numbers_length,
14324
			half = Math.floor( buttons / 2 ),
14325
			i = 1;
14326
 
14327
		if ( pages <= buttons ) {
14328
			numbers = _range( 0, pages );
14329
		}
14330
		else if ( page <= half ) {
14331
			numbers = _range( 0, buttons-2 );
14332
			numbers.push( 'ellipsis' );
14333
			numbers.push( pages-1 );
14334
		}
14335
		else if ( page >= pages - 1 - half ) {
14336
			numbers = _range( pages-(buttons-2), pages );
14337
			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14338
			numbers.splice( 0, 0, 0 );
14339
		}
14340
		else {
14341
			numbers = _range( page-half+2, page+half-1 );
14342
			numbers.push( 'ellipsis' );
14343
			numbers.push( pages-1 );
14344
			numbers.splice( 0, 0, 'ellipsis' );
14345
			numbers.splice( 0, 0, 0 );
14346
		}
14347
 
14348
		numbers.DT_el = 'span';
14349
		return numbers;
14350
	}
14351
 
14352
 
14353
	$.extend( extPagination, {
14354
		simple: function ( page, pages ) {
14355
			return [ 'previous', 'next' ];
14356
		},
14357
 
14358
		full: function ( page, pages ) {
14359
			return [  'first', 'previous', 'next', 'last' ];
14360
		},
14361
 
14362
		numbers: function ( page, pages ) {
14363
			return [ _numbers(page, pages) ];
14364
		},
14365
 
14366
		simple_numbers: function ( page, pages ) {
14367
			return [ 'previous', _numbers(page, pages), 'next' ];
14368
		},
14369
 
14370
		full_numbers: function ( page, pages ) {
14371
			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14372
		},
14373
 
14374
		// For testing and plug-ins to use
14375
		_numbers: _numbers,
14376
 
14377
		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14378
		numbers_length: 7
14379
	} );
14380
 
14381
 
14382
	$.extend( true, DataTable.ext.renderer, {
14383
		pageButton: {
14384
			_: function ( settings, host, idx, buttons, page, pages ) {
14385
				var classes = settings.oClasses;
14386
				var lang = settings.oLanguage.oPaginate;
14387
				var btnDisplay, btnClass, counter=0;
14388
 
14389
				var attach = function( container, buttons ) {
14390
					var i, ien, node, button;
14391
					var clickHandler = function ( e ) {
14392
						_fnPageChange( settings, e.data.action, true );
14393
					};
14394
 
14395
					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14396
						button = buttons[i];
14397
 
14398
						if ( $.isArray( button ) ) {
14399
							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14400
								.appendTo( container );
14401
							attach( inner, button );
14402
						}
14403
						else {
14404
							btnDisplay = null;
14405
							btnClass = '';
14406
 
14407
							switch ( button ) {
14408
								case 'ellipsis':
14409
									container.append('<span class="ellipsis">&#x2026;</span>');
14410
									break;
14411
 
14412
								case 'first':
14413
									btnDisplay = lang.sFirst;
14414
									btnClass = button + (page > 0 ?
14415
										'' : ' '+classes.sPageButtonDisabled);
14416
									break;
14417
 
14418
								case 'previous':
14419
									btnDisplay = lang.sPrevious;
14420
									btnClass = button + (page > 0 ?
14421
										'' : ' '+classes.sPageButtonDisabled);
14422
									break;
14423
 
14424
								case 'next':
14425
									btnDisplay = lang.sNext;
14426
									btnClass = button + (page < pages-1 ?
14427
										'' : ' '+classes.sPageButtonDisabled);
14428
									break;
14429
 
14430
								case 'last':
14431
									btnDisplay = lang.sLast;
14432
									btnClass = button + (page < pages-1 ?
14433
										'' : ' '+classes.sPageButtonDisabled);
14434
									break;
14435
 
14436
								default:
14437
									btnDisplay = button + 1;
14438
									btnClass = page === button ?
14439
										classes.sPageButtonActive : '';
14440
									break;
14441
							}
14442
 
14443
							if ( btnDisplay !== null ) {
14444
								node = $('<a>', {
14445
										'class': classes.sPageButton+' '+btnClass,
14446
										'aria-controls': settings.sTableId,
14447
										'data-dt-idx': counter,
14448
										'tabindex': settings.iTabIndex,
14449
										'id': idx === 0 && typeof button === 'string' ?
14450
											settings.sTableId +'_'+ button :
14451
											null
14452
									} )
14453
									.html( btnDisplay )
14454
									.appendTo( container );
14455
 
14456
								_fnBindAction(
14457
									node, {action: button}, clickHandler
14458
								);
14459
 
14460
								counter++;
14461
							}
14462
						}
14463
					}
14464
				};
14465
 
14466
				// IE9 throws an 'unknown error' if document.activeElement is used
14467
				// inside an iframe or frame. Try / catch the error. Not good for
14468
				// accessibility, but neither are frames.
14469
				var activeEl;
14470
 
14471
				try {
14472
					// Because this approach is destroying and recreating the paging
14473
					// elements, focus is lost on the select button which is bad for
14474
					// accessibility. So we want to restore focus once the draw has
14475
					// completed
14476
					activeEl = $(host).find(document.activeElement).data('dt-idx');
14477
				}
14478
				catch (e) {}
14479
 
14480
				attach( $(host).empty(), buttons );
14481
 
14482
				if ( activeEl ) {
14483
					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14484
				}
14485
			}
14486
		}
14487
	} );
14488
 
14489
 
14490
 
14491
	// Built in type detection. See model.ext.aTypes for information about
14492
	// what is required from this methods.
14493
	$.extend( DataTable.ext.type.detect, [
14494
		// Plain numbers - first since V8 detects some plain numbers as dates
14495
		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14496
		function ( d, settings )
14497
		{
14498
			var decimal = settings.oLanguage.sDecimal;
14499
			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14500
		},
14501
 
14502
		// Dates (only those recognised by the browser's Date.parse)
14503
		function ( d, settings )
14504
		{
14505
			// V8 will remove any unknown characters at the start and end of the
14506
			// expression, leading to false matches such as `$245.12` or `10%` being
14507
			// a valid date. See forum thread 18941 for detail.
14508
			if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14509
				return null;
14510
			}
14511
			var parsed = Date.parse(d);
14512
			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14513
		},
14514
 
14515
		// Formatted numbers
14516
		function ( d, settings )
14517
		{
14518
			var decimal = settings.oLanguage.sDecimal;
14519
			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14520
		},
14521
 
14522
		// HTML numeric
14523
		function ( d, settings )
14524
		{
14525
			var decimal = settings.oLanguage.sDecimal;
14526
			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14527
		},
14528
 
14529
		// HTML numeric, formatted
14530
		function ( d, settings )
14531
		{
14532
			var decimal = settings.oLanguage.sDecimal;
14533
			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14534
		},
14535
 
14536
		// HTML (this is strict checking - there must be html)
14537
		function ( d, settings )
14538
		{
14539
			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14540
				'html' : null;
14541
		}
14542
	] );
14543
 
14544
 
14545
 
14546
	// Filter formatting functions. See model.ext.ofnSearch for information about
14547
	// what is required from these methods.
14548
	//
14549
	// Note that additional search methods are added for the html numbers and
14550
	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14551
	// place is
14552
 
14553
 
14554
	$.extend( DataTable.ext.type.search, {
14555
		html: function ( data ) {
14556
			return _empty(data) ?
14557
				data :
14558
				typeof data === 'string' ?
14559
					data
14560
						.replace( _re_new_lines, " " )
14561
						.replace( _re_html, "" ) :
14562
					'';
14563
		},
14564
 
14565
		string: function ( data ) {
14566
			return _empty(data) ?
14567
				data :
14568
				typeof data === 'string' ?
14569
					data.replace( _re_new_lines, " " ) :
14570
					data;
14571
		}
14572
	} );
14573
 
14574
 
14575
 
14576
	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14577
		if ( d !== 0 && (!d || d === '-') ) {
14578
			return -Infinity;
14579
		}
14580
 
14581
		// If a decimal place other than `.` is used, it needs to be given to the
14582
		// function so we can detect it and replace with a `.` which is the only
14583
		// decimal place Javascript recognises - it is not locale aware.
14584
		if ( decimalPlace ) {
14585
			d = _numToDecimal( d, decimalPlace );
14586
		}
14587
 
14588
		if ( d.replace ) {
14589
			if ( re1 ) {
14590
				d = d.replace( re1, '' );
14591
			}
14592
 
14593
			if ( re2 ) {
14594
				d = d.replace( re2, '' );
14595
			}
14596
		}
14597
 
14598
		return d * 1;
14599
	};
14600
 
14601
 
14602
	// Add the numeric 'deformatting' functions for sorting and search. This is done
14603
	// in a function to provide an easy ability for the language options to add
14604
	// additional methods if a non-period decimal place is used.
14605
	function _addNumericSort ( decimalPlace ) {
14606
		$.each(
14607
			{
14608
				// Plain numbers
14609
				"num": function ( d ) {
14610
					return __numericReplace( d, decimalPlace );
14611
				},
14612
 
14613
				// Formatted numbers
14614
				"num-fmt": function ( d ) {
14615
					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14616
				},
14617
 
14618
				// HTML numeric
14619
				"html-num": function ( d ) {
14620
					return __numericReplace( d, decimalPlace, _re_html );
14621
				},
14622
 
14623
				// HTML numeric, formatted
14624
				"html-num-fmt": function ( d ) {
14625
					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14626
				}
14627
			},
14628
			function ( key, fn ) {
14629
				// Add the ordering method
14630
				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14631
 
14632
				// For HTML types add a search formatter that will strip the HTML
14633
				if ( key.match(/^html\-/) ) {
14634
					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14635
				}
14636
			}
14637
		);
14638
	}
14639
 
14640
 
14641
	// Default sort methods
14642
	$.extend( _ext.type.order, {
14643
		// Dates
14644
		"date-pre": function ( d ) {
14645
			return Date.parse( d ) || 0;
14646
		},
14647
 
14648
		// html
14649
		"html-pre": function ( a ) {
14650
			return _empty(a) ?
14651
				'' :
14652
				a.replace ?
14653
					a.replace( /<.*?>/g, "" ).toLowerCase() :
14654
					a+'';
14655
		},
14656
 
14657
		// string
14658
		"string-pre": function ( a ) {
14659
			// This is a little complex, but faster than always calling toString,
14660
			// http://jsperf.com/tostring-v-check
14661
			return _empty(a) ?
14662
				'' :
14663
				typeof a === 'string' ?
14664
					a.toLowerCase() :
14665
					! a.toString ?
14666
						'' :
14667
						a.toString();
14668
		},
14669
 
14670
		// string-asc and -desc are retained only for compatibility with the old
14671
		// sort methods
14672
		"string-asc": function ( x, y ) {
14673
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14674
		},
14675
 
14676
		"string-desc": function ( x, y ) {
14677
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14678
		}
14679
	} );
14680
 
14681
 
14682
	// Numeric sorting types - order doesn't matter here
14683
	_addNumericSort( '' );
14684
 
14685
 
14686
	$.extend( true, DataTable.ext.renderer, {
14687
		header: {
14688
			_: function ( settings, cell, column, classes ) {
14689
				// No additional mark-up required
14690
				// Attach a sort listener to update on sort - note that using the
14691
				// `DT` namespace will allow the event to be removed automatically
14692
				// on destroy, while the `dt` namespaced event is the one we are
14693
				// listening for
14694
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14695
					if ( settings !== ctx ) { // need to check this this is the host
14696
						return;               // table, not a nested one
14697
					}
14698
 
14699
					var colIdx = column.idx;
14700
 
14701
					cell
14702
						.removeClass(
14703
							column.sSortingClass +' '+
14704
							classes.sSortAsc +' '+
14705
							classes.sSortDesc
14706
						)
14707
						.addClass( columns[ colIdx ] == 'asc' ?
14708
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14709
								classes.sSortDesc :
14710
								column.sSortingClass
14711
						);
14712
				} );
14713
			},
14714
 
14715
			jqueryui: function ( settings, cell, column, classes ) {
14716
				$('<div/>')
14717
					.addClass( classes.sSortJUIWrapper )
14718
					.append( cell.contents() )
14719
					.append( $('<span/>')
14720
						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14721
					)
14722
					.appendTo( cell );
14723
 
14724
				// Attach a sort listener to update on sort
14725
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14726
					if ( settings !== ctx ) {
14727
						return;
14728
					}
14729
 
14730
					var colIdx = column.idx;
14731
 
14732
					cell
14733
						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14734
						.addClass( columns[ colIdx ] == 'asc' ?
14735
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14736
								classes.sSortDesc :
14737
								column.sSortingClass
14738
						);
14739
 
14740
					cell
14741
						.find( 'span.'+classes.sSortIcon )
14742
						.removeClass(
14743
							classes.sSortJUIAsc +" "+
14744
							classes.sSortJUIDesc +" "+
14745
							classes.sSortJUI +" "+
14746
							classes.sSortJUIAscAllowed +" "+
14747
							classes.sSortJUIDescAllowed
14748
						)
14749
						.addClass( columns[ colIdx ] == 'asc' ?
14750
							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14751
								classes.sSortJUIDesc :
14752
								column.sSortingClassJUI
14753
						);
14754
				} );
14755
			}
14756
		}
14757
	} );
14758
 
14759
	/*
14760
	 * Public helper functions. These aren't used internally by DataTables, or
14761
	 * called by any of the options passed into DataTables, but they can be used
14762
	 * externally by developers working with DataTables. They are helper functions
14763
	 * to make working with DataTables a little bit easier.
14764
	 */
14765
 
14766
	/**
14767
	 * Helpers for `columns.render`.
14768
	 *
14769
	 * The options defined here can be used with the `columns.render` initialisation
14770
	 * option to provide a display renderer. The following functions are defined:
14771
	 *
14772
	 * * `number` - Will format numeric data (defined by `columns.data`) for
14773
	 *   display, retaining the original unformatted data for sorting and filtering.
14774
	 *   It takes 5 parameters:
14775
	 *   * `string` - Thousands grouping separator
14776
	 *   * `string` - Decimal point indicator
14777
	 *   * `integer` - Number of decimal points to show
14778
	 *   * `string` (optional) - Prefix.
14779
	 *   * `string` (optional) - Postfix (/suffix).
14780
	 *
14781
	 * @example
14782
	 *   // Column definition using the number renderer
14783
	 *   {
14784
	 *     data: "salary",
14785
	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14786
	 *   }
14787
	 *
14788
	 * @namespace
14789
	 */
14790
	DataTable.render = {
14791
		number: function ( thousands, decimal, precision, prefix, postfix ) {
14792
			return {
14793
				display: function ( d ) {
14794
					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14795
						return d;
14796
					}
14797
 
14798
					var negative = d < 0 ? '-' : '';
14799
					d = Math.abs( parseFloat( d ) );
14800
 
14801
					var intPart = parseInt( d, 10 );
14802
					var floatPart = precision ?
14803
						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14804
						'';
14805
 
14806
					return negative + (prefix||'') +
14807
						intPart.toString().replace(
14808
							/\B(?=(\d{3})+(?!\d))/g, thousands
14809
						) +
14810
						floatPart +
14811
						(postfix||'');
14812
				}
14813
			};
14814
		}
14815
	};
14816
 
14817
 
14818
	/*
14819
	 * This is really a good bit rubbish this method of exposing the internal methods
14820
	 * publicly... - To be fixed in 2.0 using methods on the prototype
14821
	 */
14822
 
14823
 
14824
	/**
14825
	 * Create a wrapper function for exporting an internal functions to an external API.
14826
	 *  @param {string} fn API function name
14827
	 *  @returns {function} wrapped function
14828
	 *  @memberof DataTable#internal
14829
	 */
14830
	function _fnExternApiFunc (fn)
14831
	{
14832
		return function() {
14833
			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14834
				Array.prototype.slice.call(arguments)
14835
			);
14836
			return DataTable.ext.internal[fn].apply( this, args );
14837
		};
14838
	}
14839
 
14840
 
14841
	/**
14842
	 * Reference to internal functions for use by plug-in developers. Note that
14843
	 * these methods are references to internal functions and are considered to be
14844
	 * private. If you use these methods, be aware that they are liable to change
14845
	 * between versions.
14846
	 *  @namespace
14847
	 */
14848
	$.extend( DataTable.ext.internal, {
14849
		_fnExternApiFunc: _fnExternApiFunc,
14850
		_fnBuildAjax: _fnBuildAjax,
14851
		_fnAjaxUpdate: _fnAjaxUpdate,
14852
		_fnAjaxParameters: _fnAjaxParameters,
14853
		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14854
		_fnAjaxDataSrc: _fnAjaxDataSrc,
14855
		_fnAddColumn: _fnAddColumn,
14856
		_fnColumnOptions: _fnColumnOptions,
14857
		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
14858
		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14859
		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
14860
		_fnVisbleColumns: _fnVisbleColumns,
14861
		_fnGetColumns: _fnGetColumns,
14862
		_fnColumnTypes: _fnColumnTypes,
14863
		_fnApplyColumnDefs: _fnApplyColumnDefs,
14864
		_fnHungarianMap: _fnHungarianMap,
14865
		_fnCamelToHungarian: _fnCamelToHungarian,
14866
		_fnLanguageCompat: _fnLanguageCompat,
14867
		_fnBrowserDetect: _fnBrowserDetect,
14868
		_fnAddData: _fnAddData,
14869
		_fnAddTr: _fnAddTr,
14870
		_fnNodeToDataIndex: _fnNodeToDataIndex,
14871
		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
14872
		_fnGetCellData: _fnGetCellData,
14873
		_fnSetCellData: _fnSetCellData,
14874
		_fnSplitObjNotation: _fnSplitObjNotation,
14875
		_fnGetObjectDataFn: _fnGetObjectDataFn,
14876
		_fnSetObjectDataFn: _fnSetObjectDataFn,
14877
		_fnGetDataMaster: _fnGetDataMaster,
14878
		_fnClearTable: _fnClearTable,
14879
		_fnDeleteIndex: _fnDeleteIndex,
14880
		_fnInvalidate: _fnInvalidate,
14881
		_fnGetRowElements: _fnGetRowElements,
14882
		_fnCreateTr: _fnCreateTr,
14883
		_fnBuildHead: _fnBuildHead,
14884
		_fnDrawHead: _fnDrawHead,
14885
		_fnDraw: _fnDraw,
14886
		_fnReDraw: _fnReDraw,
14887
		_fnAddOptionsHtml: _fnAddOptionsHtml,
14888
		_fnDetectHeader: _fnDetectHeader,
14889
		_fnGetUniqueThs: _fnGetUniqueThs,
14890
		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
14891
		_fnFilterComplete: _fnFilterComplete,
14892
		_fnFilterCustom: _fnFilterCustom,
14893
		_fnFilterColumn: _fnFilterColumn,
14894
		_fnFilter: _fnFilter,
14895
		_fnFilterCreateSearch: _fnFilterCreateSearch,
14896
		_fnEscapeRegex: _fnEscapeRegex,
14897
		_fnFilterData: _fnFilterData,
14898
		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
14899
		_fnUpdateInfo: _fnUpdateInfo,
14900
		_fnInfoMacros: _fnInfoMacros,
14901
		_fnInitialise: _fnInitialise,
14902
		_fnInitComplete: _fnInitComplete,
14903
		_fnLengthChange: _fnLengthChange,
14904
		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
14905
		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
14906
		_fnPageChange: _fnPageChange,
14907
		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
14908
		_fnProcessingDisplay: _fnProcessingDisplay,
14909
		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
14910
		_fnScrollDraw: _fnScrollDraw,
14911
		_fnApplyToChildren: _fnApplyToChildren,
14912
		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
14913
		_fnThrottle: _fnThrottle,
14914
		_fnConvertToWidth: _fnConvertToWidth,
14915
		_fnGetWidestNode: _fnGetWidestNode,
14916
		_fnGetMaxLenString: _fnGetMaxLenString,
14917
		_fnStringToCss: _fnStringToCss,
14918
		_fnSortFlatten: _fnSortFlatten,
14919
		_fnSort: _fnSort,
14920
		_fnSortAria: _fnSortAria,
14921
		_fnSortListener: _fnSortListener,
14922
		_fnSortAttachListener: _fnSortAttachListener,
14923
		_fnSortingClasses: _fnSortingClasses,
14924
		_fnSortData: _fnSortData,
14925
		_fnSaveState: _fnSaveState,
14926
		_fnLoadState: _fnLoadState,
14927
		_fnSettingsFromNode: _fnSettingsFromNode,
14928
		_fnLog: _fnLog,
14929
		_fnMap: _fnMap,
14930
		_fnBindAction: _fnBindAction,
14931
		_fnCallbackReg: _fnCallbackReg,
14932
		_fnCallbackFire: _fnCallbackFire,
14933
		_fnLengthOverflow: _fnLengthOverflow,
14934
		_fnRenderer: _fnRenderer,
14935
		_fnDataSource: _fnDataSource,
14936
		_fnRowAttributes: _fnRowAttributes,
14937
		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14938
		                                // in 1.10, so this dead-end function is
14939
		                                // added to prevent errors
14940
	} );
14941
 
14942
 
14943
	// jQuery access
14944
	$.fn.dataTable = DataTable;
14945
 
14946
	// Legacy aliases
14947
	$.fn.dataTableSettings = DataTable.settings;
14948
	$.fn.dataTableExt = DataTable.ext;
14949
 
14950
	// With a capital `D` we return a DataTables API instance rather than a
14951
	// jQuery object
14952
	$.fn.DataTable = function ( opts ) {
14953
		return $(this).dataTable( opts ).api();
14954
	};
14955
 
14956
	// All properties that are available to $.fn.dataTable should also be
14957
	// available on $.fn.DataTable
14958
	$.each( DataTable, function ( prop, val ) {
14959
		$.fn.DataTable[ prop ] = val;
14960
	} );
14961
 
14962
 
14963
	// Information about events fired by DataTables - for documentation.
14964
	/**
14965
	 * Draw event, fired whenever the table is redrawn on the page, at the same
14966
	 * point as fnDrawCallback. This may be useful for binding events or
14967
	 * performing calculations when the table is altered at all.
14968
	 *  @name DataTable#draw.dt
14969
	 *  @event
14970
	 *  @param {event} e jQuery event object
14971
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14972
	 */
14973
 
14974
	/**
14975
	 * Search event, fired when the searching applied to the table (using the
14976
	 * built-in global search, or column filters) is altered.
14977
	 *  @name DataTable#search.dt
14978
	 *  @event
14979
	 *  @param {event} e jQuery event object
14980
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14981
	 */
14982
 
14983
	/**
14984
	 * Page change event, fired when the paging of the table is altered.
14985
	 *  @name DataTable#page.dt
14986
	 *  @event
14987
	 *  @param {event} e jQuery event object
14988
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14989
	 */
14990
 
14991
	/**
14992
	 * Order event, fired when the ordering applied to the table is altered.
14993
	 *  @name DataTable#order.dt
14994
	 *  @event
14995
	 *  @param {event} e jQuery event object
14996
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14997
	 */
14998
 
14999
	/**
15000
	 * DataTables initialisation complete event, fired when the table is fully
15001
	 * drawn, including Ajax data loaded, if Ajax data is required.
15002
	 *  @name DataTable#init.dt
15003
	 *  @event
15004
	 *  @param {event} e jQuery event object
15005
	 *  @param {object} oSettings DataTables settings object
15006
	 *  @param {object} json The JSON object request from the server - only
15007
	 *    present if client-side Ajax sourced data is used</li></ol>
15008
	 */
15009
 
15010
	/**
15011
	 * State save event, fired when the table has changed state a new state save
15012
	 * is required. This event allows modification of the state saving object
15013
	 * prior to actually doing the save, including addition or other state
15014
	 * properties (for plug-ins) or modification of a DataTables core property.
15015
	 *  @name DataTable#stateSaveParams.dt
15016
	 *  @event
15017
	 *  @param {event} e jQuery event object
15018
	 *  @param {object} oSettings DataTables settings object
15019
	 *  @param {object} json The state information to be saved
15020
	 */
15021
 
15022
	/**
15023
	 * State load event, fired when the table is loading state from the stored
15024
	 * data, but prior to the settings object being modified by the saved state
15025
	 * - allowing modification of the saved state is required or loading of
15026
	 * state for a plug-in.
15027
	 *  @name DataTable#stateLoadParams.dt
15028
	 *  @event
15029
	 *  @param {event} e jQuery event object
15030
	 *  @param {object} oSettings DataTables settings object
15031
	 *  @param {object} json The saved state information
15032
	 */
15033
 
15034
	/**
15035
	 * State loaded event, fired when state has been loaded from stored data and
15036
	 * the settings object has been modified by the loaded data.
15037
	 *  @name DataTable#stateLoaded.dt
15038
	 *  @event
15039
	 *  @param {event} e jQuery event object
15040
	 *  @param {object} oSettings DataTables settings object
15041
	 *  @param {object} json The saved state information
15042
	 */
15043
 
15044
	/**
15045
	 * Processing event, fired when DataTables is doing some kind of processing
15046
	 * (be it, order, searcg or anything else). It can be used to indicate to
15047
	 * the end user that there is something happening, or that something has
15048
	 * finished.
15049
	 *  @name DataTable#processing.dt
15050
	 *  @event
15051
	 *  @param {event} e jQuery event object
15052
	 *  @param {object} oSettings DataTables settings object
15053
	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15054
	 */
15055
 
15056
	/**
15057
	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15058
	 * request to made to the server for new data. This event is called before
15059
	 * DataTables processed the returned data, so it can also be used to pre-
15060
	 * process the data returned from the server, if needed.
15061
	 *
15062
	 * Note that this trigger is called in `fnServerData`, if you override
15063
	 * `fnServerData` and which to use this event, you need to trigger it in you
15064
	 * success function.
15065
	 *  @name DataTable#xhr.dt
15066
	 *  @event
15067
	 *  @param {event} e jQuery event object
15068
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15069
	 *  @param {object} json JSON returned from the server
15070
	 *
15071
	 *  @example
15072
	 *     // Use a custom property returned from the server in another DOM element
15073
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15074
	 *       $('#status').html( json.status );
15075
	 *     } );
15076
	 *
15077
	 *  @example
15078
	 *     // Pre-process the data returned from the server
15079
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15080
	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15081
	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15082
	 *       }
15083
	 *       // Note no return - manipulate the data directly in the JSON object.
15084
	 *     } );
15085
	 */
15086
 
15087
	/**
15088
	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15089
	 * or passing the bDestroy:true parameter in the initialisation object. This
15090
	 * can be used to remove bound events, added DOM nodes, etc.
15091
	 *  @name DataTable#destroy.dt
15092
	 *  @event
15093
	 *  @param {event} e jQuery event object
15094
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15095
	 */
15096
 
15097
	/**
15098
	 * Page length change event, fired when number of records to show on each
15099
	 * page (the length) is changed.
15100
	 *  @name DataTable#length.dt
15101
	 *  @event
15102
	 *  @param {event} e jQuery event object
15103
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15104
	 *  @param {integer} len New length
15105
	 */
15106
 
15107
	/**
15108
	 * Column sizing has changed.
15109
	 *  @name DataTable#column-sizing.dt
15110
	 *  @event
15111
	 *  @param {event} e jQuery event object
15112
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15113
	 */
15114
 
15115
	/**
15116
	 * Column visibility has changed.
15117
	 *  @name DataTable#column-visibility.dt
15118
	 *  @event
15119
	 *  @param {event} e jQuery event object
15120
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15121
	 *  @param {int} column Column index
15122
	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15123
	 */
15124
 
15125
	return $.fn.dataTable;
15126
}));
15127
 
15128
}(window, document));
15129