Project

General

Profile

1
/*! DataTables 1.10.0
2
 * ©2008-2014 SpryMedia Ltd - datatables.net/license
3
 */
4

    
5
/**
6
 * @summary     DataTables
7
 * @description Paginate, search and order HTML tables
8
 * @version     1.10.0
9
 * @file        jquery.dataTables.js
10
 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11
 * @contact     www.sprymedia.co.uk/contact
12
 * @copyright   Copyright 2008-2014 SpryMedia Ltd.
13
 *
14
 * This source file is free software, available under the following license:
15
 *   MIT license - http://datatables.net/license
16
 *
17
 * This source file is distributed in the hope that it will be useful, but
18
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20
 *
21
 * For details please refer to: http://www.datatables.net
22
 */
23

    
24
/*jslint evil: true, undef: true, browser: true */
25
/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidateRow,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26

    
27
(/** @lends <global> */function( window, document, undefined ) {
28

    
29
(function( factory ) {
30
	"use strict";
31

    
32
	if ( typeof define === 'function' && define.amd ) {
33
		// Define as an AMD module if possible
34
		define( 'datatables', ['jquery'], factory );
35
	}
36
    else if ( typeof exports === 'object' ) {
37
        // Node/CommonJS
38
        factory( require( 'jquery' ) );
39
    }
40
	else if ( jQuery && !jQuery.fn.dataTable ) {
41
		// Define using browser globals otherwise
42
		// Prevent multiple instantiations if the script is loaded twice
43
		factory( jQuery );
44
	}
45
}
46
(/** @lends <global> */function( $ ) {
47
	"use strict";
48

    
49
	/**
50
	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
51
	 * flexible tool, based upon the foundations of progressive enhancement,
52
	 * which will add advanced interaction controls to any HTML table. For a
53
	 * full list of features please refer to
54
	 * [DataTables.net](href="http://datatables.net).
55
	 *
56
	 * Note that the `DataTable` object is not a global variable but is aliased
57
	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
58
	 * be  accessed.
59
	 *
60
	 *  @class
61
	 *  @param {object} [init={}] Configuration object for DataTables. Options
62
	 *    are defined by {@link DataTable.defaults}
63
	 *  @requires jQuery 1.7+
64
	 *
65
	 *  @example
66
	 *    // Basic initialisation
67
	 *    $(document).ready( function {
68
	 *      $('#example').dataTable();
69
	 *    } );
70
	 *
71
	 *  @example
72
	 *    // Initialisation with configuration options - in this case, disable
73
	 *    // pagination and sorting.
74
	 *    $(document).ready( function {
75
	 *      $('#example').dataTable( {
76
	 *        "paginate": false,
77
	 *        "sort": false
78
	 *      } );
79
	 *    } );
80
	 */
81
	var DataTable;
82

    
83
	
84
	/*
85
	 * It is useful to have variables which are scoped locally so only the
86
	 * DataTables functions can access them and they don't leak into global space.
87
	 * At the same time these functions are often useful over multiple files in the
88
	 * core and API, so we list, or at least document, all variables which are used
89
	 * by DataTables as private variables here. This also ensures that there is no
90
	 * clashing of variable names and that they can easily referenced for reuse.
91
	 */
92
	
93
	
94
	// Defined else where
95
	//  _selector_run
96
	//  _selector_opts
97
	//  _selector_first
98
	//  _selector_row_indexes
99
	
100
	var _ext; // DataTable.ext
101
	var _Api; // DataTable.Api
102
	var _api_register; // DataTable.Api.register
103
	var _api_registerPlural; // DataTable.Api.registerPlural
104
	
105
	var _re_dic = {};
106
	var _re_new_lines = /[\r\n]/g;
107
	var _re_html = /<.*?>/g;
108
	var _re_date_start = /^[\d\+\-a-zA-Z]/;
109
	
110
	// Escape regular expression special characters
111
	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
112
	
113
	// U+2009 is thin space and U+202F is narrow no-break space, both used in many
114
	// standards as thousands separators
115
	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F]/g;
116
	
117
	
118
	var _empty = function ( d ) {
119
		return !d || d === '-' ? true : false;
120
	};
121
	
122
	
123
	var _intVal = function ( s ) {
124
		var integer = parseInt( s, 10 );
125
		return !isNaN(integer) && isFinite(s) ? integer : null;
126
	};
127
	
128
	// Convert from a formatted number with characters other than `.` as the
129
	// decimal place, to a Javascript number
130
	var _numToDecimal = function ( num, decimalPoint ) {
131
		// Cache created regular expressions for speed as this function is called often
132
		if ( ! _re_dic[ decimalPoint ] ) {
133
			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
134
		}
135
		return typeof num === 'string' ?
136
			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
137
			num;
138
	};
139
	
140
	
141
	var _isNumber = function ( d, decimalPoint, formatted ) {
142
		var strType = typeof d === 'string';
143
	
144
		if ( decimalPoint && strType ) {
145
			d = _numToDecimal( d, decimalPoint );
146
		}
147
	
148
		if ( formatted && strType ) {
149
			d = d.replace( _re_formatted_numeric, '' );
150
		}
151
	
152
		return !d || d==='-' || (!isNaN( parseFloat(d) ) && isFinite( d ));
153
	};
154
	
155
	
156
	// A string without HTML in it can be considered to be HTML still
157
	var _isHtml = function ( d ) {
158
		return !d || typeof d === 'string';
159
	};
160
	
161
	
162
	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
163
		if ( _empty( d ) ) {
164
			return true;
165
		}
166
	
167
		var html = _isHtml( d );
168
		return ! html ?
169
			null :
170
			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
171
				true :
172
				null;
173
	};
174
	
175
	
176
	var _pluck = function ( a, prop, prop2 ) {
177
		var out = [];
178
		var i=0, ien=a.length;
179
	
180
		// Could have the test in the loop for slightly smaller code, but speed
181
		// is essential here
182
		if ( prop2 !== undefined ) {
183
			for ( ; i<ien ; i++ ) {
184
				if ( a[i] && a[i][ prop ] ) {
185
					out.push( a[i][ prop ][ prop2 ] );
186
				}
187
			}
188
		}
189
		else {
190
			for ( ; i<ien ; i++ ) {
191
				if ( a[i] ) {
192
					out.push( a[i][ prop ] );
193
				}
194
			}
195
		}
196
	
197
		return out;
198
	};
199
	
200
	
201
	// Basically the same as _pluck, but rather than looping over `a` we use `order`
202
	// as the indexes to pick from `a`
203
	var _pluck_order = function ( a, order, prop, prop2 )
204
	{
205
		var out = [];
206
		var i=0, ien=order.length;
207
	
208
		// Could have the test in the loop for slightly smaller code, but speed
209
		// is essential here
210
		if ( prop2 !== undefined ) {
211
			for ( ; i<ien ; i++ ) {
212
				out.push( a[ order[i] ][ prop ][ prop2 ] );
213
			}
214
		}
215
		else {
216
			for ( ; i<ien ; i++ ) {
217
				out.push( a[ order[i] ][ prop ] );
218
			}
219
		}
220
	
221
		return out;
222
	};
223
	
224
	
225
	var _range = function ( len, start )
226
	{
227
		var out = [];
228
		var end;
229
	
230
		if ( start === undefined ) {
231
			start = 0;
232
			end = len;
233
		}
234
		else {
235
			end = start;
236
			start = len;
237
		}
238
	
239
		for ( var i=start ; i<end ; i++ ) {
240
			out.push( i );
241
		}
242
	
243
		return out;
244
	};
245
	
246
	
247
	var _stripHtml = function ( d ) {
248
		return d.replace( _re_html, '' );
249
	};
250
	
251
	
252
	/**
253
	 * Find the unique elements in a source array.
254
	 *
255
	 * @param  {array} src Source array
256
	 * @return {array} Array of unique items
257
	 * @ignore
258
	 */
259
	var _unique = function ( src )
260
	{
261
		// A faster unique method is to use object keys to identify used values,
262
		// but this doesn't work with arrays or objects, which we must also
263
		// consider. See jsperf.com/compare-array-unique-versions/4 for more
264
		// information.
265
		var
266
			out = [],
267
			val,
268
			i, ien=src.length,
269
			j, k=0;
270
	
271
		again: for ( i=0 ; i<ien ; i++ ) {
272
			val = src[i];
273
	
274
			for ( j=0 ; j<k ; j++ ) {
275
				if ( out[j] === val ) {
276
					continue again;
277
				}
278
			}
279
	
280
			out.push( val );
281
			k++;
282
		}
283
	
284
		return out;
285
	};
286
	
287
	
288
	
289
	/**
290
	 * Create a mapping object that allows camel case parameters to be looked up
291
	 * for their Hungarian counterparts. The mapping is stored in a private
292
	 * parameter called `_hungarianMap` which can be accessed on the source object.
293
	 *  @param {object} o
294
	 *  @memberof DataTable#oApi
295
	 */
296
	function _fnHungarianMap ( o )
297
	{
298
		var
299
			hungarian = 'a aa ai ao as b fn i m o s ',
300
			match,
301
			newKey,
302
			map = {};
303
	
304
		$.each( o, function (key, val) {
305
			match = key.match(/^([^A-Z]+?)([A-Z])/);
306
	
307
			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
308
			{
309
				newKey = key.replace( match[0], match[2].toLowerCase() );
310
				map[ newKey ] = key;
311
	
312
				//console.log( key, match );
313
				if ( match[1] === 'o' )
314
				{
315
					_fnHungarianMap( o[key] );
316
				}
317
			}
318
		} );
319
	
320
		o._hungarianMap = map;
321
	}
322
	
323
	
324
	/**
325
	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
326
	 * created by _fnHungarianMap.
327
	 *  @param {object} src The model object which holds all parameters that can be
328
	 *    mapped.
329
	 *  @param {object} user The object to convert from camel case to Hungarian.
330
	 *  @param {boolean} force When set to `true`, properties which already have a
331
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
332
	 *    won't be.
333
	 *  @memberof DataTable#oApi
334
	 */
335
	function _fnCamelToHungarian ( src, user, force )
336
	{
337
		if ( ! src._hungarianMap ) {
338
			_fnHungarianMap( src );
339
		}
340
	
341
		var hungarianKey;
342
	
343
		$.each( user, function (key, val) {
344
			hungarianKey = src._hungarianMap[ key ];
345
	
346
			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
347
			{
348
				// For objects, we need to buzz down into the object to copy parameters
349
				if ( hungarianKey.charAt(0) === 'o' )
350
				{
351
					// Copy the camelCase options over to the hungarian
352
					if ( ! user[ hungarianKey ] ) {
353
						user[ hungarianKey ] = {};
354
					}
355
					$.extend( true, user[hungarianKey], user[key] );
356
	
357
					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
358
				}
359
				else {
360
					user[hungarianKey] = user[ key ];
361
				}
362
			}
363
		} );
364
	}
365
	
366
	
367
	/**
368
	 * Language compatibility - when certain options are given, and others aren't, we
369
	 * need to duplicate the values over, in order to provide backwards compatibility
370
	 * with older language files.
371
	 *  @param {object} oSettings dataTables settings object
372
	 *  @memberof DataTable#oApi
373
	 */
374
	function _fnLanguageCompat( lang )
375
	{
376
		var defaults = DataTable.defaults.oLanguage;
377
		var zeroRecords = lang.sZeroRecords;
378
	
379
		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
380
		 * sZeroRecords - assuming that is given.
381
		 */
382
		if ( ! lang.sEmptyTable && zeroRecords &&
383
			defaults.sEmptyTable === "No data available in table" )
384
		{
385
			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
386
		}
387
	
388
		/* Likewise with loading records */
389
		if ( ! lang.sLoadingRecords && zeroRecords &&
390
			defaults.sLoadingRecords === "Loading..." )
391
		{
392
			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
393
		}
394
	
395
		// Old parameter name of the thousands separator mapped onto the new
396
		if ( lang.sInfoThousands ) {
397
			lang.sThousands = lang.sInfoThousands;
398
		}
399
	
400
		var decimal = lang.sDecimal;
401
		if ( decimal ) {
402
			_addNumericSort( decimal );
403
		}
404
	}
405
	
406
	
407
	/**
408
	 * Map one parameter onto another
409
	 *  @param {object} o Object to map
410
	 *  @param {*} knew The new parameter name
411
	 *  @param {*} old The old parameter name
412
	 */
413
	var _fnCompatMap = function ( o, knew, old ) {
414
		if ( o[ knew ] !== undefined ) {
415
			o[ old ] = o[ knew ];
416
		}
417
	};
418
	
419
	
420
	/**
421
	 * Provide backwards compatibility for the main DT options. Note that the new
422
	 * options are mapped onto the old parameters, so this is an external interface
423
	 * change only.
424
	 *  @param {object} init Object to map
425
	 */
426
	function _fnCompatOpts ( init )
427
	{
428
		_fnCompatMap( init, 'ordering',      'bSort' );
429
		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
430
		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
431
		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
432
		_fnCompatMap( init, 'order',         'aaSorting' );
433
		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
434
		_fnCompatMap( init, 'paging',        'bPaginate' );
435
		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
436
		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
437
		_fnCompatMap( init, 'searching',     'bFilter' );
438
	}
439
	
440
	
441
	/**
442
	 * Provide backwards compatibility for column options. Note that the new options
443
	 * are mapped onto the old parameters, so this is an external interface change
444
	 * only.
445
	 *  @param {object} init Object to map
446
	 */
447
	function _fnCompatCols ( init )
448
	{
449
		_fnCompatMap( init, 'orderable',     'bSortable' );
450
		_fnCompatMap( init, 'orderData',     'aDataSort' );
451
		_fnCompatMap( init, 'orderSequence', 'asSorting' );
452
		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
453
	}
454
	
455
	
456
	/**
457
	 * Browser feature detection for capabilities, quirks
458
	 *  @param {object} settings dataTables settings object
459
	 *  @memberof DataTable#oApi
460
	 */
461
	function _fnBrowserDetect( settings )
462
	{
463
		var browser = settings.oBrowser;
464
	
465
		// Scrolling feature / quirks detection
466
		var n = $('<div/>')
467
			.css( {
468
				position: 'absolute',
469
				top: 0,
470
				left: 0,
471
				height: 1,
472
				width: 1,
473
				overflow: 'hidden'
474
			} )
475
			.append(
476
				$('<div/>')
477
					.css( {
478
						position: 'absolute',
479
						top: 1,
480
						left: 1,
481
						width: 100,
482
						overflow: 'scroll'
483
					} )
484
					.append(
485
						$('<div class="test"/>')
486
							.css( {
487
								width: '100%',
488
								height: 10
489
							} )
490
					)
491
			)
492
			.appendTo( 'body' );
493
	
494
		var test = n.find('.test');
495
	
496
		// IE6/7 will oversize a width 100% element inside a scrolling element, to
497
		// include the width of the scrollbar, while other browsers ensure the inner
498
		// element is contained without forcing scrolling
499
		browser.bScrollOversize = test[0].offsetWidth === 100;
500
	
501
		// In rtl text layout, some browsers (most, but not all) will place the
502
		// scrollbar on the left, rather than the right.
503
		browser.bScrollbarLeft = test.offset().left !== 1;
504
	
505
		n.remove();
506
	}
507
	
508
	
509
	/**
510
	 * Array.prototype reduce[Right] method, used for browsers which don't support
511
	 * JS 1.6. Done this way to reduce code size, since we iterate either way
512
	 *  @param {object} settings dataTables settings object
513
	 *  @memberof DataTable#oApi
514
	 */
515
	function _fnReduce ( that, fn, init, start, end, inc )
516
	{
517
		var
518
			i = start,
519
			value,
520
			isSet = false;
521
	
522
		if ( init !== undefined ) {
523
			value = init;
524
			isSet = true;
525
		}
526
	
527
		while ( i !== end ) {
528
			if ( ! that.hasOwnProperty(i) ) {
529
				continue;
530
			}
531
	
532
			value = isSet ?
533
				fn( value, that[i], i, that ) :
534
				that[i];
535
	
536
			isSet = true;
537
			i += inc;
538
		}
539
	
540
		return value;
541
	}
542
	
543
	/**
544
	 * Add a column to the list used for the table with default values
545
	 *  @param {object} oSettings dataTables settings object
546
	 *  @param {node} nTh The th element for this column
547
	 *  @memberof DataTable#oApi
548
	 */
549
	function _fnAddColumn( oSettings, nTh )
550
	{
551
		// Add column to aoColumns array
552
		var oDefaults = DataTable.defaults.column;
553
		var iCol = oSettings.aoColumns.length;
554
		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
555
			"nTh": nTh ? nTh : document.createElement('th'),
556
			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
557
			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
558
			"mData": oDefaults.mData ? oDefaults.mData : iCol,
559
			idx: iCol
560
		} );
561
		oSettings.aoColumns.push( oCol );
562
	
563
		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
564
		// passed into extend can be undefined. This allows the user to give a default
565
		// with only some of the parameters defined, and also not give a default
566
		var searchCols = oSettings.aoPreSearchCols;
567
		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
568
	
569
		// Use the default column options function to initialise classes etc
570
		_fnColumnOptions( oSettings, iCol, null );
571
	}
572
	
573
	
574
	/**
575
	 * Apply options for a column
576
	 *  @param {object} oSettings dataTables settings object
577
	 *  @param {int} iCol column index to consider
578
	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
579
	 *  @memberof DataTable#oApi
580
	 */
581
	function _fnColumnOptions( oSettings, iCol, oOptions )
582
	{
583
		var oCol = oSettings.aoColumns[ iCol ];
584
		var oClasses = oSettings.oClasses;
585
		var th = $(oCol.nTh);
586
	
587
		// Try to get width information from the DOM. We can't get it from CSS
588
		// as we'd need to parse the CSS stylesheet. `width` option can override
589
		if ( ! oCol.sWidthOrig ) {
590
			// Width attribute
591
			oCol.sWidthOrig = th.attr('width') || null;
592
	
593
			// Style attribute
594
			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%])/);
595
			if ( t ) {
596
				oCol.sWidthOrig = t[1];
597
			}
598
		}
599
	
600
		/* User specified column options */
601
		if ( oOptions !== undefined && oOptions !== null )
602
		{
603
			// Backwards compatibility
604
			_fnCompatCols( oOptions );
605
	
606
			// Map camel case parameters to their Hungarian counterparts
607
			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
608
	
609
			/* Backwards compatibility for mDataProp */
610
			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
611
			{
612
				oOptions.mData = oOptions.mDataProp;
613
			}
614
	
615
			if ( oOptions.sType )
616
			{
617
				oCol._sManualType = oOptions.sType;
618
			}
619
	
620
			// `class` is a reserved word in Javascript, so we need to provide
621
			// the ability to use a valid name for the camel case input
622
			if ( oOptions.className && ! oOptions.sClass )
623
			{
624
				oOptions.sClass = oOptions.className;
625
			}
626
	
627
			$.extend( oCol, oOptions );
628
			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
629
	
630
			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
631
			 * priority if defined
632
			 */
633
			if ( typeof oOptions.iDataSort === 'number' )
634
			{
635
				oCol.aDataSort = [ oOptions.iDataSort ];
636
			}
637
			_fnMap( oCol, oOptions, "aDataSort" );
638
		}
639
	
640
		/* Cache the data get and set functions for speed */
641
		var mDataSrc = oCol.mData;
642
		var mData = _fnGetObjectDataFn( mDataSrc );
643
		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
644
	
645
		var attrTest = function( src ) {
646
			return typeof src === 'string' && src.indexOf('@') !== -1;
647
		};
648
		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
649
			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
650
		);
651
	
652
		oCol.fnGetData = function (oData, sSpecific) {
653
			var innerData = mData( oData, sSpecific );
654
	
655
			if ( oCol.mRender && (sSpecific && sSpecific !== '') )
656
			{
657
				return mRender( innerData, sSpecific, oData );
658
			}
659
			return innerData;
660
		};
661
		oCol.fnSetData = _fnSetObjectDataFn( mDataSrc );
662
	
663
		/* Feature sorting overrides column specific when off */
664
		if ( !oSettings.oFeatures.bSort )
665
		{
666
			oCol.bSortable = false;
667
			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
668
		}
669
	
670
		/* Check that the class assignment is correct for sorting */
671
		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
672
		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
673
		if ( !oCol.bSortable || (!bAsc && !bDesc) )
674
		{
675
			oCol.sSortingClass = oClasses.sSortableNone;
676
			oCol.sSortingClassJUI = "";
677
		}
678
		else if ( bAsc && !bDesc )
679
		{
680
			oCol.sSortingClass = oClasses.sSortableAsc;
681
			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
682
		}
683
		else if ( !bAsc && bDesc )
684
		{
685
			oCol.sSortingClass = oClasses.sSortableDesc;
686
			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
687
		}
688
		else
689
		{
690
			oCol.sSortingClass = oClasses.sSortable;
691
			oCol.sSortingClassJUI = oClasses.sSortJUI;
692
		}
693
	}
694
	
695
	
696
	/**
697
	 * Adjust the table column widths for new data. Note: you would probably want to
698
	 * do a redraw after calling this function!
699
	 *  @param {object} settings dataTables settings object
700
	 *  @memberof DataTable#oApi
701
	 */
702
	function _fnAdjustColumnSizing ( settings )
703
	{
704
		/* Not interested in doing column width calculation if auto-width is disabled */
705
		if ( settings.oFeatures.bAutoWidth !== false )
706
		{
707
			var columns = settings.aoColumns;
708
	
709
			_fnCalculateColumnWidths( settings );
710
			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
711
			{
712
				columns[i].nTh.style.width = columns[i].sWidth;
713
			}
714
		}
715
	
716
		var scroll = settings.oScroll;
717
		if ( scroll.sY !== '' || scroll.sX !== '')
718
		{
719
			_fnScrollDraw( settings );
720
		}
721
	
722
		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
723
	}
724
	
725
	
726
	/**
727
	 * Covert the index of a visible column to the index in the data array (take account
728
	 * of hidden columns)
729
	 *  @param {object} oSettings dataTables settings object
730
	 *  @param {int} iMatch Visible column index to lookup
731
	 *  @returns {int} i the data index
732
	 *  @memberof DataTable#oApi
733
	 */
734
	function _fnVisibleToColumnIndex( oSettings, iMatch )
735
	{
736
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
737
	
738
		return typeof aiVis[iMatch] === 'number' ?
739
			aiVis[iMatch] :
740
			null;
741
	}
742
	
743
	
744
	/**
745
	 * Covert the index of an index in the data array and convert it to the visible
746
	 *   column index (take account of hidden columns)
747
	 *  @param {int} iMatch Column index to lookup
748
	 *  @param {object} oSettings dataTables settings object
749
	 *  @returns {int} i the data index
750
	 *  @memberof DataTable#oApi
751
	 */
752
	function _fnColumnIndexToVisible( oSettings, iMatch )
753
	{
754
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
755
		var iPos = $.inArray( iMatch, aiVis );
756
	
757
		return iPos !== -1 ? iPos : null;
758
	}
759
	
760
	
761
	/**
762
	 * Get the number of visible columns
763
	 *  @param {object} oSettings dataTables settings object
764
	 *  @returns {int} i the number of visible columns
765
	 *  @memberof DataTable#oApi
766
	 */
767
	function _fnVisbleColumns( oSettings )
768
	{
769
		return _fnGetColumns( oSettings, 'bVisible' ).length;
770
	}
771
	
772
	
773
	/**
774
	 * Get an array of column indexes that match a given property
775
	 *  @param {object} oSettings dataTables settings object
776
	 *  @param {string} sParam Parameter in aoColumns to look for - typically
777
	 *    bVisible or bSearchable
778
	 *  @returns {array} Array of indexes with matched properties
779
	 *  @memberof DataTable#oApi
780
	 */
781
	function _fnGetColumns( oSettings, sParam )
782
	{
783
		var a = [];
784
	
785
		$.map( oSettings.aoColumns, function(val, i) {
786
			if ( val[sParam] ) {
787
				a.push( i );
788
			}
789
		} );
790
	
791
		return a;
792
	}
793
	
794
	
795
	/**
796
	 * Calculate the 'type' of a column
797
	 *  @param {object} settings dataTables settings object
798
	 *  @memberof DataTable#oApi
799
	 */
800
	function _fnColumnTypes ( settings )
801
	{
802
		var columns = settings.aoColumns;
803
		var data = settings.aoData;
804
		var types = DataTable.ext.type.detect;
805
		var i, ien, j, jen, k, ken;
806
		var col, cell, detectedType, cache;
807
	
808
		// For each column, spin over the 
809
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
810
			col = columns[i];
811
			cache = [];
812
	
813
			if ( ! col.sType && col._sManualType ) {
814
				col.sType = col._sManualType;
815
			}
816
			else if ( ! col.sType ) {
817
				for ( j=0, jen=types.length ; j<jen ; j++ ) {
818
					for ( k=0, ken=data.length ; k<ken ; k++ ) {
819
						// Use a cache array so we only need to get the type data
820
						// from the formatter once (when using multiple detectors)
821
						if ( cache[k] === undefined ) {
822
							cache[k] = _fnGetCellData( settings, k, i, 'type' );
823
						}
824
	
825
						detectedType = types[j]( cache[k], settings );
826
	
827
						// Doesn't match, so break early, since this type can't
828
						// apply to this column. Also, HTML is a special case since
829
						// it is so similar to `string`. Just a single match is
830
						// needed for a column to be html type
831
						if ( ! detectedType || detectedType === 'html' ) {
832
							break;
833
						}
834
					}
835
	
836
					// Type is valid for all data points in the column - use this
837
					// type
838
					if ( detectedType ) {
839
						col.sType = detectedType;
840
						break;
841
					}
842
				}
843
	
844
				// Fall back - if no type was detected, always use string
845
				if ( ! col.sType ) {
846
					col.sType = 'string';
847
				}
848
			}
849
		}
850
	}
851
	
852
	
853
	/**
854
	 * Take the column definitions and static columns arrays and calculate how
855
	 * they relate to column indexes. The callback function will then apply the
856
	 * definition found for a column to a suitable configuration object.
857
	 *  @param {object} oSettings dataTables settings object
858
	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
859
	 *  @param {array} aoCols The aoColumns array that defines columns individually
860
	 *  @param {function} fn Callback function - takes two parameters, the calculated
861
	 *    column index and the definition for that column.
862
	 *  @memberof DataTable#oApi
863
	 */
864
	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
865
	{
866
		var i, iLen, j, jLen, k, kLen, def;
867
		var columns = oSettings.aoColumns;
868
	
869
		// Column definitions with aTargets
870
		if ( aoColDefs )
871
		{
872
			/* Loop over the definitions array - loop in reverse so first instance has priority */
873
			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
874
			{
875
				def = aoColDefs[i];
876
	
877
				/* Each definition can target multiple columns, as it is an array */
878
				var aTargets = def.targets !== undefined ?
879
					def.targets :
880
					def.aTargets;
881
	
882
				if ( ! $.isArray( aTargets ) )
883
				{
884
					aTargets = [ aTargets ];
885
				}
886
	
887
				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
888
				{
889
					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
890
					{
891
						/* Add columns that we don't yet know about */
892
						while( columns.length <= aTargets[j] )
893
						{
894
							_fnAddColumn( oSettings );
895
						}
896
	
897
						/* Integer, basic index */
898
						fn( aTargets[j], def );
899
					}
900
					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
901
					{
902
						/* Negative integer, right to left column counting */
903
						fn( columns.length+aTargets[j], def );
904
					}
905
					else if ( typeof aTargets[j] === 'string' )
906
					{
907
						/* Class name matching on TH element */
908
						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
909
						{
910
							if ( aTargets[j] == "_all" ||
911
							     $(columns[k].nTh).hasClass( aTargets[j] ) )
912
							{
913
								fn( k, def );
914
							}
915
						}
916
					}
917
				}
918
			}
919
		}
920
	
921
		// Statically defined columns array
922
		if ( aoCols )
923
		{
924
			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
925
			{
926
				fn( i, aoCols[i] );
927
			}
928
		}
929
	}
930
	
931
	/**
932
	 * Add a data array to the table, creating DOM node etc. This is the parallel to
933
	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
934
	 * DOM source.
935
	 *  @param {object} oSettings dataTables settings object
936
	 *  @param {array} aData data array to be added
937
	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
938
	 *    DataTables will create a row automatically
939
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
940
	 *    if nTr is.
941
	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
942
	 *  @memberof DataTable#oApi
943
	 */
944
	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
945
	{
946
		/* Create the object for storing information about this new row */
947
		var iRow = oSettings.aoData.length;
948
		var oData = $.extend( true, {}, DataTable.models.oRow, {
949
			src: nTr ? 'dom' : 'data'
950
		} );
951
	
952
		oData._aData = aDataIn;
953
		oSettings.aoData.push( oData );
954
	
955
		/* Create the cells */
956
		var nTd, sThisType;
957
		var columns = oSettings.aoColumns;
958
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
959
		{
960
			// When working with a row, the data source object must be populated. In
961
			// all other cases, the data source object is already populated, so we
962
			// don't overwrite it, which might break bindings etc
963
			if ( nTr ) {
964
				_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
965
			}
966
			columns[i].sType = null;
967
		}
968
	
969
		/* Add to the display array */
970
		oSettings.aiDisplayMaster.push( iRow );
971
	
972
		/* Create the DOM information */
973
		if ( !oSettings.oFeatures.bDeferRender )
974
		{
975
			_fnCreateTr( oSettings, iRow, nTr, anTds );
976
		}
977
	
978
		return iRow;
979
	}
980
	
981
	
982
	/**
983
	 * Add one or more TR elements to the table. Generally we'd expect to
984
	 * use this for reading data from a DOM sourced table, but it could be
985
	 * used for an TR element. Note that if a TR is given, it is used (i.e.
986
	 * it is not cloned).
987
	 *  @param {object} settings dataTables settings object
988
	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
989
	 *  @returns {array} Array of indexes for the added rows
990
	 *  @memberof DataTable#oApi
991
	 */
992
	function _fnAddTr( settings, trs )
993
	{
994
		var row;
995
	
996
		// Allow an individual node to be passed in
997
		if ( ! (trs instanceof $) ) {
998
			trs = $(trs);
999
		}
1000
	
1001
		return trs.map( function (i, el) {
1002
			row = _fnGetRowElements( settings, el );
1003
			return _fnAddData( settings, row.data, el, row.cells );
1004
		} );
1005
	}
1006
	
1007
	
1008
	/**
1009
	 * Take a TR element and convert it to an index in aoData
1010
	 *  @param {object} oSettings dataTables settings object
1011
	 *  @param {node} n the TR element to find
1012
	 *  @returns {int} index if the node is found, null if not
1013
	 *  @memberof DataTable#oApi
1014
	 */
1015
	function _fnNodeToDataIndex( oSettings, n )
1016
	{
1017
		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
1018
	}
1019
	
1020
	
1021
	/**
1022
	 * Take a TD element and convert it into a column data index (not the visible index)
1023
	 *  @param {object} oSettings dataTables settings object
1024
	 *  @param {int} iRow The row number the TD/TH can be found in
1025
	 *  @param {node} n The TD/TH element to find
1026
	 *  @returns {int} index if the node is found, -1 if not
1027
	 *  @memberof DataTable#oApi
1028
	 */
1029
	function _fnNodeToColumnIndex( oSettings, iRow, n )
1030
	{
1031
		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
1032
	}
1033
	
1034
	
1035
	/**
1036
	 * Get the data for a given cell from the internal cache, taking into account data mapping
1037
	 *  @param {object} oSettings dataTables settings object
1038
	 *  @param {int} iRow aoData row id
1039
	 *  @param {int} iCol Column index
1040
	 *  @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
1041
	 *  @returns {*} Cell data
1042
	 *  @memberof DataTable#oApi
1043
	 */
1044
	function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
1045
	{
1046
		var oCol = oSettings.aoColumns[iCol];
1047
		var oData = oSettings.aoData[iRow]._aData;
1048
		var sData = oCol.fnGetData( oData, sSpecific );
1049
	
1050
		if ( sData === undefined )
1051
		{
1052
			if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
1053
			{
1054
				_fnLog( oSettings, 0, "Requested unknown parameter "+
1055
					(typeof oCol.mData=='function' ? '{function}' : "'"+oCol.mData+"'")+
1056
					" for row "+iRow, 4 );
1057
				oSettings.iDrawError = oSettings.iDraw;
1058
			}
1059
			return oCol.sDefaultContent;
1060
		}
1061
	
1062
		/* When the data source is null, we can use default column data */
1063
		if ( (sData === oData || sData === null) && oCol.sDefaultContent !== null )
1064
		{
1065
			sData = oCol.sDefaultContent;
1066
		}
1067
		else if ( typeof sData === 'function' )
1068
		{
1069
			// If the data source is a function, then we run it and use the return
1070
			return sData();
1071
		}
1072
	
1073
		if ( sData === null && sSpecific == 'display' )
1074
		{
1075
			return '';
1076
		}
1077
		return sData;
1078
	}
1079
	
1080
	
1081
	/**
1082
	 * Set the value for a specific cell, into the internal data cache
1083
	 *  @param {object} oSettings dataTables settings object
1084
	 *  @param {int} iRow aoData row id
1085
	 *  @param {int} iCol Column index
1086
	 *  @param {*} val Value to set
1087
	 *  @memberof DataTable#oApi
1088
	 */
1089
	function _fnSetCellData( oSettings, iRow, iCol, val )
1090
	{
1091
		var oCol = oSettings.aoColumns[iCol];
1092
		var oData = oSettings.aoData[iRow]._aData;
1093
	
1094
		oCol.fnSetData( oData, val );
1095
	}
1096
	
1097
	
1098
	// Private variable that is used to match action syntax in the data property object
1099
	var __reArray = /\[.*?\]$/;
1100
	var __reFn = /\(\)$/;
1101
	
1102
	/**
1103
	 * Split string on periods, taking into account escaped periods
1104
	 * @param  {string} str String to split
1105
	 * @return {array} Split string
1106
	 */
1107
	function _fnSplitObjNotation( str )
1108
	{
1109
		return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1110
			return s.replace('\\.', '.');
1111
		} );
1112
	}
1113
	
1114
	
1115
	/**
1116
	 * Return a function that can be used to get data from a source object, taking
1117
	 * into account the ability to use nested objects as a source
1118
	 *  @param {string|int|function} mSource The data source for the object
1119
	 *  @returns {function} Data get function
1120
	 *  @memberof DataTable#oApi
1121
	 */
1122
	function _fnGetObjectDataFn( mSource )
1123
	{
1124
		if ( $.isPlainObject( mSource ) )
1125
		{
1126
			/* Build an object of get functions, and wrap them in a single call */
1127
			var o = {};
1128
			$.each( mSource, function (key, val) {
1129
				if ( val ) {
1130
					o[key] = _fnGetObjectDataFn( val );
1131
				}
1132
			} );
1133
	
1134
			return function (data, type, extra) {
1135
				var t = o[type] || o._;
1136
				return t !== undefined ?
1137
					t(data, type, extra) :
1138
					data;
1139
			};
1140
		}
1141
		else if ( mSource === null )
1142
		{
1143
			/* Give an empty string for rendering / sorting etc */
1144
			return function (data, type) {
1145
				return data;
1146
			};
1147
		}
1148
		else if ( typeof mSource === 'function' )
1149
		{
1150
			return function (data, type, extra) {
1151
				return mSource( data, type, extra );
1152
			};
1153
		}
1154
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1155
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1156
		{
1157
			/* If there is a . in the source string then the data source is in a
1158
			 * nested object so we loop over the data for each level to get the next
1159
			 * level down. On each loop we test for undefined, and if found immediately
1160
			 * return. This allows entire objects to be missing and sDefaultContent to
1161
			 * be used if defined, rather than throwing an error
1162
			 */
1163
			var fetchData = function (data, type, src) {
1164
				var arrayNotation, funcNotation, out, innerSrc;
1165
	
1166
				if ( src !== "" )
1167
				{
1168
					var a = _fnSplitObjNotation( src );
1169
	
1170
					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1171
					{
1172
						// Check if we are dealing with special notation
1173
						arrayNotation = a[i].match(__reArray);
1174
						funcNotation = a[i].match(__reFn);
1175
	
1176
						if ( arrayNotation )
1177
						{
1178
							// Array notation
1179
							a[i] = a[i].replace(__reArray, '');
1180
	
1181
							// Condition allows simply [] to be passed in
1182
							if ( a[i] !== "" ) {
1183
								data = data[ a[i] ];
1184
							}
1185
							out = [];
1186
	
1187
							// Get the remainder of the nested object to get
1188
							a.splice( 0, i+1 );
1189
							innerSrc = a.join('.');
1190
	
1191
							// Traverse each entry in the array getting the properties requested
1192
							for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1193
								out.push( fetchData( data[j], type, innerSrc ) );
1194
							}
1195
	
1196
							// If a string is given in between the array notation indicators, that
1197
							// is used to join the strings together, otherwise an array is returned
1198
							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1199
							data = (join==="") ? out : out.join(join);
1200
	
1201
							// The inner call to fetchData has already traversed through the remainder
1202
							// of the source requested, so we exit from the loop
1203
							break;
1204
						}
1205
						else if ( funcNotation )
1206
						{
1207
							// Function call
1208
							a[i] = a[i].replace(__reFn, '');
1209
							data = data[ a[i] ]();
1210
							continue;
1211
						}
1212
	
1213
						if ( data === null || data[ a[i] ] === undefined )
1214
						{
1215
							return undefined;
1216
						}
1217
						data = data[ a[i] ];
1218
					}
1219
				}
1220
	
1221
				return data;
1222
			};
1223
	
1224
			return function (data, type) {
1225
				return fetchData( data, type, mSource );
1226
			};
1227
		}
1228
		else
1229
		{
1230
			/* Array or flat object mapping */
1231
			return function (data, type) {
1232
				return data[mSource];
1233
			};
1234
		}
1235
	}
1236
	
1237
	
1238
	/**
1239
	 * Return a function that can be used to set data from a source object, taking
1240
	 * into account the ability to use nested objects as a source
1241
	 *  @param {string|int|function} mSource The data source for the object
1242
	 *  @returns {function} Data set function
1243
	 *  @memberof DataTable#oApi
1244
	 */
1245
	function _fnSetObjectDataFn( mSource )
1246
	{
1247
		if ( $.isPlainObject( mSource ) )
1248
		{
1249
			/* Unlike get, only the underscore (global) option is used for for
1250
			 * setting data since we don't know the type here. This is why an object
1251
			 * option is not documented for `mData` (which is read/write), but it is
1252
			 * for `mRender` which is read only.
1253
			 */
1254
			return _fnSetObjectDataFn( mSource._ );
1255
		}
1256
		else if ( mSource === null )
1257
		{
1258
			/* Nothing to do when the data source is null */
1259
			return function (data, val) {};
1260
		}
1261
		else if ( typeof mSource === 'function' )
1262
		{
1263
			return function (data, val) {
1264
				mSource( data, 'set', val );
1265
			};
1266
		}
1267
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1268
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1269
		{
1270
			/* Like the get, we need to get data from a nested object */
1271
			var setData = function (data, val, src) {
1272
				var a = _fnSplitObjNotation( src ), b;
1273
				var aLast = a[a.length-1];
1274
				var arrayNotation, funcNotation, o, innerSrc;
1275
	
1276
				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
1277
				{
1278
					// Check if we are dealing with an array notation request
1279
					arrayNotation = a[i].match(__reArray);
1280
					funcNotation = a[i].match(__reFn);
1281
	
1282
					if ( arrayNotation )
1283
					{
1284
						a[i] = a[i].replace(__reArray, '');
1285
						data[ a[i] ] = [];
1286
	
1287
						// Get the remainder of the nested object to set so we can recurse
1288
						b = a.slice();
1289
						b.splice( 0, i+1 );
1290
						innerSrc = b.join('.');
1291
	
1292
						// Traverse each entry in the array setting the properties requested
1293
						for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1294
						{
1295
							o = {};
1296
							setData( o, val[j], innerSrc );
1297
							data[ a[i] ].push( o );
1298
						}
1299
	
1300
						// The inner call to setData has already traversed through the remainder
1301
						// of the source and has set the data, thus we can exit here
1302
						return;
1303
					}
1304
					else if ( funcNotation )
1305
					{
1306
						// Function call
1307
						a[i] = a[i].replace(__reFn, '');
1308
						data = data[ a[i] ]( val );
1309
					}
1310
	
1311
					// If the nested object doesn't currently exist - since we are
1312
					// trying to set the value - create it
1313
					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
1314
					{
1315
						data[ a[i] ] = {};
1316
					}
1317
					data = data[ a[i] ];
1318
				}
1319
	
1320
				// Last item in the input - i.e, the actual set
1321
				if ( aLast.match(__reFn ) )
1322
				{
1323
					// Function call
1324
					data = data[ aLast.replace(__reFn, '') ]( val );
1325
				}
1326
				else
1327
				{
1328
					// If array notation is used, we just want to strip it and use the property name
1329
					// and assign the value. If it isn't used, then we get the result we want anyway
1330
					data[ aLast.replace(__reArray, '') ] = val;
1331
				}
1332
			};
1333
	
1334
			return function (data, val) {
1335
				return setData( data, val, mSource );
1336
			};
1337
		}
1338
		else
1339
		{
1340
			/* Array or flat object mapping */
1341
			return function (data, val) {
1342
				data[mSource] = val;
1343
			};
1344
		}
1345
	}
1346
	
1347
	
1348
	/**
1349
	 * Return an array with the full table data
1350
	 *  @param {object} oSettings dataTables settings object
1351
	 *  @returns array {array} aData Master data array
1352
	 *  @memberof DataTable#oApi
1353
	 */
1354
	function _fnGetDataMaster ( settings )
1355
	{
1356
		return _pluck( settings.aoData, '_aData' );
1357
	}
1358
	
1359
	
1360
	/**
1361
	 * Nuke the table
1362
	 *  @param {object} oSettings dataTables settings object
1363
	 *  @memberof DataTable#oApi
1364
	 */
1365
	function _fnClearTable( settings )
1366
	{
1367
		settings.aoData.length = 0;
1368
		settings.aiDisplayMaster.length = 0;
1369
		settings.aiDisplay.length = 0;
1370
	}
1371
	
1372
	
1373
	 /**
1374
	 * Take an array of integers (index array) and remove a target integer (value - not
1375
	 * the key!)
1376
	 *  @param {array} a Index array to target
1377
	 *  @param {int} iTarget value to find
1378
	 *  @memberof DataTable#oApi
1379
	 */
1380
	function _fnDeleteIndex( a, iTarget, splice )
1381
	{
1382
		var iTargetIndex = -1;
1383
	
1384
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1385
		{
1386
			if ( a[i] == iTarget )
1387
			{
1388
				iTargetIndex = i;
1389
			}
1390
			else if ( a[i] > iTarget )
1391
			{
1392
				a[i]--;
1393
			}
1394
		}
1395
	
1396
		if ( iTargetIndex != -1 && splice === undefined )
1397
		{
1398
			a.splice( iTargetIndex, 1 );
1399
		}
1400
	}
1401
	
1402
	
1403
	/**
1404
	 * Mark cached data as invalid such that a re-read of the data will occur when
1405
	 * the cached data is next requested. Also update from the data source object.
1406
	 *
1407
	 * @param {object} settings DataTables settings object
1408
	 * @param  {int}    rowIdx   Row index to invalidate
1409
	 * @memberof DataTable#oApi
1410
	 *
1411
	 * @todo For the modularisation of v1.11 this will need to become a callback, so
1412
	 *   the sort and filter methods can subscribe to it. That will required
1413
	 *   initialisation options for sorting, which is why it is not already baked in
1414
	 */
1415
	function _fnInvalidateRow( settings, rowIdx, src, column )
1416
	{
1417
		var row = settings.aoData[ rowIdx ];
1418
		var i, ien;
1419
	
1420
		// Are we reading last data from DOM or the data object?
1421
		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1422
			// Read the data from the DOM
1423
			row._aData = _fnGetRowElements( settings, row ).data;
1424
		}
1425
		else {
1426
			// Reading from data object, update the DOM
1427
			var cells = row.anCells;
1428
	
1429
			if ( cells ) {
1430
				for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1431
					cells[i].innerHTML = _fnGetCellData( settings, rowIdx, i, 'display' );
1432
				}
1433
			}
1434
		}
1435
	
1436
		row._aSortData = null;
1437
		row._aFilterData = null;
1438
	
1439
		// Invalidate the type for a specific column (if given) or all columns since
1440
		// the data might have changed
1441
		var cols = settings.aoColumns;
1442
		if ( column !== undefined ) {
1443
			cols[ column ].sType = null;
1444
		}
1445
		else {
1446
			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1447
				cols[i].sType = null;
1448
			}
1449
		}
1450
	
1451
		// Update DataTables special `DT_*` attributes for the row
1452
		_fnRowAttributes( row );
1453
	}
1454
	
1455
	
1456
	/**
1457
	 * Build a data source object from an HTML row, reading the contents of the
1458
	 * cells that are in the row.
1459
	 *
1460
	 * @param {object} settings DataTables settings object
1461
	 * @param {node|object} TR element from which to read data or existing row
1462
	 *   object from which to re-read the data from the cells
1463
	 * @returns {object} Object with two parameters: `data` the data read, in
1464
	 *   document order, and `cells` and array of nodes (they can be useful to the
1465
	 *   caller, so rather than needing a second traversal to get them, just return
1466
	 *   them from here).
1467
	 * @memberof DataTable#oApi
1468
	 */
1469
	function _fnGetRowElements( settings, row )
1470
	{
1471
		var
1472
			d = [],
1473
			tds = [],
1474
			td = row.firstChild,
1475
			name, col, o, i=0, contents,
1476
			columns = settings.aoColumns;
1477
	
1478
		var attr = function ( str, data, td  ) {
1479
			if ( typeof str === 'string' ) {
1480
				var idx = str.indexOf('@');
1481
	
1482
				if ( idx !== -1 ) {
1483
					var src = str.substring( idx+1 );
1484
					o[ '@'+src ] = td.getAttribute( src );
1485
				}
1486
			}
1487
		};
1488
	
1489
		var cellProcess = function ( cell ) {
1490
			col = columns[i];
1491
			contents = $.trim(cell.innerHTML);
1492
	
1493
			if ( col && col._bAttrSrc ) {
1494
				o = {
1495
					display: contents
1496
				};
1497
	
1498
				attr( col.mData.sort, o, cell );
1499
				attr( col.mData.type, o, cell );
1500
				attr( col.mData.filter, o, cell );
1501
	
1502
				d.push( o );
1503
			}
1504
			else {
1505
				d.push( contents );
1506
			}
1507
	
1508
			tds.push( cell );
1509
			i++;
1510
		};
1511
	
1512
		if ( td ) {
1513
			// `tr` element passed in
1514
			while ( td ) {
1515
				name = td.nodeName.toUpperCase();
1516
	
1517
				if ( name == "TD" || name == "TH" ) {
1518
					cellProcess( td );
1519
				}
1520
	
1521
				td = td.nextSibling;
1522
			}
1523
		}
1524
		else {
1525
			// Existing row object passed in
1526
			tds = row.anCells;
1527
			
1528
			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1529
				cellProcess( tds[j] );
1530
			}
1531
		}
1532
	
1533
		return {
1534
			data: d,
1535
			cells: tds
1536
		};
1537
	}
1538
	/**
1539
	 * Create a new TR element (and it's TD children) for a row
1540
	 *  @param {object} oSettings dataTables settings object
1541
	 *  @param {int} iRow Row to consider
1542
	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1543
	 *    DataTables will create a row automatically
1544
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1545
	 *    if nTr is.
1546
	 *  @memberof DataTable#oApi
1547
	 */
1548
	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
1549
	{
1550
		var
1551
			row = oSettings.aoData[iRow],
1552
			rowData = row._aData,
1553
			cells = [],
1554
			nTr, nTd, oCol,
1555
			i, iLen;
1556
	
1557
		if ( row.nTr === null )
1558
		{
1559
			nTr = nTrIn || document.createElement('tr');
1560
	
1561
			row.nTr = nTr;
1562
			row.anCells = cells;
1563
	
1564
			/* Use a private property on the node to allow reserve mapping from the node
1565
			 * to the aoData array for fast look up
1566
			 */
1567
			nTr._DT_RowIndex = iRow;
1568
	
1569
			/* Special parameters can be given by the data source to be used on the row */
1570
			_fnRowAttributes( row );
1571
	
1572
			/* Process each column */
1573
			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1574
			{
1575
				oCol = oSettings.aoColumns[i];
1576
	
1577
				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1578
				cells.push( nTd );
1579
	
1580
				// Need to create the HTML if new, or if a rendering function is defined
1581
				if ( !nTrIn || oCol.mRender || oCol.mData !== i )
1582
				{
1583
					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
1584
				}
1585
	
1586
				/* Add user defined class */
1587
				if ( oCol.sClass )
1588
				{
1589
					nTd.className += ' '+oCol.sClass;
1590
				}
1591
	
1592
				// Visibility - add or remove as required
1593
				if ( oCol.bVisible && ! nTrIn )
1594
				{
1595
					nTr.appendChild( nTd );
1596
				}
1597
				else if ( ! oCol.bVisible && nTrIn )
1598
				{
1599
					nTd.parentNode.removeChild( nTd );
1600
				}
1601
	
1602
				if ( oCol.fnCreatedCell )
1603
				{
1604
					oCol.fnCreatedCell.call( oSettings.oInstance,
1605
						nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), rowData, iRow, i
1606
					);
1607
				}
1608
			}
1609
	
1610
			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
1611
		}
1612
	
1613
		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1614
		// and deployed
1615
		row.nTr.setAttribute( 'role', 'row' );
1616
	}
1617
	
1618
	
1619
	/**
1620
	 * Add attributes to a row based on the special `DT_*` parameters in a data
1621
	 * source object.
1622
	 *  @param {object} DataTables row object for the row to be modified
1623
	 *  @memberof DataTable#oApi
1624
	 */
1625
	function _fnRowAttributes( row )
1626
	{
1627
		var tr = row.nTr;
1628
		var data = row._aData;
1629
	
1630
		if ( tr ) {
1631
			if ( data.DT_RowId ) {
1632
				tr.id = data.DT_RowId;
1633
			}
1634
	
1635
			if ( data.DT_RowClass ) {
1636
				// Remove any classes added by DT_RowClass before
1637
				var a = data.DT_RowClass.split(' ');
1638
				row.__rowc = row.__rowc ?
1639
					_unique( row.__rowc.concat( a ) ) :
1640
					a;
1641
	
1642
				$(tr)
1643
					.removeClass( row.__rowc.join(' ') )
1644
					.addClass( data.DT_RowClass );
1645
			}
1646
	
1647
			if ( data.DT_RowData ) {
1648
				$(tr).data( data.DT_RowData );
1649
			}
1650
		}
1651
	}
1652
	
1653
	
1654
	/**
1655
	 * Create the HTML header for the table
1656
	 *  @param {object} oSettings dataTables settings object
1657
	 *  @memberof DataTable#oApi
1658
	 */
1659
	function _fnBuildHead( oSettings )
1660
	{
1661
		var i, ien, cell, row, column;
1662
		var thead = oSettings.nTHead;
1663
		var tfoot = oSettings.nTFoot;
1664
		var createHeader = $('th, td', thead).length === 0;
1665
		var classes = oSettings.oClasses;
1666
		var columns = oSettings.aoColumns;
1667
	
1668
		if ( createHeader ) {
1669
			row = $('<tr/>').appendTo( thead );
1670
		}
1671
	
1672
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
1673
			column = columns[i];
1674
			cell = $( column.nTh ).addClass( column.sClass );
1675
	
1676
			if ( createHeader ) {
1677
				cell.appendTo( row );
1678
			}
1679
	
1680
			// 1.11 move into sorting
1681
			if ( oSettings.oFeatures.bSort ) {
1682
				cell.addClass( column.sSortingClass );
1683
	
1684
				if ( column.bSortable !== false ) {
1685
					cell
1686
						.attr( 'tabindex', oSettings.iTabIndex )
1687
						.attr( 'aria-controls', oSettings.sTableId );
1688
	
1689
					_fnSortAttachListener( oSettings, column.nTh, i );
1690
				}
1691
			}
1692
	
1693
			if ( column.sTitle != cell.html() ) {
1694
				cell.html( column.sTitle );
1695
			}
1696
	
1697
			_fnRenderer( oSettings, 'header' )(
1698
				oSettings, cell, column, classes
1699
			);
1700
		}
1701
	
1702
		if ( createHeader ) {
1703
			_fnDetectHeader( oSettings.aoHeader, thead );
1704
		}
1705
		
1706
		/* ARIA role for the rows */
1707
	 	$(thead).find('>tr').attr('role', 'row');
1708
	
1709
		/* Deal with the footer - add classes if required */
1710
		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
1711
		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
1712
	
1713
		// Cache the footer cells. Note that we only take the cells from the first
1714
		// row in the footer. If there is more than one row the user wants to
1715
		// interact with, they need to use the table().foot() method. Note also this
1716
		// allows cells to be used for multiple columns using colspan
1717
		if ( tfoot !== null ) {
1718
			var cells = oSettings.aoFooter[0];
1719
	
1720
			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1721
				column = columns[i];
1722
				column.nTf = cells[i].cell;
1723
	
1724
				if ( column.sClass ) {
1725
					$(column.nTf).addClass( column.sClass );
1726
				}
1727
			}
1728
		}
1729
	}
1730
	
1731
	
1732
	/**
1733
	 * Draw the header (or footer) element based on the column visibility states. The
1734
	 * methodology here is to use the layout array from _fnDetectHeader, modified for
1735
	 * the instantaneous column visibility, to construct the new layout. The grid is
1736
	 * traversed over cell at a time in a rows x columns grid fashion, although each
1737
	 * cell insert can cover multiple elements in the grid - which is tracks using the
1738
	 * aApplied array. Cell inserts in the grid will only occur where there isn't
1739
	 * already a cell in that position.
1740
	 *  @param {object} oSettings dataTables settings object
1741
	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
1742
	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1743
	 *  @memberof DataTable#oApi
1744
	 */
1745
	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1746
	{
1747
		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1748
		var aoLocal = [];
1749
		var aApplied = [];
1750
		var iColumns = oSettings.aoColumns.length;
1751
		var iRowspan, iColspan;
1752
	
1753
		if ( ! aoSource )
1754
		{
1755
			return;
1756
		}
1757
	
1758
		if (  bIncludeHidden === undefined )
1759
		{
1760
			bIncludeHidden = false;
1761
		}
1762
	
1763
		/* Make a copy of the master layout array, but without the visible columns in it */
1764
		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1765
		{
1766
			aoLocal[i] = aoSource[i].slice();
1767
			aoLocal[i].nTr = aoSource[i].nTr;
1768
	
1769
			/* Remove any columns which are currently hidden */
1770
			for ( j=iColumns-1 ; j>=0 ; j-- )
1771
			{
1772
				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1773
				{
1774
					aoLocal[i].splice( j, 1 );
1775
				}
1776
			}
1777
	
1778
			/* Prep the applied array - it needs an element for each row */
1779
			aApplied.push( [] );
1780
		}
1781
	
1782
		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1783
		{
1784
			nLocalTr = aoLocal[i].nTr;
1785
	
1786
			/* All cells are going to be replaced, so empty out the row */
1787
			if ( nLocalTr )
1788
			{
1789
				while( (n = nLocalTr.firstChild) )
1790
				{
1791
					nLocalTr.removeChild( n );
1792
				}
1793
			}
1794
	
1795
			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1796
			{
1797
				iRowspan = 1;
1798
				iColspan = 1;
1799
	
1800
				/* Check to see if there is already a cell (row/colspan) covering our target
1801
				 * insert point. If there is, then there is nothing to do.
1802
				 */
1803
				if ( aApplied[i][j] === undefined )
1804
				{
1805
					nLocalTr.appendChild( aoLocal[i][j].cell );
1806
					aApplied[i][j] = 1;
1807
	
1808
					/* Expand the cell to cover as many rows as needed */
1809
					while ( aoLocal[i+iRowspan] !== undefined &&
1810
					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1811
					{
1812
						aApplied[i+iRowspan][j] = 1;
1813
						iRowspan++;
1814
					}
1815
	
1816
					/* Expand the cell to cover as many columns as needed */
1817
					while ( aoLocal[i][j+iColspan] !== undefined &&
1818
					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1819
					{
1820
						/* Must update the applied array over the rows for the columns */
1821
						for ( k=0 ; k<iRowspan ; k++ )
1822
						{
1823
							aApplied[i+k][j+iColspan] = 1;
1824
						}
1825
						iColspan++;
1826
					}
1827
	
1828
					/* Do the actual expansion in the DOM */
1829
					$(aoLocal[i][j].cell)
1830
						.attr('rowspan', iRowspan)
1831
						.attr('colspan', iColspan);
1832
				}
1833
			}
1834
		}
1835
	}
1836
	
1837
	
1838
	/**
1839
	 * Insert the required TR nodes into the table for display
1840
	 *  @param {object} oSettings dataTables settings object
1841
	 *  @memberof DataTable#oApi
1842
	 */
1843
	function _fnDraw( oSettings )
1844
	{
1845
		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1846
		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
1847
		if ( $.inArray( false, aPreDraw ) !== -1 )
1848
		{
1849
			_fnProcessingDisplay( oSettings, false );
1850
			return;
1851
		}
1852
	
1853
		var i, iLen, n;
1854
		var anRows = [];
1855
		var iRowCount = 0;
1856
		var asStripeClasses = oSettings.asStripeClasses;
1857
		var iStripes = asStripeClasses.length;
1858
		var iOpenRows = oSettings.aoOpenRows.length;
1859
		var oLang = oSettings.oLanguage;
1860
		var iInitDisplayStart = oSettings.iInitDisplayStart;
1861
		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
1862
		var aiDisplay = oSettings.aiDisplay;
1863
	
1864
		oSettings.bDrawing = true;
1865
	
1866
		/* Check and see if we have an initial draw position from state saving */
1867
		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
1868
		{
1869
			oSettings._iDisplayStart = bServerSide ?
1870
				iInitDisplayStart :
1871
				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
1872
					0 :
1873
					iInitDisplayStart;
1874
	
1875
			oSettings.iInitDisplayStart = -1;
1876
		}
1877
	
1878
		var iDisplayStart = oSettings._iDisplayStart;
1879
		var iDisplayEnd = oSettings.fnDisplayEnd();
1880
	
1881
		/* Server-side processing draw intercept */
1882
		if ( oSettings.bDeferLoading )
1883
		{
1884
			oSettings.bDeferLoading = false;
1885
			oSettings.iDraw++;
1886
			_fnProcessingDisplay( oSettings, false );
1887
		}
1888
		else if ( !bServerSide )
1889
		{
1890
			oSettings.iDraw++;
1891
		}
1892
		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
1893
		{
1894
			return;
1895
		}
1896
	
1897
		if ( aiDisplay.length !== 0 )
1898
		{
1899
			var iStart = bServerSide ? 0 : iDisplayStart;
1900
			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
1901
	
1902
			for ( var j=iStart ; j<iEnd ; j++ )
1903
			{
1904
				var iDataIndex = aiDisplay[j];
1905
				var aoData = oSettings.aoData[ iDataIndex ];
1906
				if ( aoData.nTr === null )
1907
				{
1908
					_fnCreateTr( oSettings, iDataIndex );
1909
				}
1910
	
1911
				var nRow = aoData.nTr;
1912
	
1913
				/* Remove the old striping classes and then add the new one */
1914
				if ( iStripes !== 0 )
1915
				{
1916
					var sStripe = asStripeClasses[ iRowCount % iStripes ];
1917
					if ( aoData._sRowStripe != sStripe )
1918
					{
1919
						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
1920
						aoData._sRowStripe = sStripe;
1921
					}
1922
				}
1923
	
1924
				/* Row callback functions - might want to manipulate the row */
1925
				_fnCallbackFire( oSettings, 'aoRowCallback', null,
1926
					[nRow, aoData._aData, iRowCount, j] );
1927
	
1928
				anRows.push( nRow );
1929
				iRowCount++;
1930
			}
1931
		}
1932
		else
1933
		{
1934
			/* Table is empty - create a row with an empty message in it */
1935
			var sZero = oLang.sZeroRecords;
1936
			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
1937
			{
1938
				sZero = oLang.sLoadingRecords;
1939
			}
1940
			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
1941
			{
1942
				sZero = oLang.sEmptyTable;
1943
			}
1944
	
1945
			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
1946
				.append( $('<td />', {
1947
					'valign':  'top',
1948
					'colSpan': _fnVisbleColumns( oSettings ),
1949
					'class':   oSettings.oClasses.sRowEmpty
1950
				} ).html( sZero ) )[0];
1951
		}
1952
	
1953
		/* Header and footer callbacks */
1954
		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
1955
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
1956
	
1957
		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
1958
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
1959
	
1960
		var body = $(oSettings.nTBody);
1961
	
1962
		body.children().detach();
1963
		body.append( $(anRows) );
1964
	
1965
		/* Call all required callback functions for the end of a draw */
1966
		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
1967
	
1968
		/* Draw is complete, sorting and filtering must be as well */
1969
		oSettings.bSorted = false;
1970
		oSettings.bFiltered = false;
1971
		oSettings.bDrawing = false;
1972
	}
1973
	
1974
	
1975
	/**
1976
	 * Redraw the table - taking account of the various features which are enabled
1977
	 *  @param {object} oSettings dataTables settings object
1978
	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
1979
	 *    the paging is reset to the first page
1980
	 *  @memberof DataTable#oApi
1981
	 */
1982
	function _fnReDraw( settings, holdPosition )
1983
	{
1984
		var
1985
			features = settings.oFeatures,
1986
			sort     = features.bSort,
1987
			filter   = features.bFilter;
1988
	
1989
		if ( sort ) {
1990
			_fnSort( settings );
1991
		}
1992
	
1993
		if ( filter ) {
1994
			_fnFilterComplete( settings, settings.oPreviousSearch );
1995
		}
1996
		else {
1997
			// No filtering, so we want to just use the display master
1998
			settings.aiDisplay = settings.aiDisplayMaster.slice();
1999
		}
2000
	
2001
		if ( holdPosition !== true ) {
2002
			settings._iDisplayStart = 0;
2003
		}
2004
	
2005
		_fnDraw( settings );
2006
	}
2007
	
2008
	
2009
	/**
2010
	 * Add the options to the page HTML for the table
2011
	 *  @param {object} oSettings dataTables settings object
2012
	 *  @memberof DataTable#oApi
2013
	 */
2014
	function _fnAddOptionsHtml ( oSettings )
2015
	{
2016
		var classes = oSettings.oClasses;
2017
		var table = $(oSettings.nTable);
2018
		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
2019
		var features = oSettings.oFeatures;
2020
	
2021
		// All DataTables are wrapped in a div
2022
		var insert = $('<div/>', {
2023
			id:      oSettings.sTableId+'_wrapper',
2024
			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
2025
		} );
2026
	
2027
		oSettings.nHolding = holding[0];
2028
		oSettings.nTableWrapper = insert[0];
2029
		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
2030
	
2031
		/* Loop over the user set positioning and place the elements as needed */
2032
		var aDom = oSettings.sDom.split('');
2033
		var featureNode, cOption, nNewNode, cNext, sAttr, j;
2034
		for ( var i=0 ; i<aDom.length ; i++ )
2035
		{
2036
			featureNode = null;
2037
			cOption = aDom[i];
2038
	
2039
			if ( cOption == '<' )
2040
			{
2041
				/* New container div */
2042
				nNewNode = $('<div/>')[0];
2043
	
2044
				/* Check to see if we should append an id and/or a class name to the container */
2045
				cNext = aDom[i+1];
2046
				if ( cNext == "'" || cNext == '"' )
2047
				{
2048
					sAttr = "";
2049
					j = 2;
2050
					while ( aDom[i+j] != cNext )
2051
					{
2052
						sAttr += aDom[i+j];
2053
						j++;
2054
					}
2055
	
2056
					/* Replace jQuery UI constants @todo depreciated */
2057
					if ( sAttr == "H" )
2058
					{
2059
						sAttr = classes.sJUIHeader;
2060
					}
2061
					else if ( sAttr == "F" )
2062
					{
2063
						sAttr = classes.sJUIFooter;
2064
					}
2065
	
2066
					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2067
					 * breaks the string into parts and applies them as needed
2068
					 */
2069
					if ( sAttr.indexOf('.') != -1 )
2070
					{
2071
						var aSplit = sAttr.split('.');
2072
						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
2073
						nNewNode.className = aSplit[1];
2074
					}
2075
					else if ( sAttr.charAt(0) == "#" )
2076
					{
2077
						nNewNode.id = sAttr.substr(1, sAttr.length-1);
2078
					}
2079
					else
2080
					{
2081
						nNewNode.className = sAttr;
2082
					}
2083
	
2084
					i += j; /* Move along the position array */
2085
				}
2086
	
2087
				insert.append( nNewNode );
2088
				insert = $(nNewNode);
2089
			}
2090
			else if ( cOption == '>' )
2091
			{
2092
				/* End container div */
2093
				insert = insert.parent();
2094
			}
2095
			// @todo Move options into their own plugins?
2096
			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
2097
			{
2098
				/* Length */
2099
				featureNode = _fnFeatureHtmlLength( oSettings );
2100
			}
2101
			else if ( cOption == 'f' && features.bFilter )
2102
			{
2103
				/* Filter */
2104
				featureNode = _fnFeatureHtmlFilter( oSettings );
2105
			}
2106
			else if ( cOption == 'r' && features.bProcessing )
2107
			{
2108
				/* pRocessing */
2109
				featureNode = _fnFeatureHtmlProcessing( oSettings );
2110
			}
2111
			else if ( cOption == 't' )
2112
			{
2113
				/* Table */
2114
				featureNode = _fnFeatureHtmlTable( oSettings );
2115
			}
2116
			else if ( cOption ==  'i' && features.bInfo )
2117
			{
2118
				/* Info */
2119
				featureNode = _fnFeatureHtmlInfo( oSettings );
2120
			}
2121
			else if ( cOption == 'p' && features.bPaginate )
2122
			{
2123
				/* Pagination */
2124
				featureNode = _fnFeatureHtmlPaginate( oSettings );
2125
			}
2126
			else if ( DataTable.ext.feature.length !== 0 )
2127
			{
2128
				/* Plug-in features */
2129
				var aoFeatures = DataTable.ext.feature;
2130
				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
2131
				{
2132
					if ( cOption == aoFeatures[k].cFeature )
2133
					{
2134
						featureNode = aoFeatures[k].fnInit( oSettings );
2135
						break;
2136
					}
2137
				}
2138
			}
2139
	
2140
			/* Add to the 2D features array */
2141
			if ( featureNode )
2142
			{
2143
				var aanFeatures = oSettings.aanFeatures;
2144
	
2145
				if ( ! aanFeatures[cOption] )
2146
				{
2147
					aanFeatures[cOption] = [];
2148
				}
2149
	
2150
				aanFeatures[cOption].push( featureNode );
2151
				insert.append( featureNode );
2152
			}
2153
		}
2154
	
2155
		/* Built our DOM structure - replace the holding div with what we want */
2156
		holding.replaceWith( insert );
2157
	}
2158
	
2159
	
2160
	/**
2161
	 * Use the DOM source to create up an array of header cells. The idea here is to
2162
	 * create a layout grid (array) of rows x columns, which contains a reference
2163
	 * to the cell that that point in the grid (regardless of col/rowspan), such that
2164
	 * any column / row could be removed and the new grid constructed
2165
	 *  @param array {object} aLayout Array to store the calculated layout in
2166
	 *  @param {node} nThead The header/footer element for the table
2167
	 *  @memberof DataTable#oApi
2168
	 */
2169
	function _fnDetectHeader ( aLayout, nThead )
2170
	{
2171
		var nTrs = $(nThead).children('tr');
2172
		var nTr, nCell;
2173
		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
2174
		var bUnique;
2175
		var fnShiftCol = function ( a, i, j ) {
2176
			var k = a[i];
2177
	                while ( k[j] ) {
2178
				j++;
2179
			}
2180
			return j;
2181
		};
2182
	
2183
		aLayout.splice( 0, aLayout.length );
2184
	
2185
		/* We know how many rows there are in the layout - so prep it */
2186
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2187
		{
2188
			aLayout.push( [] );
2189
		}
2190
	
2191
		/* Calculate a layout array */
2192
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2193
		{
2194
			nTr = nTrs[i];
2195
			iColumn = 0;
2196
	
2197
			/* For every cell in the row... */
2198
			nCell = nTr.firstChild;
2199
			while ( nCell ) {
2200
				if ( nCell.nodeName.toUpperCase() == "TD" ||
2201
				     nCell.nodeName.toUpperCase() == "TH" )
2202
				{
2203
					/* Get the col and rowspan attributes from the DOM and sanitise them */
2204
					iColspan = nCell.getAttribute('colspan') * 1;
2205
					iRowspan = nCell.getAttribute('rowspan') * 1;
2206
					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
2207
					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
2208
	
2209
					/* There might be colspan cells already in this row, so shift our target
2210
					 * accordingly
2211
					 */
2212
					iColShifted = fnShiftCol( aLayout, i, iColumn );
2213
	
2214
					/* Cache calculation for unique columns */
2215
					bUnique = iColspan === 1 ? true : false;
2216
	
2217
					/* If there is col / rowspan, copy the information into the layout grid */
2218
					for ( l=0 ; l<iColspan ; l++ )
2219
					{
2220
						for ( k=0 ; k<iRowspan ; k++ )
2221
						{
2222
							aLayout[i+k][iColShifted+l] = {
2223
								"cell": nCell,
2224
								"unique": bUnique
2225
							};
2226
							aLayout[i+k].nTr = nTr;
2227
						}
2228
					}
2229
				}
2230
				nCell = nCell.nextSibling;
2231
			}
2232
		}
2233
	}
2234
	
2235
	
2236
	/**
2237
	 * Get an array of unique th elements, one for each column
2238
	 *  @param {object} oSettings dataTables settings object
2239
	 *  @param {node} nHeader automatically detect the layout from this node - optional
2240
	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2241
	 *  @returns array {node} aReturn list of unique th's
2242
	 *  @memberof DataTable#oApi
2243
	 */
2244
	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
2245
	{
2246
		var aReturn = [];
2247
		if ( !aLayout )
2248
		{
2249
			aLayout = oSettings.aoHeader;
2250
			if ( nHeader )
2251
			{
2252
				aLayout = [];
2253
				_fnDetectHeader( aLayout, nHeader );
2254
			}
2255
		}
2256
	
2257
		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
2258
		{
2259
			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
2260
			{
2261
				if ( aLayout[i][j].unique &&
2262
					 (!aReturn[j] || !oSettings.bSortCellsTop) )
2263
				{
2264
					aReturn[j] = aLayout[i][j].cell;
2265
				}
2266
			}
2267
		}
2268
	
2269
		return aReturn;
2270
	}
2271
	
2272
	
2273
	
2274
	/**
2275
	 * Create an Ajax call based on the table's settings, taking into account that
2276
	 * parameters can have multiple forms, and backwards compatibility.
2277
	 *
2278
	 * @param {object} oSettings dataTables settings object
2279
	 * @param {array} data Data to send to the server, required by
2280
	 *     DataTables - may be augmented by developer callbacks
2281
	 * @param {function} fn Callback function to run when data is obtained
2282
	 */
2283
	function _fnBuildAjax( oSettings, data, fn )
2284
	{
2285
		// Compatibility with 1.9-, allow fnServerData and event to manipulate
2286
		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
2287
	
2288
		// Convert to object based for 1.10+ if using the old array scheme which can
2289
		// come from server-side processing or serverParams
2290
		if ( data && $.isArray(data) ) {
2291
			var tmp = {};
2292
			var rbracket = /(.*?)\[\]$/;
2293
	
2294
			$.each( data, function (key, val) {
2295
				var match = val.name.match(rbracket);
2296
	
2297
				if ( match ) {
2298
					// Support for arrays
2299
					var name = match[0];
2300
	
2301
					if ( ! tmp[ name ] ) {
2302
						tmp[ name ] = [];
2303
					}
2304
					tmp[ name ].push( val.value );
2305
				}
2306
				else {
2307
					tmp[val.name] = val.value;
2308
				}
2309
			} );
2310
			data = tmp;
2311
		}
2312
	
2313
		var ajaxData;
2314
		var ajax = oSettings.ajax;
2315
		var instance = oSettings.oInstance;
2316
	
2317
		if ( $.isPlainObject( ajax ) && ajax.data )
2318
		{
2319
			ajaxData = ajax.data;
2320
	
2321
			var newData = $.isFunction( ajaxData ) ?
2322
				ajaxData( data ) :  // fn can manipulate data or return an object
2323
				ajaxData;           // object or array to merge
2324
	
2325
			// If the function returned an object, use that alone
2326
			data = $.isFunction( ajaxData ) && newData ?
2327
				newData :
2328
				$.extend( true, data, newData );
2329
	
2330
			// Remove the data property as we've resolved it already and don't want
2331
			// jQuery to do it again (it is restored at the end of the function)
2332
			delete ajax.data;
2333
		}
2334
	
2335
		var baseAjax = {
2336
			"data": data,
2337
			"success": function (json) {
2338
				var error = json.error || json.sError;
2339
				if ( error ) {
2340
					oSettings.oApi._fnLog( oSettings, 0, error );
2341
				}
2342
	
2343
				oSettings.json = json;
2344
				_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2345
				fn( json );
2346
			},
2347
			"dataType": "json",
2348
			"cache": false,
2349
			"type": oSettings.sServerMethod,
2350
			"error": function (xhr, error, thrown) {
2351
				var log = oSettings.oApi._fnLog;
2352
	
2353
				if ( error == "parsererror" ) {
2354
					log( oSettings, 0, 'Invalid JSON response', 1 );
2355
				}
2356
				else if ( xhr.readyState === 4 ) {
2357
					log( oSettings, 0, 'Ajax error', 7 );
2358
				}
2359
	
2360
				_fnProcessingDisplay( oSettings, false );
2361
			}
2362
		};
2363
	
2364
		// Store the data submitted for the API
2365
		oSettings.oAjaxData = data;
2366
	
2367
		// Allow plug-ins and external processes to modify the data
2368
		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
2369
	
2370
		if ( oSettings.fnServerData )
2371
		{
2372
			// DataTables 1.9- compatibility
2373
			oSettings.fnServerData.call( instance,
2374
				oSettings.sAjaxSource,
2375
				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2376
					return { name: key, value: val };
2377
				} ),
2378
				fn,
2379
				oSettings
2380
			);
2381
		}
2382
		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
2383
		{
2384
			// DataTables 1.9- compatibility
2385
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
2386
				url: ajax || oSettings.sAjaxSource
2387
			} ) );
2388
		}
2389
		else if ( $.isFunction( ajax ) )
2390
		{
2391
			// Is a function - let the caller define what needs to be done
2392
			oSettings.jqXHR = ajax.call( instance, data, fn, oSettings );
2393
		}
2394
		else
2395
		{
2396
			// Object to extend the base settings
2397
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
2398
	
2399
			// Restore for next time around
2400
			ajax.data = ajaxData;
2401
		}
2402
	}
2403
	
2404
	
2405
	/**
2406
	 * Update the table using an Ajax call
2407
	 *  @param {object} oSettings dataTables settings object
2408
	 *  @returns {boolean} Block the table drawing or not
2409
	 *  @memberof DataTable#oApi
2410
	 */
2411
	function _fnAjaxUpdate( oSettings )
2412
	{
2413
		if ( oSettings.bAjaxDataGet )
2414
		{
2415
			oSettings.iDraw++;
2416
			_fnProcessingDisplay( oSettings, true );
2417
			var iColumns = oSettings.aoColumns.length;
2418
			var aoData = _fnAjaxParameters( oSettings );
2419
	
2420
			_fnBuildAjax( oSettings, aoData, function(json) {
2421
				_fnAjaxUpdateDraw( oSettings, json );
2422
			}, oSettings );
2423
	
2424
			return false;
2425
		}
2426
		return true;
2427
	}
2428
	
2429
	
2430
	/**
2431
	 * Build up the parameters in an object needed for a server-side processing
2432
	 * request. Note that this is basically done twice, is different ways - a modern
2433
	 * method which is used by default in DataTables 1.10 which uses objects and
2434
	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2435
	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
2436
	 * option is set.
2437
	 *  @param {object} oSettings dataTables settings object
2438
	 *  @returns {bool} block the table drawing or not
2439
	 *  @memberof DataTable#oApi
2440
	 */
2441
	function _fnAjaxParameters( settings )
2442
	{
2443
		var
2444
			columns = settings.aoColumns,
2445
			columnCount = columns.length,
2446
			features = settings.oFeatures,
2447
			preSearch = settings.oPreviousSearch,
2448
			preColSearch = settings.aoPreSearchCols,
2449
			i, data = [], dataProp, column, columnSearch,
2450
			sort = _fnSortFlatten( settings ),
2451
			displayStart = settings._iDisplayStart,
2452
			displayLength = features.bPaginate !== false ?
2453
				settings._iDisplayLength :
2454
				-1;
2455
	
2456
		var param = function ( name, value ) {
2457
			data.push( { 'name': name, 'value': value } );
2458
		};
2459
	
2460
		// DataTables 1.9- compatible method
2461
		param( 'sEcho',          settings.iDraw );
2462
		param( 'iColumns',       columnCount );
2463
		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
2464
		param( 'iDisplayStart',  displayStart );
2465
		param( 'iDisplayLength', displayLength );
2466
	
2467
		// DataTables 1.10+ method
2468
		var d = {
2469
			draw:    settings.iDraw,
2470
			columns: [],
2471
			order:   [],
2472
			start:   displayStart,
2473
			length:  displayLength,
2474
			search:  {
2475
				value: preSearch.sSearch,
2476
				regex: preSearch.bRegex
2477
			}
2478
		};
2479
	
2480
		for ( i=0 ; i<columnCount ; i++ ) {
2481
			column = columns[i];
2482
			columnSearch = preColSearch[i];
2483
			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
2484
	
2485
			d.columns.push( {
2486
				data:       dataProp,
2487
				name:       column.sName,
2488
				searchable: column.bSearchable,
2489
				orderable:  column.bSortable,
2490
				search:     {
2491
					value: columnSearch.sSearch,
2492
					regex: columnSearch.bRegex
2493
				}
2494
			} );
2495
	
2496
			param( "mDataProp_"+i, dataProp );
2497
	
2498
			if ( features.bFilter ) {
2499
				param( 'sSearch_'+i,     columnSearch.sSearch );
2500
				param( 'bRegex_'+i,      columnSearch.bRegex );
2501
				param( 'bSearchable_'+i, column.bSearchable );
2502
			}
2503
	
2504
			if ( features.bSort ) {
2505
				param( 'bSortable_'+i, column.bSortable );
2506
			}
2507
		}
2508
	
2509
		if ( features.bFilter ) {
2510
			param( 'sSearch', preSearch.sSearch );
2511
			param( 'bRegex', preSearch.bRegex );
2512
		}
2513
	
2514
		if ( features.bSort ) {
2515
			$.each( sort, function ( i, val ) {
2516
				d.order.push( { column: val.col, dir: val.dir } );
2517
	
2518
				param( 'iSortCol_'+i, val.col );
2519
				param( 'sSortDir_'+i, val.dir );
2520
			} );
2521
	
2522
			param( 'iSortingCols', sort.length );
2523
		}
2524
	
2525
		// If the legacy.ajax parameter is null, then we automatically decide which
2526
		// form to use, based on sAjaxSource
2527
		var legacy = DataTable.ext.legacy.ajax;
2528
		if ( legacy === null ) {
2529
			return settings.sAjaxSource ? data : d;
2530
		}
2531
	
2532
		// Otherwise, if legacy has been specified then we use that to decide on the
2533
		// form
2534
		return legacy ? data : d;
2535
	}
2536
	
2537
	
2538
	/**
2539
	 * Data the data from the server (nuking the old) and redraw the table
2540
	 *  @param {object} oSettings dataTables settings object
2541
	 *  @param {object} json json data return from the server.
2542
	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
2543
	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2544
	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2545
	 *  @param {array} json.aaData The data to display on this page
2546
	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
2547
	 *  @memberof DataTable#oApi
2548
	 */
2549
	function _fnAjaxUpdateDraw ( settings, json )
2550
	{
2551
		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2552
		// Support both
2553
		var compat = function ( old, modern ) {
2554
			return json[old] !== undefined ? json[old] : json[modern];
2555
		};
2556
	
2557
		var draw            = compat( 'sEcho',                'draw' );
2558
		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
2559
		var rocordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2560
	
2561
		if ( draw ) {
2562
			// Protect against out of sequence returns
2563
			if ( draw*1 < settings.iDraw ) {
2564
				return;
2565
			}
2566
			settings.iDraw = draw * 1;
2567
		}
2568
	
2569
		_fnClearTable( settings );
2570
		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
2571
		settings._iRecordsDisplay = parseInt(rocordsFiltered, 10);
2572
	
2573
		var data = _fnAjaxDataSrc( settings, json );
2574
		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2575
			_fnAddData( settings, data[i] );
2576
		}
2577
		settings.aiDisplay = settings.aiDisplayMaster.slice();
2578
	
2579
		settings.bAjaxDataGet = false;
2580
		_fnDraw( settings );
2581
	
2582
		if ( ! settings._bInitComplete ) {
2583
			_fnInitComplete( settings, json );
2584
		}
2585
	
2586
		settings.bAjaxDataGet = true;
2587
		_fnProcessingDisplay( settings, false );
2588
	}
2589
	
2590
	
2591
	/**
2592
	 * Get the data from the JSON data source to use for drawing a table. Using
2593
	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2594
	 * source object, or from a processing function.
2595
	 *  @param {object} oSettings dataTables settings object
2596
	 *  @param  {object} json Data source object / array from the server
2597
	 *  @return {array} Array of data to use
2598
	 */
2599
	function _fnAjaxDataSrc ( oSettings, json )
2600
	{
2601
		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
2602
			oSettings.ajax.dataSrc :
2603
			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
2604
	
2605
		// Compatibility with 1.9-. In order to read from aaData, check if the
2606
		// default has been changed, if not, check for aaData
2607
		if ( dataSrc === 'data' ) {
2608
			return json.aaData || json[dataSrc];
2609
		}
2610
	
2611
		return dataSrc !== "" ?
2612
			_fnGetObjectDataFn( dataSrc )( json ) :
2613
			json;
2614
	}
2615
	
2616
	
2617
	/**
2618
	 * Generate the node required for filtering text
2619
	 *  @returns {node} Filter control element
2620
	 *  @param {object} oSettings dataTables settings object
2621
	 *  @memberof DataTable#oApi
2622
	 */
2623
	function _fnFeatureHtmlFilter ( settings )
2624
	{
2625
		var classes = settings.oClasses;
2626
		var tableId = settings.sTableId;
2627
		var previousSearch = settings.oPreviousSearch;
2628
		var features = settings.aanFeatures;
2629
		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
2630
	
2631
		var str = settings.oLanguage.sSearch;
2632
		str = str.match(/_INPUT_/) ?
2633
			str.replace('_INPUT_', input) :
2634
			str+input;
2635
	
2636
		var filter = $('<div/>', {
2637
				'id': ! features.f ? tableId+'_filter' : null,
2638
				'class': classes.sFilter
2639
			} )
2640
			.append( $('<label/>' ).append( str ) );
2641
	
2642
		var searchFn = function() {
2643
			/* Update all other filter input elements for the new display */
2644
			var n = features.f;
2645
			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
2646
	
2647
			/* Now do the filter */
2648
			if ( val != previousSearch.sSearch ) {
2649
				_fnFilterComplete( settings, {
2650
					"sSearch": val,
2651
					"bRegex": previousSearch.bRegex,
2652
					"bSmart": previousSearch.bSmart ,
2653
					"bCaseInsensitive": previousSearch.bCaseInsensitive
2654
				} );
2655
	
2656
				// Need to redraw, without resorting
2657
				settings._iDisplayStart = 0;
2658
				_fnDraw( settings );
2659
			}
2660
		};
2661
		var jqFilter = $('input', filter)
2662
			.val( previousSearch.sSearch.replace('"','&quot;') )
2663
			.bind(
2664
				'keyup.DT search.DT input.DT paste.DT cut.DT',
2665
				_fnDataSource( settings ) === 'ssp' ?
2666
					_fnThrottle( searchFn, 400 ):
2667
					searchFn
2668
			)
2669
			.bind( 'keypress.DT', function(e) {
2670
				/* Prevent form submission */
2671
				if ( e.keyCode == 13 ) {
2672
					return false;
2673
				}
2674
			} )
2675
			.attr('aria-controls', tableId);
2676
	
2677
		// Update the input elements whenever the table is filtered
2678
		$(settings.nTable).on( 'filter.DT', function () {
2679
			// IE9 throws an 'unknown error' if document.activeElement is used
2680
			// inside an iframe or frame...
2681
			try {
2682
				if ( jqFilter[0] !== document.activeElement ) {
2683
					jqFilter.val( previousSearch.sSearch );
2684
				}
2685
			}
2686
			catch ( e ) {}
2687
		} );
2688
	
2689
		return filter[0];
2690
	}
2691
	
2692
	
2693
	/**
2694
	 * Filter the table using both the global filter and column based filtering
2695
	 *  @param {object} oSettings dataTables settings object
2696
	 *  @param {object} oSearch search information
2697
	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2698
	 *  @memberof DataTable#oApi
2699
	 */
2700
	function _fnFilterComplete ( oSettings, oInput, iForce )
2701
	{
2702
		var oPrevSearch = oSettings.oPreviousSearch;
2703
		var aoPrevSearch = oSettings.aoPreSearchCols;
2704
		var fnSaveFilter = function ( oFilter ) {
2705
			/* Save the filtering values */
2706
			oPrevSearch.sSearch = oFilter.sSearch;
2707
			oPrevSearch.bRegex = oFilter.bRegex;
2708
			oPrevSearch.bSmart = oFilter.bSmart;
2709
			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
2710
		};
2711
		var fnRegex = function ( o ) {
2712
			// Backwards compatibility with the bEscapeRegex option
2713
			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
2714
		};
2715
	
2716
		// Resolve any column types that are unknown due to addition or invalidation
2717
		// @todo As per sort - can this be moved into an event handler?
2718
		_fnColumnTypes( oSettings );
2719
	
2720
		/* In server-side processing all filtering is done by the server, so no point hanging around here */
2721
		if ( _fnDataSource( oSettings ) != 'ssp' )
2722
		{
2723
			/* Global filter */
2724
			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
2725
			fnSaveFilter( oInput );
2726
	
2727
			/* Now do the individual column filter */
2728
			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
2729
			{
2730
				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
2731
					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
2732
			}
2733
	
2734
			/* Custom filtering */
2735
			_fnFilterCustom( oSettings );
2736
		}
2737
		else
2738
		{
2739
			fnSaveFilter( oInput );
2740
		}
2741
	
2742
		/* Tell the draw function we have been filtering */
2743
		oSettings.bFiltered = true;
2744
		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
2745
	}
2746
	
2747
	
2748
	/**
2749
	 * Apply custom filtering functions
2750
	 *  @param {object} oSettings dataTables settings object
2751
	 *  @memberof DataTable#oApi
2752
	 */
2753
	function _fnFilterCustom( settings )
2754
	{
2755
		var filters = DataTable.ext.search;
2756
		var displayRows = settings.aiDisplay;
2757
		var row, rowIdx;
2758
	
2759
		for ( var i=0, iLen=filters.length ; i<iLen ; i++ ) {
2760
			for ( var j=displayRows.length-1 ; j>=0 ; j-- ) {
2761
				rowIdx = displayRows[ j ];
2762
				row = settings.aoData[ rowIdx ];
2763
	
2764
				if ( ! filters[i]( settings, row._aFilterData, rowIdx, row._aData ) ) {
2765
					displayRows.splice( j, 1 );
2766
				}
2767
			}
2768
		}
2769
	}
2770
	
2771
	
2772
	/**
2773
	 * Filter the table on a per-column basis
2774
	 *  @param {object} oSettings dataTables settings object
2775
	 *  @param {string} sInput string to filter on
2776
	 *  @param {int} iColumn column to filter
2777
	 *  @param {bool} bRegex treat search string as a regular expression or not
2778
	 *  @param {bool} bSmart use smart filtering or not
2779
	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
2780
	 *  @memberof DataTable#oApi
2781
	 */
2782
	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
2783
	{
2784
		if ( searchStr === '' ) {
2785
			return;
2786
		}
2787
	
2788
		var data;
2789
		var display = settings.aiDisplay;
2790
		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
2791
	
2792
		for ( var i=display.length-1 ; i>=0 ; i-- ) {
2793
			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
2794
	
2795
			if ( ! rpSearch.test( data ) ) {
2796
				display.splice( i, 1 );
2797
			}
2798
		}
2799
	}
2800
	
2801
	
2802
	/**
2803
	 * Filter the data table based on user input and draw the table
2804
	 *  @param {object} settings dataTables settings object
2805
	 *  @param {string} input string to filter on
2806
	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
2807
	 *  @param {bool} regex treat as a regular expression or not
2808
	 *  @param {bool} smart perform smart filtering or not
2809
	 *  @param {bool} caseInsensitive Do case insenstive matching or not
2810
	 *  @memberof DataTable#oApi
2811
	 */
2812
	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
2813
	{
2814
		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
2815
		var prevSearch = settings.oPreviousSearch.sSearch;
2816
		var displayMaster = settings.aiDisplayMaster;
2817
		var display, invalidated, i;
2818
	
2819
		// Need to take account of custom filtering functions - always filter
2820
		if ( DataTable.ext.search.length !== 0 ) {
2821
			force = true;
2822
		}
2823
	
2824
		// Check if any of the rows were invalidated
2825
		invalidated = _fnFilterData( settings );
2826
	
2827
		// If the input is blank - we just want the full data set
2828
		if ( input.length <= 0 ) {
2829
			settings.aiDisplay = displayMaster.slice();
2830
		}
2831
		else {
2832
			// New search - start from the master array
2833
			if ( invalidated ||
2834
				 force ||
2835
				 prevSearch.length > input.length ||
2836
				 input.indexOf(prevSearch) !== 0 ||
2837
				 settings.bSorted // On resort, the display master needs to be
2838
				                  // re-filtered since indexes will have changed
2839
			) {
2840
				settings.aiDisplay = displayMaster.slice();
2841
			}
2842
	
2843
			// Search the display array
2844
			display = settings.aiDisplay;
2845
	
2846
			for ( i=display.length-1 ; i>=0 ; i-- ) {
2847
				if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
2848
					display.splice( i, 1 );
2849
				}
2850
			}
2851
		}
2852
	}
2853
	
2854
	
2855
	/**
2856
	 * Build a regular expression object suitable for searching a table
2857
	 *  @param {string} sSearch string to search for
2858
	 *  @param {bool} bRegex treat as a regular expression or not
2859
	 *  @param {bool} bSmart perform smart filtering or not
2860
	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
2861
	 *  @returns {RegExp} constructed object
2862
	 *  @memberof DataTable#oApi
2863
	 */
2864
	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
2865
	{
2866
		search = regex ?
2867
			search :
2868
			_fnEscapeRegex( search );
2869
		
2870
		if ( smart ) {
2871
			/* For smart filtering we want to allow the search to work regardless of
2872
			 * word order. We also want double quoted text to be preserved, so word
2873
			 * order is important - a la google. So this is what we want to
2874
			 * generate:
2875
			 * 
2876
			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
2877
			 */
2878
			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || '', function ( word ) {
2879
				return word.charAt(0) === '"' ?
2880
					word.match( /^"(.*)"$/ )[1] :
2881
					word;
2882
			} );
2883
	
2884
			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
2885
		}
2886
	
2887
		return new RegExp( search, caseInsensitive ? 'i' : '' );
2888
	}
2889
	
2890
	
2891
	/**
2892
	 * scape a string such that it can be used in a regular expression
2893
	 *  @param {string} sVal string to escape
2894
	 *  @returns {string} escaped string
2895
	 *  @memberof DataTable#oApi
2896
	 */
2897
	function _fnEscapeRegex ( sVal )
2898
	{
2899
		return sVal.replace( _re_escape_regex, '\\$1' );
2900
	}
2901
	
2902
	
2903
	
2904
	var __filter_div = $('<div>')[0];
2905
	var __filter_div_textContent = __filter_div.textContent !== undefined;
2906
	
2907
	// Update the filtering data for each row if needed (by invalidation or first run)
2908
	function _fnFilterData ( settings )
2909
	{
2910
		var columns = settings.aoColumns;
2911
		var column;
2912
		var i, j, ien, jen, filterData, cellData, row;
2913
		var fomatters = DataTable.ext.type.search;
2914
		var wasInvalidated = false;
2915
	
2916
		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
2917
			row = settings.aoData[i];
2918
	
2919
			if ( ! row._aFilterData ) {
2920
				filterData = [];
2921
	
2922
				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
2923
					column = columns[j];
2924
	
2925
					if ( column.bSearchable ) {
2926
						cellData = _fnGetCellData( settings, i, j, 'filter' );
2927
	
2928
						cellData = fomatters[ column.sType ] ?
2929
							fomatters[ column.sType ]( cellData ) :
2930
							cellData !== null ?
2931
								cellData :
2932
								'';
2933
					}
2934
					else {
2935
						cellData = '';
2936
					}
2937
	
2938
					// If it looks like there is an HTML entity in the string,
2939
					// attempt to decode it so sorting works as expected. Note that
2940
					// we could use a single line of jQuery to do this, but the DOM
2941
					// method used here is much faster http://jsperf.com/html-decode
2942
					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
2943
						__filter_div.innerHTML = cellData;
2944
						cellData = __filter_div_textContent ?
2945
							__filter_div.textContent :
2946
							__filter_div.innerText;
2947
					}
2948
	
2949
					if ( cellData.replace ) {
2950
						cellData = cellData.replace(/[\r\n]/g, '');
2951
					}
2952
	
2953
					filterData.push( cellData );
2954
				}
2955
	
2956
				row._aFilterData = filterData;
2957
				row._sFilterRow = filterData.join('  ');
2958
				wasInvalidated = true;
2959
			}
2960
		}
2961
	
2962
		return wasInvalidated;
2963
	}
2964
	
2965
	/**
2966
	 * Generate the node required for the info display
2967
	 *  @param {object} oSettings dataTables settings object
2968
	 *  @returns {node} Information element
2969
	 *  @memberof DataTable#oApi
2970
	 */
2971
	function _fnFeatureHtmlInfo ( settings )
2972
	{
2973
		var
2974
			tid = settings.sTableId,
2975
			nodes = settings.aanFeatures.i,
2976
			n = $('<div/>', {
2977
				'class': settings.oClasses.sInfo,
2978
				'id': ! nodes ? tid+'_info' : null
2979
			} );
2980
	
2981
		if ( ! nodes ) {
2982
			// Update display on each draw
2983
			settings.aoDrawCallback.push( {
2984
				"fn": _fnUpdateInfo,
2985
				"sName": "information"
2986
			} );
2987
	
2988
			n
2989
				.attr( 'role', 'status' )
2990
				.attr( 'aria-live', 'polite' );
2991
	
2992
			// Table is described by our info div
2993
			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
2994
		}
2995
	
2996
		return n[0];
2997
	}
2998
	
2999
	
3000
	/**
3001
	 * Update the information elements in the display
3002
	 *  @param {object} settings dataTables settings object
3003
	 *  @memberof DataTable#oApi
3004
	 */
3005
	function _fnUpdateInfo ( settings )
3006
	{
3007
		/* Show information about the table */
3008
		var nodes = settings.aanFeatures.i;
3009
		if ( nodes.length === 0 ) {
3010
			return;
3011
		}
3012
	
3013
		var
3014
			lang  = settings.oLanguage,
3015
			start = settings._iDisplayStart+1,
3016
			end   = settings.fnDisplayEnd(),
3017
			max   = settings.fnRecordsTotal(),
3018
			total = settings.fnRecordsDisplay(),
3019
			out   = total ?
3020
				lang.sInfo :
3021
				lang.sInfoEmpty;
3022
	
3023
		if ( total !== max ) {
3024
			/* Record set after filtering */
3025
			out += ' ' + lang.sInfoFiltered;
3026
		}
3027
	
3028
		// Convert the macros
3029
		out += lang.sInfoPostFix;
3030
		out = _fnInfoMacros( settings, out );
3031
	
3032
		var callback = lang.fnInfoCallback;
3033
		if ( callback !== null ) {
3034
			out = callback.call( settings.oInstance,
3035
				settings, start, end, max, total, out
3036
			);
3037
		}
3038
	
3039
		$(nodes).html( out );
3040
	}
3041
	
3042
	
3043
	function _fnInfoMacros ( settings, str )
3044
	{
3045
		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3046
		// internally
3047
		var
3048
			formatter  = settings.fnFormatNumber,
3049
			start      = settings._iDisplayStart+1,
3050
			len        = settings._iDisplayLength,
3051
			vis        = settings.fnRecordsDisplay(),
3052
			all        = len === -1;
3053
	
3054
		return str.
3055
			replace(/_START_/g, formatter.call( settings, start ) ).
3056
			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
3057
			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
3058
			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
3059
			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
3060
			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
3061
	}
3062
	
3063
	
3064
	
3065
	/**
3066
	 * Draw the table for the first time, adding all required features
3067
	 *  @param {object} settings dataTables settings object
3068
	 *  @memberof DataTable#oApi
3069
	 */
3070
	function _fnInitialise ( settings )
3071
	{
3072
		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3073
		var columns = settings.aoColumns, column;
3074
		var features = settings.oFeatures;
3075
	
3076
		/* Ensure that the table data is fully initialised */
3077
		if ( ! settings.bInitialised ) {
3078
			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
3079
			return;
3080
		}
3081
	
3082
		/* Show the display HTML options */
3083
		_fnAddOptionsHtml( settings );
3084
	
3085
		/* Build and draw the header / footer for the table */
3086
		_fnBuildHead( settings );
3087
		_fnDrawHead( settings, settings.aoHeader );
3088
		_fnDrawHead( settings, settings.aoFooter );
3089
	
3090
		/* Okay to show that something is going on now */
3091
		_fnProcessingDisplay( settings, true );
3092
	
3093
		/* Calculate sizes for columns */
3094
		if ( features.bAutoWidth ) {
3095
			_fnCalculateColumnWidths( settings );
3096
		}
3097
	
3098
		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
3099
			column = columns[i];
3100
	
3101
			if ( column.sWidth ) {
3102
				column.nTh.style.width = _fnStringToCss( column.sWidth );
3103
			}
3104
		}
3105
	
3106
		// If there is default sorting required - let's do it. The sort function
3107
		// will do the drawing for us. Otherwise we draw the table regardless of the
3108
		// Ajax source - this allows the table to look initialised for Ajax sourcing
3109
		// data (show 'loading' message possibly)
3110
		_fnReDraw( settings );
3111
	
3112
		// Server-side processing init complete is done by _fnAjaxUpdateDraw
3113
		var dataSrc = _fnDataSource( settings );
3114
		if ( dataSrc != 'ssp' ) {
3115
			// if there is an ajax source load the data
3116
			if ( dataSrc == 'ajax' ) {
3117
				_fnBuildAjax( settings, [], function(json) {
3118
					var aData = _fnAjaxDataSrc( settings, json );
3119
	
3120
					// Got the data - add it to the table
3121
					for ( i=0 ; i<aData.length ; i++ ) {
3122
						_fnAddData( settings, aData[i] );
3123
					}
3124
	
3125
					// Reset the init display for cookie saving. We've already done
3126
					// a filter, and therefore cleared it before. So we need to make
3127
					// it appear 'fresh'
3128
					settings.iInitDisplayStart = iAjaxStart;
3129
	
3130
					_fnReDraw( settings );
3131
	
3132
					_fnProcessingDisplay( settings, false );
3133
					_fnInitComplete( settings, json );
3134
				}, settings );
3135
			}
3136
			else {
3137
				_fnProcessingDisplay( settings, false );
3138
				_fnInitComplete( settings );
3139
			}
3140
		}
3141
	}
3142
	
3143
	
3144
	/**
3145
	 * Draw the table for the first time, adding all required features
3146
	 *  @param {object} oSettings dataTables settings object
3147
	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
3148
	 *    with client-side processing (optional)
3149
	 *  @memberof DataTable#oApi
3150
	 */
3151
	function _fnInitComplete ( settings, json )
3152
	{
3153
		settings._bInitComplete = true;
3154
	
3155
		// On an Ajax load we now have data and therefore want to apply the column
3156
		// sizing
3157
		if ( json ) {
3158
			_fnAdjustColumnSizing( settings );
3159
		}
3160
	
3161
		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3162
	}
3163
	
3164
	
3165
	function _fnLengthChange ( settings, val )
3166
	{
3167
		var len = parseInt( val, 10 );
3168
		settings._iDisplayLength = len;
3169
	
3170
		_fnLengthOverflow( settings );
3171
	
3172
		// Fire length change event
3173
		_fnCallbackFire( settings, null, 'length', [settings, len] );
3174
	}
3175
	
3176
	
3177
	/**
3178
	 * Generate the node required for user display length changing
3179
	 *  @param {object} settings dataTables settings object
3180
	 *  @returns {node} Display length feature node
3181
	 *  @memberof DataTable#oApi
3182
	 */
3183
	function _fnFeatureHtmlLength ( settings )
3184
	{
3185
		var
3186
			classes  = settings.oClasses,
3187
			tableId  = settings.sTableId,
3188
			menu     = settings.aLengthMenu,
3189
			d2       = $.isArray( menu[0] ),
3190
			lengths  = d2 ? menu[0] : menu,
3191
			language = d2 ? menu[1] : menu;
3192
	
3193
		var select = $('<select/>', {
3194
			'name':          tableId+'_length',
3195
			'aria-controls': tableId,
3196
			'class':         classes.sLengthSelect
3197
		} );
3198
	
3199
		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
3200
			select[0][ i ] = new Option( language[i], lengths[i] );
3201
		}
3202
	
3203
		var div = $('<div><label/></div>').addClass( classes.sLength );
3204
		if ( ! settings.aanFeatures.l ) {
3205
			div[0].id = tableId+'_length';
3206
		}
3207
	
3208
		var a = settings.oLanguage.sLengthMenu.split(/(_MENU_)/);
3209
		div.children().append( a.length > 1 ?
3210
			[ a[0], select, a[2] ] :
3211
			a[0]
3212
		);
3213
	
3214
		// Can't use `select` variable, as user might provide their own select menu
3215
		$('select', div)
3216
			.val( settings._iDisplayLength )
3217
			.bind( 'change.DT', function(e) {
3218
				_fnLengthChange( settings, $(this).val() );
3219
				_fnDraw( settings );
3220
			} );
3221
	
3222
		// Update node value whenever anything changes the table's length
3223
		$(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
3224
			$('select', div).val( len );
3225
		} );
3226
	
3227
		return div[0];
3228
	}
3229
	
3230
	
3231
	
3232
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3233
	 * Note that most of the paging logic is done in
3234
	 * DataTable.ext.pager
3235
	 */
3236
	
3237
	/**
3238
	 * Generate the node required for default pagination
3239
	 *  @param {object} oSettings dataTables settings object
3240
	 *  @returns {node} Pagination feature node
3241
	 *  @memberof DataTable#oApi
3242
	 */
3243
	function _fnFeatureHtmlPaginate ( settings )
3244
	{
3245
		var
3246
			type   = settings.sPaginationType,
3247
			plugin = DataTable.ext.pager[ type ],
3248
			modern = typeof plugin === 'function',
3249
			redraw = function( settings ) {
3250
				_fnDraw( settings );
3251
			},
3252
			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
3253
			features = settings.aanFeatures;
3254
	
3255
		if ( ! modern ) {
3256
			plugin.fnInit( settings, node, redraw );
3257
		}
3258
	
3259
		/* Add a draw callback for the pagination on first instance, to update the paging display */
3260
		if ( ! features.p )
3261
		{
3262
			node.id = settings.sTableId+'_paginate';
3263
	
3264
			settings.aoDrawCallback.push( {
3265
				"fn": function( settings ) {
3266
					if ( modern ) {
3267
						var
3268
							start      = settings._iDisplayStart,
3269
							len        = settings._iDisplayLength,
3270
							visRecords = settings.fnRecordsDisplay(),
3271
							all        = len === -1,
3272
							page = all ? 0 : Math.ceil( start / len ),
3273
							pages = all ? 1 : Math.ceil( visRecords / len ),
3274
							buttons = plugin(page, pages),
3275
							i, ien;
3276
	
3277
						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
3278
							_fnRenderer( settings, 'pageButton' )(
3279
								settings, features.p[i], i, buttons, page, pages
3280
							);
3281
						}
3282
					}
3283
					else {
3284
						plugin.fnUpdate( settings, redraw );
3285
					}
3286
				},
3287
				"sName": "pagination"
3288
			} );
3289
		}
3290
	
3291
		return node;
3292
	}
3293
	
3294
	
3295
	/**
3296
	 * Alter the display settings to change the page
3297
	 *  @param {object} settings DataTables settings object
3298
	 *  @param {string|int} action Paging action to take: "first", "previous",
3299
	 *    "next" or "last" or page number to jump to (integer)
3300
	 *  @param [bool] redraw Automatically draw the update or not
3301
	 *  @returns {bool} true page has changed, false - no change
3302
	 *  @memberof DataTable#oApi
3303
	 */
3304
	function _fnPageChange ( settings, action, redraw )
3305
	{
3306
		var
3307
			start     = settings._iDisplayStart,
3308
			len       = settings._iDisplayLength,
3309
			records   = settings.fnRecordsDisplay();
3310
	
3311
		if ( records === 0 || len === -1 )
3312
		{
3313
			start = 0;
3314
		}
3315
		else if ( typeof action === "number" )
3316
		{
3317
			start = action * len;
3318
	
3319
			if ( start > records )
3320
			{
3321
				start = 0;
3322
			}
3323
		}
3324
		else if ( action == "first" )
3325
		{
3326
			start = 0;
3327
		}
3328
		else if ( action == "previous" )
3329
		{
3330
			start = len >= 0 ?
3331
				start - len :
3332
				0;
3333
	
3334
			if ( start < 0 )
3335
			{
3336
			  start = 0;
3337
			}
3338
		}
3339
		else if ( action == "next" )
3340
		{
3341
			if ( start + len < records )
3342
			{
3343
				start += len;
3344
			}
3345
		}
3346
		else if ( action == "last" )
3347
		{
3348
			start = Math.floor( (records-1) / len) * len;
3349
		}
3350
		else
3351
		{
3352
			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
3353
		}
3354
	
3355
		var changed = settings._iDisplayStart !== start;
3356
		settings._iDisplayStart = start;
3357
	
3358
		if ( changed ) {
3359
			_fnCallbackFire( settings, null, 'page', [settings] );
3360
	
3361
			if ( redraw ) {
3362
				_fnDraw( settings );
3363
			}
3364
		}
3365
	
3366
		return changed;
3367
	}
3368
	
3369
	
3370
	
3371
	/**
3372
	 * Generate the node required for the processing node
3373
	 *  @param {object} settings dataTables settings object
3374
	 *  @returns {node} Processing element
3375
	 *  @memberof DataTable#oApi
3376
	 */
3377
	function _fnFeatureHtmlProcessing ( settings )
3378
	{
3379
		return $('<div/>', {
3380
				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
3381
				'class': settings.oClasses.sProcessing
3382
			} )
3383
			.html( settings.oLanguage.sProcessing )
3384
			.insertBefore( settings.nTable )[0];
3385
	}
3386
	
3387
	
3388
	/**
3389
	 * Display or hide the processing indicator
3390
	 *  @param {object} settings dataTables settings object
3391
	 *  @param {bool} show Show the processing indicator (true) or not (false)
3392
	 *  @memberof DataTable#oApi
3393
	 */
3394
	function _fnProcessingDisplay ( settings, show )
3395
	{
3396
		if ( settings.oFeatures.bProcessing ) {
3397
			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
3398
		}
3399
	
3400
		_fnCallbackFire( settings, null, 'processing', [settings, show] );
3401
	}
3402
	
3403
	/**
3404
	 * Add any control elements for the table - specifically scrolling
3405
	 *  @param {object} settings dataTables settings object
3406
	 *  @returns {node} Node to add to the DOM
3407
	 *  @memberof DataTable#oApi
3408
	 */
3409
	function _fnFeatureHtmlTable ( settings )
3410
	{
3411
		var table = $(settings.nTable);
3412
	
3413
		// Add the ARIA grid role to the table
3414
		table.attr( 'role', 'grid' );
3415
	
3416
		// Scrolling from here on in
3417
		var scroll = settings.oScroll;
3418
	
3419
		if ( scroll.sX === '' && scroll.sY === '' ) {
3420
			return settings.nTable;
3421
		}
3422
	
3423
		var scrollX = scroll.sX;
3424
		var scrollY = scroll.sY;
3425
		var classes = settings.oClasses;
3426
		var caption = table.children('caption');
3427
		var captionSide = caption.length ? caption[0]._captionSide : null;
3428
		var headerClone = $( table[0].cloneNode(false) );
3429
		var footerClone = $( table[0].cloneNode(false) );
3430
		var footer = table.children('tfoot');
3431
		var _div = '<div/>';
3432
		var size = function ( s ) {
3433
			return !s ? null : _fnStringToCss( s );
3434
		};
3435
	
3436
		// This is fairly messy, but with x scrolling enabled, if the table has a
3437
		// width attribute, regardless of any width applied using the column width
3438
		// options, the browser will shrink or grow the table as needed to fit into
3439
		// that 100%. That would make the width options useless. So we remove it.
3440
		// This is okay, under the assumption that width:100% is applied to the
3441
		// table in CSS (it is in the default stylesheet) which will set the table
3442
		// width as appropriate (the attribute and css behave differently...)
3443
		if ( scroll.sX && table.attr('width') === '100%' ) {
3444
			table.removeAttr('width');
3445
		}
3446
	
3447
		if ( ! footer.length ) {
3448
			footer = null;
3449
		}
3450
	
3451
		/*
3452
		 * The HTML structure that we want to generate in this function is:
3453
		 *  div - scroller
3454
		 *    div - scroll head
3455
		 *      div - scroll head inner
3456
		 *        table - scroll head table
3457
		 *          thead - thead
3458
		 *    div - scroll body
3459
		 *      table - table (master table)
3460
		 *        thead - thead clone for sizing
3461
		 *        tbody - tbody
3462
		 *    div - scroll foot
3463
		 *      div - scroll foot inner
3464
		 *        table - scroll foot table
3465
		 *          tfoot - tfoot
3466
		 */
3467
		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
3468
			.append(
3469
				$(_div, { 'class': classes.sScrollHead } )
3470
					.css( {
3471
						overflow: 'hidden',
3472
						position: 'relative',
3473
						border: 0,
3474
						width: scrollX ? size(scrollX) : '100%'
3475
					} )
3476
					.append(
3477
						$(_div, { 'class': classes.sScrollHeadInner } )
3478
							.css( {
3479
								'box-sizing': 'content-box',
3480
								width: scroll.sXInner || '100%'
3481
							} )
3482
							.append(
3483
								headerClone
3484
									.removeAttr('id')
3485
									.css( 'margin-left', 0 )
3486
									.append(
3487
										table.children('thead')
3488
									)
3489
							)
3490
					)
3491
					.append( captionSide === 'top' ? caption : null )
3492
			)
3493
			.append(
3494
				$(_div, { 'class': classes.sScrollBody } )
3495
					.css( {
3496
						overflow: 'auto',
3497
						height: size( scrollY ),
3498
						width: size( scrollX )
3499
					} )
3500
					.append( table )
3501
			);
3502
	
3503
		if ( footer ) {
3504
			scroller.append(
3505
				$(_div, { 'class': classes.sScrollFoot } )
3506
					.css( {
3507
						overflow: 'hidden',
3508
						border: 0,
3509
						width: scrollX ? size(scrollX) : '100%'
3510
					} )
3511
					.append(
3512
						$(_div, { 'class': classes.sScrollFootInner } )
3513
							.append(
3514
								footerClone
3515
									.removeAttr('id')
3516
									.css( 'margin-left', 0 )
3517
									.append(
3518
										table.children('tfoot')
3519
									)
3520
							)
3521
					)
3522
					.append( captionSide === 'bottom' ? caption : null )
3523
			);
3524
		}
3525
	
3526
		var children = scroller.children();
3527
		var scrollHead = children[0];
3528
		var scrollBody = children[1];
3529
		var scrollFoot = footer ? children[2] : null;
3530
	
3531
		// When the body is scrolled, then we also want to scroll the headers
3532
		if ( scrollX ) {
3533
			$(scrollBody).scroll( function (e) {
3534
				var scrollLeft = this.scrollLeft;
3535
	
3536
				scrollHead.scrollLeft = scrollLeft;
3537
	
3538
				if ( footer ) {
3539
					scrollFoot.scrollLeft = scrollLeft;
3540
				}
3541
			} );
3542
		}
3543
	
3544
		settings.nScrollHead = scrollHead;
3545
		settings.nScrollBody = scrollBody;
3546
		settings.nScrollFoot = scrollFoot;
3547
	
3548
		// On redraw - align columns
3549
		settings.aoDrawCallback.push( {
3550
			"fn": _fnScrollDraw,
3551
			"sName": "scrolling"
3552
		} );
3553
	
3554
		return scroller[0];
3555
	}
3556
	
3557
	
3558
	
3559
	/**
3560
	 * Update the header, footer and body tables for resizing - i.e. column
3561
	 * alignment.
3562
	 *
3563
	 * Welcome to the most horrible function DataTables. The process that this
3564
	 * function follows is basically:
3565
	 *   1. Re-create the table inside the scrolling div
3566
	 *   2. Take live measurements from the DOM
3567
	 *   3. Apply the measurements to align the columns
3568
	 *   4. Clean up
3569
	 *
3570
	 *  @param {object} settings dataTables settings object
3571
	 *  @memberof DataTable#oApi
3572
	 */
3573
	function _fnScrollDraw ( settings )
3574
	{
3575
		// Given that this is such a monster function, a lot of variables are use
3576
		// to try and keep the minimised size as small as possible
3577
		var
3578
			scroll         = settings.oScroll,
3579
			scrollX        = scroll.sX,
3580
			scrollXInner   = scroll.sXInner,
3581
			scrollY        = scroll.sY,
3582
			barWidth       = scroll.iBarWidth,
3583
			divHeader      = $(settings.nScrollHead),
3584
			divHeaderStyle = divHeader[0].style,
3585
			divHeaderInner = divHeader.children('div'),
3586
			divHeaderInnerStyle = divHeaderInner[0].style,
3587
			divHeaderTable = divHeaderInner.children('table'),
3588
			divBodyEl      = settings.nScrollBody,
3589
			divBody        = $(divBodyEl),
3590
			divBodyStyle   = divBodyEl.style,
3591
			divFooter      = $(settings.nScrollFoot),
3592
			divFooterInner = divFooter.children('div'),
3593
			divFooterTable = divFooterInner.children('table'),
3594
			header         = $(settings.nTHead),
3595
			table          = $(settings.nTable),
3596
			tableEl        = table[0],
3597
			tableStyle     = tableEl.style,
3598
			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
3599
			browser        = settings.oBrowser,
3600
			ie67           = browser.bScrollOversize,
3601
			headerTrgEls, footerTrgEls,
3602
			headerSrcEls, footerSrcEls,
3603
			headerCopy, footerCopy,
3604
			headerWidths=[], footerWidths=[],
3605
			headerContent=[],
3606
			idx, correction, sanityWidth,
3607
			zeroOut = function(nSizer) {
3608
				var style = nSizer.style;
3609
				style.paddingTop = "0";
3610
				style.paddingBottom = "0";
3611
				style.borderTopWidth = "0";
3612
				style.borderBottomWidth = "0";
3613
				style.height = 0;
3614
			};
3615
	
3616
		/*
3617
		 * 1. Re-create the table inside the scrolling div
3618
		 */
3619
	
3620
		// Remove the old minimised thead and tfoot elements in the inner table
3621
		table.children('thead, tfoot').remove();
3622
	
3623
		// Clone the current header and footer elements and then place it into the inner table
3624
		headerCopy = header.clone().prependTo( table );
3625
		headerTrgEls = header.find('tr'); // original header is in its own table
3626
		headerSrcEls = headerCopy.find('tr');
3627
		headerCopy.find('th, td').removeAttr('tabindex');
3628
	
3629
		if ( footer ) {
3630
			footerCopy = footer.clone().prependTo( table );
3631
			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
3632
			footerSrcEls = footerCopy.find('tr');
3633
		}
3634
	
3635
	
3636
		/*
3637
		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
3638
		 */
3639
	
3640
		// Remove old sizing and apply the calculated column widths
3641
		// Get the unique column headers in the newly created (cloned) header. We want to apply the
3642
		// calculated sizes to this header
3643
		if ( ! scrollX )
3644
		{
3645
			divBodyStyle.width = '100%';
3646
			divHeader[0].style.width = '100%';
3647
		}
3648
	
3649
		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
3650
			idx = _fnVisibleToColumnIndex( settings, i );
3651
			el.style.width = settings.aoColumns[idx].sWidth;
3652
		} );
3653
	
3654
		if ( footer ) {
3655
			_fnApplyToChildren( function(n) {
3656
				n.style.width = "";
3657
			}, footerSrcEls );
3658
		}
3659
	
3660
		// If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3661
		// will end up forcing the scrollbar to appear, making our measurements wrong for when we
3662
		// then hide it (end of this function), so add the header height to the body scroller.
3663
		if ( scroll.bCollapse && scrollY !== "" ) {
3664
			divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3665
		}
3666
	
3667
		// Size the table as a whole
3668
		sanityWidth = table.outerWidth();
3669
		if ( scrollX === "" ) {
3670
			// No x scrolling
3671
			tableStyle.width = "100%";
3672
	
3673
			// IE7 will make the width of the table when 100% include the scrollbar
3674
			// - which is shouldn't. When there is a scrollbar we need to take this
3675
			// into account.
3676
			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
3677
				divBody.css('overflow-y') == "scroll")
3678
			) {
3679
				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3680
			}
3681
		}
3682
		else
3683
		{
3684
			// x scrolling
3685
			if ( scrollXInner !== "" ) {
3686
				// x scroll inner has been given - use it
3687
				tableStyle.width = _fnStringToCss(scrollXInner);
3688
			}
3689
			else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3690
				// There is y-scrolling - try to take account of the y scroll bar
3691
				tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3692
				if ( table.outerWidth() > sanityWidth-barWidth ) {
3693
					// Not possible to take account of it
3694
					tableStyle.width = _fnStringToCss( sanityWidth );
3695
				}
3696
			}
3697
			else {
3698
				// When all else fails
3699
				tableStyle.width = _fnStringToCss( sanityWidth );
3700
			}
3701
		}
3702
	
3703
		// Recalculate the sanity width - now that we've applied the required width,
3704
		// before it was a temporary variable. This is required because the column
3705
		// width calculation is done before this table DOM is created.
3706
		sanityWidth = table.outerWidth();
3707
	
3708
		// Hidden header should have zero height, so remove padding and borders. Then
3709
		// set the width based on the real headers
3710
	
3711
		// Apply all styles in one pass
3712
		_fnApplyToChildren( zeroOut, headerSrcEls );
3713
	
3714
		// Read all widths in next pass
3715
		_fnApplyToChildren( function(nSizer) {
3716
			headerContent.push( nSizer.innerHTML );
3717
			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3718
		}, headerSrcEls );
3719
	
3720
		// Apply all widths in final pass
3721
		_fnApplyToChildren( function(nToSize, i) {
3722
			nToSize.style.width = headerWidths[i];
3723
		}, headerTrgEls );
3724
	
3725
		$(headerSrcEls).height(0);
3726
	
3727
		/* Same again with the footer if we have one */
3728
		if ( footer )
3729
		{
3730
			_fnApplyToChildren( zeroOut, footerSrcEls );
3731
	
3732
			_fnApplyToChildren( function(nSizer) {
3733
				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3734
			}, footerSrcEls );
3735
	
3736
			_fnApplyToChildren( function(nToSize, i) {
3737
				nToSize.style.width = footerWidths[i];
3738
			}, footerTrgEls );
3739
	
3740
			$(footerSrcEls).height(0);
3741
		}
3742
	
3743
	
3744
		/*
3745
		 * 3. Apply the measurements
3746
		 */
3747
	
3748
		// "Hide" the header and footer that we used for the sizing. We need to keep
3749
		// the content of the cell so that the width applied to the header and body
3750
		// both match, but we want to hide it completely. We want to also fix their
3751
		// width to what they currently are
3752
		_fnApplyToChildren( function(nSizer, i) {
3753
			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
3754
			nSizer.style.width = headerWidths[i];
3755
		}, headerSrcEls );
3756
	
3757
		if ( footer )
3758
		{
3759
			_fnApplyToChildren( function(nSizer, i) {
3760
				nSizer.innerHTML = "";
3761
				nSizer.style.width = footerWidths[i];
3762
			}, footerSrcEls );
3763
		}
3764
	
3765
		// Sanity check that the table is of a sensible width. If not then we are going to get
3766
		// misalignment - try to prevent this by not allowing the table to shrink below its min width
3767
		if ( table.outerWidth() < sanityWidth )
3768
		{
3769
			// The min width depends upon if we have a vertical scrollbar visible or not */
3770
			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
3771
				divBody.css('overflow-y') == "scroll")) ?
3772
					sanityWidth+barWidth :
3773
					sanityWidth;
3774
	
3775
			// IE6/7 are a law unto themselves...
3776
			if ( ie67 && (divBodyEl.scrollHeight >
3777
				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
3778
			) {
3779
				tableStyle.width = _fnStringToCss( correction-barWidth );
3780
			}
3781
	
3782
			// And give the user a warning that we've stopped the table getting too small
3783
			if ( scrollX === "" || scrollXInner !== "" ) {
3784
				_fnLog( settings, 1, 'Possible column misalignment', 6 );
3785
			}
3786
		}
3787
		else
3788
		{
3789
			correction = '100%';
3790
		}
3791
	
3792
		// Apply to the container elements
3793
		divBodyStyle.width = _fnStringToCss( correction );
3794
		divHeaderStyle.width = _fnStringToCss( correction );
3795
	
3796
		if ( footer ) {
3797
			settings.nScrollFoot.style.width = _fnStringToCss( correction );
3798
		}
3799
	
3800
	
3801
		/*
3802
		 * 4. Clean up
3803
		 */
3804
		if ( ! scrollY ) {
3805
			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
3806
			 * the scrollbar height from the visible display, rather than adding it on. We need to
3807
			 * set the height in order to sort this. Don't want to do it in any other browsers.
3808
			 */
3809
			if ( ie67 ) {
3810
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
3811
			}
3812
		}
3813
	
3814
		if ( scrollY && scroll.bCollapse ) {
3815
			divBodyStyle.height = _fnStringToCss( scrollY );
3816
	
3817
			var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
3818
				barWidth :
3819
				0;
3820
	
3821
			if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
3822
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
3823
			}
3824
		}
3825
	
3826
		/* Finally set the width's of the header and footer tables */
3827
		var iOuterWidth = table.outerWidth();
3828
		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
3829
		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
3830
	
3831
		// Figure out if there are scrollbar present - if so then we need a the header and footer to
3832
		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
3833
		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
3834
		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
3835
		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
3836
	
3837
		if ( footer ) {
3838
			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
3839
			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
3840
			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
3841
		}
3842
	
3843
		/* Adjust the position of the header in case we loose the y-scrollbar */
3844
		divBody.scroll();
3845
	
3846
		/* If sorting or filtering has occurred, jump the scrolling back to the top */
3847
		if ( settings.bSorted || settings.bFiltered ) {
3848
			divBodyEl.scrollTop = 0;
3849
		}
3850
	}
3851
	
3852
	
3853
	
3854
	/**
3855
	 * Apply a given function to the display child nodes of an element array (typically
3856
	 * TD children of TR rows
3857
	 *  @param {function} fn Method to apply to the objects
3858
	 *  @param array {nodes} an1 List of elements to look through for display children
3859
	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
3860
	 *  @memberof DataTable#oApi
3861
	 */
3862
	function _fnApplyToChildren( fn, an1, an2 )
3863
	{
3864
		var index=0, i=0, iLen=an1.length;
3865
		var nNode1, nNode2;
3866
	
3867
		while ( i < iLen ) {
3868
			nNode1 = an1[i].firstChild;
3869
			nNode2 = an2 ? an2[i].firstChild : null;
3870
	
3871
			while ( nNode1 ) {
3872
				if ( nNode1.nodeType === 1 ) {
3873
					if ( an2 ) {
3874
						fn( nNode1, nNode2, index );
3875
					}
3876
					else {
3877
						fn( nNode1, index );
3878
					}
3879
	
3880
					index++;
3881
				}
3882
	
3883
				nNode1 = nNode1.nextSibling;
3884
				nNode2 = an2 ? nNode2.nextSibling : null;
3885
			}
3886
	
3887
			i++;
3888
		}
3889
	}
3890
	
3891
	
3892
	
3893
	var __re_html_remove = /<.*?>/g;
3894
	
3895
	
3896
	/**
3897
	 * Calculate the width of columns for the table
3898
	 *  @param {object} oSettings dataTables settings object
3899
	 *  @memberof DataTable#oApi
3900
	 */
3901
	function _fnCalculateColumnWidths ( oSettings )
3902
	{
3903
		var
3904
			table = oSettings.nTable,
3905
			columns = oSettings.aoColumns,
3906
			scroll = oSettings.oScroll,
3907
			scrollY = scroll.sY,
3908
			scrollX = scroll.sX,
3909
			scrollXInner = scroll.sXInner,
3910
			columnCount = columns.length,
3911
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
3912
			headerCells = $('th', oSettings.nTHead),
3913
			tableWidthAttr = table.getAttribute('width'),
3914
			tableContainer = table.parentNode,
3915
			userInputs = false,
3916
			i, column, columnIdx, width, outerWidth;
3917
	
3918
		/* Convert any user input sizes into pixel sizes */
3919
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
3920
			column = columns[ visibleColumns[i] ];
3921
	
3922
			if ( column.sWidth !== null ) {
3923
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
3924
	
3925
				userInputs = true;
3926
			}
3927
		}
3928
	
3929
		/* If the number of columns in the DOM equals the number that we have to
3930
		 * process in DataTables, then we can use the offsets that are created by
3931
		 * the web- browser. No custom sizes can be set in order for this to happen,
3932
		 * nor scrolling used
3933
		 */
3934
		if ( ! userInputs && ! scrollX && ! scrollY &&
3935
		    columnCount == _fnVisbleColumns( oSettings ) &&
3936
			columnCount == headerCells.length
3937
		) {
3938
			for ( i=0 ; i<columnCount ; i++ ) {
3939
				columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
3940
			}
3941
		}
3942
		else
3943
		{
3944
			// Otherwise construct a single row table with the widest node in the
3945
			// data, assign any user defined widths, then insert it into the DOM and
3946
			// allow the browser to do all the hard work of calculating table widths
3947
			var tmpTable = $( table.cloneNode( false ) )
3948
				.css( 'visibility', 'hidden' )
3949
				.removeAttr( 'id' )
3950
				.append( $(oSettings.nTHead).clone( false ) )
3951
				.append( $(oSettings.nTFoot).clone( false ) )
3952
				.append( $('<tbody><tr/></tbody>') );
3953
	
3954
			// Remove any assigned widths from the footer (from scrolling)
3955
			tmpTable.find('tfoot th, tfoot td').css('width', '');
3956
	
3957
			var tr = tmpTable.find( 'tbody tr' );
3958
	
3959
			// Apply custom sizing to the cloned header
3960
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
3961
	
3962
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
3963
				column = columns[ visibleColumns[i] ];
3964
	
3965
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
3966
					_fnStringToCss( column.sWidthOrig ) :
3967
					'';
3968
			}
3969
	
3970
			// Find the widest cell for each column and put it into the table
3971
			if ( oSettings.aoData.length ) {
3972
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
3973
					columnIdx = visibleColumns[i];
3974
					column = columns[ columnIdx ];
3975
	
3976
					$( _fnGetWidestNode( oSettings, columnIdx ) )
3977
						.clone( false )
3978
						.append( column.sContentPadding )
3979
						.appendTo( tr );
3980
				}
3981
			}
3982
	
3983
			// Table has been built, attach to the document so we can work with it
3984
			tmpTable.appendTo( tableContainer );
3985
	
3986
			// When scrolling (X or Y) we want to set the width of the table as 
3987
			// appropriate. However, when not scrolling leave the table width as it
3988
			// is. This results in slightly different, but I think correct behaviour
3989
			if ( scrollX && scrollXInner ) {
3990
				tmpTable.width( scrollXInner );
3991
			}
3992
			else if ( scrollX ) {
3993
				tmpTable.css( 'width', 'auto' );
3994
	
3995
				if ( tmpTable.width() < tableContainer.offsetWidth ) {
3996
					tmpTable.width( tableContainer.offsetWidth );
3997
				}
3998
			}
3999
			else if ( scrollY ) {
4000
				tmpTable.width( tableContainer.offsetWidth );
4001
			}
4002
			else if ( tableWidthAttr ) {
4003
				tmpTable.width( tableWidthAttr );
4004
			}
4005
	
4006
			// Take into account the y scrollbar
4007
			_fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4008
	
4009
			// Browsers need a bit of a hand when a width is assigned to any columns
4010
			// when x-scrolling as they tend to collapse the table to the min-width,
4011
			// even if we sent the column widths. So we need to keep track of what
4012
			// the table width should be by summing the user given values, and the
4013
			// automatic values
4014
			if ( scrollX )
4015
			{
4016
				var total = 0;
4017
	
4018
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
4019
					column = columns[ visibleColumns[i] ];
4020
					outerWidth = $(headerCells[i]).outerWidth();
4021
	
4022
					total += column.sWidthOrig === null ?
4023
						outerWidth :
4024
						parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4025
				}
4026
	
4027
				tmpTable.width( _fnStringToCss( total ) );
4028
				table.style.width = _fnStringToCss( total );
4029
			}
4030
	
4031
			// Get the width of each column in the constructed table
4032
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
4033
				column = columns[ visibleColumns[i] ];
4034
				width = $(headerCells[i]).width();
4035
	
4036
				if ( width ) {
4037
					column.sWidth = _fnStringToCss( width );
4038
				}
4039
			}
4040
	
4041
			table.style.width = _fnStringToCss( tmpTable.css('width') );
4042
	
4043
			// Finished with the table - ditch it
4044
			tmpTable.remove();
4045
		}
4046
	
4047
		// If there is a width attr, we want to attach an event listener which
4048
		// allows the table sizing to automatically adjust when the window is
4049
		// resized. Use the width attr rather than CSS, since we can't know if the
4050
		// CSS is a relative value or absolute - DOM read is always px.
4051
		if ( tableWidthAttr ) {
4052
			table.style.width = _fnStringToCss( tableWidthAttr );
4053
		}
4054
	
4055
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4056
			$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4057
				_fnAdjustColumnSizing( oSettings );
4058
			} ) );
4059
	
4060
			oSettings._reszEvt = true;
4061
		}
4062
	}
4063
	
4064
	
4065
	/**
4066
	 * Throttle the calls to a function. Arguments and context are maintained for
4067
	 * the throttled function
4068
	 *  @param {function} fn Function to be called
4069
	 *  @param {int} [freq=200] call frequency in mS
4070
	 *  @returns {function} wrapped function
4071
	 *  @memberof DataTable#oApi
4072
	 */
4073
	function _fnThrottle( fn, freq ) {
4074
		var
4075
			frequency = freq || 200,
4076
			last,
4077
			timer;
4078
	
4079
		return function () {
4080
			var
4081
				that = this,
4082
				now  = +new Date(),
4083
				args = arguments;
4084
	
4085
			if ( last && now < last + frequency ) {
4086
				clearTimeout( timer );
4087
	
4088
				timer = setTimeout( function () {
4089
					last = undefined;
4090
					fn.apply( that, args );
4091
				}, frequency );
4092
			}
4093
			else if ( last ) {
4094
				last = now;
4095
				fn.apply( that, args );
4096
			}
4097
			else {
4098
				last = now;
4099
			}
4100
		};
4101
	}
4102
	
4103
	
4104
	/**
4105
	 * Convert a CSS unit width to pixels (e.g. 2em)
4106
	 *  @param {string} width width to be converted
4107
	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
4108
	 *  @returns {int} width in pixels
4109
	 *  @memberof DataTable#oApi
4110
	 */
4111
	function _fnConvertToWidth ( width, parent )
4112
	{
4113
		if ( ! width ) {
4114
			return 0;
4115
		}
4116
	
4117
		var n = $('<div/>')
4118
			.css( 'width', _fnStringToCss( width ) )
4119
			.appendTo( parent || document.body );
4120
	
4121
		var val = n[0].offsetWidth;
4122
		n.remove();
4123
	
4124
		return val;
4125
	}
4126
	
4127
	
4128
	/**
4129
	 * Adjust a table's width to take account of vertical scroll bar
4130
	 *  @param {object} oSettings dataTables settings object
4131
	 *  @param {node} n table node
4132
	 *  @memberof DataTable#oApi
4133
	 */
4134
	
4135
	function _fnScrollingWidthAdjust ( settings, n )
4136
	{
4137
		var scroll = settings.oScroll;
4138
	
4139
		if ( scroll.sX || scroll.sY ) {
4140
			// When y-scrolling only, we want to remove the width of the scroll bar
4141
			// so the table + scroll bar will fit into the area available, otherwise
4142
			// we fix the table at its current size with no adjustment
4143
			var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4144
			n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4145
		}
4146
	}
4147
	
4148
	
4149
	/**
4150
	 * Get the widest node
4151
	 *  @param {object} settings dataTables settings object
4152
	 *  @param {int} colIdx column of interest
4153
	 *  @returns {node} widest table node
4154
	 *  @memberof DataTable#oApi
4155
	 */
4156
	function _fnGetWidestNode( settings, colIdx )
4157
	{
4158
		var idx = _fnGetMaxLenString( settings, colIdx );
4159
		if ( idx < 0 ) {
4160
			return null;
4161
		}
4162
	
4163
		var data = settings.aoData[ idx ];
4164
		return ! data.nTr ? // Might not have been created when deferred rendering
4165
			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
4166
			data.anCells[ colIdx ];
4167
	}
4168
	
4169
	
4170
	/**
4171
	 * Get the maximum strlen for each data column
4172
	 *  @param {object} settings dataTables settings object
4173
	 *  @param {int} colIdx column of interest
4174
	 *  @returns {string} max string length for each column
4175
	 *  @memberof DataTable#oApi
4176
	 */
4177
	function _fnGetMaxLenString( settings, colIdx )
4178
	{
4179
		var s, max=-1, maxIdx = -1;
4180
	
4181
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4182
			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4183
			s = s.replace( __re_html_remove, '' );
4184
	
4185
			if ( s.length > max ) {
4186
				max = s.length;
4187
				maxIdx = i;
4188
			}
4189
		}
4190
	
4191
		return maxIdx;
4192
	}
4193
	
4194
	
4195
	/**
4196
	 * Append a CSS unit (only if required) to a string
4197
	 *  @param {string} value to css-ify
4198
	 *  @returns {string} value with css unit
4199
	 *  @memberof DataTable#oApi
4200
	 */
4201
	function _fnStringToCss( s )
4202
	{
4203
		if ( s === null ) {
4204
			return '0px';
4205
		}
4206
	
4207
		if ( typeof s == 'number' ) {
4208
			return s < 0 ?
4209
				'0px' :
4210
				s+'px';
4211
		}
4212
	
4213
		// Check it has a unit character already
4214
		return s.match(/\d$/) ?
4215
			s+'px' :
4216
			s;
4217
	}
4218
	
4219
	
4220
	/**
4221
	 * Get the width of a scroll bar in this browser being used
4222
	 *  @returns {int} width in pixels
4223
	 *  @memberof DataTable#oApi
4224
	 */
4225
	function _fnScrollBarWidth ()
4226
	{
4227
		// On first run a static variable is set, since this is only needed once.
4228
		// Subsequent runs will just use the previously calculated value
4229
		if ( ! DataTable.__scrollbarWidth ) {
4230
			var inner = $('<p/>').css( {
4231
				width: '100%',
4232
				height: 200,
4233
				padding: 0
4234
			} )[0];
4235
	
4236
			var outer = $('<div/>')
4237
				.css( {
4238
					position: 'absolute',
4239
					top: 0,
4240
					left: 0,
4241
					width: 200,
4242
					height: 150,
4243
					padding: 0,
4244
					overflow: 'hidden',
4245
					visibility: 'hidden'
4246
				} )
4247
				.append( inner )
4248
				.appendTo( 'body' );
4249
	
4250
			var w1 = inner.offsetWidth;
4251
			outer.css( 'overflow', 'scroll' );
4252
			var w2 = inner.offsetWidth;
4253
	
4254
			if ( w1 === w2 ) {
4255
				w2 = outer[0].clientWidth;
4256
			}
4257
	
4258
			outer.remove();
4259
	
4260
			DataTable.__scrollbarWidth = w1 - w2;
4261
		}
4262
	
4263
		return DataTable.__scrollbarWidth;
4264
	}
4265
	
4266
	
4267
	
4268
	function _fnSortFlatten ( settings )
4269
	{
4270
		var
4271
			i, iLen, k, kLen,
4272
			aSort = [],
4273
			aiOrig = [],
4274
			aoColumns = settings.aoColumns,
4275
			aDataSort, iCol, sType, srcCol,
4276
			fixed = settings.aaSortingFixed,
4277
			fixedObj = $.isPlainObject( fixed ),
4278
			nestedSort = [],
4279
			add = function ( a ) {
4280
				if ( a.length && ! $.isArray( a[0] ) ) {
4281
					// 1D array
4282
					nestedSort.push( a );
4283
				}
4284
				else {
4285
					// 2D array
4286
					nestedSort.push.apply( nestedSort, a );
4287
				}
4288
			};
4289
	
4290
		// Build the sort array, with pre-fix and post-fix options if they have been
4291
		// specified
4292
		if ( $.isArray( fixed ) ) {
4293
			add( fixed );
4294
		}
4295
	
4296
		if ( fixedObj && fixed.pre ) {
4297
			add( fixed.pre );
4298
		}
4299
	
4300
		add( settings.aaSorting );
4301
	
4302
		if (fixedObj && fixed.post ) {
4303
			add( fixed.post );
4304
		}
4305
	
4306
		for ( i=0 ; i<nestedSort.length ; i++ )
4307
		{
4308
			srcCol = nestedSort[i][0];
4309
			aDataSort = aoColumns[ srcCol ].aDataSort;
4310
	
4311
			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
4312
			{
4313
				iCol = aDataSort[k];
4314
				sType = aoColumns[ iCol ].sType || 'string';
4315
	
4316
				aSort.push( {
4317
					src:       srcCol,
4318
					col:       iCol,
4319
					dir:       nestedSort[i][1],
4320
					index:     nestedSort[i][2],
4321
					type:      sType,
4322
					formatter: DataTable.ext.type.order[ sType+"-pre" ]
4323
				} );
4324
			}
4325
		}
4326
	
4327
		return aSort;
4328
	}
4329
	
4330
	/**
4331
	 * Change the order of the table
4332
	 *  @param {object} oSettings dataTables settings object
4333
	 *  @memberof DataTable#oApi
4334
	 *  @todo This really needs split up!
4335
	 */
4336
	function _fnSort ( oSettings )
4337
	{
4338
		var
4339
			i, ien, iLen, j, jLen, k, kLen,
4340
			sDataType, nTh,
4341
			aiOrig = [],
4342
			oExtSort = DataTable.ext.type.order,
4343
			aoData = oSettings.aoData,
4344
			aoColumns = oSettings.aoColumns,
4345
			aDataSort, data, iCol, sType, oSort,
4346
			formatters = 0,
4347
			sortCol,
4348
			displayMaster = oSettings.aiDisplayMaster,
4349
			aSort;
4350
	
4351
		// Resolve any column types that are unknown due to addition or invalidation
4352
		// @todo Can this be moved into a 'data-ready' handler which is called when
4353
		//   data is going to be used in the table?
4354
		_fnColumnTypes( oSettings );
4355
	
4356
		aSort = _fnSortFlatten( oSettings );
4357
	
4358
		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
4359
			sortCol = aSort[i];
4360
	
4361
			// Track if we can use the fast sort algorithm
4362
			if ( sortCol.formatter ) {
4363
				formatters++;
4364
			}
4365
	
4366
			// Load the data needed for the sort, for each cell
4367
			_fnSortData( oSettings, sortCol.col );
4368
		}
4369
	
4370
		/* No sorting required if server-side or no sorting array */
4371
		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
4372
		{
4373
			// Create a value - key array of the current row positions such that we can use their
4374
			// current position during the sort, if values match, in order to perform stable sorting
4375
			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
4376
				aiOrig[ displayMaster[i] ] = i;
4377
			}
4378
	
4379
			/* Do the sort - here we want multi-column sorting based on a given data source (column)
4380
			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4381
			 * follow on it's own, but this is what we want (example two column sorting):
4382
			 *  fnLocalSorting = function(a,b){
4383
			 *    var iTest;
4384
			 *    iTest = oSort['string-asc']('data11', 'data12');
4385
			 *      if (iTest !== 0)
4386
			 *        return iTest;
4387
			 *    iTest = oSort['numeric-desc']('data21', 'data22');
4388
			 *    if (iTest !== 0)
4389
			 *      return iTest;
4390
			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4391
			 *  }
4392
			 * Basically we have a test for each sorting column, if the data in that column is equal,
4393
			 * test the next column. If all columns match, then we use a numeric sort on the row
4394
			 * positions in the original data array to provide a stable sort.
4395
			 *
4396
			 * Note - I know it seems excessive to have two sorting methods, but the first is around
4397
			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
4398
			 * methods which do not have a pre-sort formatting function.
4399
			 */
4400
			if ( formatters === aSort.length ) {
4401
				// All sort types have formatting functions
4402
				displayMaster.sort( function ( a, b ) {
4403
					var
4404
						x, y, k, test, sort,
4405
						len=aSort.length,
4406
						dataA = aoData[a]._aSortData,
4407
						dataB = aoData[b]._aSortData;
4408
	
4409
					for ( k=0 ; k<len ; k++ ) {
4410
						sort = aSort[k];
4411
	
4412
						x = dataA[ sort.col ];
4413
						y = dataB[ sort.col ];
4414
	
4415
						test = x<y ? -1 : x>y ? 1 : 0;
4416
						if ( test !== 0 ) {
4417
							return sort.dir === 'asc' ? test : -test;
4418
						}
4419
					}
4420
	
4421
					x = aiOrig[a];
4422
					y = aiOrig[b];
4423
					return x<y ? -1 : x>y ? 1 : 0;
4424
				} );
4425
			}
4426
			else {
4427
				// Depreciated - remove in 1.11 (providing a plug-in option)
4428
				// Not all sort types have formatting methods, so we have to call their sorting
4429
				// methods.
4430
				displayMaster.sort( function ( a, b ) {
4431
					var
4432
						x, y, k, l, test, sort, fn,
4433
						len=aSort.length,
4434
						dataA = aoData[a]._aSortData,
4435
						dataB = aoData[b]._aSortData;
4436
	
4437
					for ( k=0 ; k<len ; k++ ) {
4438
						sort = aSort[k];
4439
	
4440
						x = dataA[ sort.col ];
4441
						y = dataB[ sort.col ];
4442
	
4443
						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
4444
						test = fn( x, y );
4445
						if ( test !== 0 ) {
4446
							return test;
4447
						}
4448
					}
4449
	
4450
					x = aiOrig[a];
4451
					y = aiOrig[b];
4452
					return x<y ? -1 : x>y ? 1 : 0;
4453
				} );
4454
			}
4455
		}
4456
	
4457
		/* Tell the draw function that we have sorted the data */
4458
		oSettings.bSorted = true;
4459
	}
4460
	
4461
	
4462
	function _fnSortAria ( settings )
4463
	{
4464
		var label;
4465
		var nextSort;
4466
		var columns = settings.aoColumns;
4467
		var aSort = _fnSortFlatten( settings );
4468
		var oAria = settings.oLanguage.oAria;
4469
	
4470
		// ARIA attributes - need to loop all columns, to update all (removing old
4471
		// attributes as needed)
4472
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4473
		{
4474
			var col = columns[i];
4475
			var asSorting = col.asSorting;
4476
			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
4477
			var th = col.nTh;
4478
	
4479
			// IE7 is throwing an error when setting these properties with jQuery's
4480
			// attr() and removeAttr() methods...
4481
			th.removeAttribute('aria-sort');
4482
	
4483
			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4484
			if ( col.bSortable ) {
4485
				if ( aSort.length > 0 && aSort[0].col == i ) {
4486
					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
4487
					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
4488
				}
4489
				else {
4490
					nextSort = asSorting[0];
4491
				}
4492
	
4493
				label = sTitle + ( nextSort === "asc" ?
4494
					oAria.sSortAscending :
4495
					oAria.sSortDescending
4496
				);
4497
			}
4498
			else {
4499
				label = sTitle;
4500
			}
4501
	
4502
			th.setAttribute('aria-label', label);
4503
		}
4504
	}
4505
	
4506
	
4507
	/**
4508
	 * Function to run on user sort request
4509
	 *  @param {object} settings dataTables settings object
4510
	 *  @param {node} attachTo node to attach the handler to
4511
	 *  @param {int} colIdx column sorting index
4512
	 *  @param {boolean} [append=false] Append the requested sort to the existing
4513
	 *    sort if true (i.e. multi-column sort)
4514
	 *  @param {function} [callback] callback function
4515
	 *  @memberof DataTable#oApi
4516
	 */
4517
	function _fnSortListener ( settings, colIdx, append, callback )
4518
	{
4519
		var col = settings.aoColumns[ colIdx ];
4520
		var sorting = settings.aaSorting;
4521
		var asSorting = col.asSorting;
4522
		var nextSortIdx;
4523
		var next = function ( a ) {
4524
			var idx = a._idx;
4525
			if ( idx === undefined ) {
4526
				idx = $.inArray( a[1], asSorting );
4527
			}
4528
	
4529
			return idx+1 >= asSorting.length ? 0 : idx+1;
4530
		};
4531
	
4532
		// If appending the sort then we are multi-column sorting
4533
		if ( append && settings.oFeatures.bSortMulti ) {
4534
			// Are we already doing some kind of sort on this column?
4535
			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
4536
	
4537
			if ( sortIdx !== -1 ) {
4538
				// Yes, modify the sort
4539
				nextSortIdx = next( sorting[sortIdx] );
4540
	
4541
				sorting[sortIdx][1] = asSorting[ nextSortIdx ];
4542
				sorting[sortIdx]._idx = nextSortIdx;
4543
			}
4544
			else {
4545
				// No sort on this column yet
4546
				sorting.push( [ colIdx, asSorting[0], 0 ] );
4547
				sorting[sorting.length-1]._idx = 0;
4548
			}
4549
		}
4550
		else if ( sorting.length && sorting[0][0] == colIdx ) {
4551
			// Single column - already sorting on this column, modify the sort
4552
			nextSortIdx = next( sorting[0] );
4553
	
4554
			sorting.length = 1;
4555
			sorting[0][1] = asSorting[ nextSortIdx ];
4556
			sorting[0]._idx = nextSortIdx;
4557
		}
4558
		else {
4559
			// Single column - sort only on this column
4560
			sorting.length = 0;
4561
			sorting.push( [ colIdx, asSorting[0] ] );
4562
			sorting[0]._idx = 0;
4563
		}
4564
	
4565
		// Run the sort by calling a full redraw
4566
		_fnReDraw( settings );
4567
	
4568
		// callback used for async user interaction
4569
		if ( typeof callback == 'function' ) {
4570
			callback( settings );
4571
		}
4572
	}
4573
	
4574
	
4575
	/**
4576
	 * Attach a sort handler (click) to a node
4577
	 *  @param {object} settings dataTables settings object
4578
	 *  @param {node} attachTo node to attach the handler to
4579
	 *  @param {int} colIdx column sorting index
4580
	 *  @param {function} [callback] callback function
4581
	 *  @memberof DataTable#oApi
4582
	 */
4583
	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
4584
	{
4585
		var col = settings.aoColumns[ colIdx ];
4586
	
4587
		_fnBindAction( attachTo, {}, function (e) {
4588
			/* If the column is not sortable - don't to anything */
4589
			if ( col.bSortable === false ) {
4590
				return;
4591
			}
4592
	
4593
			// If processing is enabled use a timeout to allow the processing
4594
			// display to be shown - otherwise to it synchronously
4595
			if ( settings.oFeatures.bProcessing ) {
4596
				_fnProcessingDisplay( settings, true );
4597
	
4598
				setTimeout( function() {
4599
					_fnSortListener( settings, colIdx, e.shiftKey, callback );
4600
	
4601
					// In server-side processing, the draw callback will remove the
4602
					// processing display
4603
					if ( _fnDataSource( settings ) !== 'ssp' ) {
4604
						_fnProcessingDisplay( settings, false );
4605
					}
4606
				}, 0 );
4607
			}
4608
			else {
4609
				_fnSortListener( settings, colIdx, e.shiftKey, callback );
4610
			}
4611
		} );
4612
	}
4613
	
4614
	
4615
	/**
4616
	 * Set the sorting classes on table's body, Note: it is safe to call this function
4617
	 * when bSort and bSortClasses are false
4618
	 *  @param {object} oSettings dataTables settings object
4619
	 *  @memberof DataTable#oApi
4620
	 */
4621
	function _fnSortingClasses( settings )
4622
	{
4623
		var oldSort = settings.aLastSort;
4624
		var sortClass = settings.oClasses.sSortColumn;
4625
		var sort = _fnSortFlatten( settings );
4626
		var features = settings.oFeatures;
4627
		var i, ien, colIdx;
4628
	
4629
		if ( features.bSort && features.bSortClasses ) {
4630
			// Remove old sorting classes
4631
			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
4632
				colIdx = oldSort[i].src;
4633
	
4634
				// Remove column sorting
4635
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4636
					.removeClass( sortClass + (i<2 ? i+1 : 3) );
4637
			}
4638
	
4639
			// Add new column sorting
4640
			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
4641
				colIdx = sort[i].src;
4642
	
4643
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4644
					.addClass( sortClass + (i<2 ? i+1 : 3) );
4645
			}
4646
		}
4647
	
4648
		settings.aLastSort = sort;
4649
	}
4650
	
4651
	
4652
	// Get the data to sort a column, be it from cache, fresh (populating the
4653
	// cache), or from a sort formatter
4654
	function _fnSortData( settings, idx )
4655
	{
4656
		// Custom sorting function - provided by the sort data type
4657
		var column = settings.aoColumns[ idx ];
4658
		var customSort = DataTable.ext.order[ column.sSortDataType ];
4659
		var customData;
4660
	
4661
		if ( customSort ) {
4662
			customData = customSort.call( settings.oInstance, settings, idx,
4663
				_fnColumnIndexToVisible( settings, idx )
4664
			);
4665
		}
4666
	
4667
		// Use / populate cache
4668
		var row, cellData;
4669
		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
4670
	
4671
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4672
			row = settings.aoData[i];
4673
	
4674
			if ( ! row._aSortData ) {
4675
				row._aSortData = [];
4676
			}
4677
	
4678
			if ( ! row._aSortData[idx] || customSort ) {
4679
				cellData = customSort ?
4680
					customData[i] : // If there was a custom sort function, use data from there
4681
					_fnGetCellData( settings, i, idx, 'sort' );
4682
	
4683
				row._aSortData[ idx ] = formatter ?
4684
					formatter( cellData ) :
4685
					cellData;
4686
			}
4687
		}
4688
	}
4689
	
4690
	
4691
	
4692
	/**
4693
	 * Save the state of a table
4694
	 *  @param {object} oSettings dataTables settings object
4695
	 *  @memberof DataTable#oApi
4696
	 */
4697
	function _fnSaveState ( oSettings )
4698
	{
4699
		if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )
4700
		{
4701
			return;
4702
		}
4703
	
4704
		/* Store the interesting variables */
4705
		var i, iLen;
4706
		var oState = {
4707
			"iCreate":      +new Date(),
4708
			"iStart":       oSettings._iDisplayStart,
4709
			"iLength":      oSettings._iDisplayLength,
4710
			"aaSorting":    $.extend( true, [], oSettings.aaSorting ),
4711
			"oSearch":      $.extend( true, {}, oSettings.oPreviousSearch ),
4712
			"aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ),
4713
			"abVisCols":    _pluck( oSettings.aoColumns, 'bVisible' )
4714
		};
4715
	
4716
		_fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] );
4717
	
4718
		oSettings.fnStateSaveCallback.call( oSettings.oInstance, oSettings, oState );
4719
	}
4720
	
4721
	
4722
	/**
4723
	 * Attempt to load a saved table state
4724
	 *  @param {object} oSettings dataTables settings object
4725
	 *  @param {object} oInit DataTables init object so we can override settings
4726
	 *  @memberof DataTable#oApi
4727
	 */
4728
	function _fnLoadState ( oSettings, oInit )
4729
	{
4730
		var i, ien;
4731
		var columns = oSettings.aoColumns;
4732
	
4733
		if ( ! oSettings.oFeatures.bStateSave ) {
4734
			return;
4735
		}
4736
	
4737
		var oData = oSettings.fnStateLoadCallback.call( oSettings.oInstance, oSettings );
4738
		if ( !oData ) {
4739
			return;
4740
		}
4741
	
4742
		/* Allow custom and plug-in manipulation functions to alter the saved data set and
4743
		 * cancelling of loading by returning false
4744
		 */
4745
		var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] );
4746
		if ( $.inArray( false, abStateLoad ) !== -1 ) {
4747
			return;
4748
		}
4749
	
4750
		/* Reject old data */
4751
		var duration = oSettings.iStateDuration;
4752
		if ( duration > 0 && oData.iCreate < +new Date() - (duration*1000) ) {
4753
			return;
4754
		}
4755
	
4756
		// Number of columns have changed - all bets are off, no restore of settings
4757
		if ( columns.length !== oData.aoSearchCols.length ) {
4758
			return;
4759
		}
4760
	
4761
		/* Store the saved state so it might be accessed at any time */
4762
		oSettings.oLoadedState = $.extend( true, {}, oData );
4763
	
4764
		/* Restore key features */
4765
		oSettings._iDisplayStart    = oData.iStart;
4766
		oSettings.iInitDisplayStart = oData.iStart;
4767
		oSettings._iDisplayLength   = oData.iLength;
4768
		oSettings.aaSorting = $.map( oData.aaSorting, function ( col, i ) {
4769
			return col[0] >= columns.length ?
4770
				[ 0, col[1] ] :
4771
				col;
4772
		} );
4773
	
4774
		/* Search filtering  */
4775
		$.extend( oSettings.oPreviousSearch, oData.oSearch );
4776
		$.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols );
4777
	
4778
		/* Column visibility state */
4779
		var visColumns = oData.abVisCols;
4780
		for ( i=0, ien=visColumns.length ; i<ien ; i++ ) {
4781
			columns[i].bVisible = visColumns[i];
4782
		}
4783
	
4784
		_fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] );
4785
	}
4786
	
4787
	
4788
	/**
4789
	 * Return the settings object for a particular table
4790
	 *  @param {node} table table we are using as a dataTable
4791
	 *  @returns {object} Settings object - or null if not found
4792
	 *  @memberof DataTable#oApi
4793
	 */
4794
	function _fnSettingsFromNode ( table )
4795
	{
4796
		var settings = DataTable.settings;
4797
		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
4798
	
4799
		return idx !== -1 ?
4800
			settings[ idx ] :
4801
			null;
4802
	}
4803
	
4804
	
4805
	/**
4806
	 * Log an error message
4807
	 *  @param {object} settings dataTables settings object
4808
	 *  @param {int} level log error messages, or display them to the user
4809
	 *  @param {string} msg error message
4810
	 *  @param {int} tn Technical note id to get more information about the error.
4811
	 *  @memberof DataTable#oApi
4812
	 */
4813
	function _fnLog( settings, level, msg, tn )
4814
	{
4815
		msg = 'DataTables warning: '+
4816
			(settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
4817
	
4818
		if ( tn ) {
4819
			msg += '. For more information about this error, please see '+
4820
			'http://datatables.net/tn/'+tn;
4821
		}
4822
	
4823
		if ( ! level  ) {
4824
			// Backwards compatibility pre 1.10
4825
			var ext = DataTable.ext;
4826
			var type = ext.sErrMode || ext.errMode;
4827
	
4828
			if ( type == 'alert' ) {
4829
				alert( msg );
4830
			}
4831
			else {
4832
				throw new Error(msg);
4833
			}
4834
		}
4835
		else if ( window.console && console.log ) {
4836
			console.log( msg );
4837
		}
4838
	}
4839
	
4840
	
4841
	/**
4842
	 * See if a property is defined on one object, if so assign it to the other object
4843
	 *  @param {object} ret target object
4844
	 *  @param {object} src source object
4845
	 *  @param {string} name property
4846
	 *  @param {string} [mappedName] name to map too - optional, name used if not given
4847
	 *  @memberof DataTable#oApi
4848
	 */
4849
	function _fnMap( ret, src, name, mappedName )
4850
	{
4851
		if ( $.isArray( name ) ) {
4852
			$.each( name, function (i, val) {
4853
				if ( $.isArray( val ) ) {
4854
					_fnMap( ret, src, val[0], val[1] );
4855
				}
4856
				else {
4857
					_fnMap( ret, src, val );
4858
				}
4859
			} );
4860
	
4861
			return;
4862
		}
4863
	
4864
		if ( mappedName === undefined ) {
4865
			mappedName = name;
4866
		}
4867
	
4868
		if ( src[name] !== undefined ) {
4869
			ret[mappedName] = src[name];
4870
		}
4871
	}
4872
	
4873
	
4874
	/**
4875
	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
4876
	 * shallow copy arrays. The reason we need to do this, is that we don't want to
4877
	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
4878
	 * able to override them, but we do want to deep copy arrays.
4879
	 *  @param {object} out Object to extend
4880
	 *  @param {object} extender Object from which the properties will be applied to
4881
	 *      out
4882
	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
4883
	 *      independent copy with the exception of the `data` or `aaData` parameters
4884
	 *      if they are present. This is so you can pass in a collection to
4885
	 *      DataTables and have that used as your data source without breaking the
4886
	 *      references
4887
	 *  @returns {object} out Reference, just for convenience - out === the return.
4888
	 *  @memberof DataTable#oApi
4889
	 *  @todo This doesn't take account of arrays inside the deep copied objects.
4890
	 */
4891
	function _fnExtend( out, extender, breakRefs )
4892
	{
4893
		var val;
4894
	
4895
		for ( var prop in extender ) {
4896
			if ( extender.hasOwnProperty(prop) ) {
4897
				val = extender[prop];
4898
	
4899
				if ( $.isPlainObject( val ) ) {
4900
					if ( ! $.isPlainObject( out[prop] ) ) {
4901
						out[prop] = {};
4902
					}
4903
					$.extend( true, out[prop], val );
4904
				}
4905
				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
4906
					out[prop] = val.slice();
4907
				}
4908
				else {
4909
					out[prop] = val;
4910
				}
4911
			}
4912
		}
4913
	
4914
		return out;
4915
	}
4916
	
4917
	
4918
	/**
4919
	 * Bind an event handers to allow a click or return key to activate the callback.
4920
	 * This is good for accessibility since a return on the keyboard will have the
4921
	 * same effect as a click, if the element has focus.
4922
	 *  @param {element} n Element to bind the action to
4923
	 *  @param {object} oData Data object to pass to the triggered function
4924
	 *  @param {function} fn Callback function for when the event is triggered
4925
	 *  @memberof DataTable#oApi
4926
	 */
4927
	function _fnBindAction( n, oData, fn )
4928
	{
4929
		$(n)
4930
			.bind( 'click.DT', oData, function (e) {
4931
					n.blur(); // Remove focus outline for mouse users
4932
					fn(e);
4933
				} )
4934
			.bind( 'keypress.DT', oData, function (e){
4935
					if ( e.which === 13 ) {
4936
						e.preventDefault();
4937
						fn(e);
4938
					}
4939
				} )
4940
			.bind( 'selectstart.DT', function () {
4941
					/* Take the brutal approach to cancelling text selection */
4942
					return false;
4943
				} );
4944
	}
4945
	
4946
	
4947
	/**
4948
	 * Register a callback function. Easily allows a callback function to be added to
4949
	 * an array store of callback functions that can then all be called together.
4950
	 *  @param {object} oSettings dataTables settings object
4951
	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
4952
	 *  @param {function} fn Function to be called back
4953
	 *  @param {string} sName Identifying name for the callback (i.e. a label)
4954
	 *  @memberof DataTable#oApi
4955
	 */
4956
	function _fnCallbackReg( oSettings, sStore, fn, sName )
4957
	{
4958
		if ( fn )
4959
		{
4960
			oSettings[sStore].push( {
4961
				"fn": fn,
4962
				"sName": sName
4963
			} );
4964
		}
4965
	}
4966
	
4967
	
4968
	/**
4969
	 * Fire callback functions and trigger events. Note that the loop over the
4970
	 * callback array store is done backwards! Further note that you do not want to
4971
	 * fire off triggers in time sensitive applications (for example cell creation)
4972
	 * as its slow.
4973
	 *  @param {object} settings dataTables settings object
4974
	 *  @param {string} callbackArr Name of the array storage for the callbacks in
4975
	 *      oSettings
4976
	 *  @param {string} event Name of the jQuery custom event to trigger. If null no
4977
	 *      trigger is fired
4978
	 *  @param {array} args Array of arguments to pass to the callback function /
4979
	 *      trigger
4980
	 *  @memberof DataTable#oApi
4981
	 */
4982
	function _fnCallbackFire( settings, callbackArr, event, args )
4983
	{
4984
		var ret = [];
4985
	
4986
		if ( callbackArr ) {
4987
			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
4988
				return val.fn.apply( settings.oInstance, args );
4989
			} );
4990
		}
4991
	
4992
		if ( event !== null ) {
4993
			$(settings.nTable).trigger( event+'.dt', args );
4994
		}
4995
	
4996
		return ret;
4997
	}
4998
	
4999
	
5000
	function _fnLengthOverflow ( settings )
5001
	{
5002
		var
5003
			start = settings._iDisplayStart,
5004
			end = settings.fnDisplayEnd(),
5005
			len = settings._iDisplayLength;
5006
	
5007
		/* If we have space to show extra rows (backing up from the end point - then do so */
5008
		if ( end === settings.fnRecordsDisplay() )
5009
		{
5010
			start = end - len;
5011
		}
5012
	
5013
		if ( len === -1 || start < 0 )
5014
		{
5015
			start = 0;
5016
		}
5017
	
5018
		settings._iDisplayStart = start;
5019
	}
5020
	
5021
	
5022
	function _fnRenderer( settings, type )
5023
	{
5024
		var renderer = settings.renderer;
5025
		var host = DataTable.ext.renderer[type];
5026
	
5027
		if ( $.isPlainObject( renderer ) && renderer[type] ) {
5028
			// Specific renderer for this type. If available use it, otherwise use
5029
			// the default.
5030
			return host[renderer[type]] || host._;
5031
		}
5032
		else if ( typeof renderer === 'string' ) {
5033
			// Common renderer - if there is one available for this type use it,
5034
			// otherwise use the default
5035
			return host[renderer] || host._;
5036
		}
5037
	
5038
		// Use the default
5039
		return host._;
5040
	}
5041
	
5042
	
5043
	/**
5044
	 * Detect the data source being used for the table. Used to simplify the code
5045
	 * a little (ajax) and to make it compress a little smaller.
5046
	 *
5047
	 *  @param {object} settings dataTables settings object
5048
	 *  @returns {string} Data source
5049
	 *  @memberof DataTable#oApi
5050
	 */
5051
	function _fnDataSource ( settings )
5052
	{
5053
		if ( settings.oFeatures.bServerSide ) {
5054
			return 'ssp';
5055
		}
5056
		else if ( settings.ajax || settings.sAjaxSource ) {
5057
			return 'ajax';
5058
		}
5059
		return 'dom';
5060
	}
5061
	
5062

    
5063
	DataTable = function( options )
5064
	{
5065
		/**
5066
		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5067
		 * return the resulting jQuery object.
5068
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5069
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5070
		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5071
		 *    criterion ("applied") or all TR elements (i.e. no filter).
5072
		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5073
		 *    Can be either 'current', whereby the current sorting of the table is used, or
5074
		 *    'original' whereby the original order the data was read into the table is used.
5075
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5076
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5077
		 *    'current' and filter is 'applied', regardless of what they might be given as.
5078
		 *  @returns {object} jQuery object, filtered by the given selector.
5079
		 *  @dtopt API
5080
		 *  @deprecated Since v1.10
5081
		 *
5082
		 *  @example
5083
		 *    $(document).ready(function() {
5084
		 *      var oTable = $('#example').dataTable();
5085
		 *
5086
		 *      // Highlight every second row
5087
		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
5088
		 *    } );
5089
		 *
5090
		 *  @example
5091
		 *    $(document).ready(function() {
5092
		 *      var oTable = $('#example').dataTable();
5093
		 *
5094
		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
5095
		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
5096
		 *      oTable.fnFilter('Webkit');
5097
		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5098
		 *      oTable.fnFilter('');
5099
		 *    } );
5100
		 */
5101
		this.$ = function ( sSelector, oOpts )
5102
		{
5103
			return this.api(true).$( sSelector, oOpts );
5104
		};
5105
		
5106
		
5107
		/**
5108
		 * Almost identical to $ in operation, but in this case returns the data for the matched
5109
		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5110
		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
5111
		 * rows are found, the data returned is the original data array/object that was used to
5112
		 * create the row (or a generated array if from a DOM source).
5113
		 *
5114
		 * This method is often useful in-combination with $ where both functions are given the
5115
		 * same parameters and the array indexes will match identically.
5116
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5117
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5118
		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
5119
		 *    criterion ("applied") or all elements (i.e. no filter).
5120
		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
5121
		 *    Can be either 'current', whereby the current sorting of the table is used, or
5122
		 *    'original' whereby the original order the data was read into the table is used.
5123
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5124
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5125
		 *    'current' and filter is 'applied', regardless of what they might be given as.
5126
		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
5127
		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
5128
		 *    entry in the array.
5129
		 *  @dtopt API
5130
		 *  @deprecated Since v1.10
5131
		 *
5132
		 *  @example
5133
		 *    $(document).ready(function() {
5134
		 *      var oTable = $('#example').dataTable();
5135
		 *
5136
		 *      // Get the data from the first row in the table
5137
		 *      var data = oTable._('tr:first');
5138
		 *
5139
		 *      // Do something useful with the data
5140
		 *      alert( "First cell is: "+data[0] );
5141
		 *    } );
5142
		 *
5143
		 *  @example
5144
		 *    $(document).ready(function() {
5145
		 *      var oTable = $('#example').dataTable();
5146
		 *
5147
		 *      // Filter to 'Webkit' and get all data for
5148
		 *      oTable.fnFilter('Webkit');
5149
		 *      var data = oTable._('tr', {"search": "applied"});
5150
		 *
5151
		 *      // Do something with the data
5152
		 *      alert( data.length+" rows matched the search" );
5153
		 *    } );
5154
		 */
5155
		this._ = function ( sSelector, oOpts )
5156
		{
5157
			return this.api(true).rows( sSelector, oOpts ).data();
5158
		};
5159
		
5160
		
5161
		/**
5162
		 * Create a DataTables Api instance, with the currently selected tables for
5163
		 * the Api's context.
5164
		 * @param {boolean} [traditional=false] Set the API instance's context to be
5165
		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5166
		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5167
		 *   or if all tables captured in the jQuery object should be used.
5168
		 * @return {DataTables.Api}
5169
		 */
5170
		this.api = function ( traditional )
5171
		{
5172
			return traditional ?
5173
				new _Api(
5174
					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
5175
				) :
5176
				new _Api( this );
5177
		};
5178
		
5179
		
5180
		/**
5181
		 * Add a single new row or multiple rows of data to the table. Please note
5182
		 * that this is suitable for client-side processing only - if you are using
5183
		 * server-side processing (i.e. "bServerSide": true), then to add data, you
5184
		 * must add it to the data source, i.e. the server-side, through an Ajax call.
5185
		 *  @param {array|object} data The data to be added to the table. This can be:
5186
		 *    <ul>
5187
		 *      <li>1D array of data - add a single row with the data provided</li>
5188
		 *      <li>2D array of arrays - add multiple rows in a single call</li>
5189
		 *      <li>object - data object when using <i>mData</i></li>
5190
		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
5191
		 *    </ul>
5192
		 *  @param {bool} [redraw=true] redraw the table or not
5193
		 *  @returns {array} An array of integers, representing the list of indexes in
5194
		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5195
		 *    the table.
5196
		 *  @dtopt API
5197
		 *  @deprecated Since v1.10
5198
		 *
5199
		 *  @example
5200
		 *    // Global var for counter
5201
		 *    var giCount = 2;
5202
		 *
5203
		 *    $(document).ready(function() {
5204
		 *      $('#example').dataTable();
5205
		 *    } );
5206
		 *
5207
		 *    function fnClickAddRow() {
5208
		 *      $('#example').dataTable().fnAddData( [
5209
		 *        giCount+".1",
5210
		 *        giCount+".2",
5211
		 *        giCount+".3",
5212
		 *        giCount+".4" ]
5213
		 *      );
5214
		 *
5215
		 *      giCount++;
5216
		 *    }
5217
		 */
5218
		this.fnAddData = function( data, redraw )
5219
		{
5220
			var api = this.api( true );
5221
		
5222
			/* Check if we want to add multiple rows or not */
5223
			var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
5224
				api.rows.add( data ) :
5225
				api.row.add( data );
5226
		
5227
			if ( redraw === undefined || redraw ) {
5228
				api.draw();
5229
			}
5230
		
5231
			return rows.flatten().toArray();
5232
		};
5233
		
5234
		
5235
		/**
5236
		 * This function will make DataTables recalculate the column sizes, based on the data
5237
		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5238
		 * through the sWidth parameter). This can be useful when the width of the table's
5239
		 * parent element changes (for example a window resize).
5240
		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5241
		 *  @dtopt API
5242
		 *  @deprecated Since v1.10
5243
		 *
5244
		 *  @example
5245
		 *    $(document).ready(function() {
5246
		 *      var oTable = $('#example').dataTable( {
5247
		 *        "sScrollY": "200px",
5248
		 *        "bPaginate": false
5249
		 *      } );
5250
		 *
5251
		 *      $(window).bind('resize', function () {
5252
		 *        oTable.fnAdjustColumnSizing();
5253
		 *      } );
5254
		 *    } );
5255
		 */
5256
		this.fnAdjustColumnSizing = function ( bRedraw )
5257
		{
5258
			var api = this.api( true ).columns.adjust();
5259
			var settings = api.settings()[0];
5260
			var scroll = settings.oScroll;
5261
		
5262
			if ( bRedraw === undefined || bRedraw ) {
5263
				api.draw( false );
5264
			}
5265
			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
5266
				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5267
				_fnScrollDraw( settings );
5268
			}
5269
		};
5270
		
5271
		
5272
		/**
5273
		 * Quickly and simply clear a table
5274
		 *  @param {bool} [bRedraw=true] redraw the table or not
5275
		 *  @dtopt API
5276
		 *  @deprecated Since v1.10
5277
		 *
5278
		 *  @example
5279
		 *    $(document).ready(function() {
5280
		 *      var oTable = $('#example').dataTable();
5281
		 *
5282
		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5283
		 *      oTable.fnClearTable();
5284
		 *    } );
5285
		 */
5286
		this.fnClearTable = function( bRedraw )
5287
		{
5288
			var api = this.api( true ).clear();
5289
		
5290
			if ( bRedraw === undefined || bRedraw ) {
5291
				api.draw();
5292
			}
5293
		};
5294
		
5295
		
5296
		/**
5297
		 * The exact opposite of 'opening' a row, this function will close any rows which
5298
		 * are currently 'open'.
5299
		 *  @param {node} nTr the table row to 'close'
5300
		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
5301
		 *  @dtopt API
5302
		 *  @deprecated Since v1.10
5303
		 *
5304
		 *  @example
5305
		 *    $(document).ready(function() {
5306
		 *      var oTable;
5307
		 *
5308
		 *      // 'open' an information row when a row is clicked on
5309
		 *      $('#example tbody tr').click( function () {
5310
		 *        if ( oTable.fnIsOpen(this) ) {
5311
		 *          oTable.fnClose( this );
5312
		 *        } else {
5313
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5314
		 *        }
5315
		 *      } );
5316
		 *
5317
		 *      oTable = $('#example').dataTable();
5318
		 *    } );
5319
		 */
5320
		this.fnClose = function( nTr )
5321
		{
5322
			this.api( true ).row( nTr ).child.hide();
5323
		};
5324
		
5325
		
5326
		/**
5327
		 * Remove a row for the table
5328
		 *  @param {mixed} target The index of the row from aoData to be deleted, or
5329
		 *    the TR element you want to delete
5330
		 *  @param {function|null} [callBack] Callback function
5331
		 *  @param {bool} [redraw=true] Redraw the table or not
5332
		 *  @returns {array} The row that was deleted
5333
		 *  @dtopt API
5334
		 *  @deprecated Since v1.10
5335
		 *
5336
		 *  @example
5337
		 *    $(document).ready(function() {
5338
		 *      var oTable = $('#example').dataTable();
5339
		 *
5340
		 *      // Immediately remove the first row
5341
		 *      oTable.fnDeleteRow( 0 );
5342
		 *    } );
5343
		 */
5344
		this.fnDeleteRow = function( target, callback, redraw )
5345
		{
5346
			var api = this.api( true );
5347
			var rows = api.rows( target );
5348
			var settings = rows.settings()[0];
5349
			var data = settings.aoData[ rows[0][0] ];
5350
		
5351
			rows.remove();
5352
		
5353
			if ( callback ) {
5354
				callback.call( this, settings, data );
5355
			}
5356
		
5357
			if ( redraw === undefined || redraw ) {
5358
				api.draw();
5359
			}
5360
		
5361
			return data;
5362
		};
5363
		
5364
		
5365
		/**
5366
		 * Restore the table to it's original state in the DOM by removing all of DataTables
5367
		 * enhancements, alterations to the DOM structure of the table and event listeners.
5368
		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
5369
		 *  @dtopt API
5370
		 *  @deprecated Since v1.10
5371
		 *
5372
		 *  @example
5373
		 *    $(document).ready(function() {
5374
		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
5375
		 *      var oTable = $('#example').dataTable();
5376
		 *      oTable.fnDestroy();
5377
		 *    } );
5378
		 */
5379
		this.fnDestroy = function ( remove )
5380
		{
5381
			this.api( true ).destroy( remove );
5382
		};
5383
		
5384
		
5385
		/**
5386
		 * Redraw the table
5387
		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5388
		 *  @dtopt API
5389
		 *  @deprecated Since v1.10
5390
		 *
5391
		 *  @example
5392
		 *    $(document).ready(function() {
5393
		 *      var oTable = $('#example').dataTable();
5394
		 *
5395
		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5396
		 *      oTable.fnDraw();
5397
		 *    } );
5398
		 */
5399
		this.fnDraw = function( complete )
5400
		{
5401
			// Note that this isn't an exact match to the old call to _fnDraw - it takes
5402
			// into account the new data, but can old position.
5403
			this.api( true ).draw( ! complete );
5404
		};
5405
		
5406
		
5407
		/**
5408
		 * Filter the input based on data
5409
		 *  @param {string} sInput String to filter the table on
5410
		 *  @param {int|null} [iColumn] Column to limit filtering to
5411
		 *  @param {bool} [bRegex=false] Treat as regular expression or not
5412
		 *  @param {bool} [bSmart=true] Perform smart filtering or not
5413
		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5414
		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5415
		 *  @dtopt API
5416
		 *  @deprecated Since v1.10
5417
		 *
5418
		 *  @example
5419
		 *    $(document).ready(function() {
5420
		 *      var oTable = $('#example').dataTable();
5421
		 *
5422
		 *      // Sometime later - filter...
5423
		 *      oTable.fnFilter( 'test string' );
5424
		 *    } );
5425
		 */
5426
		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
5427
		{
5428
			var api = this.api( true );
5429
		
5430
			if ( iColumn === null || iColumn === undefined ) {
5431
				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
5432
			}
5433
			else {
5434
				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
5435
			}
5436
		
5437
			api.draw();
5438
		};
5439
		
5440
		
5441
		/**
5442
		 * Get the data for the whole table, an individual row or an individual cell based on the
5443
		 * provided parameters.
5444
		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5445
		 *    a TR node then the data source for the whole row will be returned. If given as a
5446
		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
5447
		 *    cell returned. If given as an integer, then this is treated as the aoData internal
5448
		 *    data index for the row (see fnGetPosition) and the data for that row used.
5449
		 *  @param {int} [col] Optional column index that you want the data of.
5450
		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
5451
		 *    returned. If mRow is defined, just data for that row, and is iCol is
5452
		 *    defined, only data for the designated cell is returned.
5453
		 *  @dtopt API
5454
		 *  @deprecated Since v1.10
5455
		 *
5456
		 *  @example
5457
		 *    // Row data
5458
		 *    $(document).ready(function() {
5459
		 *      oTable = $('#example').dataTable();
5460
		 *
5461
		 *      oTable.$('tr').click( function () {
5462
		 *        var data = oTable.fnGetData( this );
5463
		 *        // ... do something with the array / object of data for the row
5464
		 *      } );
5465
		 *    } );
5466
		 *
5467
		 *  @example
5468
		 *    // Individual cell data
5469
		 *    $(document).ready(function() {
5470
		 *      oTable = $('#example').dataTable();
5471
		 *
5472
		 *      oTable.$('td').click( function () {
5473
		 *        var sData = oTable.fnGetData( this );
5474
		 *        alert( 'The cell clicked on had the value of '+sData );
5475
		 *      } );
5476
		 *    } );
5477
		 */
5478
		this.fnGetData = function( src, col )
5479
		{
5480
			var api = this.api( true );
5481
		
5482
			if ( src !== undefined ) {
5483
				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
5484
		
5485
				return col !== undefined || type == 'td' || type == 'th' ?
5486
					api.cell( src, col ).data() :
5487
					api.row( src ).data() || null;
5488
			}
5489
		
5490
			return api.data().toArray();
5491
		};
5492
		
5493
		
5494
		/**
5495
		 * Get an array of the TR nodes that are used in the table's body. Note that you will
5496
		 * typically want to use the '$' API method in preference to this as it is more
5497
		 * flexible.
5498
		 *  @param {int} [iRow] Optional row index for the TR element you want
5499
		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
5500
		 *    in the table's body, or iRow is defined, just the TR element requested.
5501
		 *  @dtopt API
5502
		 *  @deprecated Since v1.10
5503
		 *
5504
		 *  @example
5505
		 *    $(document).ready(function() {
5506
		 *      var oTable = $('#example').dataTable();
5507
		 *
5508
		 *      // Get the nodes from the table
5509
		 *      var nNodes = oTable.fnGetNodes( );
5510
		 *    } );
5511
		 */
5512
		this.fnGetNodes = function( iRow )
5513
		{
5514
			var api = this.api( true );
5515
		
5516
			return iRow !== undefined ?
5517
				api.row( iRow ).node() :
5518
				api.rows().nodes().flatten().toArray();
5519
		};
5520
		
5521
		
5522
		/**
5523
		 * Get the array indexes of a particular cell from it's DOM element
5524
		 * and column index including hidden columns
5525
		 *  @param {node} node this can either be a TR, TD or TH in the table's body
5526
		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
5527
		 *    if given as a cell, an array of [row index, column index (visible),
5528
		 *    column index (all)] is given.
5529
		 *  @dtopt API
5530
		 *  @deprecated Since v1.10
5531
		 *
5532
		 *  @example
5533
		 *    $(document).ready(function() {
5534
		 *      $('#example tbody td').click( function () {
5535
		 *        // Get the position of the current data from the node
5536
		 *        var aPos = oTable.fnGetPosition( this );
5537
		 *
5538
		 *        // Get the data array for this row
5539
		 *        var aData = oTable.fnGetData( aPos[0] );
5540
		 *
5541
		 *        // Update the data array and return the value
5542
		 *        aData[ aPos[1] ] = 'clicked';
5543
		 *        this.innerHTML = 'clicked';
5544
		 *      } );
5545
		 *
5546
		 *      // Init DataTables
5547
		 *      oTable = $('#example').dataTable();
5548
		 *    } );
5549
		 */
5550
		this.fnGetPosition = function( node )
5551
		{
5552
			var api = this.api( true );
5553
			var nodeName = node.nodeName.toUpperCase();
5554
		
5555
			if ( nodeName == 'TR' ) {
5556
				return api.row( node ).index();
5557
			}
5558
			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
5559
				var cell = api.cell( node ).index();
5560
		
5561
				return [
5562
					cell.row,
5563
					cell.columnVisible,
5564
					cell.column
5565
				];
5566
			}
5567
			return null;
5568
		};
5569
		
5570
		
5571
		/**
5572
		 * Check to see if a row is 'open' or not.
5573
		 *  @param {node} nTr the table row to check
5574
		 *  @returns {boolean} true if the row is currently open, false otherwise
5575
		 *  @dtopt API
5576
		 *  @deprecated Since v1.10
5577
		 *
5578
		 *  @example
5579
		 *    $(document).ready(function() {
5580
		 *      var oTable;
5581
		 *
5582
		 *      // 'open' an information row when a row is clicked on
5583
		 *      $('#example tbody tr').click( function () {
5584
		 *        if ( oTable.fnIsOpen(this) ) {
5585
		 *          oTable.fnClose( this );
5586
		 *        } else {
5587
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5588
		 *        }
5589
		 *      } );
5590
		 *
5591
		 *      oTable = $('#example').dataTable();
5592
		 *    } );
5593
		 */
5594
		this.fnIsOpen = function( nTr )
5595
		{
5596
			return this.api( true ).row( nTr ).child.isShown();
5597
		};
5598
		
5599
		
5600
		/**
5601
		 * This function will place a new row directly after a row which is currently
5602
		 * on display on the page, with the HTML contents that is passed into the
5603
		 * function. This can be used, for example, to ask for confirmation that a
5604
		 * particular record should be deleted.
5605
		 *  @param {node} nTr The table row to 'open'
5606
		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
5607
		 *  @param {string} sClass Class to give the new TD cell
5608
		 *  @returns {node} The row opened. Note that if the table row passed in as the
5609
		 *    first parameter, is not found in the table, this method will silently
5610
		 *    return.
5611
		 *  @dtopt API
5612
		 *  @deprecated Since v1.10
5613
		 *
5614
		 *  @example
5615
		 *    $(document).ready(function() {
5616
		 *      var oTable;
5617
		 *
5618
		 *      // 'open' an information row when a row is clicked on
5619
		 *      $('#example tbody tr').click( function () {
5620
		 *        if ( oTable.fnIsOpen(this) ) {
5621
		 *          oTable.fnClose( this );
5622
		 *        } else {
5623
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5624
		 *        }
5625
		 *      } );
5626
		 *
5627
		 *      oTable = $('#example').dataTable();
5628
		 *    } );
5629
		 */
5630
		this.fnOpen = function( nTr, mHtml, sClass )
5631
		{
5632
			return this.api( true )
5633
				.row( nTr )
5634
				.child( mHtml, sClass )
5635
				.show()
5636
				.child()[0];
5637
		};
5638
		
5639
		
5640
		/**
5641
		 * Change the pagination - provides the internal logic for pagination in a simple API
5642
		 * function. With this function you can have a DataTables table go to the next,
5643
		 * previous, first or last pages.
5644
		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5645
		 *    or page number to jump to (integer), note that page 0 is the first page.
5646
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5647
		 *  @dtopt API
5648
		 *  @deprecated Since v1.10
5649
		 *
5650
		 *  @example
5651
		 *    $(document).ready(function() {
5652
		 *      var oTable = $('#example').dataTable();
5653
		 *      oTable.fnPageChange( 'next' );
5654
		 *    } );
5655
		 */
5656
		this.fnPageChange = function ( mAction, bRedraw )
5657
		{
5658
			var api = this.api( true ).page( mAction );
5659
		
5660
			if ( bRedraw === undefined || bRedraw ) {
5661
				api.draw(false);
5662
			}
5663
		};
5664
		
5665
		
5666
		/**
5667
		 * Show a particular column
5668
		 *  @param {int} iCol The column whose display should be changed
5669
		 *  @param {bool} bShow Show (true) or hide (false) the column
5670
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5671
		 *  @dtopt API
5672
		 *  @deprecated Since v1.10
5673
		 *
5674
		 *  @example
5675
		 *    $(document).ready(function() {
5676
		 *      var oTable = $('#example').dataTable();
5677
		 *
5678
		 *      // Hide the second column after initialisation
5679
		 *      oTable.fnSetColumnVis( 1, false );
5680
		 *    } );
5681
		 */
5682
		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
5683
		{
5684
			var api = this.api( true ).column( iCol ).visible( bShow );
5685
		
5686
			if ( bRedraw === undefined || bRedraw ) {
5687
				api.columns.adjust().draw();
5688
			}
5689
		};
5690
		
5691
		
5692
		/**
5693
		 * Get the settings for a particular table for external manipulation
5694
		 *  @returns {object} DataTables settings object. See
5695
		 *    {@link DataTable.models.oSettings}
5696
		 *  @dtopt API
5697
		 *  @deprecated Since v1.10
5698
		 *
5699
		 *  @example
5700
		 *    $(document).ready(function() {
5701
		 *      var oTable = $('#example').dataTable();
5702
		 *      var oSettings = oTable.fnSettings();
5703
		 *
5704
		 *      // Show an example parameter from the settings
5705
		 *      alert( oSettings._iDisplayStart );
5706
		 *    } );
5707
		 */
5708
		this.fnSettings = function()
5709
		{
5710
			return _fnSettingsFromNode( this[_ext.iApiIndex] );
5711
		};
5712
		
5713
		
5714
		/**
5715
		 * Sort the table by a particular column
5716
		 *  @param {int} iCol the data index to sort on. Note that this will not match the
5717
		 *    'display index' if you have hidden data entries
5718
		 *  @dtopt API
5719
		 *  @deprecated Since v1.10
5720
		 *
5721
		 *  @example
5722
		 *    $(document).ready(function() {
5723
		 *      var oTable = $('#example').dataTable();
5724
		 *
5725
		 *      // Sort immediately with columns 0 and 1
5726
		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
5727
		 *    } );
5728
		 */
5729
		this.fnSort = function( aaSort )
5730
		{
5731
			this.api( true ).order( aaSort ).draw();
5732
		};
5733
		
5734
		
5735
		/**
5736
		 * Attach a sort listener to an element for a given column
5737
		 *  @param {node} nNode the element to attach the sort listener to
5738
		 *  @param {int} iColumn the column that a click on this node will sort on
5739
		 *  @param {function} [fnCallback] callback function when sort is run
5740
		 *  @dtopt API
5741
		 *  @deprecated Since v1.10
5742
		 *
5743
		 *  @example
5744
		 *    $(document).ready(function() {
5745
		 *      var oTable = $('#example').dataTable();
5746
		 *
5747
		 *      // Sort on column 1, when 'sorter' is clicked on
5748
		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
5749
		 *    } );
5750
		 */
5751
		this.fnSortListener = function( nNode, iColumn, fnCallback )
5752
		{
5753
			this.api( true ).order.listener( nNode, iColumn, fnCallback );
5754
		};
5755
		
5756
		
5757
		/**
5758
		 * Update a table cell or row - this method will accept either a single value to
5759
		 * update the cell with, an array of values with one element for each column or
5760
		 * an object in the same format as the original data source. The function is
5761
		 * self-referencing in order to make the multi column updates easier.
5762
		 *  @param {object|array|string} mData Data to update the cell/row with
5763
		 *  @param {node|int} mRow TR element you want to update or the aoData index
5764
		 *  @param {int} [iColumn] The column to update, give as null or undefined to
5765
		 *    update a whole row.
5766
		 *  @param {bool} [bRedraw=true] Redraw the table or not
5767
		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
5768
		 *  @returns {int} 0 on success, 1 on error
5769
		 *  @dtopt API
5770
		 *  @deprecated Since v1.10
5771
		 *
5772
		 *  @example
5773
		 *    $(document).ready(function() {
5774
		 *      var oTable = $('#example').dataTable();
5775
		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
5776
		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
5777
		 *    } );
5778
		 */
5779
		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
5780
		{
5781
			var api = this.api( true );
5782
		
5783
			if ( iColumn === undefined || iColumn === null ) {
5784
				api.row( mRow ).data( mData );
5785
			}
5786
			else {
5787
				api.cell( mRow, iColumn ).data( mData );
5788
			}
5789
		
5790
			if ( bAction === undefined || bAction ) {
5791
				api.columns.adjust();
5792
			}
5793
		
5794
			if ( bRedraw === undefined || bRedraw ) {
5795
				api.draw();
5796
			}
5797
			return 0;
5798
		};
5799
		
5800
		
5801
		/**
5802
		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
5803
		 * to ensure compatibility.
5804
		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
5805
		 *    formats "X" and "X.Y" are also acceptable.
5806
		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
5807
		 *    version, or false if this version of DataTales is not suitable
5808
		 *  @method
5809
		 *  @dtopt API
5810
		 *  @deprecated Since v1.10
5811
		 *
5812
		 *  @example
5813
		 *    $(document).ready(function() {
5814
		 *      var oTable = $('#example').dataTable();
5815
		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
5816
		 *    } );
5817
		 */
5818
		this.fnVersionCheck = _ext.fnVersionCheck;
5819
		
5820

    
5821
		var _that = this;
5822
		var emptyInit = options === undefined;
5823
		var len = this.length;
5824

    
5825
		if ( emptyInit ) {
5826
			options = {};
5827
		}
5828

    
5829
		this.oApi = this.internal = _ext.internal;
5830

    
5831
		// Extend with old style plug-in API methods
5832
		for ( var fn in DataTable.ext.internal ) {
5833
			if ( fn ) {
5834
				this[fn] = _fnExternApiFunc(fn);
5835
			}
5836
		}
5837

    
5838
		this.each(function() {
5839
			// For each initialisation we want to give it a clean initialisation
5840
			// object that can be bashed around
5841
			var o = {};
5842
			var oInit = len > 1 ? // optimisation for single table case
5843
				_fnExtend( o, options, true ) :
5844
				options;
5845

    
5846
			/*global oInit,_that,emptyInit*/
5847
			var i=0, iLen, j, jLen, k, kLen;
5848
			var sId = this.getAttribute( 'id' );
5849
			var bInitHandedOff = false;
5850
			var defaults = DataTable.defaults;
5851
			
5852
			
5853
			/* Sanity check */
5854
			if ( this.nodeName.toLowerCase() != 'table' )
5855
			{
5856
				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
5857
				return;
5858
			}
5859
			
5860
			/* Backwards compatibility for the defaults */
5861
			_fnCompatOpts( defaults );
5862
			_fnCompatCols( defaults.column );
5863
			
5864
			/* Convert the camel-case defaults to Hungarian */
5865
			_fnCamelToHungarian( defaults, defaults, true );
5866
			_fnCamelToHungarian( defaults.column, defaults.column, true );
5867
			
5868
			/* Setting up the initialisation object */
5869
			_fnCamelToHungarian( defaults, oInit );
5870
			
5871
			/* Check to see if we are re-initialising a table */
5872
			var allSettings = DataTable.settings;
5873
			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
5874
			{
5875
				/* Base check on table node */
5876
				if ( allSettings[i].nTable == this )
5877
				{
5878
					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
5879
					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
5880
			
5881
					if ( emptyInit || bRetrieve )
5882
					{
5883
						return allSettings[i].oInstance;
5884
					}
5885
					else if ( bDestroy )
5886
					{
5887
						allSettings[i].oInstance.fnDestroy();
5888
						break;
5889
					}
5890
					else
5891
					{
5892
						_fnLog( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );
5893
						return;
5894
					}
5895
				}
5896
			
5897
				/* If the element we are initialising has the same ID as a table which was previously
5898
				 * initialised, but the table nodes don't match (from before) then we destroy the old
5899
				 * instance by simply deleting it. This is under the assumption that the table has been
5900
				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
5901
				 */
5902
				if ( allSettings[i].sTableId == this.id )
5903
				{
5904
					allSettings.splice( i, 1 );
5905
					break;
5906
				}
5907
			}
5908
			
5909
			/* Ensure the table has an ID - required for accessibility */
5910
			if ( sId === null || sId === "" )
5911
			{
5912
				sId = "DataTables_Table_"+(DataTable.ext._unique++);
5913
				this.id = sId;
5914
			}
5915
			
5916
			/* Create the settings object for this table and set some of the default parameters */
5917
			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
5918
				"nTable":        this,
5919
				"oApi":          _that.internal,
5920
				"oInit":         oInit,
5921
				"sDestroyWidth": $(this)[0].style.width,
5922
				"sInstance":     sId,
5923
				"sTableId":      sId
5924
			} );
5925
			allSettings.push( oSettings );
5926
			
5927
			// Need to add the instance after the instance after the settings object has been added
5928
			// to the settings array, so we can self reference the table instance if more than one
5929
			oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
5930
			
5931
			// Backwards compatibility, before we apply all the defaults
5932
			_fnCompatOpts( oInit );
5933
			
5934
			if ( oInit.oLanguage )
5935
			{
5936
				_fnLanguageCompat( oInit.oLanguage );
5937
			}
5938
			
5939
			// If the length menu is given, but the init display length is not, use the length menu
5940
			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
5941
			{
5942
				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
5943
					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
5944
			}
5945
			
5946
			// Apply the defaults and init options to make a single init object will all
5947
			// options defined from defaults and instance options.
5948
			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
5949
			
5950
			
5951
			// Map the initialisation options onto the settings object
5952
			_fnMap( oSettings.oFeatures, oInit, [
5953
				"bPaginate",
5954
				"bLengthChange",
5955
				"bFilter",
5956
				"bSort",
5957
				"bSortMulti",
5958
				"bInfo",
5959
				"bProcessing",
5960
				"bAutoWidth",
5961
				"bSortClasses",
5962
				"bServerSide",
5963
				"bDeferRender"
5964
			] );
5965
			_fnMap( oSettings, oInit, [
5966
				"asStripeClasses",
5967
				"ajax",
5968
				"fnServerData",
5969
				"fnFormatNumber",
5970
				"sServerMethod",
5971
				"aaSorting",
5972
				"aaSortingFixed",
5973
				"aLengthMenu",
5974
				"sPaginationType",
5975
				"sAjaxSource",
5976
				"sAjaxDataProp",
5977
				"iStateDuration",
5978
				"sDom",
5979
				"bSortCellsTop",
5980
				"iTabIndex",
5981
				"fnStateLoadCallback",
5982
				"fnStateSaveCallback",
5983
				"renderer",
5984
				[ "iCookieDuration", "iStateDuration" ], // backwards compat
5985
				[ "oSearch", "oPreviousSearch" ],
5986
				[ "aoSearchCols", "aoPreSearchCols" ],
5987
				[ "iDisplayLength", "_iDisplayLength" ],
5988
				[ "bJQueryUI", "bJUI" ]
5989
			] );
5990
			_fnMap( oSettings.oScroll, oInit, [
5991
				[ "sScrollX", "sX" ],
5992
				[ "sScrollXInner", "sXInner" ],
5993
				[ "sScrollY", "sY" ],
5994
				[ "bScrollCollapse", "bCollapse" ]
5995
			] );
5996
			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
5997
			
5998
			/* Callback functions which are array driven */
5999
			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
6000
			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
6001
			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
6002
			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
6003
			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
6004
			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
6005
			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
6006
			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
6007
			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
6008
			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
6009
			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
6010
			
6011
			var oClasses = oSettings.oClasses;
6012
			
6013
			// @todo Remove in 1.11
6014
			if ( oInit.bJQueryUI )
6015
			{
6016
				/* Use the JUI classes object for display. You could clone the oStdClasses object if
6017
				 * you want to have multiple tables with multiple independent classes
6018
				 */
6019
				$.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
6020
			
6021
				if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
6022
				{
6023
					/* Set the DOM to use a layout suitable for jQuery UI's theming */
6024
					oSettings.sDom = '<"H"lfr>t<"F"ip>';
6025
				}
6026
			
6027
				if ( ! oSettings.renderer ) {
6028
					oSettings.renderer = 'jqueryui';
6029
				}
6030
				else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
6031
					oSettings.renderer.header = 'jqueryui';
6032
				}
6033
			}
6034
			else
6035
			{
6036
				$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6037
			}
6038
			$(this).addClass( oClasses.sTable );
6039
			
6040
			/* Calculate the scroll bar width and cache it for use later on */
6041
			if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6042
			{
6043
				oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6044
			}
6045
			if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6046
				oSettings.oScroll.sX = '100%';
6047
			}
6048
			
6049
			if ( oSettings.iInitDisplayStart === undefined )
6050
			{
6051
				/* Display start point, taking into account the save saving */
6052
				oSettings.iInitDisplayStart = oInit.iDisplayStart;
6053
				oSettings._iDisplayStart = oInit.iDisplayStart;
6054
			}
6055
			
6056
			if ( oInit.iDeferLoading !== null )
6057
			{
6058
				oSettings.bDeferLoading = true;
6059
				var tmp = $.isArray( oInit.iDeferLoading );
6060
				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
6061
				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
6062
			}
6063
			
6064
			/* Language definitions */
6065
			if ( oInit.oLanguage.sUrl !== "" )
6066
			{
6067
				/* Get the language definitions from a file - because this Ajax call makes the language
6068
				 * get async to the remainder of this function we use bInitHandedOff to indicate that
6069
				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6070
				 */
6071
				oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
6072
				$.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
6073
					_fnLanguageCompat( json );
6074
					_fnCamelToHungarian( defaults.oLanguage, json );
6075
					$.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
6076
					_fnInitialise( oSettings );
6077
				} );
6078
				bInitHandedOff = true;
6079
			}
6080
			else
6081
			{
6082
				$.extend( true, oSettings.oLanguage, oInit.oLanguage );
6083
			}
6084
			
6085
			
6086
			/*
6087
			 * Stripes
6088
			 */
6089
			if ( oInit.asStripeClasses === null )
6090
			{
6091
				oSettings.asStripeClasses =[
6092
					oClasses.sStripeOdd,
6093
					oClasses.sStripeEven
6094
				];
6095
			}
6096
			
6097
			/* Remove row stripe classes if they are already on the table row */
6098
			var stripeClasses = oSettings.asStripeClasses;
6099
			var rowOne = $('tbody tr:eq(0)', this);
6100
			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6101
				return rowOne.hasClass(el);
6102
			} ) ) !== -1 ) {
6103
				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
6104
				oSettings.asDestroyStripes = stripeClasses.slice();
6105
			}
6106
			
6107
			/*
6108
			 * Columns
6109
			 * See if we should load columns automatically or use defined ones
6110
			 */
6111
			var anThs = [];
6112
			var aoColumnsInit;
6113
			var nThead = this.getElementsByTagName('thead');
6114
			if ( nThead.length !== 0 )
6115
			{
6116
				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
6117
				anThs = _fnGetUniqueThs( oSettings );
6118
			}
6119
			
6120
			/* If not given a column array, generate one with nulls */
6121
			if ( oInit.aoColumns === null )
6122
			{
6123
				aoColumnsInit = [];
6124
				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6125
				{
6126
					aoColumnsInit.push( null );
6127
				}
6128
			}
6129
			else
6130
			{
6131
				aoColumnsInit = oInit.aoColumns;
6132
			}
6133
			
6134
			/* Add the columns */
6135
			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6136
			{
6137
				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
6138
			}
6139
			
6140
			/* Apply the column definitions */
6141
			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
6142
				_fnColumnOptions( oSettings, iCol, oDef );
6143
			} );
6144
			
6145
			/* HTML5 attribute detection - build an mData object automatically if the
6146
			 * attributes are found
6147
			 */
6148
			if ( rowOne.length ) {
6149
				var a = function ( cell, name ) {
6150
					return cell.getAttribute( 'data-'+name ) ? name : null;
6151
				};
6152
			
6153
				$.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
6154
					var col = oSettings.aoColumns[i];
6155
			
6156
					if ( col.mData === i ) {
6157
						var sort = a( cell, 'sort' ) || a( cell, 'order' );
6158
						var filter = a( cell, 'filter' ) || a( cell, 'search' );
6159
			
6160
						if ( sort !== null || filter !== null ) {
6161
							col.mData = {
6162
								_:      i+'.display',
6163
								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
6164
								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
6165
								filter: filter !== null ? i+'.@data-'+filter : undefined
6166
							};
6167
			
6168
							_fnColumnOptions( oSettings, i );
6169
						}
6170
					}
6171
				} );
6172
			}
6173
			
6174
			var features = oSettings.oFeatures;
6175
			
6176
			/* Must be done after everything which can be overridden by the state saving! */
6177
			if ( oInit.bStateSave )
6178
			{
6179
				features.bStateSave = true;
6180
				_fnLoadState( oSettings, oInit );
6181
				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
6182
			}
6183
			
6184
			
6185
			/*
6186
			 * Sorting
6187
			 * @todo For modularisation (1.11) this needs to do into a sort start up handler
6188
			 */
6189
			
6190
			// If aaSorting is not defined, then we use the first indicator in asSorting
6191
			// in case that has been altered, so the default sort reflects that option
6192
			if ( oInit.aaSorting === undefined )
6193
			{
6194
				var sorting = oSettings.aaSorting;
6195
				for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
6196
				{
6197
					sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
6198
				}
6199
			}
6200
			
6201
			/* Do a first pass on the sorting classes (allows any size changes to be taken into
6202
			 * account, and also will apply sorting disabled classes if disabled
6203
			 */
6204
			_fnSortingClasses( oSettings );
6205
			
6206
			if ( features.bSort )
6207
			{
6208
				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6209
					if ( oSettings.bSorted ) {
6210
						var aSort = _fnSortFlatten( oSettings );
6211
						var sortedColumns = {};
6212
			
6213
						$.each( aSort, function (i, val) {
6214
							sortedColumns[ val.src ] = val.dir;
6215
						} );
6216
			
6217
						_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
6218
						_fnSortAria( oSettings );
6219
					}
6220
				} );
6221
			}
6222
			
6223
			_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6224
				if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
6225
					_fnSortingClasses( oSettings );
6226
				}
6227
			}, 'sc' );
6228
			
6229
			
6230
			/*
6231
			 * Final init
6232
			 * Cache the header, body and footer as required, creating them if needed
6233
			 */
6234
			
6235
			/* Browser support detection */
6236
			_fnBrowserDetect( oSettings );
6237
			
6238
			// Work around for Webkit bug 83867 - store the caption-side before removing from doc
6239
			var captions = $(this).children('caption').each( function () {
6240
				this._captionSide = $(this).css('caption-side');
6241
			} );
6242
			
6243
			var thead = $(this).children('thead');
6244
			if ( thead.length === 0 )
6245
			{
6246
				thead = $('<thead/>').appendTo(this);
6247
			}
6248
			oSettings.nTHead = thead[0];
6249
			
6250
			var tbody = $(this).children('tbody');
6251
			if ( tbody.length === 0 )
6252
			{
6253
				tbody = $('<tbody/>').appendTo(this);
6254
			}
6255
			oSettings.nTBody = tbody[0];
6256
			
6257
			var tfoot = $(this).children('tfoot');
6258
			if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6259
			{
6260
				// If we are a scrolling table, and no footer has been given, then we need to create
6261
				// a tfoot element for the caption element to be appended to
6262
				tfoot = $('<tfoot/>').appendTo(this);
6263
			}
6264
			
6265
			if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6266
				$(this).addClass( oClasses.sNoFooter );
6267
			}
6268
			else if ( tfoot.length > 0 ) {
6269
				oSettings.nTFoot = tfoot[0];
6270
				_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
6271
			}
6272
			
6273
			/* Check if there is data passing into the constructor */
6274
			if ( oInit.aaData )
6275
			{
6276
				for ( i=0 ; i<oInit.aaData.length ; i++ )
6277
				{
6278
					_fnAddData( oSettings, oInit.aaData[ i ] );
6279
				}
6280
			}
6281
			else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
6282
			{
6283
				/* Grab the data from the page - only do this when deferred loading or no Ajax
6284
				 * source since there is no point in reading the DOM data if we are then going
6285
				 * to replace it with Ajax data
6286
				 */
6287
				_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
6288
			}
6289
			
6290
			/* Copy the data index array */
6291
			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6292
			
6293
			/* Initialisation complete - table can be drawn */
6294
			oSettings.bInitialised = true;
6295
			
6296
			/* Check if we need to initialise the table (it might not have been handed off to the
6297
			 * language processor)
6298
			 */
6299
			if ( bInitHandedOff === false )
6300
			{
6301
				_fnInitialise( oSettings );
6302
			}
6303
		} );
6304
		_that = null;
6305
		return this;
6306
	};
6307

    
6308
	
6309
	
6310
	/**
6311
	 * Computed structure of the DataTables API, defined by the options passed to
6312
	 * `DataTable.Api.register()` when building the API.
6313
	 *
6314
	 * The structure is built in order to speed creation and extension of the Api
6315
	 * objects since the extensions are effectively pre-parsed.
6316
	 *
6317
	 * The array is an array of objects with the following structure, where this
6318
	 * base array represents the Api prototype base:
6319
	 *
6320
	 *     [
6321
	 *       {
6322
	 *         name:      'data'                -- string   - Property name
6323
	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6324
	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6325
	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6326
	 *       },
6327
	 *       {
6328
	 *         name:     'row'
6329
	 *         val:       {},
6330
	 *         methodExt: [ ... ],
6331
	 *         propExt:   [
6332
	 *           {
6333
	 *             name:      'data'
6334
	 *             val:       function () {},
6335
	 *             methodExt: [ ... ],
6336
	 *             propExt:   [ ... ]
6337
	 *           },
6338
	 *           ...
6339
	 *         ]
6340
	 *       }
6341
	 *     ]
6342
	 *
6343
	 * @type {Array}
6344
	 * @ignore
6345
	 */
6346
	var __apiStruct = [];
6347
	
6348
	
6349
	/**
6350
	 * `Array.prototype` reference.
6351
	 *
6352
	 * @type object
6353
	 * @ignore
6354
	 */
6355
	var __arrayProto = Array.prototype;
6356
	
6357
	
6358
	/**
6359
	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6360
	 * take several different forms for ease of use.
6361
	 *
6362
	 * Each of the input parameter types will be converted to a DataTables settings
6363
	 * object where possible.
6364
	 *
6365
	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6366
	 *   of:
6367
	 *
6368
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6369
	 *     with be found and used.
6370
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6371
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6372
	 *   * `object` - DataTables settings object
6373
	 *   * `DataTables.Api` - API instance
6374
	 * @return {array|null} Matching DataTables settings objects. `null` or
6375
	 *   `undefined` is returned if no matching DataTable is found.
6376
	 * @ignore
6377
	 */
6378
	var _toSettings = function ( mixed )
6379
	{
6380
		var idx, jq;
6381
		var settings = DataTable.settings;
6382
		var tables = $.map( settings, function (el, i) {
6383
			return el.nTable;
6384
		} );
6385
	
6386
		if ( ! mixed ) {
6387
			return [];
6388
		}
6389
		else if ( mixed.nTable && mixed.oApi ) {
6390
			// DataTables settings object
6391
			return [ mixed ];
6392
		}
6393
		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6394
			// Table node
6395
			idx = $.inArray( mixed, tables );
6396
			return idx !== -1 ? [ settings[idx] ] : null;
6397
		}
6398
		else if ( mixed && typeof mixed.settings === 'function' ) {
6399
			return mixed.settings().toArray();
6400
		}
6401
		else if ( typeof mixed === 'string' ) {
6402
			// jQuery selector
6403
			jq = $(mixed);
6404
		}
6405
		else if ( mixed instanceof $ ) {
6406
			// jQuery object (also DataTables instance)
6407
			jq = mixed;
6408
		}
6409
	
6410
		if ( jq ) {
6411
			return jq.map( function(i) {
6412
				idx = $.inArray( this, tables );
6413
				return idx !== -1 ? settings[idx] : null;
6414
			} ).toArray();
6415
		}
6416
	};
6417
	
6418
	
6419
	/**
6420
	 * DataTables API class - used to control and interface with  one or more
6421
	 * DataTables enhanced tables.
6422
	 *
6423
	 * The API class is heavily based on jQuery, presenting a chainable interface
6424
	 * that you can use to interact with tables. Each instance of the API class has
6425
	 * a "context" - i.e. the tables that it will operate on. This could be a single
6426
	 * table, all tables on a page or a sub-set thereof.
6427
	 *
6428
	 * Additionally the API is designed to allow you to easily work with the data in
6429
	 * the tables, retrieving and manipulating it as required. This is done by
6430
	 * presenting the API class as an array like interface. The contents of the
6431
	 * array depend upon the actions requested by each method (for example
6432
	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6433
	 * return an array of objects or arrays depending upon your table's
6434
	 * configuration). The API object has a number of array like methods (`push`,
6435
	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6436
	 * `unique` etc) to assist your working with the data held in a table.
6437
	 *
6438
	 * Most methods (those which return an Api instance) are chainable, which means
6439
	 * the return from a method call also has all of the methods available that the
6440
	 * top level object had. For example, these two calls are equivalent:
6441
	 *
6442
	 *     // Not chained
6443
	 *     api.row.add( {...} );
6444
	 *     api.draw();
6445
	 *
6446
	 *     // Chained
6447
	 *     api.row.add( {...} ).draw();
6448
	 *
6449
	 * @class DataTable.Api
6450
	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6451
	 *   used to define which DataTables enhanced tables this API will operate on.
6452
	 *   Can be one of:
6453
	 *
6454
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6455
	 *     with be found and used.
6456
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6457
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6458
	 *   * `object` - DataTables settings object
6459
	 * @param {array} [data] Data to initialise the Api instance with.
6460
	 *
6461
	 * @example
6462
	 *   // Direct initialisation during DataTables construction
6463
	 *   var api = $('#example').DataTable();
6464
	 *
6465
	 * @example
6466
	 *   // Initialisation using a DataTables jQuery object
6467
	 *   var api = $('#example').dataTable().api();
6468
	 *
6469
	 * @example
6470
	 *   // Initialisation as a constructor
6471
	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6472
	 */
6473
	DataTable.Api = _Api = function ( context, data )
6474
	{
6475
		if ( ! this instanceof _Api ) {
6476
			throw 'DT API must be constructed as a new object';
6477
			// or should it do the 'new' for the caller?
6478
			// return new _Api.apply( this, arguments );
6479
		}
6480
	
6481
		var settings = [];
6482
		var ctxSettings = function ( o ) {
6483
			var a = _toSettings( o );
6484
			if ( a ) {
6485
				settings.push.apply( settings, a );
6486
			}
6487
		};
6488
	
6489
		if ( $.isArray( context ) ) {
6490
			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6491
				ctxSettings( context[i] );
6492
			}
6493
		}
6494
		else {
6495
			ctxSettings( context );
6496
		}
6497
	
6498
		// Remove duplicates
6499
		this.context = _unique( settings );
6500
	
6501
		// Initial data
6502
		if ( data ) {
6503
			this.push.apply( this, data.toArray ? data.toArray() : data );
6504
		}
6505
	
6506
		// selector
6507
		this.selector = {
6508
			rows: null,
6509
			cols: null,
6510
			opts: null
6511
		};
6512
	
6513
		_Api.extend( this, this, __apiStruct );
6514
	};
6515
	
6516
	
6517
	_Api.prototype = /** @lends DataTables.Api */{
6518
		/**
6519
		 * Return a new Api instance, comprised of the data held in the current
6520
		 * instance, join with the other array(s) and/or value(s).
6521
		 *
6522
		 * An alias for `Array.prototype.concat`.
6523
		 *
6524
		 * @type method
6525
		 * @param {*} value1 Arrays and/or values to concatenate.
6526
		 * @param {*} [...] Additional arrays and/or values to concatenate.
6527
		 * @returns {DataTables.Api} New API instance, comprising of the combined
6528
		 *   array.
6529
		 */
6530
		concat:  __arrayProto.concat,
6531
	
6532
	
6533
		context: [], // array of table settings objects
6534
	
6535
	
6536
		each: function ( fn )
6537
		{
6538
			if ( __arrayProto.forEach ) {
6539
				// Where possible, use the built-in forEach
6540
				__arrayProto.forEach.call( this, fn, this );
6541
			}
6542
			else {
6543
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6544
				for ( var i=0, ien=this.length ; i<ien; i++ ) {
6545
					// In strict mode the execution scope is the passed value
6546
					fn.call( this, this[i], i, this );
6547
				}
6548
			}
6549
	
6550
			return this;
6551
		},
6552
	
6553
	
6554
		eq: function ( idx )
6555
		{
6556
			var ctx = this.context;
6557
	
6558
			return ctx.length > idx ?
6559
				new _Api( ctx[idx], this[idx] ) :
6560
				null;
6561
		},
6562
	
6563
	
6564
		filter: function ( fn )
6565
		{
6566
			var a = [];
6567
	
6568
			if ( __arrayProto.filter ) {
6569
				a = __arrayProto.filter.call( this, fn, this );
6570
			}
6571
			else {
6572
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6573
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6574
					if ( fn.call( this, this[i], i, this ) ) {
6575
						a.push( this[i] );
6576
					}
6577
				}
6578
			}
6579
	
6580
			return new _Api( this.context, a );
6581
		},
6582
	
6583
	
6584
		flatten: function ()
6585
		{
6586
			var a = [];
6587
			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6588
		},
6589
	
6590
	
6591
		join:    __arrayProto.join,
6592
	
6593
	
6594
		indexOf: __arrayProto.indexOf || function (obj, start)
6595
		{
6596
			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6597
				if ( this[i] === obj ) {
6598
					return i;
6599
				}
6600
			}
6601
			return -1;
6602
		},
6603
	
6604
		// Internal only at the moment - relax?
6605
		iterator: function ( flatten, type, fn ) {
6606
			var
6607
				a = [], ret,
6608
				i, ien, j, jen,
6609
				context = this.context,
6610
				rows, items, item,
6611
				selector = this.selector;
6612
	
6613
			// Argument shifting
6614
			if ( typeof flatten === 'string' ) {
6615
				fn = type;
6616
				type = flatten;
6617
				flatten = false;
6618
			}
6619
	
6620
			for ( i=0, ien=context.length ; i<ien ; i++ ) {
6621
				if ( type === 'table' ) {
6622
					ret = fn( context[i], i );
6623
	
6624
					if ( ret !== undefined ) {
6625
						a.push( ret );
6626
					}
6627
				}
6628
				else if ( type === 'columns' || type === 'rows' ) {
6629
					// this has same length as context - one entry for each table
6630
					ret = fn( context[i], this[i], i );
6631
	
6632
					if ( ret !== undefined ) {
6633
						a.push( ret );
6634
					}
6635
				}
6636
				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6637
					// columns and rows share the same structure.
6638
					// 'this' is an array of column indexes for each context
6639
					items = this[i];
6640
	
6641
					if ( type === 'column-rows' ) {
6642
						rows = _selector_row_indexes( context[i], selector.opts );
6643
					}
6644
	
6645
					for ( j=0, jen=items.length ; j<jen ; j++ ) {
6646
						item = items[j];
6647
	
6648
						if ( type === 'cell' ) {
6649
							ret = fn( context[i], item.row, item.column, i, j );
6650
						}
6651
						else {
6652
							ret = fn( context[i], item, i, j, rows );
6653
						}
6654
	
6655
						if ( ret !== undefined ) {
6656
							a.push( ret );
6657
						}
6658
					}
6659
				}
6660
			}
6661
	
6662
			if ( a.length ) {
6663
				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6664
				var apiSelector = api.selector;
6665
				apiSelector.rows = selector.rows;
6666
				apiSelector.cols = selector.cols;
6667
				apiSelector.opts = selector.opts;
6668
				return api;
6669
			}
6670
			return this;
6671
		},
6672
	
6673
	
6674
		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
6675
		{
6676
			// Bit cheeky...
6677
			return this.indexOf.apply( this.toArray.reverse(), arguments );
6678
		},
6679
	
6680
	
6681
		length:  0,
6682
	
6683
	
6684
		map: function ( fn )
6685
		{
6686
			var a = [];
6687
	
6688
			if ( __arrayProto.map ) {
6689
				a = __arrayProto.map.call( this, fn, this );
6690
			}
6691
			else {
6692
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6693
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6694
					a.push( fn.call( this, this[i], i ) );
6695
				}
6696
			}
6697
	
6698
			return new _Api( this.context, a );
6699
		},
6700
	
6701
	
6702
		pluck: function ( prop )
6703
		{
6704
			return this.map( function ( el ) {
6705
				return el[ prop ];
6706
			} );
6707
		},
6708
	
6709
		pop:     __arrayProto.pop,
6710
	
6711
	
6712
		push:    __arrayProto.push,
6713
	
6714
	
6715
		// Does not return an API instance
6716
		reduce: __arrayProto.reduce || function ( fn, init )
6717
		{
6718
			return _fnReduce( this, fn, init, 0, this.length, 1 );
6719
		},
6720
	
6721
	
6722
		reduceRight: __arrayProto.reduceRight || function ( fn, init )
6723
		{
6724
			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
6725
		},
6726
	
6727
	
6728
		reverse: __arrayProto.reverse,
6729
	
6730
	
6731
		// Object with rows, columns and opts
6732
		selector: null,
6733
	
6734
	
6735
		shift:   __arrayProto.shift,
6736
	
6737
	
6738
		sort:    __arrayProto.sort, // ? name - order?
6739
	
6740
	
6741
		splice:  __arrayProto.splice,
6742
	
6743
	
6744
		toArray: function ()
6745
		{
6746
			return __arrayProto.slice.call( this );
6747
		},
6748
	
6749
	
6750
		to$: function ()
6751
		{
6752
			return $( this );
6753
		},
6754
	
6755
	
6756
		toJQuery: function ()
6757
		{
6758
			return $( this );
6759
		},
6760
	
6761
	
6762
		unique: function ()
6763
		{
6764
			return new _Api( this.context, _unique(this) );
6765
		},
6766
	
6767
	
6768
		unshift: __arrayProto.unshift
6769
	};
6770
	
6771
	
6772
	_Api.extend = function ( scope, obj, ext )
6773
	{
6774
		// Only extend API instances and static properties of the API
6775
		if ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
6776
			return;
6777
		}
6778
	
6779
		var
6780
			i, ien,
6781
			j, jen,
6782
			struct, inner,
6783
			methodScoping = function ( fn, struc ) {
6784
				return function () {
6785
					var ret = fn.apply( scope, arguments );
6786
	
6787
					// Method extension
6788
					_Api.extend( ret, ret, struc.methodExt );
6789
					return ret;
6790
				};
6791
			};
6792
	
6793
		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
6794
			struct = ext[i];
6795
	
6796
			// Value
6797
			obj[ struct.name ] = typeof struct.val === 'function' ?
6798
				methodScoping( struct.val, struct ) :
6799
				$.isPlainObject( struct.val ) ?
6800
					{} :
6801
					struct.val;
6802
	
6803
			obj[ struct.name ].__dt_wrapper = true;
6804
	
6805
			// Property extension
6806
			_Api.extend( scope, obj[ struct.name ], struct.propExt );
6807
		}
6808
	};
6809
	
6810
	
6811
	// @todo - Is there need for an augment function?
6812
	// _Api.augment = function ( inst, name )
6813
	// {
6814
	// 	// Find src object in the structure from the name
6815
	// 	var parts = name.split('.');
6816
	
6817
	// 	_Api.extend( inst, obj );
6818
	// };
6819
	
6820
	
6821
	//     [
6822
	//       {
6823
	//         name:      'data'                -- string   - Property name
6824
	//         val:       function () {},       -- function - Api method (or undefined if just an object
6825
	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6826
	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6827
	//       },
6828
	//       {
6829
	//         name:     'row'
6830
	//         val:       {},
6831
	//         methodExt: [ ... ],
6832
	//         propExt:   [
6833
	//           {
6834
	//             name:      'data'
6835
	//             val:       function () {},
6836
	//             methodExt: [ ... ],
6837
	//             propExt:   [ ... ]
6838
	//           },
6839
	//           ...
6840
	//         ]
6841
	//       }
6842
	//     ]
6843
	
6844
	_Api.register = _api_register = function ( name, val )
6845
	{
6846
		if ( $.isArray( name ) ) {
6847
			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
6848
				_Api.register( name[j], val );
6849
			}
6850
			return;
6851
		}
6852
	
6853
		var
6854
			i, ien,
6855
			heir = name.split('.'),
6856
			struct = __apiStruct,
6857
			key, method;
6858
	
6859
		var find = function ( src, name ) {
6860
			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
6861
				if ( src[i].name === name ) {
6862
					return src[i];
6863
				}
6864
			}
6865
			return null;
6866
		};
6867
	
6868
		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
6869
			method = heir[i].indexOf('()') !== -1;
6870
			key = method ?
6871
				heir[i].replace('()', '') :
6872
				heir[i];
6873
	
6874
			var src = find( struct, key );
6875
			if ( ! src ) {
6876
				src = {
6877
					name:      key,
6878
					val:       {},
6879
					methodExt: [],
6880
					propExt:   []
6881
				};
6882
				struct.push( src );
6883
			}
6884
	
6885
			if ( i === ien-1 ) {
6886
				src.val = val;
6887
			}
6888
			else {
6889
				struct = method ?
6890
					src.methodExt :
6891
					src.propExt;
6892
			}
6893
		}
6894
	
6895
		// Rebuild the API with the new construct
6896
		if ( _Api.ready ) {
6897
			DataTable.api.build();
6898
		}
6899
	};
6900
	
6901
	
6902
	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
6903
		_Api.register( pluralName, val );
6904
	
6905
		_Api.register( singularName, function () {
6906
			var ret = val.apply( this, arguments );
6907
	
6908
			if ( ret === this ) {
6909
				// Returned item is the API instance that was passed in, return it
6910
				return this;
6911
			}
6912
			else if ( ret instanceof _Api ) {
6913
				// New API instance returned, want the value from the first item
6914
				// in the returned array for the singular result.
6915
				return ret.length ?
6916
					$.isArray( ret[0] ) ?
6917
						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
6918
						ret[0] :
6919
					undefined;
6920
			}
6921
	
6922
			// Non-API return - just fire it back
6923
			return ret;
6924
		} );
6925
	};
6926
	
6927
	
6928
	/**
6929
	 * Selector for HTML tables. Apply the given selector to the give array of
6930
	 * DataTables settings objects.
6931
	 *
6932
	 * @param {string|integer} [selector] jQuery selector string or integer
6933
	 * @param  {array} Array of DataTables settings objects to be filtered
6934
	 * @return {array}
6935
	 * @ignore
6936
	 */
6937
	var __table_selector = function ( selector, a )
6938
	{
6939
		// Integer is used to pick out a table by index
6940
		if ( typeof selector === 'number' ) {
6941
			return [ a[ selector ] ];
6942
		}
6943
	
6944
		// Perform a jQuery selector on the table nodes
6945
		var nodes = $.map( a, function (el, i) {
6946
			return el.nTable;
6947
		} );
6948
	
6949
		return $(nodes)
6950
			.filter( selector )
6951
			.map( function (i) {
6952
				// Need to translate back from the table node to the settings
6953
				var idx = $.inArray( this, nodes );
6954
				return a[ idx ];
6955
			} )
6956
			.toArray();
6957
	};
6958
	
6959
	
6960
	
6961
	/**
6962
	 * Context selector for the API's context (i.e. the tables the API instance
6963
	 * refers to.
6964
	 *
6965
	 * @name    DataTable.Api#tables
6966
	 * @param {string|integer} [selector] Selector to pick which tables the iterator
6967
	 *   should operate on. If not given, all tables in the current context are
6968
	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
6969
	 *   select multiple tables or as an integer to select a single table.
6970
	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
6971
	 */
6972
	_api_register( 'tables()', function ( selector ) {
6973
		// A new instance is created if there was a selector specified
6974
		return selector ?
6975
			new _Api( __table_selector( selector, this.context ) ) :
6976
			this;
6977
	} );
6978
	
6979
	
6980
	_api_register( 'table()', function ( selector ) {
6981
		var tables = this.tables( selector );
6982
		var ctx = tables.context;
6983
	
6984
		// Truncate to the first matched table
6985
		return ctx.length ?
6986
			new _Api( ctx[0] ) :
6987
			tables;
6988
	} );
6989
	
6990
	
6991
	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
6992
		return this.iterator( 'table', function ( ctx ) {
6993
			return ctx.nTable;
6994
		} );
6995
	} );
6996
	
6997
	
6998
	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
6999
		return this.iterator( 'table', function ( ctx ) {
7000
			return ctx.nTBody;
7001
		} );
7002
	} );
7003
	
7004
	
7005
	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7006
		return this.iterator( 'table', function ( ctx ) {
7007
			return ctx.nTHead;
7008
		} );
7009
	} );
7010
	
7011
	
7012
	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7013
		return this.iterator( 'table', function ( ctx ) {
7014
			return ctx.nTFoot;
7015
		} );
7016
	} );
7017
	
7018
	
7019
	
7020
	/**
7021
	 * Redraw the tables in the current context.
7022
	 *
7023
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7024
	 *   position. A full re-sort and re-filter is performed when this method is
7025
	 *   called, which is why the pagination reset is the default action.
7026
	 * @returns {DataTables.Api} this
7027
	 */
7028
	_api_register( 'draw()', function ( resetPaging ) {
7029
		return this.iterator( 'table', function ( settings ) {
7030
			_fnReDraw( settings, resetPaging===false );
7031
		} );
7032
	} );
7033
	
7034
	
7035
	
7036
	/**
7037
	 * Get the current page index.
7038
	 *
7039
	 * @return {integer} Current page index (zero based)
7040
	 *//**
7041
	 * Set the current page.
7042
	 *
7043
	 * Note that if you attempt to show a page which does not exist, DataTables will
7044
	 * not throw an error, but rather reset the paging.
7045
	 *
7046
	 * @param {integer|string} action The paging action to take. This can be one of:
7047
	 *  * `integer` - The page index to jump to
7048
	 *  * `string` - An action to take:
7049
	 *    * `first` - Jump to first page.
7050
	 *    * `next` - Jump to the next page
7051
	 *    * `previous` - Jump to previous page
7052
	 *    * `last` - Jump to the last page.
7053
	 * @returns {DataTables.Api} this
7054
	 */
7055
	_api_register( 'page()', function ( action ) {
7056
		if ( action === undefined ) {
7057
			return this.page.info().page; // not an expensive call
7058
		}
7059
	
7060
		// else, have an action to take on all tables
7061
		return this.iterator( 'table', function ( settings ) {
7062
			_fnPageChange( settings, action );
7063
		} );
7064
	} );
7065
	
7066
	
7067
	/**
7068
	 * Paging information for the first table in the current context.
7069
	 *
7070
	 * If you require paging information for another table, use the `table()` method
7071
	 * with a suitable selector.
7072
	 *
7073
	 * @return {object} Object with the following properties set:
7074
	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7075
	 *  * `pages` - Total number of pages
7076
	 *  * `start` - Display index for the first record shown on the current page
7077
	 *  * `end` - Display index for the last record shown on the current page
7078
	 *  * `length` - Display length (number of records). Note that generally `start
7079
	 *    + length = end`, but this is not always true, for example if there are
7080
	 *    only 2 records to show on the final page, with a length of 10.
7081
	 *  * `recordsTotal` - Full data set length
7082
	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7083
	 *    are applied.
7084
	 */
7085
	_api_register( 'page.info()', function ( action ) {
7086
		if ( this.context.length === 0 ) {
7087
			return undefined;
7088
		}
7089
	
7090
		var
7091
			settings   = this.context[0],
7092
			start      = settings._iDisplayStart,
7093
			len        = settings._iDisplayLength,
7094
			visRecords = settings.fnRecordsDisplay(),
7095
			all        = len === -1;
7096
	
7097
		return {
7098
			"page":           all ? 0 : Math.floor( start / len ),
7099
			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7100
			"start":          start,
7101
			"end":            settings.fnDisplayEnd(),
7102
			"length":         len,
7103
			"recordsTotal":   settings.fnRecordsTotal(),
7104
			"recordsDisplay": visRecords
7105
		};
7106
	} );
7107
	
7108
	
7109
	/**
7110
	 * Get the current page length.
7111
	 *
7112
	 * @return {integer} Current page length. Note `-1` indicates that all records
7113
	 *   are to be shown.
7114
	 *//**
7115
	 * Set the current page length.
7116
	 *
7117
	 * @param {integer} Page length to set. Use `-1` to show all records.
7118
	 * @returns {DataTables.Api} this
7119
	 */
7120
	_api_register( 'page.len()', function ( len ) {
7121
		// Note that we can't call this function 'length()' because `length`
7122
		// is a Javascript property of functions which defines how many arguments
7123
		// the function expects.
7124
		if ( len === undefined ) {
7125
			return this.context.length !== 0 ?
7126
				this.context[0]._iDisplayLength :
7127
				undefined;
7128
		}
7129
	
7130
		// else, set the page length
7131
		return this.iterator( 'table', function ( settings ) {
7132
			_fnLengthChange( settings, len );
7133
		} );
7134
	} );
7135
	
7136
	
7137
	
7138
	var __reload = function ( settings, holdPosition, callback ) {
7139
		if ( _fnDataSource( settings ) == 'ssp' ) {
7140
			_fnReDraw( settings, holdPosition );
7141
		}
7142
		else {
7143
			// Trigger xhr
7144
			_fnProcessingDisplay( settings, true );
7145
	
7146
			_fnBuildAjax( settings, [], function( json ) {
7147
				_fnClearTable( settings );
7148
	
7149
				var data = _fnAjaxDataSrc( settings, json );
7150
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7151
					_fnAddData( settings, data[i] );
7152
				}
7153
	
7154
				_fnReDraw( settings, holdPosition );
7155
				_fnProcessingDisplay( settings, false );
7156
			} );
7157
		}
7158
	
7159
		// Use the draw event to trigger a callback, regardless of if it is an async
7160
		// or sync draw
7161
		if ( callback ) {
7162
			var api = new _Api( settings );
7163
	
7164
			api.one( 'draw', function () {
7165
				callback( api.ajax.json() );
7166
			} );
7167
		}
7168
	};
7169
	
7170
	
7171
	/**
7172
	 * Get the JSON response from the last Ajax request that DataTables made to the
7173
	 * server. Note that this returns the JSON from the first table in the current
7174
	 * context.
7175
	 *
7176
	 * @return {object} JSON received from the server.
7177
	 */
7178
	_api_register( 'ajax.json()', function () {
7179
		var ctx = this.context;
7180
	
7181
		if ( ctx.length > 0 ) {
7182
			return ctx[0].json;
7183
		}
7184
	
7185
		// else return undefined;
7186
	} );
7187
	
7188
	
7189
	/**
7190
	 * Get the data submitted in the last Ajax request
7191
	 */
7192
	_api_register( 'ajax.params()', function () {
7193
		var ctx = this.context;
7194
	
7195
		if ( ctx.length > 0 ) {
7196
			return ctx[0].oAjaxData;
7197
		}
7198
	
7199
		// else return undefined;
7200
	} );
7201
	
7202
	
7203
	/**
7204
	 * Reload tables from the Ajax data source. Note that this function will
7205
	 * automatically re-draw the table when the remote data has been loaded.
7206
	 *
7207
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7208
	 *   position. A full re-sort and re-filter is performed when this method is
7209
	 *   called, which is why the pagination reset is the default action.
7210
	 * @returns {DataTables.Api} this
7211
	 */
7212
	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7213
		return this.iterator( 'table', function (settings) {
7214
			__reload( settings, resetPaging===false, callback );
7215
		} );
7216
	} );
7217
	
7218
	
7219
	/**
7220
	 * Get the current Ajax URL. Note that this returns the URL from the first
7221
	 * table in the current context.
7222
	 *
7223
	 * @return {string} Current Ajax source URL
7224
	 *//**
7225
	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7226
	 * current context.
7227
	 *
7228
	 * @param {string} url URL to set.
7229
	 * @returns {DataTables.Api} this
7230
	 */
7231
	_api_register( 'ajax.url()', function ( url ) {
7232
		var ctx = this.context;
7233
	
7234
		if ( url === undefined ) {
7235
			// get
7236
			if ( ctx.length === 0 ) {
7237
				return undefined;
7238
			}
7239
			ctx = ctx[0];
7240
	
7241
			return ctx.ajax ?
7242
				$.isPlainObject( ctx.ajax ) ?
7243
					ctx.ajax.url :
7244
					ctx.ajax :
7245
				ctx.sAjaxSource;
7246
		}
7247
	
7248
		// set
7249
		return this.iterator( 'table', function ( settings ) {
7250
			if ( $.isPlainObject( settings.ajax ) ) {
7251
				settings.ajax.url = url;
7252
			}
7253
			else {
7254
				settings.ajax = url;
7255
			}
7256
			// No need to consider sAjaxSource here since DataTables gives priority
7257
			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7258
			// value of `sAjaxSource` redundant.
7259
		} );
7260
	} );
7261
	
7262
	
7263
	/**
7264
	 * Load data from the newly set Ajax URL. Note that this method is only
7265
	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7266
	 * has the same effect as calling `ajax.reload()` but is provided for
7267
	 * convenience when setting a new URL. Like `ajax.reload()` it will
7268
	 * automatically redraw the table once the remote data has been loaded.
7269
	 *
7270
	 * @returns {DataTables.Api} this
7271
	 */
7272
	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7273
		// Same as a reload, but makes sense to present it for easy access after a
7274
		// url change
7275
		return this.iterator( 'table', function ( ctx ) {
7276
			__reload( ctx, resetPaging===false, callback );
7277
		} );
7278
	} );
7279
	
7280
	
7281
	
7282
	
7283
	var _selector_run = function ( selector, select )
7284
	{
7285
		var
7286
			out = [], res,
7287
			a, i, ien, j, jen;
7288
	
7289
		// Can't just check for isArray here, as an API or jQuery instance might be
7290
		// given with their array like look
7291
		if ( ! selector || typeof selector === 'string' || selector.length === undefined ) {
7292
			selector = [ selector ];
7293
		}
7294
	
7295
		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7296
			a = selector[i] && selector[i].split ?
7297
				selector[i].split(',') :
7298
				[ selector[i] ];
7299
	
7300
			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7301
				res = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7302
	
7303
				if ( res && res.length ) {
7304
					out.push.apply( out, res );
7305
				}
7306
			}
7307
		}
7308
	
7309
		return out;
7310
	};
7311
	
7312
	
7313
	var _selector_opts = function ( opts )
7314
	{
7315
		if ( ! opts ) {
7316
			opts = {};
7317
		}
7318
	
7319
		// Backwards compatibility for 1.9- which used the terminology filter rather
7320
		// than search
7321
		if ( opts.filter && ! opts.search ) {
7322
			opts.search = opts.filter;
7323
		}
7324
	
7325
		return {
7326
			search: opts.search || 'none',
7327
			order:  opts.order  || 'current',
7328
			page:   opts.page   || 'all'
7329
		};
7330
	};
7331
	
7332
	
7333
	var _selector_first = function ( inst )
7334
	{
7335
		// Reduce the API instance to the first item found
7336
		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7337
			if ( inst[i].length > 0 ) {
7338
				// Assign the first element to the first item in the instance
7339
				// and truncate the instance and context
7340
				inst[0] = inst[i];
7341
				inst.length = 1;
7342
				inst.context = [ inst.context[i] ];
7343
	
7344
				return inst;
7345
			}
7346
		}
7347
	
7348
		// Not found - return an empty instance
7349
		inst.length = 0;
7350
		return inst;
7351
	};
7352
	
7353
	
7354
	var _selector_row_indexes = function ( settings, opts )
7355
	{
7356
		var
7357
			i, ien, tmp, a=[],
7358
			displayFiltered = settings.aiDisplay,
7359
			displayMaster = settings.aiDisplayMaster;
7360
	
7361
		var
7362
			search = opts.search,  // none, applied, removed
7363
			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7364
			page   = opts.page;    // all, current
7365
	
7366
		if ( _fnDataSource( settings ) == 'ssp' ) {
7367
			// In server-side processing mode, most options are irrelevant since
7368
			// rows not shown don't exist and the index order is the applied order
7369
			// Removed is a special case - for consistency just return an empty
7370
			// array
7371
			return search === 'removed' ?
7372
				[] :
7373
				_range( 0, displayMaster.length );
7374
		}
7375
		else if ( page == 'current' ) {
7376
			// Current page implies that order=current and fitler=applied, since it is
7377
			// fairly senseless otherwise, regardless of what order and search actually
7378
			// are
7379
			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7380
				a.push( displayFiltered[i] );
7381
			}
7382
		}
7383
		else if ( order == 'current' || order == 'applied' ) {
7384
			a = search == 'none' ?
7385
				displayMaster.slice() :                      // no search
7386
				search == 'applied' ?
7387
					displayFiltered.slice() :                // applied search
7388
					$.map( displayMaster, function (el, i) { // removed search
7389
						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7390
					} );
7391
		}
7392
		else if ( order == 'index' || order == 'original' ) {
7393
			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7394
				if ( search == 'none' ) {
7395
					a.push( i );
7396
				}
7397
				else { // applied | removed
7398
					tmp = $.inArray( i, displayFiltered );
7399
	
7400
					if ((tmp === -1 && search == 'removed') ||
7401
						(tmp === 1  && search == 'applied') )
7402
					{
7403
						a.push( i );
7404
					}
7405
				}
7406
			}
7407
		}
7408
	
7409
		return a;
7410
	};
7411
	
7412
	
7413
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7414
	 * Rows
7415
	 *
7416
	 * {}          - no selector - use all available rows
7417
	 * {integer}   - row aoData index
7418
	 * {node}      - TR node
7419
	 * {string}    - jQuery selector to apply to the TR elements
7420
	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7421
	 *
7422
	 */
7423
	
7424
	
7425
	var __row_selector = function ( settings, selector, opts )
7426
	{
7427
		return _selector_run( selector, function ( sel ) {
7428
			var selInt = _intVal( sel );
7429
	
7430
			// Short cut - selector is a number and no options provided (default is
7431
			// all records, so no need to check if the index is in there, since it
7432
			// must be - dev error if the index doesn't exist).
7433
			if ( selInt !== null && ! opts ) {
7434
				return [ selInt ];
7435
			}
7436
	
7437
			var rows = _selector_row_indexes( settings, opts );
7438
	
7439
			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7440
				// Selector - integer
7441
				return [ selInt ];
7442
			}
7443
			else if ( ! sel ) {
7444
				// Selector - none
7445
				return rows;
7446
			}
7447
	
7448
			// Get nodes in the order from the `rows` array (can't use `pluck`) @todo - use pluck_order
7449
			var nodes = [];
7450
			for ( var i=0, ien=rows.length ; i<ien ; i++ ) {
7451
				nodes.push( settings.aoData[ rows[i] ].nTr );
7452
			}
7453
	
7454
			if ( sel.nodeName ) {
7455
				// Selector - node
7456
				if ( $.inArray( sel, nodes ) !== -1 ) {
7457
					return [ sel._DT_RowIndex ];// sel is a TR node that is in the table
7458
											// and DataTables adds a prop for fast lookup
7459
				}
7460
			}
7461
	
7462
			// Selector - jQuery selector string, array of nodes or jQuery object/
7463
			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7464
			// it also allows arrays, so this will cope with all three options
7465
			return $(nodes)
7466
				.filter( sel )
7467
				.map( function () {
7468
					return this._DT_RowIndex;
7469
				} )
7470
				.toArray();
7471
		} );
7472
	};
7473
	
7474
	
7475
	/**
7476
	 *
7477
	 */
7478
	_api_register( 'rows()', function ( selector, opts ) {
7479
		// argument shifting
7480
		if ( selector === undefined ) {
7481
			selector = '';
7482
		}
7483
		else if ( $.isPlainObject( selector ) ) {
7484
			opts = selector;
7485
			selector = '';
7486
		}
7487
	
7488
		opts = _selector_opts( opts );
7489
	
7490
		var inst = this.iterator( 'table', function ( settings ) {
7491
			return __row_selector( settings, selector, opts );
7492
		} );
7493
	
7494
		// Want argument shifting here and in __row_selector?
7495
		inst.selector.rows = selector;
7496
		inst.selector.opts = opts;
7497
	
7498
		return inst;
7499
	} );
7500
	
7501
	
7502
	_api_register( 'rows().nodes()', function () {
7503
		return this.iterator( 'row', function ( settings, row ) {
7504
			return settings.aoData[ row ].nTr || undefined;
7505
		} );
7506
	} );
7507
	
7508
	_api_register( 'rows().data()', function () {
7509
		return this.iterator( true, 'rows', function ( settings, rows ) {
7510
			return _pluck_order( settings.aoData, rows, '_aData' );
7511
		} );
7512
	} );
7513
	
7514
	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7515
		return this.iterator( 'row', function ( settings, row ) {
7516
			var r = settings.aoData[ row ];
7517
			return type === 'search' ? r._aFilterData : r._aSortData;
7518
		} );
7519
	} );
7520
	
7521
	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7522
		return this.iterator( 'row', function ( settings, row ) {
7523
			_fnInvalidateRow( settings, row, src );
7524
		} );
7525
	} );
7526
	
7527
	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7528
		return this.iterator( 'row', function ( settings, row ) {
7529
			return row;
7530
		} );
7531
	} );
7532
	
7533
	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7534
		var that = this;
7535
	
7536
		return this.iterator( 'row', function ( settings, row, thatIdx ) {
7537
			var data = settings.aoData;
7538
	
7539
			data.splice( row, 1 );
7540
	
7541
			// Update the _DT_RowIndex parameter on all rows in the table
7542
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7543
				if ( data[i].nTr !== null ) {
7544
					data[i].nTr._DT_RowIndex = i;
7545
				}
7546
			}
7547
	
7548
			// Remove the target row from the search array
7549
			var displayIndex = $.inArray( row, settings.aiDisplay );
7550
	
7551
			// Delete from the display arrays
7552
			_fnDeleteIndex( settings.aiDisplayMaster, row );
7553
			_fnDeleteIndex( settings.aiDisplay, row );
7554
			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7555
	
7556
			// Check for an 'overflow' they case for displaying the table
7557
			_fnLengthOverflow( settings );
7558
		} );
7559
	} );
7560
	
7561
	
7562
	_api_register( 'rows.add()', function ( rows ) {
7563
		var newRows = this.iterator( 'table', function ( settings ) {
7564
				var row, i, ien;
7565
				var out = [];
7566
	
7567
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
7568
					row = rows[i];
7569
	
7570
					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7571
						out.push( _fnAddTr( settings, row )[0] );
7572
					}
7573
					else {
7574
						out.push( _fnAddData( settings, row ) );
7575
					}
7576
				}
7577
	
7578
				return out;
7579
			} );
7580
	
7581
		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
7582
		var modRows = this.rows( -1 );
7583
		modRows.pop();
7584
		modRows.push.apply( modRows, newRows.toArray() );
7585
	
7586
		return modRows;
7587
	} );
7588
	
7589
	
7590
	
7591
	
7592
	
7593
	/**
7594
	 *
7595
	 */
7596
	_api_register( 'row()', function ( selector, opts ) {
7597
		return _selector_first( this.rows( selector, opts ) );
7598
	} );
7599
	
7600
	
7601
	_api_register( 'row().data()', function ( data ) {
7602
		var ctx = this.context;
7603
	
7604
		if ( data === undefined ) {
7605
			// Get
7606
			return ctx.length && this.length ?
7607
				ctx[0].aoData[ this[0] ]._aData :
7608
				undefined;
7609
		}
7610
	
7611
		// Set
7612
		ctx[0].aoData[ this[0] ]._aData = data;
7613
	
7614
		// Automatically invalidate
7615
		_fnInvalidateRow( ctx[0], this[0], 'data' );
7616
	
7617
		return this;
7618
	} );
7619
	
7620
	
7621
	_api_register( 'row().node()', function () {
7622
		var ctx = this.context;
7623
	
7624
		return ctx.length && this.length ?
7625
			ctx[0].aoData[ this[0] ].nTr || null :
7626
			null;
7627
	} );
7628
	
7629
	
7630
	_api_register( 'row.add()', function ( row ) {
7631
		// Allow a jQuery object to be passed in - only a single row is added from
7632
		// it though - the first element in the set
7633
		if ( row instanceof $ && row.length ) {
7634
			row = row[0];
7635
		}
7636
	
7637
		var rows = this.iterator( 'table', function ( settings ) {
7638
			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7639
				return _fnAddTr( settings, row )[0];
7640
			}
7641
			return _fnAddData( settings, row );
7642
		} );
7643
	
7644
		// Return an Api.rows() extended instance, with the newly added row selected
7645
		return this.row( rows[0] );
7646
	} );
7647
	
7648
	
7649
	
7650
	var __details_add = function ( ctx, row, data, klass )
7651
	{
7652
		// Convert to array of TR elements
7653
		var rows = [];
7654
		var addRow = function ( r, k ) {
7655
			// If we get a TR element, then just add it directly - up to the dev
7656
			// to add the correct number of columns etc
7657
			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
7658
				rows.push( r );
7659
			}
7660
			else {
7661
				// Otherwise create a row with a wrapper
7662
				var created = $('<tr><td/></tr>');
7663
				$('td', created)
7664
					.addClass( k )
7665
					.html( r )
7666
					[0].colSpan = _fnVisbleColumns( ctx );
7667
	
7668
				rows.push( created[0] );
7669
			}
7670
		};
7671
	
7672
		if ( $.isArray( data ) || data instanceof $ ) {
7673
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7674
				addRow( data[i], klass );
7675
			}
7676
		}
7677
		else {
7678
			addRow( data, klass );
7679
		}
7680
	
7681
		if ( row._details ) {
7682
			row._details.remove();
7683
		}
7684
	
7685
		row._details = $(rows);
7686
	
7687
		// If the children were already shown, that state should be retained
7688
		if ( row._detailsShow ) {
7689
			row._details.insertAfter( row.nTr );
7690
		}
7691
	};
7692
	
7693
	
7694
	var __details_display = function ( show ) {
7695
		var ctx = this.context;
7696
	
7697
		if ( ctx.length && this.length ) {
7698
			var row = ctx[0].aoData[ this[0] ];
7699
	
7700
			if ( row._details ) {
7701
				row._detailsShow = show;
7702
				if ( show ) {
7703
					row._details.insertAfter( row.nTr );
7704
				}
7705
				else {
7706
					row._details.remove();
7707
				}
7708
	
7709
				__details_events( ctx[0] );
7710
			}
7711
		}
7712
	
7713
		return this;
7714
	};
7715
	
7716
	
7717
	var __details_events = function ( settings )
7718
	{
7719
		var api = new _Api( settings );
7720
		var namespace = '.dt.DT_details';
7721
		var drawEvent = 'draw'+namespace;
7722
		var colvisEvent = 'column-visibility'+namespace;
7723
	
7724
		api.off( drawEvent +' '+ colvisEvent );
7725
	
7726
		if ( _pluck( settings.aoData, '_details' ).length > 0 ) {
7727
			// On each draw, insert the required elements into the document
7728
			api.on( drawEvent, function () {
7729
				api.rows( {page:'current'} ).eq(0).each( function (idx) {
7730
					// Internal data grab
7731
					var row = settings.aoData[ idx ];
7732
	
7733
					if ( row._detailsShow ) {
7734
						row._details.insertAfter( row.nTr );
7735
					}
7736
				} );
7737
			} );
7738
	
7739
			// Column visibility change - update the colspan
7740
			api.on( colvisEvent, function ( e, settings, idx, vis ) {
7741
				// Update the colspan for the details rows (note, only if it already has
7742
				// a colspan)
7743
				var row, visible = _fnVisbleColumns( settings );
7744
	
7745
				for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7746
					row = settings.aoData[i];
7747
	
7748
					if ( row._details ) {
7749
						row._details.children('td[colspan]').attr('colspan', visible );
7750
					}
7751
				}
7752
			} );
7753
		}
7754
	};
7755
	
7756
	// data can be:
7757
	//  tr
7758
	//  string
7759
	//  jQuery or array of any of the above
7760
	_api_register( 'row().child()', function ( data, klass ) {
7761
		var ctx = this.context;
7762
	
7763
		if ( data === undefined ) {
7764
			// get
7765
			return ctx.length && this.length ?
7766
				ctx[0].aoData[ this[0] ]._details :
7767
				undefined;
7768
		}
7769
		else if ( ctx.length && this.length ) {
7770
			// set
7771
			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
7772
		}
7773
	
7774
		return this;
7775
	} );
7776
	
7777
	_api_register( [
7778
		'row().child.show()',
7779
		'row().child().show()'
7780
	], function () {
7781
		__details_display.call( this, true );
7782
		return this;
7783
	} );
7784
	
7785
	_api_register( [
7786
		'row().child.hide()',
7787
		'row().child().hide()'
7788
	], function () {
7789
		__details_display.call( this, false );
7790
		return this;
7791
	} );
7792
	
7793
	_api_register( 'row().child.isShown()', function () {
7794
		var ctx = this.context;
7795
	
7796
		if ( ctx.length && this.length ) {
7797
			// _detailsShown as false or undefined will fall through to return false
7798
			return ctx[0].aoData[ this[0] ]._detailsShow || false;
7799
		}
7800
		return false;
7801
	} );
7802
	
7803
	
7804
	
7805
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7806
	 * Columns
7807
	 *
7808
	 * {integer}           - column index (>=0 count from left, <0 count from right)
7809
	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
7810
	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
7811
	 * "{string}:name"     - column name
7812
	 * "{string}"          - jQuery selector on column header nodes
7813
	 *
7814
	 */
7815
	
7816
	// can be an array of these items, comma separated list, or an array of comma
7817
	// separated lists
7818
	
7819
	var __re_column_selector = /^(.*):(name|visIdx|visible)$/;
7820
	
7821
	var __column_selector = function ( settings, selector, opts )
7822
	{
7823
		var
7824
			columns = settings.aoColumns,
7825
			names = _pluck( columns, 'sName' ),
7826
			nodes = _pluck( columns, 'nTh' );
7827
	
7828
		return _selector_run( selector, function ( s ) {
7829
			var selInt = _intVal( s );
7830
	
7831
			if ( s === '' ) {
7832
				// All columns
7833
				return _range( columns.length );
7834
			}
7835
			else if ( selInt !== null ) {
7836
				// Integer selector
7837
				return [ selInt >= 0 ?
7838
					selInt : // Count from left
7839
					columns.length + selInt // Count from right (+ because its a negative value)
7840
				];
7841
			}
7842
			else {
7843
				var match = typeof s === 'string' ?
7844
					s.match( __re_column_selector ) :
7845
					'';
7846
	
7847
				if ( match ) {
7848
					switch( match[2] ) {
7849
						case 'visIdx':
7850
						case 'visible':
7851
							var idx = parseInt( match[1], 10 );
7852
							// Visible index given, convert to column index
7853
							if ( idx < 0 ) {
7854
								// Counting from the right
7855
								var visColumns = $.map( columns, function (col,i) {
7856
									return col.bVisible ? i : null;
7857
								} );
7858
								return [ visColumns[ visColumns.length + idx ] ];
7859
							}
7860
							// Counting from the left
7861
							return [ _fnVisibleToColumnIndex( settings, idx ) ];
7862
	
7863
						case 'name':
7864
							// match by name. `names` is column index complete and in order
7865
							return $.map( names, function (name, i) {
7866
								return name === match[1] ? i : null;
7867
							} );
7868
					}
7869
				}
7870
				else {
7871
					// jQuery selector on the TH elements for the columns
7872
					return $( nodes )
7873
						.filter( s )
7874
						.map( function () {
7875
							return $.inArray( this, nodes ); // `nodes` is column index complete and in order
7876
						} )
7877
						.toArray();
7878
				}
7879
			}
7880
		} );
7881
	};
7882
	
7883
	
7884
	
7885
	
7886
	
7887
	var __setColumnVis = function ( settings, column, vis ) {
7888
		var
7889
			cols = settings.aoColumns,
7890
			col  = cols[ column ],
7891
			data = settings.aoData,
7892
			row, cells, i, ien, tr;
7893
	
7894
		// Get
7895
		if ( vis === undefined ) {
7896
			return col.bVisible;
7897
		}
7898
	
7899
		// Set
7900
		// No change
7901
		if ( col.bVisible === vis ) {
7902
			return;
7903
		}
7904
	
7905
		if ( vis ) {
7906
			// Insert column
7907
			// Need to decide if we should use appendChild or insertBefore
7908
			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
7909
	
7910
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
7911
				tr = data[i].nTr;
7912
				cells = data[i].anCells;
7913
	
7914
				if ( tr ) {
7915
					// insertBefore can act like appendChild if 2nd arg is null
7916
					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
7917
				}
7918
			}
7919
		}
7920
		else {
7921
			// Remove column
7922
			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
7923
	
7924
			col.bVisible = false;
7925
			_fnDrawHead( settings, settings.aoHeader );
7926
			_fnDrawHead( settings, settings.aoFooter );
7927
	
7928
			_fnSaveState( settings );
7929
		}
7930
	
7931
		// Common actions
7932
		col.bVisible = vis;
7933
		_fnDrawHead( settings, settings.aoHeader );
7934
		_fnDrawHead( settings, settings.aoFooter );
7935
	
7936
		// Automatically adjust column sizing
7937
		_fnAdjustColumnSizing( settings );
7938
	
7939
		// Realign columns for scrolling
7940
		if ( settings.oScroll.sX || settings.oScroll.sY ) {
7941
			_fnScrollDraw( settings );
7942
		}
7943
	
7944
		_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
7945
	
7946
		_fnSaveState( settings );
7947
	};
7948
	
7949
	
7950
	/**
7951
	 *
7952
	 */
7953
	_api_register( 'columns()', function ( selector, opts ) {
7954
		// argument shifting
7955
		if ( selector === undefined ) {
7956
			selector = '';
7957
		}
7958
		else if ( $.isPlainObject( selector ) ) {
7959
			opts = selector;
7960
			selector = '';
7961
		}
7962
	
7963
		opts = _selector_opts( opts );
7964
	
7965
		var inst = this.iterator( 'table', function ( settings ) {
7966
			return __column_selector( settings, selector, opts );
7967
		} );
7968
	
7969
		// Want argument shifting here and in _row_selector?
7970
		inst.selector.cols = selector;
7971
		inst.selector.opts = opts;
7972
	
7973
		return inst;
7974
	} );
7975
	
7976
	
7977
	/**
7978
	 *
7979
	 */
7980
	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
7981
		return this.iterator( 'column', function ( settings, column ) {
7982
			return settings.aoColumns[column].nTh;
7983
		} );
7984
	} );
7985
	
7986
	
7987
	/**
7988
	 *
7989
	 */
7990
	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
7991
		return this.iterator( 'column', function ( settings, column ) {
7992
			return settings.aoColumns[column].nTf;
7993
		} );
7994
	} );
7995
	
7996
	
7997
	/**
7998
	 *
7999
	 */
8000
	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8001
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8002
			var a = [];
8003
			for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8004
				a.push( _fnGetCellData( settings, rows[row], column, '' ) );
8005
			}
8006
			return a;
8007
		} );
8008
	} );
8009
	
8010
	
8011
	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8012
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8013
			return _pluck_order( settings.aoData, rows,
8014
				type === 'search' ? '_aFilterData' : '_aSortData', column
8015
			);
8016
		} );
8017
	} );
8018
	
8019
	
8020
	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8021
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8022
			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8023
		} );
8024
	} );
8025
	
8026
	
8027
	
8028
	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis ) {
8029
		return this.iterator( 'column', function ( settings, column ) {
8030
			return vis === undefined ?
8031
				settings.aoColumns[ column ].bVisible :
8032
				__setColumnVis( settings, column, vis );
8033
		} );
8034
	} );
8035
	
8036
	
8037
	
8038
	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8039
		return this.iterator( 'column', function ( settings, column ) {
8040
			return type === 'visible' ?
8041
				_fnColumnIndexToVisible( settings, column ) :
8042
				column;
8043
		} );
8044
	} );
8045
	
8046
	
8047
	// _api_register( 'columns().show()', function () {
8048
	// 	var selector = this.selector;
8049
	// 	return this.columns( selector.cols, selector.opts ).visible( true );
8050
	// } );
8051
	
8052
	
8053
	// _api_register( 'columns().hide()', function () {
8054
	// 	var selector = this.selector;
8055
	// 	return this.columns( selector.cols, selector.opts ).visible( false );
8056
	// } );
8057
	
8058
	
8059
	
8060
	_api_register( 'columns.adjust()', function () {
8061
		return this.iterator( 'table', function ( settings ) {
8062
			_fnAdjustColumnSizing( settings );
8063
		} );
8064
	} );
8065
	
8066
	
8067
	// Convert from one column index type, to another type
8068
	_api_register( 'column.index()', function ( type, idx ) {
8069
		if ( this.context.length !== 0 ) {
8070
			var ctx = this.context[0];
8071
	
8072
			if ( type === 'fromVisible' || type === 'toData' ) {
8073
				return _fnVisibleToColumnIndex( ctx, idx );
8074
			}
8075
			else if ( type === 'fromData' || type === 'toVisible' ) {
8076
				return _fnColumnIndexToVisible( ctx, idx );
8077
			}
8078
		}
8079
	} );
8080
	
8081
	
8082
	_api_register( 'column()', function ( selector, opts ) {
8083
		return _selector_first( this.columns( selector, opts ) );
8084
	} );
8085
	
8086
	
8087
	
8088
	
8089
	var __cell_selector = function ( settings, selector, opts )
8090
	{
8091
		var data = settings.aoData;
8092
		var rows = _selector_row_indexes( settings, opts );
8093
		var cells = _pluck_order( data, rows, 'anCells' );
8094
		var allCells = $( [].concat.apply([], cells) );
8095
		var row;
8096
		var columns = settings.aoColumns.length;
8097
		var a, i, ien, j;
8098
	
8099
		return _selector_run( selector, function ( s ) {
8100
			if ( ! s ) {
8101
				// All cells
8102
				a = [];
8103
	
8104
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8105
					row = rows[i];
8106
	
8107
					for ( j=0 ; j<columns ; j++ ) {
8108
						a.push( {
8109
							row: row,
8110
							column: j
8111
						} );
8112
					}
8113
				}
8114
	
8115
				return a;
8116
			}
8117
			else if ( $.isPlainObject( s ) ) {
8118
				return [s];
8119
			}
8120
	
8121
			// jQuery filtered cells
8122
			return allCells
8123
				.filter( s )
8124
				.map( function (i, el) {
8125
					row = el.parentNode._DT_RowIndex;
8126
	
8127
					return {
8128
						row: row,
8129
						column: $.inArray( el, data[ row ].anCells )
8130
					};
8131
				} )
8132
				.toArray();
8133
		} );
8134
	};
8135
	
8136
	
8137
	
8138
	
8139
	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8140
		// Argument shifting
8141
		if ( $.isPlainObject( rowSelector ) ) {
8142
			// If passing in a cell index
8143
			if ( rowSelector.row ) {
8144
				opts = columnSelector;
8145
				columnSelector = null;
8146
			}
8147
			else {
8148
				opts = rowSelector;
8149
				rowSelector = null;
8150
			}
8151
		}
8152
		if ( $.isPlainObject( columnSelector ) ) {
8153
			opts = columnSelector;
8154
			columnSelector = null;
8155
		}
8156
	
8157
		// Cell selector
8158
		if ( columnSelector === null || columnSelector === undefined ) {
8159
			return this.iterator( 'table', function ( settings ) {
8160
				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8161
			} );
8162
		}
8163
	
8164
		// Row + column selector
8165
		var columns = this.columns( columnSelector, opts );
8166
		var rows = this.rows( rowSelector, opts );
8167
		var a, i, ien, j, jen;
8168
	
8169
		var cells = this.iterator( 'table', function ( settings, idx ) {
8170
			a = [];
8171
	
8172
			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8173
				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8174
					a.push( {
8175
						row:    rows[idx][i],
8176
						column: columns[idx][j]
8177
					} );
8178
				}
8179
			}
8180
	
8181
			return a;
8182
		} );
8183
	
8184
		$.extend( cells.selector, {
8185
			cols: columnSelector,
8186
			rows: rowSelector,
8187
			opts: opts
8188
		} );
8189
	
8190
		return cells;
8191
	} );
8192
	
8193
	
8194
	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8195
		return this.iterator( 'cell', function ( settings, row, column ) {
8196
			return settings.aoData[ row ].anCells[ column ];
8197
		} );
8198
	} );
8199
	
8200
	
8201
	_api_register( 'cells().data()', function () {
8202
		return this.iterator( 'cell', function ( settings, row, column ) {
8203
			return _fnGetCellData( settings, row, column );
8204
		} );
8205
	} );
8206
	
8207
	
8208
	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8209
		type = type === 'search' ? '_aFilterData' : '_aSortData';
8210
	
8211
		return this.iterator( 'cell', function ( settings, row, column ) {
8212
			return settings.aoData[ row ][ type ][ column ];
8213
		} );
8214
	} );
8215
	
8216
	
8217
	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8218
		return this.iterator( 'cell', function ( settings, row, column ) {
8219
			return {
8220
				row: row,
8221
				column: column,
8222
				columnVisible: _fnColumnIndexToVisible( settings, column )
8223
			};
8224
		} );
8225
	} );
8226
	
8227
	
8228
	_api_register( [
8229
		'cells().invalidate()',
8230
		'cell().invalidate()'
8231
	], function ( src ) {
8232
		var selector = this.selector;
8233
	
8234
		// Use the rows method of the instance to perform the invalidation, rather
8235
		// than doing it here. This avoids needing to handle duplicate rows from
8236
		// the cells.
8237
		this.rows( selector.rows, selector.opts ).invalidate( src );
8238
	
8239
		return this;
8240
	} );
8241
	
8242
	
8243
	
8244
	
8245
	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8246
		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8247
	} );
8248
	
8249
	
8250
	
8251
	_api_register( 'cell().data()', function ( data ) {
8252
		var ctx = this.context;
8253
		var cell = this[0];
8254
	
8255
		if ( data === undefined ) {
8256
			// Get
8257
			return ctx.length && cell.length ?
8258
				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8259
				undefined;
8260
		}
8261
	
8262
		// Set
8263
		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8264
		_fnInvalidateRow( ctx[0], cell[0].row, 'data', cell[0].column );
8265
	
8266
		return this;
8267
	} );
8268
	
8269
	
8270
	
8271
	/**
8272
	 * Get current ordering (sorting) that has been applied to the table.
8273
	 *
8274
	 * @returns {array} 2D array containing the sorting information for the first
8275
	 *   table in the current context. Each element in the parent array represents
8276
	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8277
	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8278
	 *   the column index that the sorting condition applies to, the second is the
8279
	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8280
	 *   index of the sorting order from the `column.sorting` initialisation array.
8281
	 *//**
8282
	 * Set the ordering for the table.
8283
	 *
8284
	 * @param {integer} order Column index to sort upon.
8285
	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8286
	 * @returns {DataTables.Api} this
8287
	 *//**
8288
	 * Set the ordering for the table.
8289
	 *
8290
	 * @param {array} order 1D array of sorting information to be applied.
8291
	 * @param {array} [...] Optional additional sorting conditions
8292
	 * @returns {DataTables.Api} this
8293
	 *//**
8294
	 * Set the ordering for the table.
8295
	 *
8296
	 * @param {array} order 2D array of sorting information to be applied.
8297
	 * @returns {DataTables.Api} this
8298
	 */
8299
	_api_register( 'order()', function ( order, dir ) {
8300
		var ctx = this.context;
8301
	
8302
		if ( order === undefined ) {
8303
			// get
8304
			return ctx.length !== 0 ?
8305
				ctx[0].aaSorting :
8306
				undefined;
8307
		}
8308
	
8309
		// set
8310
		if ( typeof order === 'number' ) {
8311
			// Simple column / direction passed in
8312
			order = [ [ order, dir ] ];
8313
		}
8314
		else if ( ! $.isArray( order[0] ) ) {
8315
			// Arguments passed in (list of 1D arrays)
8316
			order = Array.prototype.slice.call( arguments );
8317
		}
8318
		// otherwise a 2D array was passed in
8319
	
8320
		return this.iterator( 'table', function ( settings ) {
8321
			settings.aaSorting = order.slice();
8322
		} );
8323
	} );
8324
	
8325
	
8326
	/**
8327
	 * Attach a sort listener to an element for a given column
8328
	 *
8329
	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8330
	 *   listener to. This can take the form of a single DOM node, a jQuery
8331
	 *   collection of nodes or a jQuery selector which will identify the node(s).
8332
	 * @param {integer} column the column that a click on this node will sort on
8333
	 * @param {function} [callback] callback function when sort is run
8334
	 * @returns {DataTables.Api} this
8335
	 */
8336
	_api_register( 'order.listener()', function ( node, column, callback ) {
8337
		return this.iterator( 'table', function ( settings ) {
8338
			_fnSortAttachListener( settings, node, column, callback );
8339
		} );
8340
	} );
8341
	
8342
	
8343
	// Order by the selected column(s)
8344
	_api_register( [
8345
		'columns().order()',
8346
		'column().order()'
8347
	], function ( dir ) {
8348
		var that = this;
8349
	
8350
		return this.iterator( 'table', function ( settings, i ) {
8351
			var sort = [];
8352
	
8353
			$.each( that[i], function (j, col) {
8354
				sort.push( [ col, dir ] );
8355
			} );
8356
	
8357
			settings.aaSorting = sort;
8358
		} );
8359
	} );
8360
	
8361
	
8362
	
8363
	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8364
		var ctx = this.context;
8365
	
8366
		if ( input === undefined ) {
8367
			// get
8368
			return ctx.length !== 0 ?
8369
				ctx[0].oPreviousSearch.sSearch :
8370
				undefined;
8371
		}
8372
	
8373
		// set
8374
		return this.iterator( 'table', function ( settings ) {
8375
			if ( ! settings.oFeatures.bFilter ) {
8376
				return;
8377
			}
8378
	
8379
			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8380
				"sSearch": input+"",
8381
				"bRegex":  regex === null ? false : regex,
8382
				"bSmart":  smart === null ? true  : smart,
8383
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
8384
			} ), 1 );
8385
		} );
8386
	} );
8387
	
8388
	
8389
	_api_register( [
8390
		'columns().search()',
8391
		'column().search()'
8392
	], function ( input, regex, smart, caseInsen ) {
8393
		return this.iterator( 'column', function ( settings, column ) {
8394
			var preSearch = settings.aoPreSearchCols;
8395
	
8396
			if ( input === undefined ) {
8397
				// get
8398
				return preSearch[ column ].sSearch;
8399
			}
8400
	
8401
			// set
8402
			if ( ! settings.oFeatures.bFilter ) {
8403
				return;
8404
			}
8405
	
8406
			$.extend( preSearch[ column ], {
8407
				"sSearch": input+"",
8408
				"bRegex":  regex === null ? false : regex,
8409
				"bSmart":  smart === null ? true  : smart,
8410
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
8411
			} );
8412
	
8413
			_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8414
		} );
8415
	} );
8416
	
8417
	
8418
	
8419
	/**
8420
	 * Provide a common method for plug-ins to check the version of DataTables being
8421
	 * used, in order to ensure compatibility.
8422
	 *
8423
	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
8424
	 *    Note that the formats "X" and "X.Y" are also acceptable.
8425
	 *  @returns {boolean} true if this version of DataTables is greater or equal to
8426
	 *    the required version, or false if this version of DataTales is not
8427
	 *    suitable
8428
	 *  @static
8429
	 *  @dtopt API-Static
8430
	 *
8431
	 *  @example
8432
	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8433
	 */
8434
	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
8435
	{
8436
		var aThis = DataTable.version.split('.');
8437
		var aThat = version.split('.');
8438
		var iThis, iThat;
8439
	
8440
		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
8441
			iThis = parseInt( aThis[i], 10 ) || 0;
8442
			iThat = parseInt( aThat[i], 10 ) || 0;
8443
	
8444
			// Parts are the same, keep comparing
8445
			if (iThis === iThat) {
8446
				continue;
8447
			}
8448
	
8449
			// Parts are different, return immediately
8450
			return iThis > iThat;
8451
		}
8452
	
8453
		return true;
8454
	};
8455
	
8456
	
8457
	/**
8458
	 * Check if a `<table>` node is a DataTable table already or not.
8459
	 *
8460
	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
8461
	 *      selector for the table to test. Note that if more than more than one
8462
	 *      table is passed on, only the first will be checked
8463
	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
8464
	 *  @static
8465
	 *  @dtopt API-Static
8466
	 *
8467
	 *  @example
8468
	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8469
	 *      $('#example').dataTable();
8470
	 *    }
8471
	 */
8472
	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
8473
	{
8474
		var t = $(table).get(0);
8475
		var is = false;
8476
	
8477
		$.each( DataTable.settings, function (i, o) {
8478
			if ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {
8479
				is = true;
8480
			}
8481
		} );
8482
	
8483
		return is;
8484
	};
8485
	
8486
	
8487
	/**
8488
	 * Get all DataTable tables that have been initialised - optionally you can
8489
	 * select to get only currently visible tables.
8490
	 *
8491
	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
8492
	 *    or visible tables only.
8493
	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
8494
	 *    DataTables
8495
	 *  @static
8496
	 *  @dtopt API-Static
8497
	 *
8498
	 *  @example
8499
	 *    $.each( $.fn.dataTable.tables(true), function () {
8500
	 *      $(table).DataTable().columns.adjust();
8501
	 *    } );
8502
	 */
8503
	DataTable.tables = DataTable.fnTables = function ( visible )
8504
	{
8505
		return jQuery.map( DataTable.settings, function (o) {
8506
			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8507
				return o.nTable;
8508
			}
8509
		} );
8510
	};
8511
	
8512
	
8513
	/**
8514
	 * Convert from camel case parameters to Hungarian notation. This is made public
8515
	 * for the extensions to provide the same ability as DataTables core to accept
8516
	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
8517
	 * parameters.
8518
	 *
8519
	 *  @param {object} src The model object which holds all parameters that can be
8520
	 *    mapped.
8521
	 *  @param {object} user The object to convert from camel case to Hungarian.
8522
	 *  @param {boolean} force When set to `true`, properties which already have a
8523
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
8524
	 *    won't be.
8525
	 */
8526
	DataTable.camelToHungarian = _fnCamelToHungarian;
8527
	
8528
	
8529
	
8530
	/**
8531
	 *
8532
	 */
8533
	_api_register( '$()', function ( selector, opts ) {
8534
		var
8535
			rows   = this.rows( opts ).nodes(), // Get all rows
8536
			jqRows = $(rows);
8537
	
8538
		return $( [].concat(
8539
			jqRows.filter( selector ).toArray(),
8540
			jqRows.find( selector ).toArray()
8541
		) );
8542
	} );
8543
	
8544
	
8545
	// jQuery functions to operate on the tables
8546
	$.each( [ 'on', 'one', 'off' ], function (i, key) {
8547
		_api_register( key+'()', function ( /* event, handler */ ) {
8548
			var args = Array.prototype.slice.call(arguments);
8549
	
8550
			// Add the `dt` namespace automatically if it isn't already present
8551
			if ( args[0].indexOf( '.dt' ) === -1 ) {
8552
				args[0] += '.dt';
8553
			}
8554
	
8555
			var inst = $( this.tables().nodes() );
8556
			inst[key].apply( inst, args );
8557
			return this;
8558
		} );
8559
	} );
8560
	
8561
	
8562
	_api_register( 'clear()', function () {
8563
		return this.iterator( 'table', function ( settings ) {
8564
			_fnClearTable( settings );
8565
		} );
8566
	} );
8567
	
8568
	
8569
	_api_register( 'settings()', function () {
8570
		return new _Api( this.context, this.context );
8571
	} );
8572
	
8573
	
8574
	_api_register( 'data()', function () {
8575
		return this.iterator( 'table', function ( settings ) {
8576
			return _pluck( settings.aoData, '_aData' );
8577
		} ).flatten();
8578
	} );
8579
	
8580
	
8581
	_api_register( 'destroy()', function ( remove ) {
8582
		remove = remove || false;
8583
	
8584
		return this.iterator( 'table', function ( settings ) {
8585
			var orig      = settings.nTableWrapper.parentNode;
8586
			var classes   = settings.oClasses;
8587
			var table     = settings.nTable;
8588
			var tbody     = settings.nTBody;
8589
			var thead     = settings.nTHead;
8590
			var tfoot     = settings.nTFoot;
8591
			var jqTable   = $(table);
8592
			var jqTbody   = $(tbody);
8593
			var jqWrapper = $(settings.nTableWrapper);
8594
			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
8595
			var i, ien;
8596
	
8597
			// Flag to note that the table is currently being destroyed - no action
8598
			// should be taken
8599
			settings.bDestroying = true;
8600
	
8601
			// Fire off the destroy callbacks for plug-ins etc
8602
			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
8603
	
8604
			// If not being removed from the document, make all columns visible
8605
			if ( ! remove ) {
8606
				new _Api( settings ).columns().visible( true );
8607
			}
8608
	
8609
			// Blitz all `DT` namespaced events (these are internal events, the
8610
			// lowercase, `dt` events are user subscribed and they are responsible
8611
			// for removing them
8612
			jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
8613
			$(window).unbind('.DT-'+settings.sInstance);
8614
	
8615
			// When scrolling we had to break the table up - restore it
8616
			if ( table != thead.parentNode ) {
8617
				jqTable.children('thead').detach();
8618
				jqTable.append( thead );
8619
			}
8620
	
8621
			if ( tfoot && table != tfoot.parentNode ) {
8622
				jqTable.children('tfoot').detach();
8623
				jqTable.append( tfoot );
8624
			}
8625
	
8626
			// Remove the DataTables generated nodes, events and classes
8627
			jqTable.detach();
8628
			jqWrapper.detach();
8629
	
8630
			settings.aaSorting = [];
8631
			settings.aaSortingFixed = [];
8632
			_fnSortingClasses( settings );
8633
	
8634
			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
8635
	
8636
			$('th, td', thead).removeClass( classes.sSortable+' '+
8637
				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
8638
			);
8639
	
8640
			if ( settings.bJUI ) {
8641
				$('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
8642
				$('th, td', thead).each( function () {
8643
					var wrapper = $('div.'+classes.sSortJUIWrapper, this);
8644
					$(this).append( wrapper.contents() );
8645
					wrapper.detach();
8646
				} );
8647
			}
8648
	
8649
			if ( ! remove && orig ) {
8650
				// insertBefore acts like appendChild if !arg[1]
8651
				orig.insertBefore( table, settings.nTableReinsertBefore );
8652
			}
8653
	
8654
			// Add the TR elements back into the table in their original order
8655
			jqTbody.children().detach();
8656
			jqTbody.append( rows );
8657
	
8658
			// Restore the width of the original table - was read from the style property,
8659
			// so we can restore directly to that
8660
			jqTable
8661
				.css( 'width', settings.sDestroyWidth )
8662
				.removeClass( classes.sTable );
8663
	
8664
			// If the were originally stripe classes - then we add them back here.
8665
			// Note this is not fool proof (for example if not all rows had stripe
8666
			// classes - but it's a good effort without getting carried away
8667
			ien = settings.asDestroyStripes.length;
8668
	
8669
			if ( ien ) {
8670
				jqTbody.children().each( function (i) {
8671
					$(this).addClass( settings.asDestroyStripes[i % ien] );
8672
				} );
8673
			}
8674
	
8675
			/* Remove the settings object from the settings array */
8676
			var idx = $.inArray( settings, DataTable.settings );
8677
			if ( idx !== -1 ) {
8678
				DataTable.settings.splice( idx, 1 );
8679
			}
8680
		} );
8681
	} );
8682
	
8683

    
8684
	/**
8685
	 * Version string for plug-ins to check compatibility. Allowed format is
8686
	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
8687
	 * only for non-release builds. See http://semver.org/ for more information.
8688
	 *  @member
8689
	 *  @type string
8690
	 *  @default Version number
8691
	 */
8692
	DataTable.version = "1.10.0";
8693

    
8694
	/**
8695
	 * Private data store, containing all of the settings objects that are
8696
	 * created for the tables on a given page.
8697
	 *
8698
	 * Note that the `DataTable.settings` object is aliased to
8699
	 * `jQuery.fn.dataTableExt` through which it may be accessed and
8700
	 * manipulated, or `jQuery.fn.dataTable.settings`.
8701
	 *  @member
8702
	 *  @type array
8703
	 *  @default []
8704
	 *  @private
8705
	 */
8706
	DataTable.settings = [];
8707

    
8708
	/**
8709
	 * Object models container, for the various models that DataTables has
8710
	 * available to it. These models define the objects that are used to hold
8711
	 * the active state and configuration of the table.
8712
	 *  @namespace
8713
	 */
8714
	DataTable.models = {};
8715
	
8716
	
8717
	
8718
	/**
8719
	 * Template object for the way in which DataTables holds information about
8720
	 * search information for the global filter and individual column filters.
8721
	 *  @namespace
8722
	 */
8723
	DataTable.models.oSearch = {
8724
		/**
8725
		 * Flag to indicate if the filtering should be case insensitive or not
8726
		 *  @type boolean
8727
		 *  @default true
8728
		 */
8729
		"bCaseInsensitive": true,
8730
	
8731
		/**
8732
		 * Applied search term
8733
		 *  @type string
8734
		 *  @default <i>Empty string</i>
8735
		 */
8736
		"sSearch": "",
8737
	
8738
		/**
8739
		 * Flag to indicate if the search term should be interpreted as a
8740
		 * regular expression (true) or not (false) and therefore and special
8741
		 * regex characters escaped.
8742
		 *  @type boolean
8743
		 *  @default false
8744
		 */
8745
		"bRegex": false,
8746
	
8747
		/**
8748
		 * Flag to indicate if DataTables is to use its smart filtering or not.
8749
		 *  @type boolean
8750
		 *  @default true
8751
		 */
8752
		"bSmart": true
8753
	};
8754
	
8755
	
8756
	
8757
	
8758
	/**
8759
	 * Template object for the way in which DataTables holds information about
8760
	 * each individual row. This is the object format used for the settings
8761
	 * aoData array.
8762
	 *  @namespace
8763
	 */
8764
	DataTable.models.oRow = {
8765
		/**
8766
		 * TR element for the row
8767
		 *  @type node
8768
		 *  @default null
8769
		 */
8770
		"nTr": null,
8771
	
8772
		/**
8773
		 * Array of TD elements for each row. This is null until the row has been
8774
		 * created.
8775
		 *  @type array nodes
8776
		 *  @default []
8777
		 */
8778
		"anCells": null,
8779
	
8780
		/**
8781
		 * Data object from the original data source for the row. This is either
8782
		 * an array if using the traditional form of DataTables, or an object if
8783
		 * using mData options. The exact type will depend on the passed in
8784
		 * data from the data source, or will be an array if using DOM a data
8785
		 * source.
8786
		 *  @type array|object
8787
		 *  @default []
8788
		 */
8789
		"_aData": [],
8790
	
8791
		/**
8792
		 * Sorting data cache - this array is ostensibly the same length as the
8793
		 * number of columns (although each index is generated only as it is
8794
		 * needed), and holds the data that is used for sorting each column in the
8795
		 * row. We do this cache generation at the start of the sort in order that
8796
		 * the formatting of the sort data need be done only once for each cell
8797
		 * per sort. This array should not be read from or written to by anything
8798
		 * other than the master sorting methods.
8799
		 *  @type array
8800
		 *  @default null
8801
		 *  @private
8802
		 */
8803
		"_aSortData": null,
8804
	
8805
		/**
8806
		 * Per cell filtering data cache. As per the sort data cache, used to
8807
		 * increase the performance of the filtering in DataTables
8808
		 *  @type array
8809
		 *  @default null
8810
		 *  @private
8811
		 */
8812
		"_aFilterData": null,
8813
	
8814
		/**
8815
		 * Filtering data cache. This is the same as the cell filtering cache, but
8816
		 * in this case a string rather than an array. This is easily computed with
8817
		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
8818
		 * needed on every search (memory traded for performance)
8819
		 *  @type array
8820
		 *  @default null
8821
		 *  @private
8822
		 */
8823
		"_sFilterRow": null,
8824
	
8825
		/**
8826
		 * Cache of the class name that DataTables has applied to the row, so we
8827
		 * can quickly look at this variable rather than needing to do a DOM check
8828
		 * on className for the nTr property.
8829
		 *  @type string
8830
		 *  @default <i>Empty string</i>
8831
		 *  @private
8832
		 */
8833
		"_sRowStripe": "",
8834
	
8835
		/**
8836
		 * Denote if the original data source was from the DOM, or the data source
8837
		 * object. This is used for invalidating data, so DataTables can
8838
		 * automatically read data from the original source, unless uninstructed
8839
		 * otherwise.
8840
		 *  @type string
8841
		 *  @default null
8842
		 *  @private
8843
		 */
8844
		"src": null
8845
	};
8846
	
8847
	
8848
	/**
8849
	 * Template object for the column information object in DataTables. This object
8850
	 * is held in the settings aoColumns array and contains all the information that
8851
	 * DataTables needs about each individual column.
8852
	 *
8853
	 * Note that this object is related to {@link DataTable.defaults.column}
8854
	 * but this one is the internal data store for DataTables's cache of columns.
8855
	 * It should NOT be manipulated outside of DataTables. Any configuration should
8856
	 * be done through the initialisation options.
8857
	 *  @namespace
8858
	 */
8859
	DataTable.models.oColumn = {
8860
		/**
8861
		 * Column index. This could be worked out on-the-fly with $.inArray, but it
8862
		 * is faster to just hold it as a variable
8863
		 *  @type integer
8864
		 *  @default null
8865
		 */
8866
		"idx": null,
8867
	
8868
		/**
8869
		 * A list of the columns that sorting should occur on when this column
8870
		 * is sorted. That this property is an array allows multi-column sorting
8871
		 * to be defined for a column (for example first name / last name columns
8872
		 * would benefit from this). The values are integers pointing to the
8873
		 * columns to be sorted on (typically it will be a single integer pointing
8874
		 * at itself, but that doesn't need to be the case).
8875
		 *  @type array
8876
		 */
8877
		"aDataSort": null,
8878
	
8879
		/**
8880
		 * Define the sorting directions that are applied to the column, in sequence
8881
		 * as the column is repeatedly sorted upon - i.e. the first value is used
8882
		 * as the sorting direction when the column if first sorted (clicked on).
8883
		 * Sort it again (click again) and it will move on to the next index.
8884
		 * Repeat until loop.
8885
		 *  @type array
8886
		 */
8887
		"asSorting": null,
8888
	
8889
		/**
8890
		 * Flag to indicate if the column is searchable, and thus should be included
8891
		 * in the filtering or not.
8892
		 *  @type boolean
8893
		 */
8894
		"bSearchable": null,
8895
	
8896
		/**
8897
		 * Flag to indicate if the column is sortable or not.
8898
		 *  @type boolean
8899
		 */
8900
		"bSortable": null,
8901
	
8902
		/**
8903
		 * Flag to indicate if the column is currently visible in the table or not
8904
		 *  @type boolean
8905
		 */
8906
		"bVisible": null,
8907
	
8908
		/**
8909
		 * Store for manual type assignment using the `column.type` option. This
8910
		 * is held in store so we can manipulate the column's `sType` property.
8911
		 *  @type string
8912
		 *  @default null
8913
		 *  @private
8914
		 */
8915
		"_sManualType": null,
8916
	
8917
		/**
8918
		 * Flag to indicate if HTML5 data attributes should be used as the data
8919
		 * source for filtering or sorting. True is either are.
8920
		 *  @type boolean
8921
		 *  @default false
8922
		 *  @private
8923
		 */
8924
		"_bAttrSrc": false,
8925
	
8926
		/**
8927
		 * Developer definable function that is called whenever a cell is created (Ajax source,
8928
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
8929
		 * allowing you to modify the DOM element (add background colour for example) when the
8930
		 * element is available.
8931
		 *  @type function
8932
		 *  @param {element} nTd The TD node that has been created
8933
		 *  @param {*} sData The Data for the cell
8934
		 *  @param {array|object} oData The data for the whole row
8935
		 *  @param {int} iRow The row index for the aoData data store
8936
		 *  @default null
8937
		 */
8938
		"fnCreatedCell": null,
8939
	
8940
		/**
8941
		 * Function to get data from a cell in a column. You should <b>never</b>
8942
		 * access data directly through _aData internally in DataTables - always use
8943
		 * the method attached to this property. It allows mData to function as
8944
		 * required. This function is automatically assigned by the column
8945
		 * initialisation method
8946
		 *  @type function
8947
		 *  @param {array|object} oData The data array/object for the array
8948
		 *    (i.e. aoData[]._aData)
8949
		 *  @param {string} sSpecific The specific data type you want to get -
8950
		 *    'display', 'type' 'filter' 'sort'
8951
		 *  @returns {*} The data for the cell from the given row's data
8952
		 *  @default null
8953
		 */
8954
		"fnGetData": null,
8955
	
8956
		/**
8957
		 * Function to set data for a cell in the column. You should <b>never</b>
8958
		 * set the data directly to _aData internally in DataTables - always use
8959
		 * this method. It allows mData to function as required. This function
8960
		 * is automatically assigned by the column initialisation method
8961
		 *  @type function
8962
		 *  @param {array|object} oData The data array/object for the array
8963
		 *    (i.e. aoData[]._aData)
8964
		 *  @param {*} sValue Value to set
8965
		 *  @default null
8966
		 */
8967
		"fnSetData": null,
8968
	
8969
		/**
8970
		 * Property to read the value for the cells in the column from the data
8971
		 * source array / object. If null, then the default content is used, if a
8972
		 * function is given then the return from the function is used.
8973
		 *  @type function|int|string|null
8974
		 *  @default null
8975
		 */
8976
		"mData": null,
8977
	
8978
		/**
8979
		 * Partner property to mData which is used (only when defined) to get
8980
		 * the data - i.e. it is basically the same as mData, but without the
8981
		 * 'set' option, and also the data fed to it is the result from mData.
8982
		 * This is the rendering method to match the data method of mData.
8983
		 *  @type function|int|string|null
8984
		 *  @default null
8985
		 */
8986
		"mRender": null,
8987
	
8988
		/**
8989
		 * Unique header TH/TD element for this column - this is what the sorting
8990
		 * listener is attached to (if sorting is enabled.)
8991
		 *  @type node
8992
		 *  @default null
8993
		 */
8994
		"nTh": null,
8995
	
8996
		/**
8997
		 * Unique footer TH/TD element for this column (if there is one). Not used
8998
		 * in DataTables as such, but can be used for plug-ins to reference the
8999
		 * footer for each column.
9000
		 *  @type node
9001
		 *  @default null
9002
		 */
9003
		"nTf": null,
9004
	
9005
		/**
9006
		 * The class to apply to all TD elements in the table's TBODY for the column
9007
		 *  @type string
9008
		 *  @default null
9009
		 */
9010
		"sClass": null,
9011
	
9012
		/**
9013
		 * When DataTables calculates the column widths to assign to each column,
9014
		 * it finds the longest string in each column and then constructs a
9015
		 * temporary table and reads the widths from that. The problem with this
9016
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9017
		 * string - thus the calculation can go wrong (doing it properly and putting
9018
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9019
		 * a "work around" we provide this option. It will append its value to the
9020
		 * text that is found to be the longest string for the column - i.e. padding.
9021
		 *  @type string
9022
		 */
9023
		"sContentPadding": null,
9024
	
9025
		/**
9026
		 * Allows a default value to be given for a column's data, and will be used
9027
		 * whenever a null data source is encountered (this can be because mData
9028
		 * is set to null, or because the data source itself is null).
9029
		 *  @type string
9030
		 *  @default null
9031
		 */
9032
		"sDefaultContent": null,
9033
	
9034
		/**
9035
		 * Name for the column, allowing reference to the column by name as well as
9036
		 * by index (needs a lookup to work by name).
9037
		 *  @type string
9038
		 */
9039
		"sName": null,
9040
	
9041
		/**
9042
		 * Custom sorting data type - defines which of the available plug-ins in
9043
		 * afnSortData the custom sorting will use - if any is defined.
9044
		 *  @type string
9045
		 *  @default std
9046
		 */
9047
		"sSortDataType": 'std',
9048
	
9049
		/**
9050
		 * Class to be applied to the header element when sorting on this column
9051
		 *  @type string
9052
		 *  @default null
9053
		 */
9054
		"sSortingClass": null,
9055
	
9056
		/**
9057
		 * Class to be applied to the header element when sorting on this column -
9058
		 * when jQuery UI theming is used.
9059
		 *  @type string
9060
		 *  @default null
9061
		 */
9062
		"sSortingClassJUI": null,
9063
	
9064
		/**
9065
		 * Title of the column - what is seen in the TH element (nTh).
9066
		 *  @type string
9067
		 */
9068
		"sTitle": null,
9069
	
9070
		/**
9071
		 * Column sorting and filtering type
9072
		 *  @type string
9073
		 *  @default null
9074
		 */
9075
		"sType": null,
9076
	
9077
		/**
9078
		 * Width of the column
9079
		 *  @type string
9080
		 *  @default null
9081
		 */
9082
		"sWidth": null,
9083
	
9084
		/**
9085
		 * Width of the column when it was first "encountered"
9086
		 *  @type string
9087
		 *  @default null
9088
		 */
9089
		"sWidthOrig": null
9090
	};
9091
	
9092
	
9093
	/*
9094
	 * Developer note: The properties of the object below are given in Hungarian
9095
	 * notation, that was used as the interface for DataTables prior to v1.10, however
9096
	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9097
	 * breaking backwards compatibility utterly with this change, the Hungarian
9098
	 * version is still, internally the primary interface, but is is not documented
9099
	 * - hence the @name tags in each doc comment. This allows a Javascript function
9100
	 * to create a map from Hungarian notation to camel case (going the other direction
9101
	 * would require each property to be listed, which would at around 3K to the size
9102
	 * of DataTables, while this method is about a 0.5K hit.
9103
	 *
9104
	 * Ultimately this does pave the way for Hungarian notation to be dropped
9105
	 * completely, but that is a massive amount of work and will break current
9106
	 * installs (therefore is on-hold until v2).
9107
	 */
9108
	
9109
	/**
9110
	 * Initialisation options that can be given to DataTables at initialisation
9111
	 * time.
9112
	 *  @namespace
9113
	 */
9114
	DataTable.defaults = {
9115
		/**
9116
		 * An array of data to use for the table, passed in at initialisation which
9117
		 * will be used in preference to any data which is already in the DOM. This is
9118
		 * particularly useful for constructing tables purely in Javascript, for
9119
		 * example with a custom Ajax call.
9120
		 *  @type array
9121
		 *  @default null
9122
		 *
9123
		 *  @dtopt Option
9124
		 *  @name DataTable.defaults.data
9125
		 *
9126
		 *  @example
9127
		 *    // Using a 2D array data source
9128
		 *    $(document).ready( function () {
9129
		 *      $('#example').dataTable( {
9130
		 *        "data": [
9131
		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9132
		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9133
		 *        ],
9134
		 *        "columns": [
9135
		 *          { "title": "Engine" },
9136
		 *          { "title": "Browser" },
9137
		 *          { "title": "Platform" },
9138
		 *          { "title": "Version" },
9139
		 *          { "title": "Grade" }
9140
		 *        ]
9141
		 *      } );
9142
		 *    } );
9143
		 *
9144
		 *  @example
9145
		 *    // Using an array of objects as a data source (`data`)
9146
		 *    $(document).ready( function () {
9147
		 *      $('#example').dataTable( {
9148
		 *        "data": [
9149
		 *          {
9150
		 *            "engine":   "Trident",
9151
		 *            "browser":  "Internet Explorer 4.0",
9152
		 *            "platform": "Win 95+",
9153
		 *            "version":  4,
9154
		 *            "grade":    "X"
9155
		 *          },
9156
		 *          {
9157
		 *            "engine":   "Trident",
9158
		 *            "browser":  "Internet Explorer 5.0",
9159
		 *            "platform": "Win 95+",
9160
		 *            "version":  5,
9161
		 *            "grade":    "C"
9162
		 *          }
9163
		 *        ],
9164
		 *        "columns": [
9165
		 *          { "title": "Engine",   "data": "engine" },
9166
		 *          { "title": "Browser",  "data": "browser" },
9167
		 *          { "title": "Platform", "data": "platform" },
9168
		 *          { "title": "Version",  "data": "version" },
9169
		 *          { "title": "Grade",    "data": "grade" }
9170
		 *        ]
9171
		 *      } );
9172
		 *    } );
9173
		 */
9174
		"aaData": null,
9175
	
9176
	
9177
		/**
9178
		 * If ordering is enabled, then DataTables will perform a first pass sort on
9179
		 * initialisation. You can define which column(s) the sort is performed
9180
		 * upon, and the sorting direction, with this variable. The `sorting` array
9181
		 * should contain an array for each column to be sorted initially containing
9182
		 * the column's index and a direction string ('asc' or 'desc').
9183
		 *  @type array
9184
		 *  @default [[0,'asc']]
9185
		 *
9186
		 *  @dtopt Option
9187
		 *  @name DataTable.defaults.order
9188
		 *
9189
		 *  @example
9190
		 *    // Sort by 3rd column first, and then 4th column
9191
		 *    $(document).ready( function() {
9192
		 *      $('#example').dataTable( {
9193
		 *        "order": [[2,'asc'], [3,'desc']]
9194
		 *      } );
9195
		 *    } );
9196
		 *
9197
		 *    // No initial sorting
9198
		 *    $(document).ready( function() {
9199
		 *      $('#example').dataTable( {
9200
		 *        "order": []
9201
		 *      } );
9202
		 *    } );
9203
		 */
9204
		"aaSorting": [[0,'asc']],
9205
	
9206
	
9207
		/**
9208
		 * This parameter is basically identical to the `sorting` parameter, but
9209
		 * cannot be overridden by user interaction with the table. What this means
9210
		 * is that you could have a column (visible or hidden) which the sorting
9211
		 * will always be forced on first - any sorting after that (from the user)
9212
		 * will then be performed as required. This can be useful for grouping rows
9213
		 * together.
9214
		 *  @type array
9215
		 *  @default null
9216
		 *
9217
		 *  @dtopt Option
9218
		 *  @name DataTable.defaults.orderFixed
9219
		 *
9220
		 *  @example
9221
		 *    $(document).ready( function() {
9222
		 *      $('#example').dataTable( {
9223
		 *        "orderFixed": [[0,'asc']]
9224
		 *      } );
9225
		 *    } )
9226
		 */
9227
		"aaSortingFixed": [],
9228
	
9229
	
9230
		/**
9231
		 * DataTables can be instructed to load data to display in the table from a
9232
		 * Ajax source. This option defines how that Ajax call is made and where to.
9233
		 *
9234
		 * The `ajax` property has three different modes of operation, depending on
9235
		 * how it is defined. These are:
9236
		 *
9237
		 * * `string` - Set the URL from where the data should be loaded from.
9238
		 * * `object` - Define properties for `jQuery.ajax`.
9239
		 * * `function` - Custom data get function
9240
		 *
9241
		 * `string`
9242
		 * --------
9243
		 *
9244
		 * As a string, the `ajax` property simply defines the URL from which
9245
		 * DataTables will load data.
9246
		 *
9247
		 * `object`
9248
		 * --------
9249
		 *
9250
		 * As an object, the parameters in the object are passed to
9251
		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9252
		 * of the Ajax request. DataTables has a number of default parameters which
9253
		 * you can override using this option. Please refer to the jQuery
9254
		 * documentation for a full description of the options available, although
9255
		 * the following parameters provide additional options in DataTables or
9256
		 * require special consideration:
9257
		 *
9258
		 * * `data` - As with jQuery, `data` can be provided as an object, but it
9259
		 *   can also be used as a function to manipulate the data DataTables sends
9260
		 *   to the server. The function takes a single parameter, an object of
9261
		 *   parameters with the values that DataTables has readied for sending. An
9262
		 *   object may be returned which will be merged into the DataTables
9263
		 *   defaults, or you can add the items to the object that was passed in and
9264
		 *   not return anything from the function. This supersedes `fnServerParams`
9265
		 *   from DataTables 1.9-.
9266
		 *
9267
		 * * `dataSrc` - By default DataTables will look for the property `data` (or
9268
		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9269
		 *   from an Ajax source or for server-side processing - this parameter
9270
		 *   allows that property to be changed. You can use Javascript dotted
9271
		 *   object notation to get a data source for multiple levels of nesting, or
9272
		 *   it my be used as a function. As a function it takes a single parameter,
9273
		 *   the JSON returned from the server, which can be manipulated as
9274
		 *   required, with the returned value being that used by DataTables as the
9275
		 *   data source for the table. This supersedes `sAjaxDataProp` from
9276
		 *   DataTables 1.9-.
9277
		 *
9278
		 * * `success` - Should not be overridden it is used internally in
9279
		 *   DataTables. To manipulate / transform the data returned by the server
9280
		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9281
		 *
9282
		 * `function`
9283
		 * ----------
9284
		 *
9285
		 * As a function, making the Ajax call is left up to yourself allowing
9286
		 * complete control of the Ajax request. Indeed, if desired, a method other
9287
		 * than Ajax could be used to obtain the required data, such as Web storage
9288
		 * or an AIR database.
9289
		 *
9290
		 * The function is given four parameters and no return is required. The
9291
		 * parameters are:
9292
		 *
9293
		 * 1. _object_ - Data to send to the server
9294
		 * 2. _function_ - Callback function that must be executed when the required
9295
		 *    data has been obtained. That data should be passed into the callback
9296
		 *    as the only parameter
9297
		 * 3. _object_ - DataTables settings object for the table
9298
		 *
9299
		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
9300
		 *
9301
		 *  @type string|object|function
9302
		 *  @default null
9303
		 *
9304
		 *  @dtopt Option
9305
		 *  @name DataTable.defaults.ajax
9306
		 *  @since 1.10.0
9307
		 *
9308
		 * @example
9309
		 *   // Get JSON data from a file via Ajax.
9310
		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9311
		 *   $('#example').dataTable( {
9312
		 *     "ajax": "data.json"
9313
		 *   } );
9314
		 *
9315
		 * @example
9316
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
9317
		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9318
		 *   $('#example').dataTable( {
9319
		 *     "ajax": {
9320
		 *       "url": "data.json",
9321
		 *       "dataSrc": "tableData"
9322
		 *     }
9323
		 *   } );
9324
		 *
9325
		 * @example
9326
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
9327
		 *   // from a plain array rather than an array in an object
9328
		 *   $('#example').dataTable( {
9329
		 *     "ajax": {
9330
		 *       "url": "data.json",
9331
		 *       "dataSrc": ""
9332
		 *     }
9333
		 *   } );
9334
		 *
9335
		 * @example
9336
		 *   // Manipulate the data returned from the server - add a link to data
9337
		 *   // (note this can, should, be done using `render` for the column - this
9338
		 *   // is just a simple example of how the data can be manipulated).
9339
		 *   $('#example').dataTable( {
9340
		 *     "ajax": {
9341
		 *       "url": "data.json",
9342
		 *       "dataSrc": function ( json ) {
9343
		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9344
		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9345
		 *         }
9346
		 *         return json;
9347
		 *       }
9348
		 *     }
9349
		 *   } );
9350
		 *
9351
		 * @example
9352
		 *   // Add data to the request
9353
		 *   $('#example').dataTable( {
9354
		 *     "ajax": {
9355
		 *       "url": "data.json",
9356
		 *       "data": function ( d ) {
9357
		 *         return {
9358
		 *           "extra_search": $('#extra').val()
9359
		 *         };
9360
		 *       }
9361
		 *     }
9362
		 *   } );
9363
		 *
9364
		 * @example
9365
		 *   // Send request as POST
9366
		 *   $('#example').dataTable( {
9367
		 *     "ajax": {
9368
		 *       "url": "data.json",
9369
		 *       "type": "POST"
9370
		 *     }
9371
		 *   } );
9372
		 *
9373
		 * @example
9374
		 *   // Get the data from localStorage (could interface with a form for
9375
		 *   // adding, editing and removing rows).
9376
		 *   $('#example').dataTable( {
9377
		 *     "ajax": function (data, callback, settings) {
9378
		 *       callback(
9379
		 *         JSON.parse( localStorage.getItem('dataTablesData') )
9380
		 *       );
9381
		 *     }
9382
		 *   } );
9383
		 */
9384
		"ajax": null,
9385
	
9386
	
9387
		/**
9388
		 * This parameter allows you to readily specify the entries in the length drop
9389
		 * down menu that DataTables shows when pagination is enabled. It can be
9390
		 * either a 1D array of options which will be used for both the displayed
9391
		 * option and the value, or a 2D array which will use the array in the first
9392
		 * position as the value, and the array in the second position as the
9393
		 * displayed options (useful for language strings such as 'All').
9394
		 *
9395
		 * Note that the `pageLength` property will be automatically set to the
9396
		 * first value given in this array, unless `pageLength` is also provided.
9397
		 *  @type array
9398
		 *  @default [ 10, 25, 50, 100 ]
9399
		 *
9400
		 *  @dtopt Option
9401
		 *  @name DataTable.defaults.lengthMenu
9402
		 *
9403
		 *  @example
9404
		 *    $(document).ready( function() {
9405
		 *      $('#example').dataTable( {
9406
		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9407
		 *      } );
9408
		 *    } );
9409
		 */
9410
		"aLengthMenu": [ 10, 25, 50, 100 ],
9411
	
9412
	
9413
		/**
9414
		 * The `columns` option in the initialisation parameter allows you to define
9415
		 * details about the way individual columns behave. For a full list of
9416
		 * column options that can be set, please see
9417
		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
9418
		 * define your columns, you must have an entry in the array for every single
9419
		 * column that you have in your table (these can be null if you don't which
9420
		 * to specify any options).
9421
		 *  @member
9422
		 *
9423
		 *  @name DataTable.defaults.column
9424
		 */
9425
		"aoColumns": null,
9426
	
9427
		/**
9428
		 * Very similar to `columns`, `columnDefs` allows you to target a specific
9429
		 * column, multiple columns, or all columns, using the `targets` property of
9430
		 * each object in the array. This allows great flexibility when creating
9431
		 * tables, as the `columnDefs` arrays can be of any length, targeting the
9432
		 * columns you specifically want. `columnDefs` may use any of the column
9433
		 * options available: {@link DataTable.defaults.column}, but it _must_
9434
		 * have `targets` defined in each object in the array. Values in the `targets`
9435
		 * array may be:
9436
		 *   <ul>
9437
		 *     <li>a string - class name will be matched on the TH for the column</li>
9438
		 *     <li>0 or a positive integer - column index counting from the left</li>
9439
		 *     <li>a negative integer - column index counting from the right</li>
9440
		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
9441
		 *   </ul>
9442
		 *  @member
9443
		 *
9444
		 *  @name DataTable.defaults.columnDefs
9445
		 */
9446
		"aoColumnDefs": null,
9447
	
9448
	
9449
		/**
9450
		 * Basically the same as `search`, this parameter defines the individual column
9451
		 * filtering state at initialisation time. The array must be of the same size
9452
		 * as the number of columns, and each element be an object with the parameters
9453
		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
9454
		 * accepted and the default will be used.
9455
		 *  @type array
9456
		 *  @default []
9457
		 *
9458
		 *  @dtopt Option
9459
		 *  @name DataTable.defaults.searchCols
9460
		 *
9461
		 *  @example
9462
		 *    $(document).ready( function() {
9463
		 *      $('#example').dataTable( {
9464
		 *        "searchCols": [
9465
		 *          null,
9466
		 *          { "search": "My filter" },
9467
		 *          null,
9468
		 *          { "search": "^[0-9]", "escapeRegex": false }
9469
		 *        ]
9470
		 *      } );
9471
		 *    } )
9472
		 */
9473
		"aoSearchCols": [],
9474
	
9475
	
9476
		/**
9477
		 * An array of CSS classes that should be applied to displayed rows. This
9478
		 * array may be of any length, and DataTables will apply each class
9479
		 * sequentially, looping when required.
9480
		 *  @type array
9481
		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
9482
		 *    options</i>
9483
		 *
9484
		 *  @dtopt Option
9485
		 *  @name DataTable.defaults.stripeClasses
9486
		 *
9487
		 *  @example
9488
		 *    $(document).ready( function() {
9489
		 *      $('#example').dataTable( {
9490
		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
9491
		 *      } );
9492
		 *    } )
9493
		 */
9494
		"asStripeClasses": null,
9495
	
9496
	
9497
		/**
9498
		 * Enable or disable automatic column width calculation. This can be disabled
9499
		 * as an optimisation (it takes some time to calculate the widths) if the
9500
		 * tables widths are passed in using `columns`.
9501
		 *  @type boolean
9502
		 *  @default true
9503
		 *
9504
		 *  @dtopt Features
9505
		 *  @name DataTable.defaults.autoWidth
9506
		 *
9507
		 *  @example
9508
		 *    $(document).ready( function () {
9509
		 *      $('#example').dataTable( {
9510
		 *        "autoWidth": false
9511
		 *      } );
9512
		 *    } );
9513
		 */
9514
		"bAutoWidth": true,
9515
	
9516
	
9517
		/**
9518
		 * Deferred rendering can provide DataTables with a huge speed boost when you
9519
		 * are using an Ajax or JS data source for the table. This option, when set to
9520
		 * true, will cause DataTables to defer the creation of the table elements for
9521
		 * each row until they are needed for a draw - saving a significant amount of
9522
		 * time.
9523
		 *  @type boolean
9524
		 *  @default false
9525
		 *
9526
		 *  @dtopt Features
9527
		 *  @name DataTable.defaults.deferRender
9528
		 *
9529
		 *  @example
9530
		 *    $(document).ready( function() {
9531
		 *      $('#example').dataTable( {
9532
		 *        "ajax": "sources/arrays.txt",
9533
		 *        "deferRender": true
9534
		 *      } );
9535
		 *    } );
9536
		 */
9537
		"bDeferRender": false,
9538
	
9539
	
9540
		/**
9541
		 * Replace a DataTable which matches the given selector and replace it with
9542
		 * one which has the properties of the new initialisation object passed. If no
9543
		 * table matches the selector, then the new DataTable will be constructed as
9544
		 * per normal.
9545
		 *  @type boolean
9546
		 *  @default false
9547
		 *
9548
		 *  @dtopt Options
9549
		 *  @name DataTable.defaults.destroy
9550
		 *
9551
		 *  @example
9552
		 *    $(document).ready( function() {
9553
		 *      $('#example').dataTable( {
9554
		 *        "srollY": "200px",
9555
		 *        "paginate": false
9556
		 *      } );
9557
		 *
9558
		 *      // Some time later....
9559
		 *      $('#example').dataTable( {
9560
		 *        "filter": false,
9561
		 *        "destroy": true
9562
		 *      } );
9563
		 *    } );
9564
		 */
9565
		"bDestroy": false,
9566
	
9567
	
9568
		/**
9569
		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
9570
		 * that it allows the end user to input multiple words (space separated) and
9571
		 * will match a row containing those words, even if not in the order that was
9572
		 * specified (this allow matching across multiple columns). Note that if you
9573
		 * wish to use filtering in DataTables this must remain 'true' - to remove the
9574
		 * default filtering input box and retain filtering abilities, please use
9575
		 * {@link DataTable.defaults.dom}.
9576
		 *  @type boolean
9577
		 *  @default true
9578
		 *
9579
		 *  @dtopt Features
9580
		 *  @name DataTable.defaults.searching
9581
		 *
9582
		 *  @example
9583
		 *    $(document).ready( function () {
9584
		 *      $('#example').dataTable( {
9585
		 *        "searching": false
9586
		 *      } );
9587
		 *    } );
9588
		 */
9589
		"bFilter": true,
9590
	
9591
	
9592
		/**
9593
		 * Enable or disable the table information display. This shows information
9594
		 * about the data that is currently visible on the page, including information
9595
		 * about filtered data if that action is being performed.
9596
		 *  @type boolean
9597
		 *  @default true
9598
		 *
9599
		 *  @dtopt Features
9600
		 *  @name DataTable.defaults.info
9601
		 *
9602
		 *  @example
9603
		 *    $(document).ready( function () {
9604
		 *      $('#example').dataTable( {
9605
		 *        "info": false
9606
		 *      } );
9607
		 *    } );
9608
		 */
9609
		"bInfo": true,
9610
	
9611
	
9612
		/**
9613
		 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
9614
		 * slightly different and additional mark-up from what DataTables has
9615
		 * traditionally used).
9616
		 *  @type boolean
9617
		 *  @default false
9618
		 *
9619
		 *  @dtopt Features
9620
		 *  @name DataTable.defaults.jQueryUI
9621
		 *
9622
		 *  @example
9623
		 *    $(document).ready( function() {
9624
		 *      $('#example').dataTable( {
9625
		 *        "jQueryUI": true
9626
		 *      } );
9627
		 *    } );
9628
		 */
9629
		"bJQueryUI": false,
9630
	
9631
	
9632
		/**
9633
		 * Allows the end user to select the size of a formatted page from a select
9634
		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
9635
		 *  @type boolean
9636
		 *  @default true
9637
		 *
9638
		 *  @dtopt Features
9639
		 *  @name DataTable.defaults.lengthChange
9640
		 *
9641
		 *  @example
9642
		 *    $(document).ready( function () {
9643
		 *      $('#example').dataTable( {
9644
		 *        "lengthChange": false
9645
		 *      } );
9646
		 *    } );
9647
		 */
9648
		"bLengthChange": true,
9649
	
9650
	
9651
		/**
9652
		 * Enable or disable pagination.
9653
		 *  @type boolean
9654
		 *  @default true
9655
		 *
9656
		 *  @dtopt Features
9657
		 *  @name DataTable.defaults.paging
9658
		 *
9659
		 *  @example
9660
		 *    $(document).ready( function () {
9661
		 *      $('#example').dataTable( {
9662
		 *        "paging": false
9663
		 *      } );
9664
		 *    } );
9665
		 */
9666
		"bPaginate": true,
9667
	
9668
	
9669
		/**
9670
		 * Enable or disable the display of a 'processing' indicator when the table is
9671
		 * being processed (e.g. a sort). This is particularly useful for tables with
9672
		 * large amounts of data where it can take a noticeable amount of time to sort
9673
		 * the entries.
9674
		 *  @type boolean
9675
		 *  @default false
9676
		 *
9677
		 *  @dtopt Features
9678
		 *  @name DataTable.defaults.processing
9679
		 *
9680
		 *  @example
9681
		 *    $(document).ready( function () {
9682
		 *      $('#example').dataTable( {
9683
		 *        "processing": true
9684
		 *      } );
9685
		 *    } );
9686
		 */
9687
		"bProcessing": false,
9688
	
9689
	
9690
		/**
9691
		 * Retrieve the DataTables object for the given selector. Note that if the
9692
		 * table has already been initialised, this parameter will cause DataTables
9693
		 * to simply return the object that has already been set up - it will not take
9694
		 * account of any changes you might have made to the initialisation object
9695
		 * passed to DataTables (setting this parameter to true is an acknowledgement
9696
		 * that you understand this). `destroy` can be used to reinitialise a table if
9697
		 * you need.
9698
		 *  @type boolean
9699
		 *  @default false
9700
		 *
9701
		 *  @dtopt Options
9702
		 *  @name DataTable.defaults.retrieve
9703
		 *
9704
		 *  @example
9705
		 *    $(document).ready( function() {
9706
		 *      initTable();
9707
		 *      tableActions();
9708
		 *    } );
9709
		 *
9710
		 *    function initTable ()
9711
		 *    {
9712
		 *      return $('#example').dataTable( {
9713
		 *        "scrollY": "200px",
9714
		 *        "paginate": false,
9715
		 *        "retrieve": true
9716
		 *      } );
9717
		 *    }
9718
		 *
9719
		 *    function tableActions ()
9720
		 *    {
9721
		 *      var table = initTable();
9722
		 *      // perform API operations with oTable
9723
		 *    }
9724
		 */
9725
		"bRetrieve": false,
9726
	
9727
	
9728
		/**
9729
		 * When vertical (y) scrolling is enabled, DataTables will force the height of
9730
		 * the table's viewport to the given height at all times (useful for layout).
9731
		 * However, this can look odd when filtering data down to a small data set,
9732
		 * and the footer is left "floating" further down. This parameter (when
9733
		 * enabled) will cause DataTables to collapse the table's viewport down when
9734
		 * the result set will fit within the given Y height.
9735
		 *  @type boolean
9736
		 *  @default false
9737
		 *
9738
		 *  @dtopt Options
9739
		 *  @name DataTable.defaults.scrollCollapse
9740
		 *
9741
		 *  @example
9742
		 *    $(document).ready( function() {
9743
		 *      $('#example').dataTable( {
9744
		 *        "scrollY": "200",
9745
		 *        "scrollCollapse": true
9746
		 *      } );
9747
		 *    } );
9748
		 */
9749
		"bScrollCollapse": false,
9750
	
9751
	
9752
		/**
9753
		 * Configure DataTables to use server-side processing. Note that the
9754
		 * `ajax` parameter must also be given in order to give DataTables a
9755
		 * source to obtain the required data for each draw.
9756
		 *  @type boolean
9757
		 *  @default false
9758
		 *
9759
		 *  @dtopt Features
9760
		 *  @dtopt Server-side
9761
		 *  @name DataTable.defaults.serverSide
9762
		 *
9763
		 *  @example
9764
		 *    $(document).ready( function () {
9765
		 *      $('#example').dataTable( {
9766
		 *        "serverSide": true,
9767
		 *        "ajax": "xhr.php"
9768
		 *      } );
9769
		 *    } );
9770
		 */
9771
		"bServerSide": false,
9772
	
9773
	
9774
		/**
9775
		 * Enable or disable sorting of columns. Sorting of individual columns can be
9776
		 * disabled by the `sortable` option for each column.
9777
		 *  @type boolean
9778
		 *  @default true
9779
		 *
9780
		 *  @dtopt Features
9781
		 *  @name DataTable.defaults.ordering
9782
		 *
9783
		 *  @example
9784
		 *    $(document).ready( function () {
9785
		 *      $('#example').dataTable( {
9786
		 *        "ordering": false
9787
		 *      } );
9788
		 *    } );
9789
		 */
9790
		"bSort": true,
9791
	
9792
	
9793
		/**
9794
		 * Enable or display DataTables' ability to sort multiple columns at the
9795
		 * same time (activated by shift-click by the user).
9796
		 *  @type boolean
9797
		 *  @default true
9798
		 *
9799
		 *  @dtopt Options
9800
		 *  @name DataTable.defaults.orderMulti
9801
		 *
9802
		 *  @example
9803
		 *    // Disable multiple column sorting ability
9804
		 *    $(document).ready( function () {
9805
		 *      $('#example').dataTable( {
9806
		 *        "orderMulti": false
9807
		 *      } );
9808
		 *    } );
9809
		 */
9810
		"bSortMulti": true,
9811
	
9812
	
9813
		/**
9814
		 * Allows control over whether DataTables should use the top (true) unique
9815
		 * cell that is found for a single column, or the bottom (false - default).
9816
		 * This is useful when using complex headers.
9817
		 *  @type boolean
9818
		 *  @default false
9819
		 *
9820
		 *  @dtopt Options
9821
		 *  @name DataTable.defaults.orderCellsTop
9822
		 *
9823
		 *  @example
9824
		 *    $(document).ready( function() {
9825
		 *      $('#example').dataTable( {
9826
		 *        "orderCellsTop": true
9827
		 *      } );
9828
		 *    } );
9829
		 */
9830
		"bSortCellsTop": false,
9831
	
9832
	
9833
		/**
9834
		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
9835
		 * `sorting\_3` to the columns which are currently being sorted on. This is
9836
		 * presented as a feature switch as it can increase processing time (while
9837
		 * classes are removed and added) so for large data sets you might want to
9838
		 * turn this off.
9839
		 *  @type boolean
9840
		 *  @default true
9841
		 *
9842
		 *  @dtopt Features
9843
		 *  @name DataTable.defaults.orderClasses
9844
		 *
9845
		 *  @example
9846
		 *    $(document).ready( function () {
9847
		 *      $('#example').dataTable( {
9848
		 *        "orderClasses": false
9849
		 *      } );
9850
		 *    } );
9851
		 */
9852
		"bSortClasses": true,
9853
	
9854
	
9855
		/**
9856
		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
9857
		 * used to save table display information such as pagination information,
9858
		 * display length, filtering and sorting. As such when the end user reloads
9859
		 * the page the display display will match what thy had previously set up.
9860
		 *
9861
		 * Due to the use of `localStorage` the default state saving is not supported
9862
		 * in IE6 or 7. If state saving is required in those browsers, use
9863
		 * `stateSaveCallback` to provide a storage solution such as cookies.
9864
		 *  @type boolean
9865
		 *  @default false
9866
		 *
9867
		 *  @dtopt Features
9868
		 *  @name DataTable.defaults.stateSave
9869
		 *
9870
		 *  @example
9871
		 *    $(document).ready( function () {
9872
		 *      $('#example').dataTable( {
9873
		 *        "stateSave": true
9874
		 *      } );
9875
		 *    } );
9876
		 */
9877
		"bStateSave": false,
9878
	
9879
	
9880
		/**
9881
		 * This function is called when a TR element is created (and all TD child
9882
		 * elements have been inserted), or registered if using a DOM source, allowing
9883
		 * manipulation of the TR element (adding classes etc).
9884
		 *  @type function
9885
		 *  @param {node} row "TR" element for the current row
9886
		 *  @param {array} data Raw data array for this row
9887
		 *  @param {int} dataIndex The index of this row in the internal aoData array
9888
		 *
9889
		 *  @dtopt Callbacks
9890
		 *  @name DataTable.defaults.createdRow
9891
		 *
9892
		 *  @example
9893
		 *    $(document).ready( function() {
9894
		 *      $('#example').dataTable( {
9895
		 *        "createdRow": function( row, data, dataIndex ) {
9896
		 *          // Bold the grade for all 'A' grade browsers
9897
		 *          if ( data[4] == "A" )
9898
		 *          {
9899
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
9900
		 *          }
9901
		 *        }
9902
		 *      } );
9903
		 *    } );
9904
		 */
9905
		"fnCreatedRow": null,
9906
	
9907
	
9908
		/**
9909
		 * This function is called on every 'draw' event, and allows you to
9910
		 * dynamically modify any aspect you want about the created DOM.
9911
		 *  @type function
9912
		 *  @param {object} settings DataTables settings object
9913
		 *
9914
		 *  @dtopt Callbacks
9915
		 *  @name DataTable.defaults.drawCallback
9916
		 *
9917
		 *  @example
9918
		 *    $(document).ready( function() {
9919
		 *      $('#example').dataTable( {
9920
		 *        "drawCallback": function( settings ) {
9921
		 *          alert( 'DataTables has redrawn the table' );
9922
		 *        }
9923
		 *      } );
9924
		 *    } );
9925
		 */
9926
		"fnDrawCallback": null,
9927
	
9928
	
9929
		/**
9930
		 * Identical to fnHeaderCallback() but for the table footer this function
9931
		 * allows you to modify the table footer on every 'draw' event.
9932
		 *  @type function
9933
		 *  @param {node} foot "TR" element for the footer
9934
		 *  @param {array} data Full table data (as derived from the original HTML)
9935
		 *  @param {int} start Index for the current display starting point in the
9936
		 *    display array
9937
		 *  @param {int} end Index for the current display ending point in the
9938
		 *    display array
9939
		 *  @param {array int} display Index array to translate the visual position
9940
		 *    to the full data array
9941
		 *
9942
		 *  @dtopt Callbacks
9943
		 *  @name DataTable.defaults.footerCallback
9944
		 *
9945
		 *  @example
9946
		 *    $(document).ready( function() {
9947
		 *      $('#example').dataTable( {
9948
		 *        "footerCallback": function( tfoot, data, start, end, display ) {
9949
		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
9950
		 *        }
9951
		 *      } );
9952
		 *    } )
9953
		 */
9954
		"fnFooterCallback": null,
9955
	
9956
	
9957
		/**
9958
		 * When rendering large numbers in the information element for the table
9959
		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
9960
		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
9961
		 * rendered as "1,000,000") to help readability for the end user. This
9962
		 * function will override the default method DataTables uses.
9963
		 *  @type function
9964
		 *  @member
9965
		 *  @param {int} toFormat number to be formatted
9966
		 *  @returns {string} formatted string for DataTables to show the number
9967
		 *
9968
		 *  @dtopt Callbacks
9969
		 *  @name DataTable.defaults.formatNumber
9970
		 *
9971
		 *  @example
9972
		 *    // Format a number using a single quote for the separator (note that
9973
		 *    // this can also be done with the language.thousands option)
9974
		 *    $(document).ready( function() {
9975
		 *      $('#example').dataTable( {
9976
		 *        "formatNumber": function ( toFormat ) {
9977
		 *          return toFormat.toString().replace(
9978
		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
9979
		 *          );
9980
		 *        };
9981
		 *      } );
9982
		 *    } );
9983
		 */
9984
		"fnFormatNumber": function ( toFormat ) {
9985
			return toFormat.toString().replace(
9986
				/\B(?=(\d{3})+(?!\d))/g,
9987
				this.oLanguage.sThousands
9988
			);
9989
		},
9990
	
9991
	
9992
		/**
9993
		 * This function is called on every 'draw' event, and allows you to
9994
		 * dynamically modify the header row. This can be used to calculate and
9995
		 * display useful information about the table.
9996
		 *  @type function
9997
		 *  @param {node} head "TR" element for the header
9998
		 *  @param {array} data Full table data (as derived from the original HTML)
9999
		 *  @param {int} start Index for the current display starting point in the
10000
		 *    display array
10001
		 *  @param {int} end Index for the current display ending point in the
10002
		 *    display array
10003
		 *  @param {array int} display Index array to translate the visual position
10004
		 *    to the full data array
10005
		 *
10006
		 *  @dtopt Callbacks
10007
		 *  @name DataTable.defaults.headerCallback
10008
		 *
10009
		 *  @example
10010
		 *    $(document).ready( function() {
10011
		 *      $('#example').dataTable( {
10012
		 *        "fheaderCallback": function( head, data, start, end, display ) {
10013
		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10014
		 *        }
10015
		 *      } );
10016
		 *    } )
10017
		 */
10018
		"fnHeaderCallback": null,
10019
	
10020
	
10021
		/**
10022
		 * The information element can be used to convey information about the current
10023
		 * state of the table. Although the internationalisation options presented by
10024
		 * DataTables are quite capable of dealing with most customisations, there may
10025
		 * be times where you wish to customise the string further. This callback
10026
		 * allows you to do exactly that.
10027
		 *  @type function
10028
		 *  @param {object} oSettings DataTables settings object
10029
		 *  @param {int} start Starting position in data for the draw
10030
		 *  @param {int} end End position in data for the draw
10031
		 *  @param {int} max Total number of rows in the table (regardless of
10032
		 *    filtering)
10033
		 *  @param {int} total Total number of rows in the data set, after filtering
10034
		 *  @param {string} pre The string that DataTables has formatted using it's
10035
		 *    own rules
10036
		 *  @returns {string} The string to be displayed in the information element.
10037
		 *
10038
		 *  @dtopt Callbacks
10039
		 *  @name DataTable.defaults.infoCallback
10040
		 *
10041
		 *  @example
10042
		 *    $('#example').dataTable( {
10043
		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10044
		 *        return start +" to "+ end;
10045
		 *      }
10046
		 *    } );
10047
		 */
10048
		"fnInfoCallback": null,
10049
	
10050
	
10051
		/**
10052
		 * Called when the table has been initialised. Normally DataTables will
10053
		 * initialise sequentially and there will be no need for this function,
10054
		 * however, this does not hold true when using external language information
10055
		 * since that is obtained using an async XHR call.
10056
		 *  @type function
10057
		 *  @param {object} settings DataTables settings object
10058
		 *  @param {object} json The JSON object request from the server - only
10059
		 *    present if client-side Ajax sourced data is used
10060
		 *
10061
		 *  @dtopt Callbacks
10062
		 *  @name DataTable.defaults.initComplete
10063
		 *
10064
		 *  @example
10065
		 *    $(document).ready( function() {
10066
		 *      $('#example').dataTable( {
10067
		 *        "initComplete": function(settings, json) {
10068
		 *          alert( 'DataTables has finished its initialisation.' );
10069
		 *        }
10070
		 *      } );
10071
		 *    } )
10072
		 */
10073
		"fnInitComplete": null,
10074
	
10075
	
10076
		/**
10077
		 * Called at the very start of each table draw and can be used to cancel the
10078
		 * draw by returning false, any other return (including undefined) results in
10079
		 * the full draw occurring).
10080
		 *  @type function
10081
		 *  @param {object} settings DataTables settings object
10082
		 *  @returns {boolean} False will cancel the draw, anything else (including no
10083
		 *    return) will allow it to complete.
10084
		 *
10085
		 *  @dtopt Callbacks
10086
		 *  @name DataTable.defaults.preDrawCallback
10087
		 *
10088
		 *  @example
10089
		 *    $(document).ready( function() {
10090
		 *      $('#example').dataTable( {
10091
		 *        "preDrawCallback": function( settings ) {
10092
		 *          if ( $('#test').val() == 1 ) {
10093
		 *            return false;
10094
		 *          }
10095
		 *        }
10096
		 *      } );
10097
		 *    } );
10098
		 */
10099
		"fnPreDrawCallback": null,
10100
	
10101
	
10102
		/**
10103
		 * This function allows you to 'post process' each row after it have been
10104
		 * generated for each table draw, but before it is rendered on screen. This
10105
		 * function might be used for setting the row class name etc.
10106
		 *  @type function
10107
		 *  @param {node} row "TR" element for the current row
10108
		 *  @param {array} data Raw data array for this row
10109
		 *  @param {int} displayIndex The display index for the current table draw
10110
		 *  @param {int} displayIndexFull The index of the data in the full list of
10111
		 *    rows (after filtering)
10112
		 *
10113
		 *  @dtopt Callbacks
10114
		 *  @name DataTable.defaults.rowCallback
10115
		 *
10116
		 *  @example
10117
		 *    $(document).ready( function() {
10118
		 *      $('#example').dataTable( {
10119
		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10120
		 *          // Bold the grade for all 'A' grade browsers
10121
		 *          if ( data[4] == "A" ) {
10122
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10123
		 *          }
10124
		 *        }
10125
		 *      } );
10126
		 *    } );
10127
		 */
10128
		"fnRowCallback": null,
10129
	
10130
	
10131
		/**
10132
		 * __Deprecated__ The functionality provided by this parameter has now been
10133
		 * superseded by that provided through `ajax`, which should be used instead.
10134
		 *
10135
		 * This parameter allows you to override the default function which obtains
10136
		 * the data from the server so something more suitable for your application.
10137
		 * For example you could use POST data, or pull information from a Gears or
10138
		 * AIR database.
10139
		 *  @type function
10140
		 *  @member
10141
		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10142
		 *  @param {array} data A key/value pair object containing the data to send
10143
		 *    to the server
10144
		 *  @param {function} callback to be called on completion of the data get
10145
		 *    process that will draw the data on the page.
10146
		 *  @param {object} settings DataTables settings object
10147
		 *
10148
		 *  @dtopt Callbacks
10149
		 *  @dtopt Server-side
10150
		 *  @name DataTable.defaults.serverData
10151
		 *
10152
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10153
		 */
10154
		"fnServerData": null,
10155
	
10156
	
10157
		/**
10158
		 * __Deprecated__ The functionality provided by this parameter has now been
10159
		 * superseded by that provided through `ajax`, which should be used instead.
10160
		 *
10161
		 *  It is often useful to send extra data to the server when making an Ajax
10162
		 * request - for example custom filtering information, and this callback
10163
		 * function makes it trivial to send extra information to the server. The
10164
		 * passed in parameter is the data set that has been constructed by
10165
		 * DataTables, and you can add to this or modify it as you require.
10166
		 *  @type function
10167
		 *  @param {array} data Data array (array of objects which are name/value
10168
		 *    pairs) that has been constructed by DataTables and will be sent to the
10169
		 *    server. In the case of Ajax sourced data with server-side processing
10170
		 *    this will be an empty array, for server-side processing there will be a
10171
		 *    significant number of parameters!
10172
		 *  @returns {undefined} Ensure that you modify the data array passed in,
10173
		 *    as this is passed by reference.
10174
		 *
10175
		 *  @dtopt Callbacks
10176
		 *  @dtopt Server-side
10177
		 *  @name DataTable.defaults.serverParams
10178
		 *
10179
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10180
		 */
10181
		"fnServerParams": null,
10182
	
10183
	
10184
		/**
10185
		 * Load the table state. With this function you can define from where, and how, the
10186
		 * state of a table is loaded. By default DataTables will load from `localStorage`
10187
		 * but you might wish to use a server-side database or cookies.
10188
		 *  @type function
10189
		 *  @member
10190
		 *  @param {object} settings DataTables settings object
10191
		 *  @return {object} The DataTables state object to be loaded
10192
		 *
10193
		 *  @dtopt Callbacks
10194
		 *  @name DataTable.defaults.stateLoadCallback
10195
		 *
10196
		 *  @example
10197
		 *    $(document).ready( function() {
10198
		 *      $('#example').dataTable( {
10199
		 *        "stateSave": true,
10200
		 *        "stateLoadCallback": function (settings) {
10201
		 *          var o;
10202
		 *
10203
		 *          // Send an Ajax request to the server to get the data. Note that
10204
		 *          // this is a synchronous request.
10205
		 *          $.ajax( {
10206
		 *            "url": "/state_load",
10207
		 *            "async": false,
10208
		 *            "dataType": "json",
10209
		 *            "success": function (json) {
10210
		 *              o = json;
10211
		 *            }
10212
		 *          } );
10213
		 *
10214
		 *          return o;
10215
		 *        }
10216
		 *      } );
10217
		 *    } );
10218
		 */
10219
		"fnStateLoadCallback": function ( settings ) {
10220
			try {
10221
				return JSON.parse(
10222
					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10223
						'DataTables_'+settings.sInstance+'_'+location.pathname
10224
					)
10225
				);
10226
			} catch (e) {}
10227
		},
10228
	
10229
	
10230
		/**
10231
		 * Callback which allows modification of the saved state prior to loading that state.
10232
		 * This callback is called when the table is loading state from the stored data, but
10233
		 * prior to the settings object being modified by the saved state. Note that for
10234
		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10235
		 * a plug-in.
10236
		 *  @type function
10237
		 *  @param {object} settings DataTables settings object
10238
		 *  @param {object} data The state object that is to be loaded
10239
		 *
10240
		 *  @dtopt Callbacks
10241
		 *  @name DataTable.defaults.stateLoadParams
10242
		 *
10243
		 *  @example
10244
		 *    // Remove a saved filter, so filtering is never loaded
10245
		 *    $(document).ready( function() {
10246
		 *      $('#example').dataTable( {
10247
		 *        "stateSave": true,
10248
		 *        "stateLoadParams": function (settings, data) {
10249
		 *          data.oSearch.sSearch = "";
10250
		 *        }
10251
		 *      } );
10252
		 *    } );
10253
		 *
10254
		 *  @example
10255
		 *    // Disallow state loading by returning false
10256
		 *    $(document).ready( function() {
10257
		 *      $('#example').dataTable( {
10258
		 *        "stateSave": true,
10259
		 *        "stateLoadParams": function (settings, data) {
10260
		 *          return false;
10261
		 *        }
10262
		 *      } );
10263
		 *    } );
10264
		 */
10265
		"fnStateLoadParams": null,
10266
	
10267
	
10268
		/**
10269
		 * Callback that is called when the state has been loaded from the state saving method
10270
		 * and the DataTables settings object has been modified as a result of the loaded state.
10271
		 *  @type function
10272
		 *  @param {object} settings DataTables settings object
10273
		 *  @param {object} data The state object that was loaded
10274
		 *
10275
		 *  @dtopt Callbacks
10276
		 *  @name DataTable.defaults.stateLoaded
10277
		 *
10278
		 *  @example
10279
		 *    // Show an alert with the filtering value that was saved
10280
		 *    $(document).ready( function() {
10281
		 *      $('#example').dataTable( {
10282
		 *        "stateSave": true,
10283
		 *        "stateLoaded": function (settings, data) {
10284
		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10285
		 *        }
10286
		 *      } );
10287
		 *    } );
10288
		 */
10289
		"fnStateLoaded": null,
10290
	
10291
	
10292
		/**
10293
		 * Save the table state. This function allows you to define where and how the state
10294
		 * information for the table is stored By default DataTables will use `localStorage`
10295
		 * but you might wish to use a server-side database or cookies.
10296
		 *  @type function
10297
		 *  @member
10298
		 *  @param {object} settings DataTables settings object
10299
		 *  @param {object} data The state object to be saved
10300
		 *
10301
		 *  @dtopt Callbacks
10302
		 *  @name DataTable.defaults.stateSaveCallback
10303
		 *
10304
		 *  @example
10305
		 *    $(document).ready( function() {
10306
		 *      $('#example').dataTable( {
10307
		 *        "stateSave": true,
10308
		 *        "stateSaveCallback": function (settings, data) {
10309
		 *          // Send an Ajax request to the server with the state object
10310
		 *          $.ajax( {
10311
		 *            "url": "/state_save",
10312
		 *            "data": data,
10313
		 *            "dataType": "json",
10314
		 *            "method": "POST"
10315
		 *            "success": function () {}
10316
		 *          } );
10317
		 *        }
10318
		 *      } );
10319
		 *    } );
10320
		 */
10321
		"fnStateSaveCallback": function ( settings, data ) {
10322
			try {
10323
				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
10324
					'DataTables_'+settings.sInstance+'_'+location.pathname,
10325
					JSON.stringify( data )
10326
				);
10327
			} catch (e) {}
10328
		},
10329
	
10330
	
10331
		/**
10332
		 * Callback which allows modification of the state to be saved. Called when the table
10333
		 * has changed state a new state save is required. This method allows modification of
10334
		 * the state saving object prior to actually doing the save, including addition or
10335
		 * other state properties or modification. Note that for plug-in authors, you should
10336
		 * use the `stateSaveParams` event to save parameters for a plug-in.
10337
		 *  @type function
10338
		 *  @param {object} settings DataTables settings object
10339
		 *  @param {object} data The state object to be saved
10340
		 *
10341
		 *  @dtopt Callbacks
10342
		 *  @name DataTable.defaults.stateSaveParams
10343
		 *
10344
		 *  @example
10345
		 *    // Remove a saved filter, so filtering is never saved
10346
		 *    $(document).ready( function() {
10347
		 *      $('#example').dataTable( {
10348
		 *        "stateSave": true,
10349
		 *        "stateSaveParams": function (settings, data) {
10350
		 *          data.oSearch.sSearch = "";
10351
		 *        }
10352
		 *      } );
10353
		 *    } );
10354
		 */
10355
		"fnStateSaveParams": null,
10356
	
10357
	
10358
		/**
10359
		 * Duration for which the saved state information is considered valid. After this period
10360
		 * has elapsed the state will be returned to the default.
10361
		 * Value is given in seconds.
10362
		 *  @type int
10363
		 *  @default 7200 <i>(2 hours)</i>
10364
		 *
10365
		 *  @dtopt Options
10366
		 *  @name DataTable.defaults.stateDuration
10367
		 *
10368
		 *  @example
10369
		 *    $(document).ready( function() {
10370
		 *      $('#example').dataTable( {
10371
		 *        "stateDuration": 60*60*24; // 1 day
10372
		 *      } );
10373
		 *    } )
10374
		 */
10375
		"iStateDuration": 7200,
10376
	
10377
	
10378
		/**
10379
		 * When enabled DataTables will not make a request to the server for the first
10380
		 * page draw - rather it will use the data already on the page (no sorting etc
10381
		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10382
		 * is used to indicate that deferred loading is required, but it is also used
10383
		 * to tell DataTables how many records there are in the full table (allowing
10384
		 * the information element and pagination to be displayed correctly). In the case
10385
		 * where a filtering is applied to the table on initial load, this can be
10386
		 * indicated by giving the parameter as an array, where the first element is
10387
		 * the number of records available after filtering and the second element is the
10388
		 * number of records without filtering (allowing the table information element
10389
		 * to be shown correctly).
10390
		 *  @type int | array
10391
		 *  @default null
10392
		 *
10393
		 *  @dtopt Options
10394
		 *  @name DataTable.defaults.deferLoading
10395
		 *
10396
		 *  @example
10397
		 *    // 57 records available in the table, no filtering applied
10398
		 *    $(document).ready( function() {
10399
		 *      $('#example').dataTable( {
10400
		 *        "serverSide": true,
10401
		 *        "ajax": "scripts/server_processing.php",
10402
		 *        "deferLoading": 57
10403
		 *      } );
10404
		 *    } );
10405
		 *
10406
		 *  @example
10407
		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
10408
		 *    $(document).ready( function() {
10409
		 *      $('#example').dataTable( {
10410
		 *        "serverSide": true,
10411
		 *        "ajax": "scripts/server_processing.php",
10412
		 *        "deferLoading": [ 57, 100 ],
10413
		 *        "search": {
10414
		 *          "search": "my_filter"
10415
		 *        }
10416
		 *      } );
10417
		 *    } );
10418
		 */
10419
		"iDeferLoading": null,
10420
	
10421
	
10422
		/**
10423
		 * Number of rows to display on a single page when using pagination. If
10424
		 * feature enabled (`lengthChange`) then the end user will be able to override
10425
		 * this to a custom setting using a pop-up menu.
10426
		 *  @type int
10427
		 *  @default 10
10428
		 *
10429
		 *  @dtopt Options
10430
		 *  @name DataTable.defaults.pageLength
10431
		 *
10432
		 *  @example
10433
		 *    $(document).ready( function() {
10434
		 *      $('#example').dataTable( {
10435
		 *        "pageLength": 50
10436
		 *      } );
10437
		 *    } )
10438
		 */
10439
		"iDisplayLength": 10,
10440
	
10441
	
10442
		/**
10443
		 * Define the starting point for data display when using DataTables with
10444
		 * pagination. Note that this parameter is the number of records, rather than
10445
		 * the page number, so if you have 10 records per page and want to start on
10446
		 * the third page, it should be "20".
10447
		 *  @type int
10448
		 *  @default 0
10449
		 *
10450
		 *  @dtopt Options
10451
		 *  @name DataTable.defaults.displayStart
10452
		 *
10453
		 *  @example
10454
		 *    $(document).ready( function() {
10455
		 *      $('#example').dataTable( {
10456
		 *        "displayStart": 20
10457
		 *      } );
10458
		 *    } )
10459
		 */
10460
		"iDisplayStart": 0,
10461
	
10462
	
10463
		/**
10464
		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
10465
		 * and filtering) by adding a `tabindex` attribute to the required elements. This
10466
		 * allows you to tab through the controls and press the enter key to activate them.
10467
		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
10468
		 * You can overrule this using this parameter if you wish. Use a value of -1 to
10469
		 * disable built-in keyboard navigation.
10470
		 *  @type int
10471
		 *  @default 0
10472
		 *
10473
		 *  @dtopt Options
10474
		 *  @name DataTable.defaults.tabIndex
10475
		 *
10476
		 *  @example
10477
		 *    $(document).ready( function() {
10478
		 *      $('#example').dataTable( {
10479
		 *        "tabIndex": 1
10480
		 *      } );
10481
		 *    } );
10482
		 */
10483
		"iTabIndex": 0,
10484
	
10485
	
10486
		/**
10487
		 * Classes that DataTables assigns to the various components and features
10488
		 * that it adds to the HTML table. This allows classes to be configured
10489
		 * during initialisation in addition to through the static
10490
		 * {@link DataTable.ext.oStdClasses} object).
10491
		 *  @namespace
10492
		 *  @name DataTable.defaults.classes
10493
		 */
10494
		"oClasses": {},
10495
	
10496
	
10497
		/**
10498
		 * All strings that DataTables uses in the user interface that it creates
10499
		 * are defined in this object, allowing you to modified them individually or
10500
		 * completely replace them all as required.
10501
		 *  @namespace
10502
		 *  @name DataTable.defaults.language
10503
		 */
10504
		"oLanguage": {
10505
			/**
10506
			 * Strings that are used for WAI-ARIA labels and controls only (these are not
10507
			 * actually visible on the page, but will be read by screenreaders, and thus
10508
			 * must be internationalised as well).
10509
			 *  @namespace
10510
			 *  @name DataTable.defaults.language.aria
10511
			 */
10512
			"oAria": {
10513
				/**
10514
				 * ARIA label that is added to the table headers when the column may be
10515
				 * sorted ascending by activing the column (click or return when focused).
10516
				 * Note that the column header is prefixed to this string.
10517
				 *  @type string
10518
				 *  @default : activate to sort column ascending
10519
				 *
10520
				 *  @dtopt Language
10521
				 *  @name DataTable.defaults.language.aria.sortAscending
10522
				 *
10523
				 *  @example
10524
				 *    $(document).ready( function() {
10525
				 *      $('#example').dataTable( {
10526
				 *        "language": {
10527
				 *          "aria": {
10528
				 *            "sortAscending": " - click/return to sort ascending"
10529
				 *          }
10530
				 *        }
10531
				 *      } );
10532
				 *    } );
10533
				 */
10534
				"sSortAscending": ": activate to sort column ascending",
10535
	
10536
				/**
10537
				 * ARIA label that is added to the table headers when the column may be
10538
				 * sorted descending by activing the column (click or return when focused).
10539
				 * Note that the column header is prefixed to this string.
10540
				 *  @type string
10541
				 *  @default : activate to sort column ascending
10542
				 *
10543
				 *  @dtopt Language
10544
				 *  @name DataTable.defaults.language.aria.sortDescending
10545
				 *
10546
				 *  @example
10547
				 *    $(document).ready( function() {
10548
				 *      $('#example').dataTable( {
10549
				 *        "language": {
10550
				 *          "aria": {
10551
				 *            "sortDescending": " - click/return to sort descending"
10552
				 *          }
10553
				 *        }
10554
				 *      } );
10555
				 *    } );
10556
				 */
10557
				"sSortDescending": ": activate to sort column descending"
10558
			},
10559
	
10560
			/**
10561
			 * Pagination string used by DataTables for the built-in pagination
10562
			 * control types.
10563
			 *  @namespace
10564
			 *  @name DataTable.defaults.language.paginate
10565
			 */
10566
			"oPaginate": {
10567
				/**
10568
				 * Text to use when using the 'full_numbers' type of pagination for the
10569
				 * button to take the user to the first page.
10570
				 *  @type string
10571
				 *  @default First
10572
				 *
10573
				 *  @dtopt Language
10574
				 *  @name DataTable.defaults.language.paginate.first
10575
				 *
10576
				 *  @example
10577
				 *    $(document).ready( function() {
10578
				 *      $('#example').dataTable( {
10579
				 *        "language": {
10580
				 *          "paginate": {
10581
				 *            "first": "First page"
10582
				 *          }
10583
				 *        }
10584
				 *      } );
10585
				 *    } );
10586
				 */
10587
				"sFirst": "First",
10588
	
10589
	
10590
				/**
10591
				 * Text to use when using the 'full_numbers' type of pagination for the
10592
				 * button to take the user to the last page.
10593
				 *  @type string
10594
				 *  @default Last
10595
				 *
10596
				 *  @dtopt Language
10597
				 *  @name DataTable.defaults.language.paginate.last
10598
				 *
10599
				 *  @example
10600
				 *    $(document).ready( function() {
10601
				 *      $('#example').dataTable( {
10602
				 *        "language": {
10603
				 *          "paginate": {
10604
				 *            "last": "Last page"
10605
				 *          }
10606
				 *        }
10607
				 *      } );
10608
				 *    } );
10609
				 */
10610
				"sLast": "Last",
10611
	
10612
	
10613
				/**
10614
				 * Text to use for the 'next' pagination button (to take the user to the
10615
				 * next page).
10616
				 *  @type string
10617
				 *  @default Next
10618
				 *
10619
				 *  @dtopt Language
10620
				 *  @name DataTable.defaults.language.paginate.next
10621
				 *
10622
				 *  @example
10623
				 *    $(document).ready( function() {
10624
				 *      $('#example').dataTable( {
10625
				 *        "language": {
10626
				 *          "paginate": {
10627
				 *            "next": "Next page"
10628
				 *          }
10629
				 *        }
10630
				 *      } );
10631
				 *    } );
10632
				 */
10633
				"sNext": "Next",
10634
	
10635
	
10636
				/**
10637
				 * Text to use for the 'previous' pagination button (to take the user to
10638
				 * the previous page).
10639
				 *  @type string
10640
				 *  @default Previous
10641
				 *
10642
				 *  @dtopt Language
10643
				 *  @name DataTable.defaults.language.paginate.previous
10644
				 *
10645
				 *  @example
10646
				 *    $(document).ready( function() {
10647
				 *      $('#example').dataTable( {
10648
				 *        "language": {
10649
				 *          "paginate": {
10650
				 *            "previous": "Previous page"
10651
				 *          }
10652
				 *        }
10653
				 *      } );
10654
				 *    } );
10655
				 */
10656
				"sPrevious": "Previous"
10657
			},
10658
	
10659
			/**
10660
			 * This string is shown in preference to `zeroRecords` when the table is
10661
			 * empty of data (regardless of filtering). Note that this is an optional
10662
			 * parameter - if it is not given, the value of `zeroRecords` will be used
10663
			 * instead (either the default or given value).
10664
			 *  @type string
10665
			 *  @default No data available in table
10666
			 *
10667
			 *  @dtopt Language
10668
			 *  @name DataTable.defaults.language.emptyTable
10669
			 *
10670
			 *  @example
10671
			 *    $(document).ready( function() {
10672
			 *      $('#example').dataTable( {
10673
			 *        "language": {
10674
			 *          "emptyTable": "No data available in table"
10675
			 *        }
10676
			 *      } );
10677
			 *    } );
10678
			 */
10679
			"sEmptyTable": "No data available in table",
10680
	
10681
	
10682
			/**
10683
			 * This string gives information to the end user about the information
10684
			 * that is current on display on the page. The following tokens can be
10685
			 * used in the string and will be dynamically replaced as the table
10686
			 * display updates. This tokens can be placed anywhere in the string, or
10687
			 * removed as needed by the language requires:
10688
			 *
10689
			 * * `\_START\_` - Display index of the first record on the current page
10690
			 * * `\_END\_` - Display index of the last record on the current page
10691
			 * * `\_TOTAL\_` - Number of records in the table after filtering
10692
			 * * `\_MAX\_` - Number of records in the table without filtering
10693
			 * * `\_PAGE\_` - Current page number
10694
			 * * `\_PAGES\_` - Total number of pages of data in the table
10695
			 *
10696
			 *  @type string
10697
			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
10698
			 *
10699
			 *  @dtopt Language
10700
			 *  @name DataTable.defaults.language.info
10701
			 *
10702
			 *  @example
10703
			 *    $(document).ready( function() {
10704
			 *      $('#example').dataTable( {
10705
			 *        "language": {
10706
			 *          "info": "Showing page _PAGE_ of _PAGES_"
10707
			 *        }
10708
			 *      } );
10709
			 *    } );
10710
			 */
10711
			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
10712
	
10713
	
10714
			/**
10715
			 * Display information string for when the table is empty. Typically the
10716
			 * format of this string should match `info`.
10717
			 *  @type string
10718
			 *  @default Showing 0 to 0 of 0 entries
10719
			 *
10720
			 *  @dtopt Language
10721
			 *  @name DataTable.defaults.language.infoEmpty
10722
			 *
10723
			 *  @example
10724
			 *    $(document).ready( function() {
10725
			 *      $('#example').dataTable( {
10726
			 *        "language": {
10727
			 *          "infoEmpty": "No entries to show"
10728
			 *        }
10729
			 *      } );
10730
			 *    } );
10731
			 */
10732
			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
10733
	
10734
	
10735
			/**
10736
			 * When a user filters the information in a table, this string is appended
10737
			 * to the information (`info`) to give an idea of how strong the filtering
10738
			 * is. The variable _MAX_ is dynamically updated.
10739
			 *  @type string
10740
			 *  @default (filtered from _MAX_ total entries)
10741
			 *
10742
			 *  @dtopt Language
10743
			 *  @name DataTable.defaults.language.infoFiltered
10744
			 *
10745
			 *  @example
10746
			 *    $(document).ready( function() {
10747
			 *      $('#example').dataTable( {
10748
			 *        "language": {
10749
			 *          "infoFiltered": " - filtering from _MAX_ records"
10750
			 *        }
10751
			 *      } );
10752
			 *    } );
10753
			 */
10754
			"sInfoFiltered": "(filtered from _MAX_ total entries)",
10755
	
10756
	
10757
			/**
10758
			 * If can be useful to append extra information to the info string at times,
10759
			 * and this variable does exactly that. This information will be appended to
10760
			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
10761
			 * being used) at all times.
10762
			 *  @type string
10763
			 *  @default <i>Empty string</i>
10764
			 *
10765
			 *  @dtopt Language
10766
			 *  @name DataTable.defaults.language.infoPostFix
10767
			 *
10768
			 *  @example
10769
			 *    $(document).ready( function() {
10770
			 *      $('#example').dataTable( {
10771
			 *        "language": {
10772
			 *          "infoPostFix": "All records shown are derived from real information."
10773
			 *        }
10774
			 *      } );
10775
			 *    } );
10776
			 */
10777
			"sInfoPostFix": "",
10778
	
10779
	
10780
			/**
10781
			 * This decimal place operator is a little different from the other
10782
			 * language options since DataTables doesn't output floating point
10783
			 * numbers, so it won't ever use this for display of a number. Rather,
10784
			 * what this parameter does is modify the sort methods of the table so
10785
			 * that numbers which are in a format which has a character other than
10786
			 * a period (`.`) as a decimal place will be sorted numerically.
10787
			 *
10788
			 * Note that numbers with different decimal places cannot be shown in
10789
			 * the same table and still be sortable, the table must be consistent.
10790
			 * However, multiple different tables on the page can use different
10791
			 * decimal place characters.
10792
			 *  @type string
10793
			 *  @default 
10794
			 *
10795
			 *  @dtopt Language
10796
			 *  @name DataTable.defaults.language.decimal
10797
			 *
10798
			 *  @example
10799
			 *    $(document).ready( function() {
10800
			 *      $('#example').dataTable( {
10801
			 *        "language": {
10802
			 *          "decimal": ","
10803
			 *          "thousands": "."
10804
			 *        }
10805
			 *      } );
10806
			 *    } );
10807
			 */
10808
			"sDecimal": "",
10809
	
10810
	
10811
			/**
10812
			 * DataTables has a build in number formatter (`formatNumber`) which is
10813
			 * used to format large numbers that are used in the table information.
10814
			 * By default a comma is used, but this can be trivially changed to any
10815
			 * character you wish with this parameter.
10816
			 *  @type string
10817
			 *  @default ,
10818
			 *
10819
			 *  @dtopt Language
10820
			 *  @name DataTable.defaults.language.thousands
10821
			 *
10822
			 *  @example
10823
			 *    $(document).ready( function() {
10824
			 *      $('#example').dataTable( {
10825
			 *        "language": {
10826
			 *          "thousands": "'"
10827
			 *        }
10828
			 *      } );
10829
			 *    } );
10830
			 */
10831
			"sThousands": ",",
10832
	
10833
	
10834
			/**
10835
			 * Detail the action that will be taken when the drop down menu for the
10836
			 * pagination length option is changed. The '_MENU_' variable is replaced
10837
			 * with a default select list of 10, 25, 50 and 100, and can be replaced
10838
			 * with a custom select box if required.
10839
			 *  @type string
10840
			 *  @default Show _MENU_ entries
10841
			 *
10842
			 *  @dtopt Language
10843
			 *  @name DataTable.defaults.language.lengthMenu
10844
			 *
10845
			 *  @example
10846
			 *    // Language change only
10847
			 *    $(document).ready( function() {
10848
			 *      $('#example').dataTable( {
10849
			 *        "language": {
10850
			 *          "lengthMenu": "Display _MENU_ records"
10851
			 *        }
10852
			 *      } );
10853
			 *    } );
10854
			 *
10855
			 *  @example
10856
			 *    // Language and options change
10857
			 *    $(document).ready( function() {
10858
			 *      $('#example').dataTable( {
10859
			 *        "language": {
10860
			 *          "lengthMenu": 'Display <select>'+
10861
			 *            '<option value="10">10</option>'+
10862
			 *            '<option value="20">20</option>'+
10863
			 *            '<option value="30">30</option>'+
10864
			 *            '<option value="40">40</option>'+
10865
			 *            '<option value="50">50</option>'+
10866
			 *            '<option value="-1">All</option>'+
10867
			 *            '</select> records'
10868
			 *        }
10869
			 *      } );
10870
			 *    } );
10871
			 */
10872
			"sLengthMenu": "Show _MENU_ entries",
10873
	
10874
	
10875
			/**
10876
			 * When using Ajax sourced data and during the first draw when DataTables is
10877
			 * gathering the data, this message is shown in an empty row in the table to
10878
			 * indicate to the end user the the data is being loaded. Note that this
10879
			 * parameter is not used when loading data by server-side processing, just
10880
			 * Ajax sourced data with client-side processing.
10881
			 *  @type string
10882
			 *  @default Loading...
10883
			 *
10884
			 *  @dtopt Language
10885
			 *  @name DataTable.defaults.language.loadingRecords
10886
			 *
10887
			 *  @example
10888
			 *    $(document).ready( function() {
10889
			 *      $('#example').dataTable( {
10890
			 *        "language": {
10891
			 *          "loadingRecords": "Please wait - loading..."
10892
			 *        }
10893
			 *      } );
10894
			 *    } );
10895
			 */
10896
			"sLoadingRecords": "Loading...",
10897
	
10898
	
10899
			/**
10900
			 * Text which is displayed when the table is processing a user action
10901
			 * (usually a sort command or similar).
10902
			 *  @type string
10903
			 *  @default Processing...
10904
			 *
10905
			 *  @dtopt Language
10906
			 *  @name DataTable.defaults.language.processing
10907
			 *
10908
			 *  @example
10909
			 *    $(document).ready( function() {
10910
			 *      $('#example').dataTable( {
10911
			 *        "language": {
10912
			 *          "processing": "DataTables is currently busy"
10913
			 *        }
10914
			 *      } );
10915
			 *    } );
10916
			 */
10917
			"sProcessing": "Processing...",
10918
	
10919
	
10920
			/**
10921
			 * Details the actions that will be taken when the user types into the
10922
			 * filtering input text box. The variable "_INPUT_", if used in the string,
10923
			 * is replaced with the HTML text box for the filtering input allowing
10924
			 * control over where it appears in the string. If "_INPUT_" is not given
10925
			 * then the input box is appended to the string automatically.
10926
			 *  @type string
10927
			 *  @default Search:
10928
			 *
10929
			 *  @dtopt Language
10930
			 *  @name DataTable.defaults.language.search
10931
			 *
10932
			 *  @example
10933
			 *    // Input text box will be appended at the end automatically
10934
			 *    $(document).ready( function() {
10935
			 *      $('#example').dataTable( {
10936
			 *        "language": {
10937
			 *          "search": "Filter records:"
10938
			 *        }
10939
			 *      } );
10940
			 *    } );
10941
			 *
10942
			 *  @example
10943
			 *    // Specify where the filter should appear
10944
			 *    $(document).ready( function() {
10945
			 *      $('#example').dataTable( {
10946
			 *        "language": {
10947
			 *          "search": "Apply filter _INPUT_ to table"
10948
			 *        }
10949
			 *      } );
10950
			 *    } );
10951
			 */
10952
			"sSearch": "Search:",
10953
	
10954
	
10955
			/**
10956
			 * All of the language information can be stored in a file on the
10957
			 * server-side, which DataTables will look up if this parameter is passed.
10958
			 * It must store the URL of the language file, which is in a JSON format,
10959
			 * and the object has the same properties as the oLanguage object in the
10960
			 * initialiser object (i.e. the above parameters). Please refer to one of
10961
			 * the example language files to see how this works in action.
10962
			 *  @type string
10963
			 *  @default <i>Empty string - i.e. disabled</i>
10964
			 *
10965
			 *  @dtopt Language
10966
			 *  @name DataTable.defaults.language.url
10967
			 *
10968
			 *  @example
10969
			 *    $(document).ready( function() {
10970
			 *      $('#example').dataTable( {
10971
			 *        "language": {
10972
			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
10973
			 *        }
10974
			 *      } );
10975
			 *    } );
10976
			 */
10977
			"sUrl": "",
10978
	
10979
	
10980
			/**
10981
			 * Text shown inside the table records when the is no information to be
10982
			 * displayed after filtering. `emptyTable` is shown when there is simply no
10983
			 * information in the table at all (regardless of filtering).
10984
			 *  @type string
10985
			 *  @default No matching records found
10986
			 *
10987
			 *  @dtopt Language
10988
			 *  @name DataTable.defaults.language.zeroRecords
10989
			 *
10990
			 *  @example
10991
			 *    $(document).ready( function() {
10992
			 *      $('#example').dataTable( {
10993
			 *        "language": {
10994
			 *          "zeroRecords": "No records to display"
10995
			 *        }
10996
			 *      } );
10997
			 *    } );
10998
			 */
10999
			"sZeroRecords": "No matching records found"
11000
		},
11001
	
11002
	
11003
		/**
11004
		 * This parameter allows you to have define the global filtering state at
11005
		 * initialisation time. As an object the `search` parameter must be
11006
		 * defined, but all other parameters are optional. When `regex` is true,
11007
		 * the search string will be treated as a regular expression, when false
11008
		 * (default) it will be treated as a straight string. When `smart`
11009
		 * DataTables will use it's smart filtering methods (to word match at
11010
		 * any point in the data), when false this will not be done.
11011
		 *  @namespace
11012
		 *  @extends DataTable.models.oSearch
11013
		 *
11014
		 *  @dtopt Options
11015
		 *  @name DataTable.defaults.search
11016
		 *
11017
		 *  @example
11018
		 *    $(document).ready( function() {
11019
		 *      $('#example').dataTable( {
11020
		 *        "search": {"search": "Initial search"}
11021
		 *      } );
11022
		 *    } )
11023
		 */
11024
		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11025
	
11026
	
11027
		/**
11028
		 * __Deprecated__ The functionality provided by this parameter has now been
11029
		 * superseded by that provided through `ajax`, which should be used instead.
11030
		 *
11031
		 * By default DataTables will look for the property `data` (or `aaData` for
11032
		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11033
		 * source or for server-side processing - this parameter allows that
11034
		 * property to be changed. You can use Javascript dotted object notation to
11035
		 * get a data source for multiple levels of nesting.
11036
		 *  @type string
11037
		 *  @default data
11038
		 *
11039
		 *  @dtopt Options
11040
		 *  @dtopt Server-side
11041
		 *  @name DataTable.defaults.ajaxDataProp
11042
		 *
11043
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11044
		 */
11045
		"sAjaxDataProp": "data",
11046
	
11047
	
11048
		/**
11049
		 * __Deprecated__ The functionality provided by this parameter has now been
11050
		 * superseded by that provided through `ajax`, which should be used instead.
11051
		 *
11052
		 * You can instruct DataTables to load data from an external
11053
		 * source using this parameter (use aData if you want to pass data in you
11054
		 * already have). Simply provide a url a JSON object can be obtained from.
11055
		 *  @type string
11056
		 *  @default null
11057
		 *
11058
		 *  @dtopt Options
11059
		 *  @dtopt Server-side
11060
		 *  @name DataTable.defaults.ajaxSource
11061
		 *
11062
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11063
		 */
11064
		"sAjaxSource": null,
11065
	
11066
	
11067
		/**
11068
		 * This initialisation variable allows you to specify exactly where in the
11069
		 * DOM you want DataTables to inject the various controls it adds to the page
11070
		 * (for example you might want the pagination controls at the top of the
11071
		 * table). DIV elements (with or without a custom class) can also be added to
11072
		 * aid styling. The follow syntax is used:
11073
		 *   <ul>
11074
		 *     <li>The following options are allowed:
11075
		 *       <ul>
11076
		 *         <li>'l' - Length changing</li>
11077
		 *         <li>'f' - Filtering input</li>
11078
		 *         <li>'t' - The table!</li>
11079
		 *         <li>'i' - Information</li>
11080
		 *         <li>'p' - Pagination</li>
11081
		 *         <li>'r' - pRocessing</li>
11082
		 *       </ul>
11083
		 *     </li>
11084
		 *     <li>The following constants are allowed:
11085
		 *       <ul>
11086
		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11087
		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11088
		 *       </ul>
11089
		 *     </li>
11090
		 *     <li>The following syntax is expected:
11091
		 *       <ul>
11092
		 *         <li>'&lt;' and '&gt;' - div elements</li>
11093
		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11094
		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11095
		 *       </ul>
11096
		 *     </li>
11097
		 *     <li>Examples:
11098
		 *       <ul>
11099
		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11100
		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11101
		 *       </ul>
11102
		 *     </li>
11103
		 *   </ul>
11104
		 *  @type string
11105
		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11106
		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11107
		 *
11108
		 *  @dtopt Options
11109
		 *  @name DataTable.defaults.dom
11110
		 *
11111
		 *  @example
11112
		 *    $(document).ready( function() {
11113
		 *      $('#example').dataTable( {
11114
		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11115
		 *      } );
11116
		 *    } );
11117
		 */
11118
		"sDom": "lfrtip",
11119
	
11120
	
11121
		/**
11122
		 * DataTables features four different built-in options for the buttons to
11123
		 * display for pagination control:
11124
		 *
11125
		 * * `simple` - 'Previous' and 'Next' buttons only
11126
		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11127
		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11128
		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11129
		 *   page numbers
11130
		 *  
11131
		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11132
		 *  @type string
11133
		 *  @default simple_numbers
11134
		 *
11135
		 *  @dtopt Options
11136
		 *  @name DataTable.defaults.pagingType
11137
		 *
11138
		 *  @example
11139
		 *    $(document).ready( function() {
11140
		 *      $('#example').dataTable( {
11141
		 *        "pagingType": "full_numbers"
11142
		 *      } );
11143
		 *    } )
11144
		 */
11145
		"sPaginationType": "simple_numbers",
11146
	
11147
	
11148
		/**
11149
		 * Enable horizontal scrolling. When a table is too wide to fit into a
11150
		 * certain layout, or you have a large number of columns in the table, you
11151
		 * can enable x-scrolling to show the table in a viewport, which can be
11152
		 * scrolled. This property can be `true` which will allow the table to
11153
		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11154
		 * case it will be treated as a pixel measurement). Setting as simply `true`
11155
		 * is recommended.
11156
		 *  @type boolean|string
11157
		 *  @default <i>blank string - i.e. disabled</i>
11158
		 *
11159
		 *  @dtopt Features
11160
		 *  @name DataTable.defaults.scrollX
11161
		 *
11162
		 *  @example
11163
		 *    $(document).ready( function() {
11164
		 *      $('#example').dataTable( {
11165
		 *        "scrollX": true,
11166
		 *        "scrollCollapse": true
11167
		 *      } );
11168
		 *    } );
11169
		 */
11170
		"sScrollX": "",
11171
	
11172
	
11173
		/**
11174
		 * This property can be used to force a DataTable to use more width than it
11175
		 * might otherwise do when x-scrolling is enabled. For example if you have a
11176
		 * table which requires to be well spaced, this parameter is useful for
11177
		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11178
		 * any CSS unit, or a number (in which case it will be treated as a pixel
11179
		 * measurement).
11180
		 *  @type string
11181
		 *  @default <i>blank string - i.e. disabled</i>
11182
		 *
11183
		 *  @dtopt Options
11184
		 *  @name DataTable.defaults.scrollXInner
11185
		 *
11186
		 *  @example
11187
		 *    $(document).ready( function() {
11188
		 *      $('#example').dataTable( {
11189
		 *        "scrollX": "100%",
11190
		 *        "scrollXInner": "110%"
11191
		 *      } );
11192
		 *    } );
11193
		 */
11194
		"sScrollXInner": "",
11195
	
11196
	
11197
		/**
11198
		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11199
		 * to the given height, and enable scrolling for any data which overflows the
11200
		 * current viewport. This can be used as an alternative to paging to display
11201
		 * a lot of data in a small area (although paging and scrolling can both be
11202
		 * enabled at the same time). This property can be any CSS unit, or a number
11203
		 * (in which case it will be treated as a pixel measurement).
11204
		 *  @type string
11205
		 *  @default <i>blank string - i.e. disabled</i>
11206
		 *
11207
		 *  @dtopt Features
11208
		 *  @name DataTable.defaults.scrollY
11209
		 *
11210
		 *  @example
11211
		 *    $(document).ready( function() {
11212
		 *      $('#example').dataTable( {
11213
		 *        "scrollY": "200px",
11214
		 *        "paginate": false
11215
		 *      } );
11216
		 *    } );
11217
		 */
11218
		"sScrollY": "",
11219
	
11220
	
11221
		/**
11222
		 * __Deprecated__ The functionality provided by this parameter has now been
11223
		 * superseded by that provided through `ajax`, which should be used instead.
11224
		 *
11225
		 * Set the HTTP method that is used to make the Ajax call for server-side
11226
		 * processing or Ajax sourced data.
11227
		 *  @type string
11228
		 *  @default GET
11229
		 *
11230
		 *  @dtopt Options
11231
		 *  @dtopt Server-side
11232
		 *  @name DataTable.defaults.serverMethod
11233
		 *
11234
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11235
		 */
11236
		"sServerMethod": "GET",
11237
	
11238
	
11239
		/**
11240
		 * DataTables makes use of renderers when displaying HTML elements for
11241
		 * a table. These renderers can be added or modified by plug-ins to
11242
		 * generate suitable mark-up for a site. For example the Bootstrap
11243
		 * integration plug-in for DataTables uses a paging button renderer to
11244
		 * display pagination buttons in the mark-up required by Bootstrap.
11245
		 *
11246
		 * For further information about the renderers available see
11247
		 * DataTable.ext.renderer
11248
		 *  @type string|object
11249
		 *  @default null
11250
		 *
11251
		 *  @name DataTable.defaults.renderer
11252
		 *
11253
		 */
11254
		"renderer": null
11255
	};
11256
	
11257
	_fnHungarianMap( DataTable.defaults );
11258
	
11259
	
11260
	
11261
	/*
11262
	 * Developer note - See note in model.defaults.js about the use of Hungarian
11263
	 * notation and camel case.
11264
	 */
11265
	
11266
	/**
11267
	 * Column options that can be given to DataTables at initialisation time.
11268
	 *  @namespace
11269
	 */
11270
	DataTable.defaults.column = {
11271
		/**
11272
		 * Define which column(s) an order will occur on for this column. This
11273
		 * allows a column's ordering to take multiple columns into account when
11274
		 * doing a sort or use the data from a different column. For example first
11275
		 * name / last name columns make sense to do a multi-column sort over the
11276
		 * two columns.
11277
		 *  @type array|int
11278
		 *  @default null <i>Takes the value of the column index automatically</i>
11279
		 *
11280
		 *  @name DataTable.defaults.column.orderData
11281
		 *  @dtopt Columns
11282
		 *
11283
		 *  @example
11284
		 *    // Using `columnDefs`
11285
		 *    $(document).ready( function() {
11286
		 *      $('#example').dataTable( {
11287
		 *        "columnDefs": [
11288
		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11289
		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11290
		 *          { "orderData": 2, "targets": [ 2 ] }
11291
		 *        ]
11292
		 *      } );
11293
		 *    } );
11294
		 *
11295
		 *  @example
11296
		 *    // Using `columns`
11297
		 *    $(document).ready( function() {
11298
		 *      $('#example').dataTable( {
11299
		 *        "columns": [
11300
		 *          { "orderData": [ 0, 1 ] },
11301
		 *          { "orderData": [ 1, 0 ] },
11302
		 *          { "orderData": 2 },
11303
		 *          null,
11304
		 *          null
11305
		 *        ]
11306
		 *      } );
11307
		 *    } );
11308
		 */
11309
		"aDataSort": null,
11310
		"iDataSort": -1,
11311
	
11312
	
11313
		/**
11314
		 * You can control the default ordering direction, and even alter the
11315
		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11316
		 * using this parameter.
11317
		 *  @type array
11318
		 *  @default [ 'asc', 'desc' ]
11319
		 *
11320
		 *  @name DataTable.defaults.column.orderSequence
11321
		 *  @dtopt Columns
11322
		 *
11323
		 *  @example
11324
		 *    // Using `columnDefs`
11325
		 *    $(document).ready( function() {
11326
		 *      $('#example').dataTable( {
11327
		 *        "columnDefs": [
11328
		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11329
		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11330
		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11331
		 *        ]
11332
		 *      } );
11333
		 *    } );
11334
		 *
11335
		 *  @example
11336
		 *    // Using `columns`
11337
		 *    $(document).ready( function() {
11338
		 *      $('#example').dataTable( {
11339
		 *        "columns": [
11340
		 *          null,
11341
		 *          { "orderSequence": [ "asc" ] },
11342
		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
11343
		 *          { "orderSequence": [ "desc" ] },
11344
		 *          null
11345
		 *        ]
11346
		 *      } );
11347
		 *    } );
11348
		 */
11349
		"asSorting": [ 'asc', 'desc' ],
11350
	
11351
	
11352
		/**
11353
		 * Enable or disable filtering on the data in this column.
11354
		 *  @type boolean
11355
		 *  @default true
11356
		 *
11357
		 *  @name DataTable.defaults.column.searchable
11358
		 *  @dtopt Columns
11359
		 *
11360
		 *  @example
11361
		 *    // Using `columnDefs`
11362
		 *    $(document).ready( function() {
11363
		 *      $('#example').dataTable( {
11364
		 *        "columnDefs": [
11365
		 *          { "searchable": false, "targets": [ 0 ] }
11366
		 *        ] } );
11367
		 *    } );
11368
		 *
11369
		 *  @example
11370
		 *    // Using `columns`
11371
		 *    $(document).ready( function() {
11372
		 *      $('#example').dataTable( {
11373
		 *        "columns": [
11374
		 *          { "searchable": false },
11375
		 *          null,
11376
		 *          null,
11377
		 *          null,
11378
		 *          null
11379
		 *        ] } );
11380
		 *    } );
11381
		 */
11382
		"bSearchable": true,
11383
	
11384
	
11385
		/**
11386
		 * Enable or disable ordering on this column.
11387
		 *  @type boolean
11388
		 *  @default true
11389
		 *
11390
		 *  @name DataTable.defaults.column.orderable
11391
		 *  @dtopt Columns
11392
		 *
11393
		 *  @example
11394
		 *    // Using `columnDefs`
11395
		 *    $(document).ready( function() {
11396
		 *      $('#example').dataTable( {
11397
		 *        "columnDefs": [
11398
		 *          { "orderable": false, "targets": [ 0 ] }
11399
		 *        ] } );
11400
		 *    } );
11401
		 *
11402
		 *  @example
11403
		 *    // Using `columns`
11404
		 *    $(document).ready( function() {
11405
		 *      $('#example').dataTable( {
11406
		 *        "columns": [
11407
		 *          { "orderable": false },
11408
		 *          null,
11409
		 *          null,
11410
		 *          null,
11411
		 *          null
11412
		 *        ] } );
11413
		 *    } );
11414
		 */
11415
		"bSortable": true,
11416
	
11417
	
11418
		/**
11419
		 * Enable or disable the display of this column.
11420
		 *  @type boolean
11421
		 *  @default true
11422
		 *
11423
		 *  @name DataTable.defaults.column.visible
11424
		 *  @dtopt Columns
11425
		 *
11426
		 *  @example
11427
		 *    // Using `columnDefs`
11428
		 *    $(document).ready( function() {
11429
		 *      $('#example').dataTable( {
11430
		 *        "columnDefs": [
11431
		 *          { "visible": false, "targets": [ 0 ] }
11432
		 *        ] } );
11433
		 *    } );
11434
		 *
11435
		 *  @example
11436
		 *    // Using `columns`
11437
		 *    $(document).ready( function() {
11438
		 *      $('#example').dataTable( {
11439
		 *        "columns": [
11440
		 *          { "visible": false },
11441
		 *          null,
11442
		 *          null,
11443
		 *          null,
11444
		 *          null
11445
		 *        ] } );
11446
		 *    } );
11447
		 */
11448
		"bVisible": true,
11449
	
11450
	
11451
		/**
11452
		 * Developer definable function that is called whenever a cell is created (Ajax source,
11453
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11454
		 * allowing you to modify the DOM element (add background colour for example) when the
11455
		 * element is available.
11456
		 *  @type function
11457
		 *  @param {element} td The TD node that has been created
11458
		 *  @param {*} cellData The Data for the cell
11459
		 *  @param {array|object} rowData The data for the whole row
11460
		 *  @param {int} row The row index for the aoData data store
11461
		 *  @param {int} col The column index for aoColumns
11462
		 *
11463
		 *  @name DataTable.defaults.column.createdCell
11464
		 *  @dtopt Columns
11465
		 *
11466
		 *  @example
11467
		 *    $(document).ready( function() {
11468
		 *      $('#example').dataTable( {
11469
		 *        "columnDefs": [ {
11470
		 *          "targets": [3],
11471
		 *          "createdCell": function (td, cellData, rowData, row, col) {
11472
		 *            if ( cellData == "1.7" ) {
11473
		 *              $(td).css('color', 'blue')
11474
		 *            }
11475
		 *          }
11476
		 *        } ]
11477
		 *      });
11478
		 *    } );
11479
		 */
11480
		"fnCreatedCell": null,
11481
	
11482
	
11483
		/**
11484
		 * This parameter has been replaced by `data` in DataTables to ensure naming
11485
		 * consistency. `dataProp` can still be used, as there is backwards
11486
		 * compatibility in DataTables for this option, but it is strongly
11487
		 * recommended that you use `data` in preference to `dataProp`.
11488
		 *  @name DataTable.defaults.column.dataProp
11489
		 */
11490
	
11491
	
11492
		/**
11493
		 * This property can be used to read data from any data source property,
11494
		 * including deeply nested objects / properties. `data` can be given in a
11495
		 * number of different ways which effect its behaviour:
11496
		 *
11497
		 * * `integer` - treated as an array index for the data source. This is the
11498
		 *   default that DataTables uses (incrementally increased for each column).
11499
		 * * `string` - read an object property from the data source. There are
11500
		 *   three 'special' options that can be used in the string to alter how
11501
		 *   DataTables reads the data from the source object:
11502
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11503
		 *      Javascript to read from nested objects, so to can the options
11504
		 *      specified in `data`. For example: `browser.version` or
11505
		 *      `browser.name`. If your object parameter name contains a period, use
11506
		 *      `\\` to escape it - i.e. `first\\.name`.
11507
		 *    * `[]` - Array notation. DataTables can automatically combine data
11508
		 *      from and array source, joining the data with the characters provided
11509
		 *      between the two brackets. For example: `name[, ]` would provide a
11510
		 *      comma-space separated list from the source array. If no characters
11511
		 *      are provided between the brackets, the original array source is
11512
		 *      returned.
11513
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
11514
		 *      execute a function of the name given. For example: `browser()` for a
11515
		 *      simple function on the data source, `browser.version()` for a
11516
		 *      function in a nested property or even `browser().version` to get an
11517
		 *      object property if the function called returns an object. Note that
11518
		 *      function notation is recommended for use in `render` rather than
11519
		 *      `data` as it is much simpler to use as a renderer.
11520
		 * * `null` - use the original data source for the row rather than plucking
11521
		 *   data directly from it. This action has effects on two other
11522
		 *   initialisation options:
11523
		 *    * `defaultContent` - When null is given as the `data` option and
11524
		 *      `defaultContent` is specified for the column, the value defined by
11525
		 *      `defaultContent` will be used for the cell.
11526
		 *    * `render` - When null is used for the `data` option and the `render`
11527
		 *      option is specified for the column, the whole data source for the
11528
		 *      row is used for the renderer.
11529
		 * * `function` - the function given will be executed whenever DataTables
11530
		 *   needs to set or get the data for a cell in the column. The function
11531
		 *   takes three parameters:
11532
		 *    * Parameters:
11533
		 *      * `{array|object}` The data source for the row
11534
		 *      * `{string}` The type call data requested - this will be 'set' when
11535
		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
11536
		 *        when gathering data. Note that when `undefined` is given for the
11537
		 *        type DataTables expects to get the raw data for the object back<
11538
		 *      * `{*}` Data to set when the second parameter is 'set'.
11539
		 *    * Return:
11540
		 *      * The return value from the function is not required when 'set' is
11541
		 *        the type of call, but otherwise the return is what will be used
11542
		 *        for the data requested.
11543
		 *
11544
		 * Note that `data` is a getter and setter option. If you just require
11545
		 * formatting of data for output, you will likely want to use `render` which
11546
		 * is simply a getter and thus simpler to use.
11547
		 *
11548
		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
11549
		 * name change reflects the flexibility of this property and is consistent
11550
		 * with the naming of mRender. If 'mDataProp' is given, then it will still
11551
		 * be used by DataTables, as it automatically maps the old name to the new
11552
		 * if required.
11553
		 *
11554
		 *  @type string|int|function|null
11555
		 *  @default null <i>Use automatically calculated column index</i>
11556
		 *
11557
		 *  @name DataTable.defaults.column.data
11558
		 *  @dtopt Columns
11559
		 *
11560
		 *  @example
11561
		 *    // Read table data from objects
11562
		 *    // JSON structure for each row:
11563
		 *    //   {
11564
		 *    //      "engine": {value},
11565
		 *    //      "browser": {value},
11566
		 *    //      "platform": {value},
11567
		 *    //      "version": {value},
11568
		 *    //      "grade": {value}
11569
		 *    //   }
11570
		 *    $(document).ready( function() {
11571
		 *      $('#example').dataTable( {
11572
		 *        "ajaxSource": "sources/objects.txt",
11573
		 *        "columns": [
11574
		 *          { "data": "engine" },
11575
		 *          { "data": "browser" },
11576
		 *          { "data": "platform" },
11577
		 *          { "data": "version" },
11578
		 *          { "data": "grade" }
11579
		 *        ]
11580
		 *      } );
11581
		 *    } );
11582
		 *
11583
		 *  @example
11584
		 *    // Read information from deeply nested objects
11585
		 *    // JSON structure for each row:
11586
		 *    //   {
11587
		 *    //      "engine": {value},
11588
		 *    //      "browser": {value},
11589
		 *    //      "platform": {
11590
		 *    //         "inner": {value}
11591
		 *    //      },
11592
		 *    //      "details": [
11593
		 *    //         {value}, {value}
11594
		 *    //      ]
11595
		 *    //   }
11596
		 *    $(document).ready( function() {
11597
		 *      $('#example').dataTable( {
11598
		 *        "ajaxSource": "sources/deep.txt",
11599
		 *        "columns": [
11600
		 *          { "data": "engine" },
11601
		 *          { "data": "browser" },
11602
		 *          { "data": "platform.inner" },
11603
		 *          { "data": "platform.details.0" },
11604
		 *          { "data": "platform.details.1" }
11605
		 *        ]
11606
		 *      } );
11607
		 *    } );
11608
		 *
11609
		 *  @example
11610
		 *    // Using `data` as a function to provide different information for
11611
		 *    // sorting, filtering and display. In this case, currency (price)
11612
		 *    $(document).ready( function() {
11613
		 *      $('#example').dataTable( {
11614
		 *        "columnDefs": [ {
11615
		 *          "targets": [ 0 ],
11616
		 *          "data": function ( source, type, val ) {
11617
		 *            if (type === 'set') {
11618
		 *              source.price = val;
11619
		 *              // Store the computed dislay and filter values for efficiency
11620
		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
11621
		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
11622
		 *              return;
11623
		 *            }
11624
		 *            else if (type === 'display') {
11625
		 *              return source.price_display;
11626
		 *            }
11627
		 *            else if (type === 'filter') {
11628
		 *              return source.price_filter;
11629
		 *            }
11630
		 *            // 'sort', 'type' and undefined all just use the integer
11631
		 *            return source.price;
11632
		 *          }
11633
		 *        } ]
11634
		 *      } );
11635
		 *    } );
11636
		 *
11637
		 *  @example
11638
		 *    // Using default content
11639
		 *    $(document).ready( function() {
11640
		 *      $('#example').dataTable( {
11641
		 *        "columnDefs": [ {
11642
		 *          "targets": [ 0 ],
11643
		 *          "data": null,
11644
		 *          "defaultContent": "Click to edit"
11645
		 *        } ]
11646
		 *      } );
11647
		 *    } );
11648
		 *
11649
		 *  @example
11650
		 *    // Using array notation - outputting a list from an array
11651
		 *    $(document).ready( function() {
11652
		 *      $('#example').dataTable( {
11653
		 *        "columnDefs": [ {
11654
		 *          "targets": [ 0 ],
11655
		 *          "data": "name[, ]"
11656
		 *        } ]
11657
		 *      } );
11658
		 *    } );
11659
		 *
11660
		 */
11661
		"mData": null,
11662
	
11663
	
11664
		/**
11665
		 * This property is the rendering partner to `data` and it is suggested that
11666
		 * when you want to manipulate data for display (including filtering,
11667
		 * sorting etc) without altering the underlying data for the table, use this
11668
		 * property. `render` can be considered to be the the read only companion to
11669
		 * `data` which is read / write (then as such more complex). Like `data`
11670
		 * this option can be given in a number of different ways to effect its
11671
		 * behaviour:
11672
		 *
11673
		 * * `integer` - treated as an array index for the data source. This is the
11674
		 *   default that DataTables uses (incrementally increased for each column).
11675
		 * * `string` - read an object property from the data source. There are
11676
		 *   three 'special' options that can be used in the string to alter how
11677
		 *   DataTables reads the data from the source object:
11678
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11679
		 *      Javascript to read from nested objects, so to can the options
11680
		 *      specified in `data`. For example: `browser.version` or
11681
		 *      `browser.name`. If your object parameter name contains a period, use
11682
		 *      `\\` to escape it - i.e. `first\\.name`.
11683
		 *    * `[]` - Array notation. DataTables can automatically combine data
11684
		 *      from and array source, joining the data with the characters provided
11685
		 *      between the two brackets. For example: `name[, ]` would provide a
11686
		 *      comma-space separated list from the source array. If no characters
11687
		 *      are provided between the brackets, the original array source is
11688
		 *      returned.
11689
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
11690
		 *      execute a function of the name given. For example: `browser()` for a
11691
		 *      simple function on the data source, `browser.version()` for a
11692
		 *      function in a nested property or even `browser().version` to get an
11693
		 *      object property if the function called returns an object.
11694
		 * * `object` - use different data for the different data types requested by
11695
		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
11696
		 *   of the object is the data type the property refers to and the value can
11697
		 *   defined using an integer, string or function using the same rules as
11698
		 *   `render` normally does. Note that an `_` option _must_ be specified.
11699
		 *   This is the default value to use if you haven't specified a value for
11700
		 *   the data type requested by DataTables.
11701
		 * * `function` - the function given will be executed whenever DataTables
11702
		 *   needs to set or get the data for a cell in the column. The function
11703
		 *   takes three parameters:
11704
		 *    * Parameters:
11705
		 *      * {array|object} The data source for the row (based on `data`)
11706
		 *      * {string} The type call data requested - this will be 'filter',
11707
		 *        'display', 'type' or 'sort'.
11708
		 *      * {array|object} The full data source for the row (not based on
11709
		 *        `data`)
11710
		 *    * Return:
11711
		 *      * The return value from the function is what will be used for the
11712
		 *        data requested.
11713
		 *
11714
		 *  @type string|int|function|object|null
11715
		 *  @default null Use the data source value.
11716
		 *
11717
		 *  @name DataTable.defaults.column.render
11718
		 *  @dtopt Columns
11719
		 *
11720
		 *  @example
11721
		 *    // Create a comma separated list from an array of objects
11722
		 *    $(document).ready( function() {
11723
		 *      $('#example').dataTable( {
11724
		 *        "ajaxSource": "sources/deep.txt",
11725
		 *        "columns": [
11726
		 *          { "data": "engine" },
11727
		 *          { "data": "browser" },
11728
		 *          {
11729
		 *            "data": "platform",
11730
		 *            "render": "[, ].name"
11731
		 *          }
11732
		 *        ]
11733
		 *      } );
11734
		 *    } );
11735
		 *
11736
		 *  @example
11737
		 *    // Execute a function to obtain data
11738
		 *    $(document).ready( function() {
11739
		 *      $('#example').dataTable( {
11740
		 *        "columnDefs": [ {
11741
		 *          "targets": [ 0 ],
11742
		 *          "data": null, // Use the full data source object for the renderer's source
11743
		 *          "render": "browserName()"
11744
		 *        } ]
11745
		 *      } );
11746
		 *    } );
11747
		 *
11748
		 *  @example
11749
		 *    // As an object, extracting different data for the different types
11750
		 *    // This would be used with a data source such as:
11751
		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
11752
		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
11753
		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
11754
		 *    // the formatted phone number is the one that is shown in the table.
11755
		 *    $(document).ready( function() {
11756
		 *      $('#example').dataTable( {
11757
		 *        "columnDefs": [ {
11758
		 *          "targets": [ 0 ],
11759
		 *          "data": null, // Use the full data source object for the renderer's source
11760
		 *          "render": {
11761
		 *            "_": "phone",
11762
		 *            "filter": "phone_filter",
11763
		 *            "display": "phone_display"
11764
		 *          }
11765
		 *        } ]
11766
		 *      } );
11767
		 *    } );
11768
		 *
11769
		 *  @example
11770
		 *    // Use as a function to create a link from the data source
11771
		 *    $(document).ready( function() {
11772
		 *      $('#example').dataTable( {
11773
		 *        "columnDefs": [ {
11774
		 *          "targets": [ 0 ],
11775
		 *          "data": "download_link",
11776
		 *          "render": function ( data, type, full ) {
11777
		 *            return '<a href="'+data+'">Download</a>';
11778
		 *          }
11779
		 *        } ]
11780
		 *      } );
11781
		 *    } );
11782
		 */
11783
		"mRender": null,
11784
	
11785
	
11786
		/**
11787
		 * Change the cell type created for the column - either TD cells or TH cells. This
11788
		 * can be useful as TH cells have semantic meaning in the table body, allowing them
11789
		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
11790
		 *  @type string
11791
		 *  @default td
11792
		 *
11793
		 *  @name DataTable.defaults.column.cellType
11794
		 *  @dtopt Columns
11795
		 *
11796
		 *  @example
11797
		 *    // Make the first column use TH cells
11798
		 *    $(document).ready( function() {
11799
		 *      $('#example').dataTable( {
11800
		 *        "columnDefs": [ {
11801
		 *          "targets": [ 0 ],
11802
		 *          "cellType": "th"
11803
		 *        } ]
11804
		 *      } );
11805
		 *    } );
11806
		 */
11807
		"sCellType": "td",
11808
	
11809
	
11810
		/**
11811
		 * Class to give to each cell in this column.
11812
		 *  @type string
11813
		 *  @default <i>Empty string</i>
11814
		 *
11815
		 *  @name DataTable.defaults.column.class
11816
		 *  @dtopt Columns
11817
		 *
11818
		 *  @example
11819
		 *    // Using `columnDefs`
11820
		 *    $(document).ready( function() {
11821
		 *      $('#example').dataTable( {
11822
		 *        "columnDefs": [
11823
		 *          { "class": "my_class", "targets": [ 0 ] }
11824
		 *        ]
11825
		 *      } );
11826
		 *    } );
11827
		 *
11828
		 *  @example
11829
		 *    // Using `columns`
11830
		 *    $(document).ready( function() {
11831
		 *      $('#example').dataTable( {
11832
		 *        "columns": [
11833
		 *          { "class": "my_class" },
11834
		 *          null,
11835
		 *          null,
11836
		 *          null,
11837
		 *          null
11838
		 *        ]
11839
		 *      } );
11840
		 *    } );
11841
		 */
11842
		"sClass": "",
11843
	
11844
		/**
11845
		 * When DataTables calculates the column widths to assign to each column,
11846
		 * it finds the longest string in each column and then constructs a
11847
		 * temporary table and reads the widths from that. The problem with this
11848
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
11849
		 * string - thus the calculation can go wrong (doing it properly and putting
11850
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
11851
		 * a "work around" we provide this option. It will append its value to the
11852
		 * text that is found to be the longest string for the column - i.e. padding.
11853
		 * Generally you shouldn't need this!
11854
		 *  @type string
11855
		 *  @default <i>Empty string<i>
11856
		 *
11857
		 *  @name DataTable.defaults.column.contentPadding
11858
		 *  @dtopt Columns
11859
		 *
11860
		 *  @example
11861
		 *    // Using `columns`
11862
		 *    $(document).ready( function() {
11863
		 *      $('#example').dataTable( {
11864
		 *        "columns": [
11865
		 *          null,
11866
		 *          null,
11867
		 *          null,
11868
		 *          {
11869
		 *            "contentPadding": "mmm"
11870
		 *          }
11871
		 *        ]
11872
		 *      } );
11873
		 *    } );
11874
		 */
11875
		"sContentPadding": "",
11876
	
11877
	
11878
		/**
11879
		 * Allows a default value to be given for a column's data, and will be used
11880
		 * whenever a null data source is encountered (this can be because `data`
11881
		 * is set to null, or because the data source itself is null).
11882
		 *  @type string
11883
		 *  @default null
11884
		 *
11885
		 *  @name DataTable.defaults.column.defaultContent
11886
		 *  @dtopt Columns
11887
		 *
11888
		 *  @example
11889
		 *    // Using `columnDefs`
11890
		 *    $(document).ready( function() {
11891
		 *      $('#example').dataTable( {
11892
		 *        "columnDefs": [
11893
		 *          {
11894
		 *            "data": null,
11895
		 *            "defaultContent": "Edit",
11896
		 *            "targets": [ -1 ]
11897
		 *          }
11898
		 *        ]
11899
		 *      } );
11900
		 *    } );
11901
		 *
11902
		 *  @example
11903
		 *    // Using `columns`
11904
		 *    $(document).ready( function() {
11905
		 *      $('#example').dataTable( {
11906
		 *        "columns": [
11907
		 *          null,
11908
		 *          null,
11909
		 *          null,
11910
		 *          {
11911
		 *            "data": null,
11912
		 *            "defaultContent": "Edit"
11913
		 *          }
11914
		 *        ]
11915
		 *      } );
11916
		 *    } );
11917
		 */
11918
		"sDefaultContent": null,
11919
	
11920
	
11921
		/**
11922
		 * This parameter is only used in DataTables' server-side processing. It can
11923
		 * be exceptionally useful to know what columns are being displayed on the
11924
		 * client side, and to map these to database fields. When defined, the names
11925
		 * also allow DataTables to reorder information from the server if it comes
11926
		 * back in an unexpected order (i.e. if you switch your columns around on the
11927
		 * client-side, your server-side code does not also need updating).
11928
		 *  @type string
11929
		 *  @default <i>Empty string</i>
11930
		 *
11931
		 *  @name DataTable.defaults.column.name
11932
		 *  @dtopt Columns
11933
		 *
11934
		 *  @example
11935
		 *    // Using `columnDefs`
11936
		 *    $(document).ready( function() {
11937
		 *      $('#example').dataTable( {
11938
		 *        "columnDefs": [
11939
		 *          { "name": "engine", "targets": [ 0 ] },
11940
		 *          { "name": "browser", "targets": [ 1 ] },
11941
		 *          { "name": "platform", "targets": [ 2 ] },
11942
		 *          { "name": "version", "targets": [ 3 ] },
11943
		 *          { "name": "grade", "targets": [ 4 ] }
11944
		 *        ]
11945
		 *      } );
11946
		 *    } );
11947
		 *
11948
		 *  @example
11949
		 *    // Using `columns`
11950
		 *    $(document).ready( function() {
11951
		 *      $('#example').dataTable( {
11952
		 *        "columns": [
11953
		 *          { "name": "engine" },
11954
		 *          { "name": "browser" },
11955
		 *          { "name": "platform" },
11956
		 *          { "name": "version" },
11957
		 *          { "name": "grade" }
11958
		 *        ]
11959
		 *      } );
11960
		 *    } );
11961
		 */
11962
		"sName": "",
11963
	
11964
	
11965
		/**
11966
		 * Defines a data source type for the ordering which can be used to read
11967
		 * real-time information from the table (updating the internally cached
11968
		 * version) prior to ordering. This allows ordering to occur on user
11969
		 * editable elements such as form inputs.
11970
		 *  @type string
11971
		 *  @default std
11972
		 *
11973
		 *  @name DataTable.defaults.column.orderDataType
11974
		 *  @dtopt Columns
11975
		 *
11976
		 *  @example
11977
		 *    // Using `columnDefs`
11978
		 *    $(document).ready( function() {
11979
		 *      $('#example').dataTable( {
11980
		 *        "columnDefs": [
11981
		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
11982
		 *          { "type": "numeric", "targets": [ 3 ] },
11983
		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
11984
		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
11985
		 *        ]
11986
		 *      } );
11987
		 *    } );
11988
		 *
11989
		 *  @example
11990
		 *    // Using `columns`
11991
		 *    $(document).ready( function() {
11992
		 *      $('#example').dataTable( {
11993
		 *        "columns": [
11994
		 *          null,
11995
		 *          null,
11996
		 *          { "orderDataType": "dom-text" },
11997
		 *          { "orderDataType": "dom-text", "type": "numeric" },
11998
		 *          { "orderDataType": "dom-select" },
11999
		 *          { "orderDataType": "dom-checkbox" }
12000
		 *        ]
12001
		 *      } );
12002
		 *    } );
12003
		 */
12004
		"sSortDataType": "std",
12005
	
12006
	
12007
		/**
12008
		 * The title of this column.
12009
		 *  @type string
12010
		 *  @default null <i>Derived from the 'TH' value for this column in the
12011
		 *    original HTML table.</i>
12012
		 *
12013
		 *  @name DataTable.defaults.column.title
12014
		 *  @dtopt Columns
12015
		 *
12016
		 *  @example
12017
		 *    // Using `columnDefs`
12018
		 *    $(document).ready( function() {
12019
		 *      $('#example').dataTable( {
12020
		 *        "columnDefs": [
12021
		 *          { "title": "My column title", "targets": [ 0 ] }
12022
		 *        ]
12023
		 *      } );
12024
		 *    } );
12025
		 *
12026
		 *  @example
12027
		 *    // Using `columns`
12028
		 *    $(document).ready( function() {
12029
		 *      $('#example').dataTable( {
12030
		 *        "columns": [
12031
		 *          { "title": "My column title" },
12032
		 *          null,
12033
		 *          null,
12034
		 *          null,
12035
		 *          null
12036
		 *        ]
12037
		 *      } );
12038
		 *    } );
12039
		 */
12040
		"sTitle": null,
12041
	
12042
	
12043
		/**
12044
		 * The type allows you to specify how the data for this column will be
12045
		 * ordered. Four types (string, numeric, date and html (which will strip
12046
		 * HTML tags before ordering)) are currently available. Note that only date
12047
		 * formats understood by Javascript's Date() object will be accepted as type
12048
		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12049
		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12050
		 * through plug-ins.
12051
		 *  @type string
12052
		 *  @default null <i>Auto-detected from raw data</i>
12053
		 *
12054
		 *  @name DataTable.defaults.column.type
12055
		 *  @dtopt Columns
12056
		 *
12057
		 *  @example
12058
		 *    // Using `columnDefs`
12059
		 *    $(document).ready( function() {
12060
		 *      $('#example').dataTable( {
12061
		 *        "columnDefs": [
12062
		 *          { "type": "html", "targets": [ 0 ] }
12063
		 *        ]
12064
		 *      } );
12065
		 *    } );
12066
		 *
12067
		 *  @example
12068
		 *    // Using `columns`
12069
		 *    $(document).ready( function() {
12070
		 *      $('#example').dataTable( {
12071
		 *        "columns": [
12072
		 *          { "type": "html" },
12073
		 *          null,
12074
		 *          null,
12075
		 *          null,
12076
		 *          null
12077
		 *        ]
12078
		 *      } );
12079
		 *    } );
12080
		 */
12081
		"sType": null,
12082
	
12083
	
12084
		/**
12085
		 * Defining the width of the column, this parameter may take any CSS value
12086
		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12087
		 * been given a specific width through this interface ensuring that the table
12088
		 * remains readable.
12089
		 *  @type string
12090
		 *  @default null <i>Automatic</i>
12091
		 *
12092
		 *  @name DataTable.defaults.column.width
12093
		 *  @dtopt Columns
12094
		 *
12095
		 *  @example
12096
		 *    // Using `columnDefs`
12097
		 *    $(document).ready( function() {
12098
		 *      $('#example').dataTable( {
12099
		 *        "columnDefs": [
12100
		 *          { "width": "20%", "targets": [ 0 ] }
12101
		 *        ]
12102
		 *      } );
12103
		 *    } );
12104
		 *
12105
		 *  @example
12106
		 *    // Using `columns`
12107
		 *    $(document).ready( function() {
12108
		 *      $('#example').dataTable( {
12109
		 *        "columns": [
12110
		 *          { "width": "20%" },
12111
		 *          null,
12112
		 *          null,
12113
		 *          null,
12114
		 *          null
12115
		 *        ]
12116
		 *      } );
12117
		 *    } );
12118
		 */
12119
		"sWidth": null
12120
	};
12121
	
12122
	_fnHungarianMap( DataTable.defaults.column );
12123
	
12124
	
12125
	
12126
	/**
12127
	 * DataTables settings object - this holds all the information needed for a
12128
	 * given table, including configuration, data and current application of the
12129
	 * table options. DataTables does not have a single instance for each DataTable
12130
	 * with the settings attached to that instance, but rather instances of the
12131
	 * DataTable "class" are created on-the-fly as needed (typically by a
12132
	 * $().dataTable() call) and the settings object is then applied to that
12133
	 * instance.
12134
	 *
12135
	 * Note that this object is related to {@link DataTable.defaults} but this
12136
	 * one is the internal data store for DataTables's cache of columns. It should
12137
	 * NOT be manipulated outside of DataTables. Any configuration should be done
12138
	 * through the initialisation options.
12139
	 *  @namespace
12140
	 *  @todo Really should attach the settings object to individual instances so we
12141
	 *    don't need to create new instances on each $().dataTable() call (if the
12142
	 *    table already exists). It would also save passing oSettings around and
12143
	 *    into every single function. However, this is a very significant
12144
	 *    architecture change for DataTables and will almost certainly break
12145
	 *    backwards compatibility with older installations. This is something that
12146
	 *    will be done in 2.0.
12147
	 */
12148
	DataTable.models.oSettings = {
12149
		/**
12150
		 * Primary features of DataTables and their enablement state.
12151
		 *  @namespace
12152
		 */
12153
		"oFeatures": {
12154
	
12155
			/**
12156
			 * Flag to say if DataTables should automatically try to calculate the
12157
			 * optimum table and columns widths (true) or not (false).
12158
			 * Note that this parameter will be set by the initialisation routine. To
12159
			 * set a default use {@link DataTable.defaults}.
12160
			 *  @type boolean
12161
			 */
12162
			"bAutoWidth": null,
12163
	
12164
			/**
12165
			 * Delay the creation of TR and TD elements until they are actually
12166
			 * needed by a driven page draw. This can give a significant speed
12167
			 * increase for Ajax source and Javascript source data, but makes no
12168
			 * difference at all fro DOM and server-side processing tables.
12169
			 * Note that this parameter will be set by the initialisation routine. To
12170
			 * set a default use {@link DataTable.defaults}.
12171
			 *  @type boolean
12172
			 */
12173
			"bDeferRender": null,
12174
	
12175
			/**
12176
			 * Enable filtering on the table or not. Note that if this is disabled
12177
			 * then there is no filtering at all on the table, including fnFilter.
12178
			 * To just remove the filtering input use sDom and remove the 'f' option.
12179
			 * Note that this parameter will be set by the initialisation routine. To
12180
			 * set a default use {@link DataTable.defaults}.
12181
			 *  @type boolean
12182
			 */
12183
			"bFilter": null,
12184
	
12185
			/**
12186
			 * Table information element (the 'Showing x of y records' div) enable
12187
			 * flag.
12188
			 * Note that this parameter will be set by the initialisation routine. To
12189
			 * set a default use {@link DataTable.defaults}.
12190
			 *  @type boolean
12191
			 */
12192
			"bInfo": null,
12193
	
12194
			/**
12195
			 * Present a user control allowing the end user to change the page size
12196
			 * when pagination is enabled.
12197
			 * Note that this parameter will be set by the initialisation routine. To
12198
			 * set a default use {@link DataTable.defaults}.
12199
			 *  @type boolean
12200
			 */
12201
			"bLengthChange": null,
12202
	
12203
			/**
12204
			 * Pagination enabled or not. Note that if this is disabled then length
12205
			 * changing must also be disabled.
12206
			 * Note that this parameter will be set by the initialisation routine. To
12207
			 * set a default use {@link DataTable.defaults}.
12208
			 *  @type boolean
12209
			 */
12210
			"bPaginate": null,
12211
	
12212
			/**
12213
			 * Processing indicator enable flag whenever DataTables is enacting a
12214
			 * user request - typically an Ajax request for server-side processing.
12215
			 * Note that this parameter will be set by the initialisation routine. To
12216
			 * set a default use {@link DataTable.defaults}.
12217
			 *  @type boolean
12218
			 */
12219
			"bProcessing": null,
12220
	
12221
			/**
12222
			 * Server-side processing enabled flag - when enabled DataTables will
12223
			 * get all data from the server for every draw - there is no filtering,
12224
			 * sorting or paging done on the client-side.
12225
			 * Note that this parameter will be set by the initialisation routine. To
12226
			 * set a default use {@link DataTable.defaults}.
12227
			 *  @type boolean
12228
			 */
12229
			"bServerSide": null,
12230
	
12231
			/**
12232
			 * Sorting enablement flag.
12233
			 * Note that this parameter will be set by the initialisation routine. To
12234
			 * set a default use {@link DataTable.defaults}.
12235
			 *  @type boolean
12236
			 */
12237
			"bSort": null,
12238
	
12239
			/**
12240
			 * Multi-column sorting
12241
			 * Note that this parameter will be set by the initialisation routine. To
12242
			 * set a default use {@link DataTable.defaults}.
12243
			 *  @type boolean
12244
			 */
12245
			"bSortMulti": null,
12246
	
12247
			/**
12248
			 * Apply a class to the columns which are being sorted to provide a
12249
			 * visual highlight or not. This can slow things down when enabled since
12250
			 * there is a lot of DOM interaction.
12251
			 * Note that this parameter will be set by the initialisation routine. To
12252
			 * set a default use {@link DataTable.defaults}.
12253
			 *  @type boolean
12254
			 */
12255
			"bSortClasses": null,
12256
	
12257
			/**
12258
			 * State saving enablement flag.
12259
			 * Note that this parameter will be set by the initialisation routine. To
12260
			 * set a default use {@link DataTable.defaults}.
12261
			 *  @type boolean
12262
			 */
12263
			"bStateSave": null
12264
		},
12265
	
12266
	
12267
		/**
12268
		 * Scrolling settings for a table.
12269
		 *  @namespace
12270
		 */
12271
		"oScroll": {
12272
			/**
12273
			 * When the table is shorter in height than sScrollY, collapse the
12274
			 * table container down to the height of the table (when true).
12275
			 * Note that this parameter will be set by the initialisation routine. To
12276
			 * set a default use {@link DataTable.defaults}.
12277
			 *  @type boolean
12278
			 */
12279
			"bCollapse": null,
12280
	
12281
			/**
12282
			 * Width of the scrollbar for the web-browser's platform. Calculated
12283
			 * during table initialisation.
12284
			 *  @type int
12285
			 *  @default 0
12286
			 */
12287
			"iBarWidth": 0,
12288
	
12289
			/**
12290
			 * Viewport width for horizontal scrolling. Horizontal scrolling is
12291
			 * disabled if an empty string.
12292
			 * Note that this parameter will be set by the initialisation routine. To
12293
			 * set a default use {@link DataTable.defaults}.
12294
			 *  @type string
12295
			 */
12296
			"sX": null,
12297
	
12298
			/**
12299
			 * Width to expand the table to when using x-scrolling. Typically you
12300
			 * should not need to use this.
12301
			 * Note that this parameter will be set by the initialisation routine. To
12302
			 * set a default use {@link DataTable.defaults}.
12303
			 *  @type string
12304
			 *  @deprecated
12305
			 */
12306
			"sXInner": null,
12307
	
12308
			/**
12309
			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
12310
			 * if an empty string.
12311
			 * Note that this parameter will be set by the initialisation routine. To
12312
			 * set a default use {@link DataTable.defaults}.
12313
			 *  @type string
12314
			 */
12315
			"sY": null
12316
		},
12317
	
12318
		/**
12319
		 * Language information for the table.
12320
		 *  @namespace
12321
		 *  @extends DataTable.defaults.oLanguage
12322
		 */
12323
		"oLanguage": {
12324
			/**
12325
			 * Information callback function. See
12326
			 * {@link DataTable.defaults.fnInfoCallback}
12327
			 *  @type function
12328
			 *  @default null
12329
			 */
12330
			"fnInfoCallback": null
12331
		},
12332
	
12333
		/**
12334
		 * Browser support parameters
12335
		 *  @namespace
12336
		 */
12337
		"oBrowser": {
12338
			/**
12339
			 * Indicate if the browser incorrectly calculates width:100% inside a
12340
			 * scrolling element (IE6/7)
12341
			 *  @type boolean
12342
			 *  @default false
12343
			 */
12344
			"bScrollOversize": false,
12345
	
12346
			/**
12347
			 * Determine if the vertical scrollbar is on the right or left of the
12348
			 * scrolling container - needed for rtl language layout, although not
12349
			 * all browsers move the scrollbar (Safari).
12350
			 *  @type boolean
12351
			 *  @default false
12352
			 */
12353
			"bScrollbarLeft": false
12354
		},
12355
	
12356
	
12357
		"ajax": null,
12358
	
12359
	
12360
		/**
12361
		 * Array referencing the nodes which are used for the features. The
12362
		 * parameters of this object match what is allowed by sDom - i.e.
12363
		 *   <ul>
12364
		 *     <li>'l' - Length changing</li>
12365
		 *     <li>'f' - Filtering input</li>
12366
		 *     <li>'t' - The table!</li>
12367
		 *     <li>'i' - Information</li>
12368
		 *     <li>'p' - Pagination</li>
12369
		 *     <li>'r' - pRocessing</li>
12370
		 *   </ul>
12371
		 *  @type array
12372
		 *  @default []
12373
		 */
12374
		"aanFeatures": [],
12375
	
12376
		/**
12377
		 * Store data information - see {@link DataTable.models.oRow} for detailed
12378
		 * information.
12379
		 *  @type array
12380
		 *  @default []
12381
		 */
12382
		"aoData": [],
12383
	
12384
		/**
12385
		 * Array of indexes which are in the current display (after filtering etc)
12386
		 *  @type array
12387
		 *  @default []
12388
		 */
12389
		"aiDisplay": [],
12390
	
12391
		/**
12392
		 * Array of indexes for display - no filtering
12393
		 *  @type array
12394
		 *  @default []
12395
		 */
12396
		"aiDisplayMaster": [],
12397
	
12398
		/**
12399
		 * Store information about each column that is in use
12400
		 *  @type array
12401
		 *  @default []
12402
		 */
12403
		"aoColumns": [],
12404
	
12405
		/**
12406
		 * Store information about the table's header
12407
		 *  @type array
12408
		 *  @default []
12409
		 */
12410
		"aoHeader": [],
12411
	
12412
		/**
12413
		 * Store information about the table's footer
12414
		 *  @type array
12415
		 *  @default []
12416
		 */
12417
		"aoFooter": [],
12418
	
12419
		/**
12420
		 * Store the applied global search information in case we want to force a
12421
		 * research or compare the old search to a new one.
12422
		 * Note that this parameter will be set by the initialisation routine. To
12423
		 * set a default use {@link DataTable.defaults}.
12424
		 *  @namespace
12425
		 *  @extends DataTable.models.oSearch
12426
		 */
12427
		"oPreviousSearch": {},
12428
	
12429
		/**
12430
		 * Store the applied search for each column - see
12431
		 * {@link DataTable.models.oSearch} for the format that is used for the
12432
		 * filtering information for each column.
12433
		 *  @type array
12434
		 *  @default []
12435
		 */
12436
		"aoPreSearchCols": [],
12437
	
12438
		/**
12439
		 * Sorting that is applied to the table. Note that the inner arrays are
12440
		 * used in the following manner:
12441
		 * <ul>
12442
		 *   <li>Index 0 - column number</li>
12443
		 *   <li>Index 1 - current sorting direction</li>
12444
		 * </ul>
12445
		 * Note that this parameter will be set by the initialisation routine. To
12446
		 * set a default use {@link DataTable.defaults}.
12447
		 *  @type array
12448
		 *  @todo These inner arrays should really be objects
12449
		 */
12450
		"aaSorting": null,
12451
	
12452
		/**
12453
		 * Sorting that is always applied to the table (i.e. prefixed in front of
12454
		 * aaSorting).
12455
		 * Note that this parameter will be set by the initialisation routine. To
12456
		 * set a default use {@link DataTable.defaults}.
12457
		 *  @type array
12458
		 *  @default []
12459
		 */
12460
		"aaSortingFixed": [],
12461
	
12462
		/**
12463
		 * Classes to use for the striping of a table.
12464
		 * Note that this parameter will be set by the initialisation routine. To
12465
		 * set a default use {@link DataTable.defaults}.
12466
		 *  @type array
12467
		 *  @default []
12468
		 */
12469
		"asStripeClasses": null,
12470
	
12471
		/**
12472
		 * If restoring a table - we should restore its striping classes as well
12473
		 *  @type array
12474
		 *  @default []
12475
		 */
12476
		"asDestroyStripes": [],
12477
	
12478
		/**
12479
		 * If restoring a table - we should restore its width
12480
		 *  @type int
12481
		 *  @default 0
12482
		 */
12483
		"sDestroyWidth": 0,
12484
	
12485
		/**
12486
		 * Callback functions array for every time a row is inserted (i.e. on a draw).
12487
		 *  @type array
12488
		 *  @default []
12489
		 */
12490
		"aoRowCallback": [],
12491
	
12492
		/**
12493
		 * Callback functions for the header on each draw.
12494
		 *  @type array
12495
		 *  @default []
12496
		 */
12497
		"aoHeaderCallback": [],
12498
	
12499
		/**
12500
		 * Callback function for the footer on each draw.
12501
		 *  @type array
12502
		 *  @default []
12503
		 */
12504
		"aoFooterCallback": [],
12505
	
12506
		/**
12507
		 * Array of callback functions for draw callback functions
12508
		 *  @type array
12509
		 *  @default []
12510
		 */
12511
		"aoDrawCallback": [],
12512
	
12513
		/**
12514
		 * Array of callback functions for row created function
12515
		 *  @type array
12516
		 *  @default []
12517
		 */
12518
		"aoRowCreatedCallback": [],
12519
	
12520
		/**
12521
		 * Callback functions for just before the table is redrawn. A return of
12522
		 * false will be used to cancel the draw.
12523
		 *  @type array
12524
		 *  @default []
12525
		 */
12526
		"aoPreDrawCallback": [],
12527
	
12528
		/**
12529
		 * Callback functions for when the table has been initialised.
12530
		 *  @type array
12531
		 *  @default []
12532
		 */
12533
		"aoInitComplete": [],
12534
	
12535
	
12536
		/**
12537
		 * Callbacks for modifying the settings to be stored for state saving, prior to
12538
		 * saving state.
12539
		 *  @type array
12540
		 *  @default []
12541
		 */
12542
		"aoStateSaveParams": [],
12543
	
12544
		/**
12545
		 * Callbacks for modifying the settings that have been stored for state saving
12546
		 * prior to using the stored values to restore the state.
12547
		 *  @type array
12548
		 *  @default []
12549
		 */
12550
		"aoStateLoadParams": [],
12551
	
12552
		/**
12553
		 * Callbacks for operating on the settings object once the saved state has been
12554
		 * loaded
12555
		 *  @type array
12556
		 *  @default []
12557
		 */
12558
		"aoStateLoaded": [],
12559
	
12560
		/**
12561
		 * Cache the table ID for quick access
12562
		 *  @type string
12563
		 *  @default <i>Empty string</i>
12564
		 */
12565
		"sTableId": "",
12566
	
12567
		/**
12568
		 * The TABLE node for the main table
12569
		 *  @type node
12570
		 *  @default null
12571
		 */
12572
		"nTable": null,
12573
	
12574
		/**
12575
		 * Permanent ref to the thead element
12576
		 *  @type node
12577
		 *  @default null
12578
		 */
12579
		"nTHead": null,
12580
	
12581
		/**
12582
		 * Permanent ref to the tfoot element - if it exists
12583
		 *  @type node
12584
		 *  @default null
12585
		 */
12586
		"nTFoot": null,
12587
	
12588
		/**
12589
		 * Permanent ref to the tbody element
12590
		 *  @type node
12591
		 *  @default null
12592
		 */
12593
		"nTBody": null,
12594
	
12595
		/**
12596
		 * Cache the wrapper node (contains all DataTables controlled elements)
12597
		 *  @type node
12598
		 *  @default null
12599
		 */
12600
		"nTableWrapper": null,
12601
	
12602
		/**
12603
		 * Indicate if when using server-side processing the loading of data
12604
		 * should be deferred until the second draw.
12605
		 * Note that this parameter will be set by the initialisation routine. To
12606
		 * set a default use {@link DataTable.defaults}.
12607
		 *  @type boolean
12608
		 *  @default false
12609
		 */
12610
		"bDeferLoading": false,
12611
	
12612
		/**
12613
		 * Indicate if all required information has been read in
12614
		 *  @type boolean
12615
		 *  @default false
12616
		 */
12617
		"bInitialised": false,
12618
	
12619
		/**
12620
		 * Information about open rows. Each object in the array has the parameters
12621
		 * 'nTr' and 'nParent'
12622
		 *  @type array
12623
		 *  @default []
12624
		 */
12625
		"aoOpenRows": [],
12626
	
12627
		/**
12628
		 * Dictate the positioning of DataTables' control elements - see
12629
		 * {@link DataTable.model.oInit.sDom}.
12630
		 * Note that this parameter will be set by the initialisation routine. To
12631
		 * set a default use {@link DataTable.defaults}.
12632
		 *  @type string
12633
		 *  @default null
12634
		 */
12635
		"sDom": null,
12636
	
12637
		/**
12638
		 * Which type of pagination should be used.
12639
		 * Note that this parameter will be set by the initialisation routine. To
12640
		 * set a default use {@link DataTable.defaults}.
12641
		 *  @type string
12642
		 *  @default two_button
12643
		 */
12644
		"sPaginationType": "two_button",
12645
	
12646
		/**
12647
		 * The state duration (for `stateSave`) in seconds.
12648
		 * Note that this parameter will be set by the initialisation routine. To
12649
		 * set a default use {@link DataTable.defaults}.
12650
		 *  @type int
12651
		 *  @default 0
12652
		 */
12653
		"iStateDuration": 0,
12654
	
12655
		/**
12656
		 * Array of callback functions for state saving. Each array element is an
12657
		 * object with the following parameters:
12658
		 *   <ul>
12659
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
12660
		 *       and the JSON string to save that has been thus far created. Returns
12661
		 *       a JSON string to be inserted into a json object
12662
		 *       (i.e. '"param": [ 0, 1, 2]')</li>
12663
		 *     <li>string:sName - name of callback</li>
12664
		 *   </ul>
12665
		 *  @type array
12666
		 *  @default []
12667
		 */
12668
		"aoStateSave": [],
12669
	
12670
		/**
12671
		 * Array of callback functions for state loading. Each array element is an
12672
		 * object with the following parameters:
12673
		 *   <ul>
12674
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
12675
		 *       and the object stored. May return false to cancel state loading</li>
12676
		 *     <li>string:sName - name of callback</li>
12677
		 *   </ul>
12678
		 *  @type array
12679
		 *  @default []
12680
		 */
12681
		"aoStateLoad": [],
12682
	
12683
		/**
12684
		 * State that was loaded. Useful for back reference
12685
		 *  @type object
12686
		 *  @default null
12687
		 */
12688
		"oLoadedState": null,
12689
	
12690
		/**
12691
		 * Source url for AJAX data for the table.
12692
		 * Note that this parameter will be set by the initialisation routine. To
12693
		 * set a default use {@link DataTable.defaults}.
12694
		 *  @type string
12695
		 *  @default null
12696
		 */
12697
		"sAjaxSource": null,
12698
	
12699
		/**
12700
		 * Property from a given object from which to read the table data from. This
12701
		 * can be an empty string (when not server-side processing), in which case
12702
		 * it is  assumed an an array is given directly.
12703
		 * Note that this parameter will be set by the initialisation routine. To
12704
		 * set a default use {@link DataTable.defaults}.
12705
		 *  @type string
12706
		 */
12707
		"sAjaxDataProp": null,
12708
	
12709
		/**
12710
		 * Note if draw should be blocked while getting data
12711
		 *  @type boolean
12712
		 *  @default true
12713
		 */
12714
		"bAjaxDataGet": true,
12715
	
12716
		/**
12717
		 * The last jQuery XHR object that was used for server-side data gathering.
12718
		 * This can be used for working with the XHR information in one of the
12719
		 * callbacks
12720
		 *  @type object
12721
		 *  @default null
12722
		 */
12723
		"jqXHR": null,
12724
	
12725
		/**
12726
		 * JSON returned from the server in the last Ajax request
12727
		 *  @type object
12728
		 *  @default undefined
12729
		 */
12730
		"json": undefined,
12731
	
12732
		/**
12733
		 * Data submitted as part of the last Ajax request
12734
		 *  @type object
12735
		 *  @default undefined
12736
		 */
12737
		"oAjaxData": undefined,
12738
	
12739
		/**
12740
		 * Function to get the server-side data.
12741
		 * Note that this parameter will be set by the initialisation routine. To
12742
		 * set a default use {@link DataTable.defaults}.
12743
		 *  @type function
12744
		 */
12745
		"fnServerData": null,
12746
	
12747
		/**
12748
		 * Functions which are called prior to sending an Ajax request so extra
12749
		 * parameters can easily be sent to the server
12750
		 *  @type array
12751
		 *  @default []
12752
		 */
12753
		"aoServerParams": [],
12754
	
12755
		/**
12756
		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
12757
		 * required).
12758
		 * Note that this parameter will be set by the initialisation routine. To
12759
		 * set a default use {@link DataTable.defaults}.
12760
		 *  @type string
12761
		 */
12762
		"sServerMethod": null,
12763
	
12764
		/**
12765
		 * Format numbers for display.
12766
		 * Note that this parameter will be set by the initialisation routine. To
12767
		 * set a default use {@link DataTable.defaults}.
12768
		 *  @type function
12769
		 */
12770
		"fnFormatNumber": null,
12771
	
12772
		/**
12773
		 * List of options that can be used for the user selectable length menu.
12774
		 * Note that this parameter will be set by the initialisation routine. To
12775
		 * set a default use {@link DataTable.defaults}.
12776
		 *  @type array
12777
		 *  @default []
12778
		 */
12779
		"aLengthMenu": null,
12780
	
12781
		/**
12782
		 * Counter for the draws that the table does. Also used as a tracker for
12783
		 * server-side processing
12784
		 *  @type int
12785
		 *  @default 0
12786
		 */
12787
		"iDraw": 0,
12788
	
12789
		/**
12790
		 * Indicate if a redraw is being done - useful for Ajax
12791
		 *  @type boolean
12792
		 *  @default false
12793
		 */
12794
		"bDrawing": false,
12795
	
12796
		/**
12797
		 * Draw index (iDraw) of the last error when parsing the returned data
12798
		 *  @type int
12799
		 *  @default -1
12800
		 */
12801
		"iDrawError": -1,
12802
	
12803
		/**
12804
		 * Paging display length
12805
		 *  @type int
12806
		 *  @default 10
12807
		 */
12808
		"_iDisplayLength": 10,
12809
	
12810
		/**
12811
		 * Paging start point - aiDisplay index
12812
		 *  @type int
12813
		 *  @default 0
12814
		 */
12815
		"_iDisplayStart": 0,
12816
	
12817
		/**
12818
		 * Server-side processing - number of records in the result set
12819
		 * (i.e. before filtering), Use fnRecordsTotal rather than
12820
		 * this property to get the value of the number of records, regardless of
12821
		 * the server-side processing setting.
12822
		 *  @type int
12823
		 *  @default 0
12824
		 *  @private
12825
		 */
12826
		"_iRecordsTotal": 0,
12827
	
12828
		/**
12829
		 * Server-side processing - number of records in the current display set
12830
		 * (i.e. after filtering). Use fnRecordsDisplay rather than
12831
		 * this property to get the value of the number of records, regardless of
12832
		 * the server-side processing setting.
12833
		 *  @type boolean
12834
		 *  @default 0
12835
		 *  @private
12836
		 */
12837
		"_iRecordsDisplay": 0,
12838
	
12839
		/**
12840
		 * Flag to indicate if jQuery UI marking and classes should be used.
12841
		 * Note that this parameter will be set by the initialisation routine. To
12842
		 * set a default use {@link DataTable.defaults}.
12843
		 *  @type boolean
12844
		 */
12845
		"bJUI": null,
12846
	
12847
		/**
12848
		 * The classes to use for the table
12849
		 *  @type object
12850
		 *  @default {}
12851
		 */
12852
		"oClasses": {},
12853
	
12854
		/**
12855
		 * Flag attached to the settings object so you can check in the draw
12856
		 * callback if filtering has been done in the draw. Deprecated in favour of
12857
		 * events.
12858
		 *  @type boolean
12859
		 *  @default false
12860
		 *  @deprecated
12861
		 */
12862
		"bFiltered": false,
12863
	
12864
		/**
12865
		 * Flag attached to the settings object so you can check in the draw
12866
		 * callback if sorting has been done in the draw. Deprecated in favour of
12867
		 * events.
12868
		 *  @type boolean
12869
		 *  @default false
12870
		 *  @deprecated
12871
		 */
12872
		"bSorted": false,
12873
	
12874
		/**
12875
		 * Indicate that if multiple rows are in the header and there is more than
12876
		 * one unique cell per column, if the top one (true) or bottom one (false)
12877
		 * should be used for sorting / title by DataTables.
12878
		 * Note that this parameter will be set by the initialisation routine. To
12879
		 * set a default use {@link DataTable.defaults}.
12880
		 *  @type boolean
12881
		 */
12882
		"bSortCellsTop": null,
12883
	
12884
		/**
12885
		 * Initialisation object that is used for the table
12886
		 *  @type object
12887
		 *  @default null
12888
		 */
12889
		"oInit": null,
12890
	
12891
		/**
12892
		 * Destroy callback functions - for plug-ins to attach themselves to the
12893
		 * destroy so they can clean up markup and events.
12894
		 *  @type array
12895
		 *  @default []
12896
		 */
12897
		"aoDestroyCallback": [],
12898
	
12899
	
12900
		/**
12901
		 * Get the number of records in the current record set, before filtering
12902
		 *  @type function
12903
		 */
12904
		"fnRecordsTotal": function ()
12905
		{
12906
			return _fnDataSource( this ) == 'ssp' ?
12907
				this._iRecordsTotal * 1 :
12908
				this.aiDisplayMaster.length;
12909
		},
12910
	
12911
		/**
12912
		 * Get the number of records in the current record set, after filtering
12913
		 *  @type function
12914
		 */
12915
		"fnRecordsDisplay": function ()
12916
		{
12917
			return _fnDataSource( this ) == 'ssp' ?
12918
				this._iRecordsDisplay * 1 :
12919
				this.aiDisplay.length;
12920
		},
12921
	
12922
		/**
12923
		 * Get the display end point - aiDisplay index
12924
		 *  @type function
12925
		 */
12926
		"fnDisplayEnd": function ()
12927
		{
12928
			var
12929
				len      = this._iDisplayLength,
12930
				start    = this._iDisplayStart,
12931
				calc     = start + len,
12932
				records  = this.aiDisplay.length,
12933
				features = this.oFeatures,
12934
				paginate = features.bPaginate;
12935
	
12936
			if ( features.bServerSide ) {
12937
				return paginate === false || len === -1 ?
12938
					start + records :
12939
					Math.min( start+len, this._iRecordsDisplay );
12940
			}
12941
			else {
12942
				return ! paginate || calc>records || len===-1 ?
12943
					records :
12944
					calc;
12945
			}
12946
		},
12947
	
12948
		/**
12949
		 * The DataTables object for this table
12950
		 *  @type object
12951
		 *  @default null
12952
		 */
12953
		"oInstance": null,
12954
	
12955
		/**
12956
		 * Unique identifier for each instance of the DataTables object. If there
12957
		 * is an ID on the table node, then it takes that value, otherwise an
12958
		 * incrementing internal counter is used.
12959
		 *  @type string
12960
		 *  @default null
12961
		 */
12962
		"sInstance": null,
12963
	
12964
		/**
12965
		 * tabindex attribute value that is added to DataTables control elements, allowing
12966
		 * keyboard navigation of the table and its controls.
12967
		 */
12968
		"iTabIndex": 0,
12969
	
12970
		/**
12971
		 * DIV container for the footer scrolling table if scrolling
12972
		 */
12973
		"nScrollHead": null,
12974
	
12975
		/**
12976
		 * DIV container for the footer scrolling table if scrolling
12977
		 */
12978
		"nScrollFoot": null,
12979
	
12980
		/**
12981
		 * Last applied sort
12982
		 *  @type array
12983
		 *  @default []
12984
		 */
12985
		"aLastSort": [],
12986
	
12987
		/**
12988
		 * Stored plug-in instances
12989
		 *  @type object
12990
		 *  @default {}
12991
		 */
12992
		"oPlugins": {}
12993
	};
12994

    
12995
	/**
12996
	 * Extension object for DataTables that is used to provide all extension
12997
	 * options.
12998
	 *
12999
	 * Note that the `DataTable.ext` object is available through
13000
	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13001
	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13002
	 *  @namespace
13003
	 *  @extends DataTable.models.ext
13004
	 */
13005
	
13006
	
13007
	/**
13008
	 * DataTables extensions
13009
	 * 
13010
	 * This namespace acts as a collection area for plug-ins that can be used to
13011
	 * extend DataTables capabilities. Indeed many of the build in methods
13012
	 * use this method to provide their own capabilities (sorting methods for
13013
	 * example).
13014
	 *
13015
	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13016
	 * reasons
13017
	 *
13018
	 *  @namespace
13019
	 */
13020
	DataTable.ext = _ext = {
13021
		/**
13022
		 * Element class names
13023
		 *
13024
		 *  @type object
13025
		 *  @default {}
13026
		 */
13027
		classes: {},
13028
	
13029
	
13030
		/**
13031
		 * Error reporting.
13032
		 * 
13033
		 * How should DataTables report an error. Can take the value 'alert' or
13034
		 * 'throw'
13035
		 *
13036
		 *  @type string
13037
		 *  @default alert
13038
		 */
13039
		errMode: "alert",
13040
	
13041
	
13042
		/**
13043
		 * Feature plug-ins.
13044
		 * 
13045
		 * This is an array of objects which describe the feature plug-ins that are
13046
		 * available to DataTables. These feature plug-ins are then available for
13047
		 * use through the `dom` initialisation option.
13048
		 * 
13049
		 * Each feature plug-in is described by an object which must have the
13050
		 * following properties:
13051
		 * 
13052
		 * * `fnInit` - function that is used to initialise the plug-in,
13053
		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13054
		 *   instillation option. This is case sensitive.
13055
		 *
13056
		 * The `fnInit` function has the following input parameters:
13057
		 *
13058
		 * 1. `{object}` DataTables settings object: see
13059
		 *    {@link DataTable.models.oSettings}
13060
		 *
13061
		 * And the following return is expected:
13062
		 * 
13063
		 * * {node|null} The element which contains your feature. Note that the
13064
		 *   return may also be void if your plug-in does not require to inject any
13065
		 *   DOM elements into DataTables control (`dom`) - for example this might
13066
		 *   be useful when developing a plug-in which allows table control via
13067
		 *   keyboard entry
13068
		 *
13069
		 *  @type array
13070
		 *
13071
		 *  @example
13072
		 *    $.fn.dataTable.ext.features.push( {
13073
		 *      "fnInit": function( oSettings ) {
13074
		 *        return new TableTools( { "oDTSettings": oSettings } );
13075
		 *      },
13076
		 *      "cFeature": "T"
13077
		 *    } );
13078
		 */
13079
		feature: [],
13080
	
13081
	
13082
		/**
13083
		 * Row searching.
13084
		 * 
13085
		 * This method of searching is complimentary to the default type based
13086
		 * searching, and a lot more comprehensive as it allows you complete control
13087
		 * over the searching logic. Each element in this array is a function
13088
		 * (parameters described below) that is called for every row in the table,
13089
		 * and your logic decides if it should be included in the searching data set
13090
		 * or not.
13091
		 *
13092
		 * Searching functions have the following input parameters:
13093
		 *
13094
		 * 1. `{object}` DataTables settings object: see
13095
		 *    {@link DataTable.models.oSettings}
13096
		 * 2. `{array|object}` Data for the row to be processed (same as the
13097
		 *    original format that was passed in as the data source, or an array
13098
		 *    from a DOM data source
13099
		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13100
		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13101
		 *
13102
		 * And the following return is expected:
13103
		 *
13104
		 * * {boolean} Include the row in the searched result set (true) or not
13105
		 *   (false)
13106
		 *
13107
		 * Note that as with the main search ability in DataTables, technically this
13108
		 * is "filtering", since it is subtractive. However, for consistency in
13109
		 * naming we call it searching here.
13110
		 *
13111
		 *  @type array
13112
		 *  @default []
13113
		 *
13114
		 *  @example
13115
		 *    // The following example shows custom search being applied to the
13116
		 *    // fourth column (i.e. the data[3] index) based on two input values
13117
		 *    // from the end-user, matching the data in a certain range.
13118
		 *    $.fn.dataTable.ext.search.push(
13119
		 *      function( settings, data, dataIndex ) {
13120
		 *        var min = document.getElementById('min').value * 1;
13121
		 *        var max = document.getElementById('max').value * 1;
13122
		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13123
		 *
13124
		 *        if ( min == "" && max == "" ) {
13125
		 *          return true;
13126
		 *        }
13127
		 *        else if ( min == "" && version < max ) {
13128
		 *          return true;
13129
		 *        }
13130
		 *        else if ( min < version && "" == max ) {
13131
		 *          return true;
13132
		 *        }
13133
		 *        else if ( min < version && version < max ) {
13134
		 *          return true;
13135
		 *        }
13136
		 *        return false;
13137
		 *      }
13138
		 *    );
13139
		 */
13140
		search: [],
13141
	
13142
	
13143
		/**
13144
		 * Internal functions, exposed for used in plug-ins.
13145
		 * 
13146
		 * Please note that you should not need to use the internal methods for
13147
		 * anything other than a plug-in (and even then, try to avoid if possible).
13148
		 * The internal function may change between releases.
13149
		 *
13150
		 *  @type object
13151
		 *  @default {}
13152
		 */
13153
		internal: {},
13154
	
13155
	
13156
		/**
13157
		 * Legacy configuration options. Enable and disable legacy options that
13158
		 * are available in DataTables.
13159
		 *
13160
		 *  @type object
13161
		 */
13162
		legacy: {
13163
			/**
13164
			 * Enable / disable DataTables 1.9 compatible server-side processing
13165
			 * requests
13166
			 *
13167
			 *  @type boolean
13168
			 *  @default null
13169
			 */
13170
			ajax: null
13171
		},
13172
	
13173
	
13174
		/**
13175
		 * Pagination plug-in methods.
13176
		 * 
13177
		 * Each entry in this object is a function and defines which buttons should
13178
		 * be shown by the pagination rendering method that is used for the table:
13179
		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13180
		 * buttons are displayed in the document, while the functions here tell it
13181
		 * what buttons to display. This is done by returning an array of button
13182
		 * descriptions (what each button will do).
13183
		 *
13184
		 * Pagination types (the four built in options and any additional plug-in
13185
		 * options defined here) can be used through the `paginationType`
13186
		 * initialisation parameter.
13187
		 *
13188
		 * The functions defined take two parameters:
13189
		 *
13190
		 * 1. `{int} page` The current page index
13191
		 * 2. `{int} pages` The number of pages in the table
13192
		 *
13193
		 * Each function is expected to return an array where each element of the
13194
		 * array can be one of:
13195
		 *
13196
		 * * `first` - Jump to first page when activated
13197
		 * * `last` - Jump to last page when activated
13198
		 * * `previous` - Show previous page when activated
13199
		 * * `next` - Show next page when activated
13200
		 * * `{int}` - Show page of the index given
13201
		 * * `{array}` - A nested array containing the above elements to add a
13202
		 *   containing 'DIV' element (might be useful for styling).
13203
		 *
13204
		 * Note that DataTables v1.9- used this object slightly differently whereby
13205
		 * an object with two functions would be defined for each plug-in. That
13206
		 * ability is still supported by DataTables 1.10+ to provide backwards
13207
		 * compatibility, but this option of use is now decremented and no longer
13208
		 * documented in DataTables 1.10+.
13209
		 *
13210
		 *  @type object
13211
		 *  @default {}
13212
		 *
13213
		 *  @example
13214
		 *    // Show previous, next and current page buttons only
13215
		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13216
		 *      return [ 'previous', page, 'next' ];
13217
		 *    };
13218
		 */
13219
		pager: {},
13220
	
13221
	
13222
		renderer: {
13223
			pageButton: {},
13224
			header: {}
13225
		},
13226
	
13227
	
13228
		/**
13229
		 * Ordering plug-ins - custom data source
13230
		 * 
13231
		 * The extension options for ordering of data available here is complimentary
13232
		 * to the default type based ordering that DataTables typically uses. It
13233
		 * allows much greater control over the the data that is being used to
13234
		 * order a column, but is necessarily therefore more complex.
13235
		 * 
13236
		 * This type of ordering is useful if you want to do ordering based on data
13237
		 * live from the DOM (for example the contents of an 'input' element) rather
13238
		 * than just the static string that DataTables knows of.
13239
		 * 
13240
		 * The way these plug-ins work is that you create an array of the values you
13241
		 * wish to be ordering for the column in question and then return that
13242
		 * array. The data in the array much be in the index order of the rows in
13243
		 * the table (not the currently ordering order!). Which order data gathering
13244
		 * function is run here depends on the `dt-init columns.orderDataType`
13245
		 * parameter that is used for the column (if any).
13246
		 *
13247
		 * The functions defined take two parameters:
13248
		 *
13249
		 * 1. `{object}` DataTables settings object: see
13250
		 *    {@link DataTable.models.oSettings}
13251
		 * 2. `{int}` Target column index
13252
		 *
13253
		 * Each function is expected to return an array:
13254
		 *
13255
		 * * `{array}` Data for the column to be ordering upon
13256
		 *
13257
		 *  @type array
13258
		 *
13259
		 *  @example
13260
		 *    // Ordering using `input` node values
13261
		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
13262
		 *    {
13263
		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13264
		 *        return $('input', td).val();
13265
		 *      } );
13266
		 *    }
13267
		 */
13268
		order: {},
13269
	
13270
	
13271
		/**
13272
		 * Type based plug-ins.
13273
		 *
13274
		 * Each column in DataTables has a type assigned to it, either by automatic
13275
		 * detection or by direct assignment using the `type` option for the column.
13276
		 * The type of a column will effect how it is ordering and search (plug-ins
13277
		 * can also make use of the column type if required).
13278
		 *
13279
		 * @namespace
13280
		 */
13281
		type: {
13282
			/**
13283
			 * Type detection functions.
13284
			 *
13285
			 * The functions defined in this object are used to automatically detect
13286
			 * a column's type, making initialisation of DataTables super easy, even
13287
			 * when complex data is in the table.
13288
			 *
13289
			 * The functions defined take two parameters:
13290
			 *
13291
		     *  1. `{*}` Data from the column cell to be analysed
13292
		     *  2. `{settings}` DataTables settings object. This can be used to
13293
		     *     perform context specific type detection - for example detection
13294
		     *     based on language settings such as using a comma for a decimal
13295
		     *     place. Generally speaking the options from the settings will not
13296
		     *     be required
13297
			 *
13298
			 * Each function is expected to return:
13299
			 *
13300
			 * * `{string|null}` Data type detected, or null if unknown (and thus
13301
			 *   pass it on to the other type detection functions.
13302
			 *
13303
			 *  @type array
13304
			 *
13305
			 *  @example
13306
			 *    // Currency type detection plug-in:
13307
			 *    $.fn.dataTable.ext.type.detect.push(
13308
			 *      function ( data, settings ) {
13309
			 *        // Check the numeric part
13310
			 *        if ( ! $.isNumeric( data.substring(1) ) ) {
13311
			 *          return null;
13312
			 *        }
13313
			 *
13314
			 *        // Check prefixed by currency
13315
			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
13316
			 *          return 'currency';
13317
			 *        }
13318
			 *        return null;
13319
			 *      }
13320
			 *    );
13321
			 */
13322
			detect: [],
13323
	
13324
	
13325
			/**
13326
			 * Type based search formatting.
13327
			 *
13328
			 * The type based searching functions can be used to pre-format the
13329
			 * data to be search on. For example, it can be used to strip HTML
13330
			 * tags or to de-format telephone numbers for numeric only searching.
13331
			 *
13332
			 * Note that is a search is not defined for a column of a given type,
13333
			 * no search formatting will be performed.
13334
			 * 
13335
			 * Pre-processing of searching data plug-ins - When you assign the sType
13336
			 * for a column (or have it automatically detected for you by DataTables
13337
			 * or a type detection plug-in), you will typically be using this for
13338
			 * custom sorting, but it can also be used to provide custom searching
13339
			 * by allowing you to pre-processing the data and returning the data in
13340
			 * the format that should be searched upon. This is done by adding
13341
			 * functions this object with a parameter name which matches the sType
13342
			 * for that target column. This is the corollary of <i>afnSortData</i>
13343
			 * for searching data.
13344
			 *
13345
			 * The functions defined take a single parameter:
13346
			 *
13347
		     *  1. `{*}` Data from the column cell to be prepared for searching
13348
			 *
13349
			 * Each function is expected to return:
13350
			 *
13351
			 * * `{string|null}` Formatted string that will be used for the searching.
13352
			 *
13353
			 *  @type object
13354
			 *  @default {}
13355
			 *
13356
			 *  @example
13357
			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
13358
			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
13359
			 *    }
13360
			 */
13361
			search: {},
13362
	
13363
	
13364
			/**
13365
			 * Type based ordering.
13366
			 *
13367
			 * The column type tells DataTables what ordering to apply to the table
13368
			 * when a column is sorted upon. The order for each type that is defined,
13369
			 * is defined by the functions available in this object.
13370
			 *
13371
			 * Each ordering option can be described by three properties added to
13372
			 * this object:
13373
			 *
13374
			 * * `{type}-pre` - Pre-formatting function
13375
			 * * `{type}-asc` - Ascending order function
13376
			 * * `{type}-desc` - Descending order function
13377
			 *
13378
			 * All three can be used together, only `{type}-pre` or only
13379
			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
13380
			 * that only `{type}-pre` is used, as this provides the optimal
13381
			 * implementation in terms of speed, although the others are provided
13382
			 * for compatibility with existing Javascript sort functions.
13383
			 *
13384
			 * `{type}-pre`: Functions defined take a single parameter:
13385
			 *
13386
		     *  1. `{*}` Data from the column cell to be prepared for ordering
13387
			 *
13388
			 * And return:
13389
			 *
13390
			 * * `{*}` Data to be sorted upon
13391
			 *
13392
			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
13393
			 * functions, taking two parameters:
13394
			 *
13395
		     *  1. `{*}` Data to compare to the second parameter
13396
		     *  2. `{*}` Data to compare to the first parameter
13397
			 *
13398
			 * And returning:
13399
			 *
13400
			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
13401
			 *   than the second parameter, ===0 if the two parameters are equal and
13402
			 *   >0 if the first parameter should be sorted height than the second
13403
			 *   parameter.
13404
			 * 
13405
			 *  @type object
13406
			 *  @default {}
13407
			 *
13408
			 *  @example
13409
			 *    // Numeric ordering of formatted numbers with a pre-formatter
13410
			 *    $.extend( $.fn.dataTable.ext.type.order, {
13411
			 *      "string-pre": function(x) {
13412
			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
13413
			 *        return parseFloat( a );
13414
			 *      }
13415
			 *    } );
13416
			 *
13417
			 *  @example
13418
			 *    // Case-sensitive string ordering, with no pre-formatting method
13419
			 *    $.extend( $.fn.dataTable.ext.order, {
13420
			 *      "string-case-asc": function(x,y) {
13421
			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13422
			 *      },
13423
			 *      "string-case-desc": function(x,y) {
13424
			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13425
			 *      }
13426
			 *    } );
13427
			 */
13428
			order: {}
13429
		},
13430
	
13431
		/**
13432
		 * Unique DataTables instance counter
13433
		 *
13434
		 * @type int
13435
		 * @private
13436
		 */
13437
		_unique: 0,
13438
	
13439
	
13440
		//
13441
		// Depreciated
13442
		// The following properties are retained for backwards compatiblity only.
13443
		// The should not be used in new projects and will be removed in a future
13444
		// version
13445
		//
13446
	
13447
		/**
13448
		 * Version check function.
13449
		 *  @type function
13450
		 *  @depreciated Since 1.10
13451
		 */
13452
		fnVersionCheck: DataTable.fnVersionCheck,
13453
	
13454
	
13455
		/**
13456
		 * Index for what 'this' index API functions should use
13457
		 *  @type int
13458
		 *  @deprecated Since v1.10
13459
		 */
13460
		iApiIndex: 0,
13461
	
13462
	
13463
		/**
13464
		 * jQuery UI class container
13465
		 *  @type object
13466
		 *  @deprecated Since v1.10
13467
		 */
13468
		oJUIClasses: {},
13469
	
13470
	
13471
		/**
13472
		 * Software version
13473
		 *  @type string
13474
		 *  @deprecated Since v1.10
13475
		 */
13476
		sVersion: DataTable.version
13477
	};
13478
	
13479
	
13480
	//
13481
	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
13482
	//
13483
	$.extend( _ext, {
13484
		afnFiltering: _ext.search,
13485
		aTypes:       _ext.type.detect,
13486
		ofnSearch:    _ext.type.search,
13487
		oSort:        _ext.type.order,
13488
		afnSortData:  _ext.order,
13489
		aoFeatures:   _ext.feature,
13490
		oApi:         _ext.internal,
13491
		oStdClasses:  _ext.classes,
13492
		oPagination:  _ext.pager
13493
	} );
13494
	
13495
	
13496
	$.extend( DataTable.ext.classes, {
13497
		"sTable": "dataTable",
13498
		"sNoFooter": "no-footer",
13499
	
13500
		/* Paging buttons */
13501
		"sPageButton": "paginate_button",
13502
		"sPageButtonActive": "current",
13503
		"sPageButtonDisabled": "disabled",
13504
	
13505
		/* Striping classes */
13506
		"sStripeOdd": "odd",
13507
		"sStripeEven": "even",
13508
	
13509
		/* Empty row */
13510
		"sRowEmpty": "dataTables_empty",
13511
	
13512
		/* Features */
13513
		"sWrapper": "dataTables_wrapper",
13514
		"sFilter": "dataTables_filter",
13515
		"sInfo": "dataTables_info",
13516
		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
13517
		"sLength": "dataTables_length",
13518
		"sProcessing": "dataTables_processing",
13519
	
13520
		/* Sorting */
13521
		"sSortAsc": "sorting_asc",
13522
		"sSortDesc": "sorting_desc",
13523
		"sSortable": "sorting", /* Sortable in both directions */
13524
		"sSortableAsc": "sorting_asc_disabled",
13525
		"sSortableDesc": "sorting_desc_disabled",
13526
		"sSortableNone": "sorting_disabled",
13527
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
13528
	
13529
		/* Filtering */
13530
		"sFilterInput": "",
13531
	
13532
		/* Page length */
13533
		"sLengthSelect": "",
13534
	
13535
		/* Scrolling */
13536
		"sScrollWrapper": "dataTables_scroll",
13537
		"sScrollHead": "dataTables_scrollHead",
13538
		"sScrollHeadInner": "dataTables_scrollHeadInner",
13539
		"sScrollBody": "dataTables_scrollBody",
13540
		"sScrollFoot": "dataTables_scrollFoot",
13541
		"sScrollFootInner": "dataTables_scrollFootInner",
13542
	
13543
		/* Misc */
13544
		"sHeaderTH": "",
13545
		"sFooterTH": "",
13546
	
13547
		// Deprecated
13548
		"sSortJUIAsc": "",
13549
		"sSortJUIDesc": "",
13550
		"sSortJUI": "",
13551
		"sSortJUIAscAllowed": "",
13552
		"sSortJUIDescAllowed": "",
13553
		"sSortJUIWrapper": "",
13554
		"sSortIcon": "",
13555
		"sJUIHeader": "",
13556
		"sJUIFooter": ""
13557
	} );
13558
	
13559
	
13560
	(function() {
13561
	
13562
	// Reused strings for better compression. Closure compiler appears to have a
13563
	// weird edge case where it is trying to expand strings rather than use the
13564
	// variable version. This results in about 200 bytes being added, for very
13565
	// little preference benefit since it this run on script load only.
13566
	var _empty = '';
13567
	_empty = '';
13568
	
13569
	var _stateDefault = _empty + 'ui-state-default';
13570
	var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
13571
	var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
13572
	
13573
	$.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
13574
		/* Full numbers paging buttons */
13575
		"sPageButton":         "fg-button ui-button "+_stateDefault,
13576
		"sPageButtonActive":   "ui-state-disabled",
13577
		"sPageButtonDisabled": "ui-state-disabled",
13578
	
13579
		/* Features */
13580
		"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
13581
			"ui-buttonset-multi paging_", /* Note that the type is postfixed */
13582
	
13583
		/* Sorting */
13584
		"sSortAsc":            _stateDefault+" sorting_asc",
13585
		"sSortDesc":           _stateDefault+" sorting_desc",
13586
		"sSortable":           _stateDefault+" sorting",
13587
		"sSortableAsc":        _stateDefault+" sorting_asc_disabled",
13588
		"sSortableDesc":       _stateDefault+" sorting_desc_disabled",
13589
		"sSortableNone":       _stateDefault+" sorting_disabled",
13590
		"sSortJUIAsc":         _sortIcon+"triangle-1-n",
13591
		"sSortJUIDesc":        _sortIcon+"triangle-1-s",
13592
		"sSortJUI":            _sortIcon+"carat-2-n-s",
13593
		"sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
13594
		"sSortJUIDescAllowed": _sortIcon+"carat-1-s",
13595
		"sSortJUIWrapper":     "DataTables_sort_wrapper",
13596
		"sSortIcon":           "DataTables_sort_icon",
13597
	
13598
		/* Scrolling */
13599
		"sScrollHead": "dataTables_scrollHead "+_stateDefault,
13600
		"sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
13601
	
13602
		/* Misc */
13603
		"sHeaderTH":  _stateDefault,
13604
		"sFooterTH":  _stateDefault,
13605
		"sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
13606
		"sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
13607
	} );
13608
	
13609
	}());
13610
	
13611
	
13612
	
13613
	var extPagination = DataTable.ext.pager;
13614
	
13615
	function _numbers ( page, pages ) {
13616
		var
13617
			numbers = [],
13618
			buttons = extPagination.numbers_length,
13619
			half = Math.floor( buttons / 2 ),
13620
			i = 1;
13621
	
13622
		if ( pages <= buttons ) {
13623
			numbers = _range( 0, pages );
13624
		}
13625
		else if ( page <= half ) {
13626
			numbers = _range( 0, buttons-2 );
13627
			numbers.push( 'ellipsis' );
13628
			numbers.push( pages-1 );
13629
		}
13630
		else if ( page >= pages - 1 - half ) {
13631
			numbers = _range( pages-(buttons-2), pages );
13632
			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
13633
			numbers.splice( 0, 0, 0 );
13634
		}
13635
		else {
13636
			numbers = _range( page-1, page+2 );
13637
			numbers.push( 'ellipsis' );
13638
			numbers.push( pages-1 );
13639
			numbers.splice( 0, 0, 'ellipsis' );
13640
			numbers.splice( 0, 0, 0 );
13641
		}
13642
	
13643
		numbers.DT_el = 'span';
13644
		return numbers;
13645
	}
13646
	
13647
	
13648
	$.extend( extPagination, {
13649
		simple: function ( page, pages ) {
13650
			return [ 'previous', 'next' ];
13651
		},
13652
	
13653
		full: function ( page, pages ) {
13654
			return [  'first', 'previous', 'next', 'last' ];
13655
		},
13656
	
13657
		simple_numbers: function ( page, pages ) {
13658
			return [ 'previous', _numbers(page, pages), 'next' ];
13659
		},
13660
	
13661
		full_numbers: function ( page, pages ) {
13662
			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
13663
		},
13664
	
13665
		// For testing and plug-ins to use
13666
		_numbers: _numbers,
13667
		numbers_length: 7
13668
	} );
13669
	
13670
	
13671
	$.extend( true, DataTable.ext.renderer, {
13672
		pageButton: {
13673
			_: function ( settings, host, idx, buttons, page, pages ) {
13674
				var classes = settings.oClasses;
13675
				var lang = settings.oLanguage.oPaginate;
13676
				var btnDisplay, btnClass, counter=0;
13677
	
13678
				var attach = function( container, buttons ) {
13679
					var i, ien, node, button;
13680
					var clickHandler = function ( e ) {
13681
						_fnPageChange( settings, e.data.action, true );
13682
					};
13683
	
13684
					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
13685
						button = buttons[i];
13686
	
13687
						if ( $.isArray( button ) ) {
13688
							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
13689
								.appendTo( container );
13690
							attach( inner, button );
13691
						}
13692
						else {
13693
							btnDisplay = '';
13694
							btnClass = '';
13695
	
13696
							switch ( button ) {
13697
								case 'ellipsis':
13698
									container.append('<span>&hellip;</span>');
13699
									break;
13700
	
13701
								case 'first':
13702
									btnDisplay = lang.sFirst;
13703
									btnClass = button + (page > 0 ?
13704
										'' : ' '+classes.sPageButtonDisabled);
13705
									break;
13706
	
13707
								case 'previous':
13708
									btnDisplay = lang.sPrevious;
13709
									btnClass = button + (page > 0 ?
13710
										'' : ' '+classes.sPageButtonDisabled);
13711
									break;
13712
	
13713
								case 'next':
13714
									btnDisplay = lang.sNext;
13715
									btnClass = button + (page < pages-1 ?
13716
										'' : ' '+classes.sPageButtonDisabled);
13717
									break;
13718
	
13719
								case 'last':
13720
									btnDisplay = lang.sLast;
13721
									btnClass = button + (page < pages-1 ?
13722
										'' : ' '+classes.sPageButtonDisabled);
13723
									break;
13724
	
13725
								default:
13726
									btnDisplay = button + 1;
13727
									btnClass = page === button ?
13728
										classes.sPageButtonActive : '';
13729
									break;
13730
							}
13731
	
13732
							if ( btnDisplay ) {
13733
								node = $('<a>', {
13734
										'class': classes.sPageButton+' '+btnClass,
13735
										'aria-controls': settings.sTableId,
13736
										'data-dt-idx': counter,
13737
										'tabindex': settings.iTabIndex,
13738
										'id': idx === 0 && typeof button === 'string' ?
13739
											settings.sTableId +'_'+ button :
13740
											null
13741
									} )
13742
									.html( btnDisplay )
13743
									.appendTo( container );
13744
	
13745
								_fnBindAction(
13746
									node, {action: button}, clickHandler
13747
								);
13748
	
13749
								counter++;
13750
							}
13751
						}
13752
					}
13753
				};
13754
	
13755
				// Because this approach is destroying and recreating the paging
13756
				// elements, focus is lost on the select button which is bad for
13757
				// accessibility. So we want to restore focus once the draw has
13758
				// completed
13759
				var activeEl = $(document.activeElement).data('dt-idx');
13760
	
13761
				attach( $(host).empty(), buttons );
13762
	
13763
				if ( activeEl !== null ) {
13764
					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
13765
				}
13766
			}
13767
		}
13768
	} );
13769
	
13770
	
13771
	
13772
	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
13773
		if ( !d || d === '-' ) {
13774
			return -Infinity;
13775
		}
13776
	
13777
		// If a decimal place other than `.` is used, it needs to be given to the
13778
		// function so we can detect it and replace with a `.` which is the only
13779
		// decimal place Javascript recognises - it is not locale aware.
13780
		if ( decimalPlace ) {
13781
			d = _numToDecimal( d, decimalPlace );
13782
		}
13783
	
13784
		if ( d.replace ) {
13785
			if ( re1 ) {
13786
				d = d.replace( re1, '' );
13787
			}
13788
	
13789
			if ( re2 ) {
13790
				d = d.replace( re2, '' );
13791
			}
13792
		}
13793
	
13794
		return d * 1;
13795
	};
13796
	
13797
	
13798
	// Add the numeric 'deformatting' functions for sorting. This is done in a
13799
	// function to provide an easy ability for the language options to add
13800
	// additional methods if a non-period decimal place is used.
13801
	function _addNumericSort ( decimalPlace ) {
13802
		$.each(
13803
			{
13804
				// Plain numbers
13805
				"num": function ( d ) {
13806
					return __numericReplace( d, decimalPlace );
13807
				},
13808
	
13809
				// Formatted numbers
13810
				"num-fmt": function ( d ) {
13811
					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
13812
				},
13813
	
13814
				// HTML numeric
13815
				"html-num": function ( d ) {
13816
					return __numericReplace( d, decimalPlace, _re_html );
13817
				},
13818
	
13819
				// HTML numeric, formatted
13820
				"html-num-fmt": function ( d ) {
13821
					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
13822
				}
13823
			},
13824
			function ( key, fn ) {
13825
				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
13826
			}
13827
		);
13828
	}
13829
	
13830
	
13831
	// Default sort methods
13832
	$.extend( _ext.type.order, {
13833
		// Dates
13834
		"date-pre": function ( d ) {
13835
			return Date.parse( d ) || 0;
13836
		},
13837
	
13838
		// html
13839
		"html-pre": function ( a ) {
13840
			return ! a ?
13841
				'' :
13842
				a.replace ?
13843
					a.replace( /<.*?>/g, "" ).toLowerCase() :
13844
					a+'';
13845
		},
13846
	
13847
		// string
13848
		"string-pre": function ( a ) {
13849
			return typeof a === 'string' ?
13850
				a.toLowerCase() :
13851
				! a || ! a.toString ?
13852
					'' :
13853
					a.toString();
13854
		},
13855
	
13856
		// string-asc and -desc are retained only for compatibility with the old
13857
		// sort methods
13858
		"string-asc": function ( x, y ) {
13859
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13860
		},
13861
	
13862
		"string-desc": function ( x, y ) {
13863
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13864
		}
13865
	} );
13866
	
13867
	
13868
	// Numeric sorting types - order doesn't matter here
13869
	_addNumericSort( '' );
13870
	
13871
	
13872
	// Built in type detection. See model.ext.aTypes for information about
13873
	// what is required from this methods.
13874
	$.extend( DataTable.ext.type.detect, [
13875
		// Plain numbers - first since V8 detects some plain numbers as dates
13876
		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
13877
		function ( d, settings )
13878
		{
13879
			var decimal = settings.oLanguage.sDecimal;
13880
			return _isNumber( d, decimal ) ? 'num'+decimal : null;
13881
		},
13882
	
13883
		// Dates (only those recognised by the browser's Date.parse)
13884
		function ( d, settings )
13885
		{
13886
			// V8 will remove any unknown characters at the start of the expression,
13887
			// leading to false matches such as `$245.12` being a valid date. See
13888
			// forum thread 18941 for detail.
13889
			if ( d && ! _re_date_start.test(d) ) {
13890
				return null;
13891
			}
13892
			var parsed = Date.parse(d);
13893
			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
13894
		},
13895
	
13896
		// Formatted numbers
13897
		function ( d, settings )
13898
		{
13899
			var decimal = settings.oLanguage.sDecimal;
13900
			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
13901
		},
13902
	
13903
		// HTML numeric
13904
		function ( d, settings )
13905
		{
13906
			var decimal = settings.oLanguage.sDecimal;
13907
			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
13908
		},
13909
	
13910
		// HTML numeric, formatted
13911
		function ( d, settings )
13912
		{
13913
			var decimal = settings.oLanguage.sDecimal;
13914
			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
13915
		},
13916
	
13917
		// HTML (this is strict checking - there must be html)
13918
		function ( d, settings )
13919
		{
13920
			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
13921
				'html' : null;
13922
		}
13923
	] );
13924
	
13925
	
13926
	
13927
	// Filter formatting functions. See model.ext.ofnSearch for information about
13928
	// what is required from these methods.
13929
	
13930
	
13931
	$.extend( DataTable.ext.type.search, {
13932
		html: function ( data ) {
13933
			return _empty(data) ?
13934
				'' :
13935
				typeof data === 'string' ?
13936
					data
13937
						.replace( _re_new_lines, " " )
13938
						.replace( _re_html, "" ) :
13939
					'';
13940
		},
13941
	
13942
		string: function ( data ) {
13943
			return _empty(data) ?
13944
				'' :
13945
				typeof data === 'string' ?
13946
					data.replace( _re_new_lines, " " ) :
13947
					data;
13948
		}
13949
	} );
13950
	
13951
	
13952
	
13953
	$.extend( true, DataTable.ext.renderer, {
13954
		header: {
13955
			_: function ( settings, cell, column, classes ) {
13956
				// No additional mark-up required
13957
				// Attach a sort listener to update on sort - note that using the
13958
				// `DT` namespace will allow the event to be removed automatically
13959
				// on destroy, while the `dt` namespaced event is the one we are
13960
				// listening for
13961
				$(settings.nTable).on( 'order.dt.DT', function ( e, settings, sorting, columns ) {
13962
					var colIdx = column.idx;
13963
	
13964
					cell
13965
						.removeClass(
13966
							column.sSortingClass +' '+
13967
							classes.sSortAsc +' '+
13968
							classes.sSortDesc
13969
						)
13970
						.addClass( columns[ colIdx ] == 'asc' ?
13971
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
13972
								classes.sSortDesc :
13973
								column.sSortingClass
13974
						);
13975
				} );
13976
			},
13977
	
13978
			jqueryui: function ( settings, cell, column, classes ) {
13979
				var colIdx = column.idx;
13980
	
13981
				$('<div/>')
13982
					.addClass( classes.sSortJUIWrapper )
13983
					.append( cell.contents() )
13984
					.append( $('<span/>')
13985
						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
13986
					)
13987
					.appendTo( cell );
13988
	
13989
				// Attach a sort listener to update on sort
13990
				$(settings.nTable).on( 'order.dt.DT', function ( e, settings, sorting, columns ) {
13991
					cell
13992
						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
13993
						.addClass( columns[ colIdx ] == 'asc' ?
13994
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
13995
								classes.sSortDesc :
13996
								column.sSortingClass
13997
						);
13998
	
13999
					cell
14000
						.find( 'span.'+classes.sSortIcon )
14001
						.removeClass(
14002
							classes.sSortJUIAsc +" "+
14003
							classes.sSortJUIDesc +" "+
14004
							classes.sSortJUI +" "+
14005
							classes.sSortJUIAscAllowed +" "+
14006
							classes.sSortJUIDescAllowed
14007
						)
14008
						.addClass( columns[ colIdx ] == 'asc' ?
14009
							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14010
								classes.sSortJUIDesc :
14011
								column.sSortingClassJUI
14012
						);
14013
				} );
14014
			}
14015
		}
14016
	} );
14017
	
14018
	/*
14019
	 * Public helper functions. These aren't used internally by DataTables, or
14020
	 * called by any of the options passed into DataTables, but they can be used
14021
	 * externally by developers working with DataTables. They are helper functions
14022
	 * to make working with DataTables a little bit easier.
14023
	 */
14024
	
14025
	/**
14026
	 * Helpers for `columns.render`.
14027
	 *
14028
	 * The options defined here can be used with the `columns.render` initialisation
14029
	 * option to provide a display renderer. The following functions are defined:
14030
	 *
14031
	 * * `number` - Will format numeric data (defined by `columns.data`) for
14032
	 *   display, retaining the original unformatted data for sorting and filtering.
14033
	 *   It takes 4 parameters:
14034
	 *   * `string` - Thousands grouping separator
14035
	 *   * `string` - Decimal point indicator
14036
	 *   * `integer` - Number of decimal points to show
14037
	 *   * `string` (optional) - Prefix.
14038
	 *
14039
	 * @example
14040
	 *   // Column definition using the number renderer
14041
	 *   {
14042
	 *     data: "salary",
14043
	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14044
	 *   }
14045
	 *
14046
	 * @namespace
14047
	 */
14048
	DataTable.render = {
14049
		number: function ( thousands, decimal, precision, prefix ) {
14050
			return {
14051
				display: function ( d ) {
14052
					d = parseFloat( d );
14053
					var intPart = parseInt( d, 10 );
14054
					var floatPart = precision ?
14055
						(decimal+(d - intPart).toFixed( precision )).substring( 2 ):
14056
						'';
14057
	
14058
					return (prefix||'') +
14059
						intPart.toString().replace(
14060
							/\B(?=(\d{3})+(?!\d))/g, thousands
14061
						) +
14062
						floatPart;
14063
				}
14064
			};
14065
		}
14066
	};
14067
	
14068
	
14069
	/*
14070
	 * This is really a good bit rubbish this method of exposing the internal methods
14071
	 * publicly... - To be fixed in 2.0 using methods on the prototype
14072
	 */
14073
	
14074
	
14075
	/**
14076
	 * Create a wrapper function for exporting an internal functions to an external API.
14077
	 *  @param {string} fn API function name
14078
	 *  @returns {function} wrapped function
14079
	 *  @memberof DataTable#internal
14080
	 */
14081
	function _fnExternApiFunc (fn)
14082
	{
14083
		return function() {
14084
			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14085
				Array.prototype.slice.call(arguments)
14086
			);
14087
			return DataTable.ext.internal[fn].apply( this, args );
14088
		};
14089
	}
14090
	
14091
	
14092
	/**
14093
	 * Reference to internal functions for use by plug-in developers. Note that
14094
	 * these methods are references to internal functions and are considered to be
14095
	 * private. If you use these methods, be aware that they are liable to change
14096
	 * between versions.
14097
	 *  @namespace
14098
	 */
14099
	$.extend( DataTable.ext.internal, {
14100
		_fnExternApiFunc: _fnExternApiFunc,
14101
		_fnBuildAjax: _fnBuildAjax,
14102
		_fnAjaxUpdate: _fnAjaxUpdate,
14103
		_fnAjaxParameters: _fnAjaxParameters,
14104
		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14105
		_fnAjaxDataSrc: _fnAjaxDataSrc,
14106
		_fnAddColumn: _fnAddColumn,
14107
		_fnColumnOptions: _fnColumnOptions,
14108
		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
14109
		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14110
		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
14111
		_fnVisbleColumns: _fnVisbleColumns,
14112
		_fnGetColumns: _fnGetColumns,
14113
		_fnColumnTypes: _fnColumnTypes,
14114
		_fnApplyColumnDefs: _fnApplyColumnDefs,
14115
		_fnHungarianMap: _fnHungarianMap,
14116
		_fnCamelToHungarian: _fnCamelToHungarian,
14117
		_fnLanguageCompat: _fnLanguageCompat,
14118
		_fnBrowserDetect: _fnBrowserDetect,
14119
		_fnAddData: _fnAddData,
14120
		_fnAddTr: _fnAddTr,
14121
		_fnNodeToDataIndex: _fnNodeToDataIndex,
14122
		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
14123
		_fnGetCellData: _fnGetCellData,
14124
		_fnSetCellData: _fnSetCellData,
14125
		_fnSplitObjNotation: _fnSplitObjNotation,
14126
		_fnGetObjectDataFn: _fnGetObjectDataFn,
14127
		_fnSetObjectDataFn: _fnSetObjectDataFn,
14128
		_fnGetDataMaster: _fnGetDataMaster,
14129
		_fnClearTable: _fnClearTable,
14130
		_fnDeleteIndex: _fnDeleteIndex,
14131
		_fnInvalidateRow: _fnInvalidateRow,
14132
		_fnGetRowElements: _fnGetRowElements,
14133
		_fnCreateTr: _fnCreateTr,
14134
		_fnBuildHead: _fnBuildHead,
14135
		_fnDrawHead: _fnDrawHead,
14136
		_fnDraw: _fnDraw,
14137
		_fnReDraw: _fnReDraw,
14138
		_fnAddOptionsHtml: _fnAddOptionsHtml,
14139
		_fnDetectHeader: _fnDetectHeader,
14140
		_fnGetUniqueThs: _fnGetUniqueThs,
14141
		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
14142
		_fnFilterComplete: _fnFilterComplete,
14143
		_fnFilterCustom: _fnFilterCustom,
14144
		_fnFilterColumn: _fnFilterColumn,
14145
		_fnFilter: _fnFilter,
14146
		_fnFilterCreateSearch: _fnFilterCreateSearch,
14147
		_fnEscapeRegex: _fnEscapeRegex,
14148
		_fnFilterData: _fnFilterData,
14149
		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
14150
		_fnUpdateInfo: _fnUpdateInfo,
14151
		_fnInfoMacros: _fnInfoMacros,
14152
		_fnInitialise: _fnInitialise,
14153
		_fnInitComplete: _fnInitComplete,
14154
		_fnLengthChange: _fnLengthChange,
14155
		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
14156
		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
14157
		_fnPageChange: _fnPageChange,
14158
		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
14159
		_fnProcessingDisplay: _fnProcessingDisplay,
14160
		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
14161
		_fnScrollDraw: _fnScrollDraw,
14162
		_fnApplyToChildren: _fnApplyToChildren,
14163
		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
14164
		_fnThrottle: _fnThrottle,
14165
		_fnConvertToWidth: _fnConvertToWidth,
14166
		_fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14167
		_fnGetWidestNode: _fnGetWidestNode,
14168
		_fnGetMaxLenString: _fnGetMaxLenString,
14169
		_fnStringToCss: _fnStringToCss,
14170
		_fnScrollBarWidth: _fnScrollBarWidth,
14171
		_fnSortFlatten: _fnSortFlatten,
14172
		_fnSort: _fnSort,
14173
		_fnSortAria: _fnSortAria,
14174
		_fnSortListener: _fnSortListener,
14175
		_fnSortAttachListener: _fnSortAttachListener,
14176
		_fnSortingClasses: _fnSortingClasses,
14177
		_fnSortData: _fnSortData,
14178
		_fnSaveState: _fnSaveState,
14179
		_fnLoadState: _fnLoadState,
14180
		_fnSettingsFromNode: _fnSettingsFromNode,
14181
		_fnLog: _fnLog,
14182
		_fnMap: _fnMap,
14183
		_fnBindAction: _fnBindAction,
14184
		_fnCallbackReg: _fnCallbackReg,
14185
		_fnCallbackFire: _fnCallbackFire,
14186
		_fnLengthOverflow: _fnLengthOverflow,
14187
		_fnRenderer: _fnRenderer,
14188
		_fnDataSource: _fnDataSource,
14189
		_fnRowAttributes: _fnRowAttributes,
14190
		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14191
		                                // in 1.10, so this dead-end function is
14192
		                                // added to prevent errors
14193
	} );
14194
	
14195

    
14196
	// jQuery access
14197
	$.fn.dataTable = DataTable;
14198

    
14199
	// Legacy aliases
14200
	$.fn.dataTableSettings = DataTable.settings;
14201
	$.fn.dataTableExt = DataTable.ext;
14202

    
14203
	// With a capital `D` we return a DataTables API instance rather than a
14204
	// jQuery object
14205
	$.fn.DataTable = function ( opts ) {
14206
		return $(this).dataTable( opts ).api();
14207
	};
14208

    
14209
	// All properties that are available to $.fn.dataTable should also be
14210
	// available on $.fn.DataTable
14211
	$.each( DataTable, function ( prop, val ) {
14212
		$.fn.DataTable[ prop ] = val;
14213
	} );
14214

    
14215

    
14216
	// Information about events fired by DataTables - for documentation.
14217
	/**
14218
	 * Draw event, fired whenever the table is redrawn on the page, at the same
14219
	 * point as fnDrawCallback. This may be useful for binding events or
14220
	 * performing calculations when the table is altered at all.
14221
	 *  @name DataTable#draw.dt
14222
	 *  @event
14223
	 *  @param {event} e jQuery event object
14224
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14225
	 */
14226

    
14227
	/**
14228
	 * Search event, fired when the searching applied to the table (using the
14229
	 * built-in global search, or column filters) is altered.
14230
	 *  @name DataTable#search.dt
14231
	 *  @event
14232
	 *  @param {event} e jQuery event object
14233
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14234
	 */
14235

    
14236
	/**
14237
	 * Page change event, fired when the paging of the table is altered.
14238
	 *  @name DataTable#page.dt
14239
	 *  @event
14240
	 *  @param {event} e jQuery event object
14241
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14242
	 */
14243

    
14244
	/**
14245
	 * Order event, fired when the ordering applied to the table is altered.
14246
	 *  @name DataTable#order.dt
14247
	 *  @event
14248
	 *  @param {event} e jQuery event object
14249
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14250
	 */
14251

    
14252
	/**
14253
	 * DataTables initialisation complete event, fired when the table is fully
14254
	 * drawn, including Ajax data loaded, if Ajax data is required.
14255
	 *  @name DataTable#init.dt
14256
	 *  @event
14257
	 *  @param {event} e jQuery event object
14258
	 *  @param {object} oSettings DataTables settings object
14259
	 *  @param {object} json The JSON object request from the server - only
14260
	 *    present if client-side Ajax sourced data is used</li></ol>
14261
	 */
14262

    
14263
	/**
14264
	 * State save event, fired when the table has changed state a new state save
14265
	 * is required. This event allows modification of the state saving object
14266
	 * prior to actually doing the save, including addition or other state
14267
	 * properties (for plug-ins) or modification of a DataTables core property.
14268
	 *  @name DataTable#stateSaveParams.dt
14269
	 *  @event
14270
	 *  @param {event} e jQuery event object
14271
	 *  @param {object} oSettings DataTables settings object
14272
	 *  @param {object} json The state information to be saved
14273
	 */
14274

    
14275
	/**
14276
	 * State load event, fired when the table is loading state from the stored
14277
	 * data, but prior to the settings object being modified by the saved state
14278
	 * - allowing modification of the saved state is required or loading of
14279
	 * state for a plug-in.
14280
	 *  @name DataTable#stateLoadParams.dt
14281
	 *  @event
14282
	 *  @param {event} e jQuery event object
14283
	 *  @param {object} oSettings DataTables settings object
14284
	 *  @param {object} json The saved state information
14285
	 */
14286

    
14287
	/**
14288
	 * State loaded event, fired when state has been loaded from stored data and
14289
	 * the settings object has been modified by the loaded data.
14290
	 *  @name DataTable#stateLoaded.dt
14291
	 *  @event
14292
	 *  @param {event} e jQuery event object
14293
	 *  @param {object} oSettings DataTables settings object
14294
	 *  @param {object} json The saved state information
14295
	 */
14296

    
14297
	/**
14298
	 * Processing event, fired when DataTables is doing some kind of processing
14299
	 * (be it, order, searcg or anything else). It can be used to indicate to
14300
	 * the end user that there is something happening, or that something has
14301
	 * finished.
14302
	 *  @name DataTable#processing.dt
14303
	 *  @event
14304
	 *  @param {event} e jQuery event object
14305
	 *  @param {object} oSettings DataTables settings object
14306
	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
14307
	 */
14308

    
14309
	/**
14310
	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
14311
	 * request to made to the server for new data. This event is called before
14312
	 * DataTables processed the returned data, so it can also be used to pre-
14313
	 * process the data returned from the server, if needed.
14314
	 *
14315
	 * Note that this trigger is called in `fnServerData`, if you override
14316
	 * `fnServerData` and which to use this event, you need to trigger it in you
14317
	 * success function.
14318
	 *  @name DataTable#xhr.dt
14319
	 *  @event
14320
	 *  @param {event} e jQuery event object
14321
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14322
	 *  @param {object} json JSON returned from the server
14323
	 *
14324
	 *  @example
14325
	 *     // Use a custom property returned from the server in another DOM element
14326
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14327
	 *       $('#status').html( json.status );
14328
	 *     } );
14329
	 *
14330
	 *  @example
14331
	 *     // Pre-process the data returned from the server
14332
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14333
	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
14334
	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
14335
	 *       }
14336
	 *       // Note no return - manipulate the data directly in the JSON object.
14337
	 *     } );
14338
	 */
14339

    
14340
	/**
14341
	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
14342
	 * or passing the bDestroy:true parameter in the initialisation object. This
14343
	 * can be used to remove bound events, added DOM nodes, etc.
14344
	 *  @name DataTable#destroy.dt
14345
	 *  @event
14346
	 *  @param {event} e jQuery event object
14347
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14348
	 */
14349

    
14350
	/**
14351
	 * Page length change event, fired when number of records to show on each
14352
	 * page (the length) is changed.
14353
	 *  @name DataTable#length.dt
14354
	 *  @event
14355
	 *  @param {event} e jQuery event object
14356
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14357
	 *  @param {integer} len New length
14358
	 */
14359

    
14360
	/**
14361
	 * Column sizing has changed.
14362
	 *  @name DataTable#column-sizing.dt
14363
	 *  @event
14364
	 *  @param {event} e jQuery event object
14365
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14366
	 */
14367

    
14368
	/**
14369
	 * Column visibility has changed.
14370
	 *  @name DataTable#column-visibility.dt
14371
	 *  @event
14372
	 *  @param {event} e jQuery event object
14373
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14374
	 *  @param {int} column Column index
14375
	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
14376
	 */
14377

    
14378
	return $.fn.dataTable;
14379
}));
14380

    
14381
}(window, document));
14382

    
(1-1/3)