PageSourceSearch

https://artlofthotel.com/cdn/datatables/jquery.dataTables.js

js artlofthotel.com collected 2026-10-09 00:01:19 UTC 438,979 bytes, 14,951 lines download raw bytes

1/*! DataTables 1.10.7
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.7
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,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_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        module.exports = factory( require( 'jquery' ) );
39    }
40	else if ( jQuery && !jQuery.fn.dataTable ) {
41		// Define using browser globals otherwise
42		// Prevent multiple instantiations if the script is loaded twice
43		factory( jQuery );
44	}
45}
46(/** @lends <global> */function( $ ) {
47	"use strict";
48
49	/**
50	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
51	 * flexible tool, based upon the foundations of progressive enhancement,
52	 * which will add advanced interaction controls to any HTML table. For a
53	 * full list of features please refer to
54	 * [DataTables.net](href="http://datatables.net).
55	 *
56	 * Note that the `DataTable` object is not a global variable but is aliased
57	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
58	 * be  accessed.
59	 *
60	 *  @class
61	 *  @param {object} [init={}] Configuration object for DataTables. Options
62	 *    are defined by {@link DataTable.defaults}
63	 *  @requires jQuery 1.7+
64	 *
65	 *  @example
66	 *    // Basic initialisation
67	 *    $(document).ready( function {
68	 *      $('#example').dataTable();
69	 *    } );
70	 *
71	 *  @example
72	 *    // Initialisation with configuration options - in this case, disable
73	 *    // pagination and sorting.
74	 *    $(document).ready( function {
75	 *      $('#example').dataTable( {
76	 *        "paginate": false,
77	 *        "sort": false
78	 *      } );
79	 *    } );
80	 */
81	var DataTable;
82
83	
84	/*
vendor: 38,531 bytes, lines 85-1471
85	 * It is useful to have variables which are scoped locally so only the
86	 * DataTables functions can access them and they don't leak into global space.
87	 * At the same time these functions are often useful over multiple files in the
88	 * core and API, so we list, or at least document, all variables which are used
89	 * by DataTables as private variables here. This also ensures that there is no
90	 * clashing of variable names and that they can easily referenced for reuse.
91	 */
92	
93	
94	// Defined else where
95	//  _selector_run
96	//  _selector_opts
97	//  _selector_first
98	//  _selector_row_indexes
99	
100	var _ext; // DataTable.ext
101	var _Api; // DataTable.Api
102	var _api_register; // DataTable.Api.register
103	var _api_registerPlural; // DataTable.Api.registerPlural
104	
105	var _re_dic = {};
106	var _re_new_lines = /[\r\n]/g;
107	var _re_html = /<.*?>/g;
108	var _re_date_start = /^[\w\+\-]/;
109	var _re_date_end = /[\w\+\-]$/;
110	
111	// Escape regular expression special characters
112	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
113	
114	// http://en.wikipedia.org/wiki/Foreign_exchange_market
115	// - \u20BD - Russian ruble.
116	// - \u20a9 - South Korean Won
117	// - \u20BA - Turkish Lira
118	// - \u20B9 - Indian Rupee
119	// - R - Brazil (R$) and South Africa
120	// - fr - Swiss Franc
121	// - kr - Swedish krona, Norwegian krone and Danish krone
122	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
123	//   standards as thousands separators.
124	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
125	
126	
127	var _empty = function ( d ) {
128		return !d || d === true || d === '-' ? true : false;
129	};
130	
131	
132	var _intVal = function ( s ) {
133		var integer = parseInt( s, 10 );
134		return !isNaN(integer) && isFinite(s) ? integer : null;
135	};
136	
137	// Convert from a formatted number with characters other than `.` as the
138	// decimal place, to a Javascript number
139	var _numToDecimal = function ( num, decimalPoint ) {
140		// Cache created regular expressions for speed as this function is called often
141		if ( ! _re_dic[ decimalPoint ] ) {
142			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
143		}
144		return typeof num === 'string' && decimalPoint !== '.' ?
145			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
146			num;
147	};
148	
149	
150	var _isNumber = function ( d, decimalPoint, formatted ) {
151		var strType = typeof d === 'string';
152	
153		// If empty return immediately so there must be a number if it is a
154		// formatted string (this stops the string "k", or "kr", etc being detected
155		// as a formatted number for currency
156		if ( _empty( d ) ) {
157			return true;
158		}
159	
160		if ( decimalPoint && strType ) {
161			d = _numToDecimal( d, decimalPoint );
162		}
163	
164		if ( formatted && strType ) {
165			d = d.replace( _re_formatted_numeric, '' );
166		}
167	
168		return !isNaN( parseFloat(d) ) && isFinite( d );
169	};
170	
171	
172	// A string without HTML in it can be considered to be HTML still
173	var _isHtml = function ( d ) {
174		return _empty( d ) || typeof d === 'string';
175	};
176	
177	
178	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
179		if ( _empty( d ) ) {
180			return true;
181		}
182	
183		var html = _isHtml( d );
184		return ! html ?
185			null :
186			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
187				true :
188				null;
189	};
190	
191	
192	var _pluck = function ( a, prop, prop2 ) {
193		var out = [];
194		var i=0, ien=a.length;
195	
196		// Could have the test in the loop for slightly smaller code, but speed
197		// is essential here
198		if ( prop2 !== undefined ) {
199			for ( ; i<ien ; i++ ) {
200				if ( a[i] && a[i][ prop ] ) {
201					out.push( a[i][ prop ][ prop2 ] );
202				}
203			}
204		}
205		else {
206			for ( ; i<ien ; i++ ) {
207				if ( a[i] ) {
208					out.push( a[i][ prop ] );
209				}
210			}
211		}
212	
213		return out;
214	};
215	
216	
217	// Basically the same as _pluck, but rather than looping over `a` we use `order`
218	// as the indexes to pick from `a`
219	var _pluck_order = function ( a, order, prop, prop2 )
220	{
221		var out = [];
222		var i=0, ien=order.length;
223	
224		// Could have the test in the loop for slightly smaller code, but speed
225		// is essential here
226		if ( prop2 !== undefined ) {
227			for ( ; i<ien ; i++ ) {
228				if ( a[ order[i] ][ prop ] ) {
229					out.push( a[ order[i] ][ prop ][ prop2 ] );
230				}
231			}
232		}
233		else {
234			for ( ; i<ien ; i++ ) {
235				out.push( a[ order[i] ][ prop ] );
236			}
237		}
238	
239		return out;
240	};
241	
242	
243	var _range = function ( len, start )
244	{
245		var out = [];
246		var end;
247	
248		if ( start === undefined ) {
249			start = 0;
250			end = len;
251		}
252		else {
253			end = start;
254			start = len;
255		}
256	
257		for ( var i=start ; i<end ; i++ ) {
258			out.push( i );
259		}
260	
261		return out;
262	};
263	
264	
265	var _removeEmpty = function ( a )
266	{
267		var out = [];
268	
269		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
270			if ( a[i] ) { // careful - will remove all falsy values!
271				out.push( a[i] );
272			}
273		}
274	
275		return out;
276	};
277	
278	
279	var _stripHtml = function ( d ) {
280		return d.replace( _re_html, '' );
281	};
282	
283	
284	/**
285	 * Find the unique elements in a source array.
286	 *
287	 * @param  {array} src Source array
288	 * @return {array} Array of unique items
289	 * @ignore
290	 */
291	var _unique = function ( src )
292	{
293		// A faster unique method is to use object keys to identify used values,
294		// but this doesn't work with arrays or objects, which we must also
295		// consider. See jsperf.com/compare-array-unique-versions/4 for more
296		// information.
297		var
298			out = [],
299			val,
300			i, ien=src.length,
301			j, k=0;
302	
303		again: for ( i=0 ; i<ien ; i++ ) {
304			val = src[i];
305	
306			for ( j=0 ; j<k ; j++ ) {
307				if ( out[j] === val ) {
308					continue again;
309				}
310			}
311	
312			out.push( val );
313			k++;
314		}
315	
316		return out;
317	};
318	
319	
320	
321	/**
322	 * Create a mapping object that allows camel case parameters to be looked up
323	 * for their Hungarian counterparts. The mapping is stored in a private
324	 * parameter called `_hungarianMap` which can be accessed on the source object.
325	 *  @param {object} o
326	 *  @memberof DataTable#oApi
327	 */
328	function _fnHungarianMap ( o )
329	{
330		var
331			hungarian = 'a aa ai ao as b fn i m o s ',
332			match,
333			newKey,
334			map = {};
335	
336		$.each( o, function (key, val) {
337			match = key.match(/^([^A-Z]+?)([A-Z])/);
338	
339			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
340			{
341				newKey = key.replace( match[0], match[2].toLowerCase() );
342				map[ newKey ] = key;
343	
344				if ( match[1] === 'o' )
345				{
346					_fnHungarianMap( o[key] );
347				}
348			}
349		} );
350	
351		o._hungarianMap = map;
352	}
353	
354	
355	/**
356	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
357	 * created by _fnHungarianMap.
358	 *  @param {object} src The model object which holds all parameters that can be
359	 *    mapped.
360	 *  @param {object} user The object to convert from camel case to Hungarian.
361	 *  @param {boolean} force When set to `true`, properties which already have a
362	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
363	 *    won't be.
364	 *  @memberof DataTable#oApi
365	 */
366	function _fnCamelToHungarian ( src, user, force )
367	{
368		if ( ! src._hungarianMap ) {
369			_fnHungarianMap( src );
370		}
371	
372		var hungarianKey;
373	
374		$.each( user, function (key, val) {
375			hungarianKey = src._hungarianMap[ key ];
376	
377			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
378			{
379				// For objects, we need to buzz down into the object to copy parameters
380				if ( hungarianKey.charAt(0) === 'o' )
381				{
382					// Copy the camelCase options over to the hungarian
383					if ( ! user[ hungarianKey ] ) {
384						user[ hungarianKey ] = {};
385					}
386					$.extend( true, user[hungarianKey], user[key] );
387	
388					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
389				}
390				else {
391					user[hungarianKey] = user[ key ];
392				}
393			}
394		} );
395	}
396	
397	
398	/**
399	 * Language compatibility - when certain options are given, and others aren't, we
400	 * need to duplicate the values over, in order to provide backwards compatibility
401	 * with older language files.
402	 *  @param {object} oSettings dataTables settings object
403	 *  @memberof DataTable#oApi
404	 */
405	function _fnLanguageCompat( lang )
406	{
407		var defaults = DataTable.defaults.oLanguage;
408		var zeroRecords = lang.sZeroRecords;
409	
410		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
411		 * sZeroRecords - assuming that is given.
412		 */
413		if ( ! lang.sEmptyTable && zeroRecords &&
414			defaults.sEmptyTable === "No data available in table" )
415		{
416			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
417		}
418	
419		/* Likewise with loading records */
420		if ( ! lang.sLoadingRecords && zeroRecords &&
421			defaults.sLoadingRecords === "Loading..." )
422		{
423			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
424		}
425	
426		// Old parameter name of the thousands separator mapped onto the new
427		if ( lang.sInfoThousands ) {
428			lang.sThousands = lang.sInfoThousands;
429		}
430	
431		var decimal = lang.sDecimal;
432		if ( decimal ) {
433			_addNumericSort( decimal );
434		}
435	}
436	
437	
438	/**
439	 * Map one parameter onto another
440	 *  @param {object} o Object to map
441	 *  @param {*} knew The new parameter name
442	 *  @param {*} old The old parameter name
443	 */
444	var _fnCompatMap = function ( o, knew, old ) {
445		if ( o[ knew ] !== undefined ) {
446			o[ old ] = o[ knew ];
447		}
448	};
449	
450	
451	/**
452	 * Provide backwards compatibility for the main DT options. Note that the new
453	 * options are mapped onto the old parameters, so this is an external interface
454	 * change only.
455	 *  @param {object} init Object to map
456	 */
457	function _fnCompatOpts ( init )
458	{
459		_fnCompatMap( init, 'ordering',      'bSort' );
460		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
461		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
462		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
463		_fnCompatMap( init, 'order',         'aaSorting' );
464		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
465		_fnCompatMap( init, 'paging',        'bPaginate' );
466		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
467		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
468		_fnCompatMap( init, 'searching',     'bFilter' );
469	
470		// Column search objects are in an array, so it needs to be converted
471		// element by element
472		var searchCols = init.aoSearchCols;
473	
474		if ( searchCols ) {
475			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
476				if ( searchCols[i] ) {
477					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
478				}
479			}
480		}
481	}
482	
483	
484	/**
485	 * Provide backwards compatibility for column options. Note that the new options
486	 * are mapped onto the old parameters, so this is an external interface change
487	 * only.
488	 *  @param {object} init Object to map
489	 */
490	function _fnCompatCols ( init )
491	{
492		_fnCompatMap( init, 'orderable',     'bSortable' );
493		_fnCompatMap( init, 'orderData',     'aDataSort' );
494		_fnCompatMap( init, 'orderSequence', 'asSorting' );
495		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
496	
497		// orderData can be given as an integer
498		var dataSort = init.aDataSort;
499		if ( dataSort && ! $.isArray( dataSort ) ) {
500			init.aDataSort = [ dataSort ];
501		}
502	}
503	
504	
505	/**
506	 * Browser feature detection for capabilities, quirks
507	 *  @param {object} settings dataTables settings object
508	 *  @memberof DataTable#oApi
509	 */
510	function _fnBrowserDetect( settings )
511	{
512		var browser = settings.oBrowser;
513	
514		// Scrolling feature / quirks detection
515		var n = $('<div/>')
516			.css( {
517				position: 'absolute',
518				top: 0,
519				left: 0,
520				height: 1,
521				width: 1,
522				overflow: 'hidden'
523			} )
524			.append(
525				$('<div/>')
526					.css( {
527						position: 'absolute',
528						top: 1,
529						left: 1,
530						width: 100,
531						overflow: 'scroll'
532					} )
533					.append(
534						$('<div class="test"/>')
535							.css( {
536								width: '100%',
537								height: 10
538							} )
539					)
540			)
541			.appendTo( 'body' );
542	
543		var test = n.find('.test');
544	
545		// IE6/7 will oversize a width 100% element inside a scrolling element, to
546		// include the width of the scrollbar, while other browsers ensure the inner
547		// element is contained without forcing scrolling
548		browser.bScrollOversize = test[0].offsetWidth === 100;
549	
550		// In rtl text layout, some browsers (most, but not all) will place the
551		// scrollbar on the left, rather than the right.
552		browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1;
553	
554		n.remove();
555	}
556	
557	
558	/**
559	 * Array.prototype reduce[Right] method, used for browsers which don't support
560	 * JS 1.6. Done this way to reduce code size, since we iterate either way
561	 *  @param {object} settings dataTables settings object
562	 *  @memberof DataTable#oApi
563	 */
564	function _fnReduce ( that, fn, init, start, end, inc )
565	{
566		var
567			i = start,
568			value,
569			isSet = false;
570	
571		if ( init !== undefined ) {
572			value = init;
573			isSet = true;
574		}
575	
576		while ( i !== end ) {
577			if ( ! that.hasOwnProperty(i) ) {
578				continue;
579			}
580	
581			value = isSet ?
582				fn( value, that[i], i, that ) :
583				that[i];
584	
585			isSet = true;
586			i += inc;
587		}
588	
589		return value;
590	}
591	
592	/**
593	 * Add a column to the list used for the table with default values
594	 *  @param {object} oSettings dataTables settings object
595	 *  @param {node} nTh The th element for this column
596	 *  @memberof DataTable#oApi
597	 */
598	function _fnAddColumn( oSettings, nTh )
599	{
600		// Add column to aoColumns array
601		var oDefaults = DataTable.defaults.column;
602		var iCol = oSettings.aoColumns.length;
603		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
604			"nTh": nTh ? nTh : document.createElement('th'),
605			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
606			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
607			"mData": oDefaults.mData ? oDefaults.mData : iCol,
608			idx: iCol
609		} );
610		oSettings.aoColumns.push( oCol );
611	
612		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
613		// passed into extend can be undefined. This allows the user to give a default
614		// with only some of the parameters defined, and also not give a default
615		var searchCols = oSettings.aoPreSearchCols;
616		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
617	
618		// Use the default column options function to initialise classes etc
619		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
620	}
621	
622	
623	/**
624	 * Apply options for a column
625	 *  @param {object} oSettings dataTables settings object
626	 *  @param {int} iCol column index to consider
627	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
628	 *  @memberof DataTable#oApi
629	 */
630	function _fnColumnOptions( oSettings, iCol, oOptions )
631	{
632		var oCol = oSettings.aoColumns[ iCol ];
633		var oClasses = oSettings.oClasses;
634		var th = $(oCol.nTh);
635	
636		// Try to get width information from the DOM. We can't get it from CSS
637		// as we'd need to parse the CSS stylesheet. `width` option can override
638		if ( ! oCol.sWidthOrig ) {
639			// Width attribute
640			oCol.sWidthOrig = th.attr('width') || null;
641	
642			// Style attribute
643			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
644			if ( t ) {
645				oCol.sWidthOrig = t[1];
646			}
647		}
648	
649		/* User specified column options */
650		if ( oOptions !== undefined && oOptions !== null )
651		{
652			// Backwards compatibility
653			_fnCompatCols( oOptions );
654	
655			// Map camel case parameters to their Hungarian counterparts
656			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
657	
658			/* Backwards compatibility for mDataProp */
659			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
660			{
661				oOptions.mData = oOptions.mDataProp;
662			}
663	
664			if ( oOptions.sType )
665			{
666				oCol._sManualType = oOptions.sType;
667			}
668	
669			// `class` is a reserved word in Javascript, so we need to provide
670			// the ability to use a valid name for the camel case input
671			if ( oOptions.className && ! oOptions.sClass )
672			{
673				oOptions.sClass = oOptions.className;
674			}
675	
676			$.extend( oCol, oOptions );
677			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
678	
679			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
680			 * priority if defined
681			 */
682			if ( oOptions.iDataSort !== undefined )
683			{
684				oCol.aDataSort = [ oOptions.iDataSort ];
685			}
686			_fnMap( oCol, oOptions, "aDataSort" );
687		}
688	
689		/* Cache the data get and set functions for speed */
690		var mDataSrc = oCol.mData;
691		var mData = _fnGetObjectDataFn( mDataSrc );
692		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
693	
694		var attrTest = function( src ) {
695			return typeof src === 'string' && src.indexOf('@') !== -1;
696		};
697		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
698			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
699		);
700	
701		oCol.fnGetData = function (rowData, type, meta) {
702			var innerData = mData( rowData, type, undefined, meta );
703	
704			return mRender && type ?
705				mRender( innerData, type, rowData, meta ) :
706				innerData;
707		};
708		oCol.fnSetData = function ( rowData, val, meta ) {
709			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
710		};
711	
712		// Indicate if DataTables should read DOM data as an object or array
713		// Used in _fnGetRowElements
714		if ( typeof mDataSrc !== 'number' ) {
715			oSettings._rowReadObject = true;
716		}
717	
718		/* Feature sorting overrides column specific when off */
719		if ( !oSettings.oFeatures.bSort )
720		{
721			oCol.bSortable = false;
722			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
723		}
724	
725		/* Check that the class assignment is correct for sorting */
726		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
727		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
728		if ( !oCol.bSortable || (!bAsc && !bDesc) )
729		{
730			oCol.sSortingClass = oClasses.sSortableNone;
731			oCol.sSortingClassJUI = "";
732		}
733		else if ( bAsc && !bDesc )
734		{
735			oCol.sSortingClass = oClasses.sSortableAsc;
736			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
737		}
738		else if ( !bAsc && bDesc )
739		{
740			oCol.sSortingClass = oClasses.sSortableDesc;
741			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
742		}
743		else
744		{
745			oCol.sSortingClass = oClasses.sSortable;
746			oCol.sSortingClassJUI = oClasses.sSortJUI;
747		}
748	}
749	
750	
751	/**
752	 * Adjust the table column widths for new data. Note: you would probably want to
753	 * do a redraw after calling this function!
754	 *  @param {object} settings dataTables settings object
755	 *  @memberof DataTable#oApi
756	 */
757	function _fnAdjustColumnSizing ( settings )
758	{
759		/* Not interested in doing column width calculation if auto-width is disabled */
760		if ( settings.oFeatures.bAutoWidth !== false )
761		{
762			var columns = settings.aoColumns;
763	
764			_fnCalculateColumnWidths( settings );
765			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
766			{
767				columns[i].nTh.style.width = columns[i].sWidth;
768			}
769		}
770	
771		var scroll = settings.oScroll;
772		if ( scroll.sY !== '' || scroll.sX !== '')
773		{
774			_fnScrollDraw( settings );
775		}
776	
777		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
778	}
779	
780	
781	/**
782	 * Covert the index of a visible column to the index in the data array (take account
783	 * of hidden columns)
784	 *  @param {object} oSettings dataTables settings object
785	 *  @param {int} iMatch Visible column index to lookup
786	 *  @returns {int} i the data index
787	 *  @memberof DataTable#oApi
788	 */
789	function _fnVisibleToColumnIndex( oSettings, iMatch )
790	{
791		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
792	
793		return typeof aiVis[iMatch] === 'number' ?
794			aiVis[iMatch] :
795			null;
796	}
797	
798	
799	/**
800	 * Covert the index of an index in the data array and convert it to the visible
801	 *   column index (take account of hidden columns)
802	 *  @param {int} iMatch Column index to lookup
803	 *  @param {object} oSettings dataTables settings object
804	 *  @returns {int} i the data index
805	 *  @memberof DataTable#oApi
806	 */
807	function _fnColumnIndexToVisible( oSettings, iMatch )
808	{
809		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
810		var iPos = $.inArray( iMatch, aiVis );
811	
812		return iPos !== -1 ? iPos : null;
813	}
814	
815	
816	/**
817	 * Get the number of visible columns
818	 *  @param {object} oSettings dataTables settings object
819	 *  @returns {int} i the number of visible columns
820	 *  @memberof DataTable#oApi
821	 */
822	function _fnVisbleColumns( oSettings )
823	{
824		return _fnGetColumns( oSettings, 'bVisible' ).length;
825	}
826	
827	
828	/**
829	 * Get an array of column indexes that match a given property
830	 *  @param {object} oSettings dataTables settings object
831	 *  @param {string} sParam Parameter in aoColumns to look for - typically
832	 *    bVisible or bSearchable
833	 *  @returns {array} Array of indexes with matched properties
834	 *  @memberof DataTable#oApi
835	 */
836	function _fnGetColumns( oSettings, sParam )
837	{
838		var a = [];
839	
840		$.map( oSettings.aoColumns, function(val, i) {
841			if ( val[sParam] ) {
842				a.push( i );
843			}
844		} );
845	
846		return a;
847	}
848	
849	
850	/**
851	 * Calculate the 'type' of a column
852	 *  @param {object} settings dataTables settings object
853	 *  @memberof DataTable#oApi
854	 */
855	function _fnColumnTypes ( settings )
856	{
857		var columns = settings.aoColumns;
858		var data = settings.aoData;
859		var types = DataTable.ext.type.detect;
860		var i, ien, j, jen, k, ken;
861		var col, cell, detectedType, cache;
862	
863		// For each column, spin over the 
864		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
865			col = columns[i];
866			cache = [];
867	
868			if ( ! col.sType && col._sManualType ) {
869				col.sType = col._sManualType;
870			}
871			else if ( ! col.sType ) {
872				for ( j=0, jen=types.length ; j<jen ; j++ ) {
873					for ( k=0, ken=data.length ; k<ken ; k++ ) {
874						// Use a cache array so we only need to get the type data
875						// from the formatter once (when using multiple detectors)
876						if ( cache[k] === undefined ) {
877							cache[k] = _fnGetCellData( settings, k, i, 'type' );
878						}
879	
880						detectedType = types[j]( cache[k], settings );
881	
882						// If null, then this type can't apply to this column, so
883						// rather than testing all cells, break out. There is an
884						// exception for the last type which is `html`. We need to
885						// scan all rows since it is possible to mix string and HTML
886						// types
887						if ( ! detectedType && j !== types.length-1 ) {
888							break;
889						}
890	
891						// Only a single match is needed for html type since it is
892						// bottom of the pile and very similar to string
893						if ( detectedType === 'html' ) {
894							break;
895						}
896					}
897	
898					// Type is valid for all data points in the column - use this
899					// type
900					if ( detectedType ) {
901						col.sType = detectedType;
902						break;
903					}
904				}
905	
906				// Fall back - if no type was detected, always use string
907				if ( ! col.sType ) {
908					col.sType = 'string';
909				}
910			}
911		}
912	}
913	
914	
915	/**
916	 * Take the column definitions and static columns arrays and calculate how
917	 * they relate to column indexes. The callback function will then apply the
918	 * definition found for a column to a suitable configuration object.
919	 *  @param {object} oSettings dataTables settings object
920	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
921	 *  @param {array} aoCols The aoColumns array that defines columns individually
922	 *  @param {function} fn Callback function - takes two parameters, the calculated
923	 *    column index and the definition for that column.
924	 *  @memberof DataTable#oApi
925	 */
926	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
927	{
928		var i, iLen, j, jLen, k, kLen, def;
929		var columns = oSettings.aoColumns;
930	
931		// Column definitions with aTargets
932		if ( aoColDefs )
933		{
934			/* Loop over the definitions array - loop in reverse so first instance has priority */
935			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
936			{
937				def = aoColDefs[i];
938	
939				/* Each definition can target multiple columns, as it is an array */
940				var aTargets = def.targets !== undefined ?
941					def.targets :
942					def.aTargets;
943	
944				if ( ! $.isArray( aTargets ) )
945				{
946					aTargets = [ aTargets ];
947				}
948	
949				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
950				{
951					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
952					{
953						/* Add columns that we don't yet know about */
954						while( columns.length <= aTargets[j] )
955						{
956							_fnAddColumn( oSettings );
957						}
958	
959						/* Integer, basic index */
960						fn( aTargets[j], def );
961					}
962					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
963					{
964						/* Negative integer, right to left column counting */
965						fn( columns.length+aTargets[j], def );
966					}
967					else if ( typeof aTargets[j] === 'string' )
968					{
969						/* Class name matching on TH element */
970						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
971						{
972							if ( aTargets[j] == "_all" ||
973							     $(columns[k].nTh).hasClass( aTargets[j] ) )
974							{
975								fn( k, def );
976							}
977						}
978					}
979				}
980			}
981		}
982	
983		// Statically defined columns array
984		if ( aoCols )
985		{
986			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
987			{
988				fn( i, aoCols[i] );
989			}
990		}
991	}
992	
993	/**
994	 * Add a data array to the table, creating DOM node etc. This is the parallel to
995	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
996	 * DOM source.
997	 *  @param {object} oSettings dataTables settings object
998	 *  @param {array} aData data array to be added
999	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
1000	 *    DataTables will create a row automatically
1001	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1002	 *    if nTr is.
1003	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
1004	 *  @memberof DataTable#oApi
1005	 */
1006	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
1007	{
1008		/* Create the object for storing information about this new row */
1009		var iRow = oSettings.aoData.length;
1010		var oData = $.extend( true, {}, DataTable.models.oRow, {
1011			src: nTr ? 'dom' : 'data'
1012		} );
1013	
1014		oData._aData = aDataIn;
1015		oSettings.aoData.push( oData );
1016	
1017		/* Create the cells */
1018		var nTd, sThisType;
1019		var columns = oSettings.aoColumns;
1020		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
1021		{
1022			// When working with a row, the data source object must be populated. In
1023			// all other cases, the data source object is already populated, so we
1024			// don't overwrite it, which might break bindings etc
1025			if ( nTr ) {
1026				_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
1027			}
1028			columns[i].sType = null;
1029		}
1030	
1031		/* Add to the display array */
1032		oSettings.aiDisplayMaster.push( iRow );
1033	
1034		/* Create the DOM information, or register it if already present */
1035		if ( nTr || ! oSettings.oFeatures.bDeferRender )
1036		{
1037			_fnCreateTr( oSettings, iRow, nTr, anTds );
1038		}
1039	
1040		return iRow;
1041	}
1042	
1043	
1044	/**
1045	 * Add one or more TR elements to the table. Generally we'd expect to
1046	 * use this for reading data from a DOM sourced table, but it could be
1047	 * used for an TR element. Note that if a TR is given, it is used (i.e.
1048	 * it is not cloned).
1049	 *  @param {object} settings dataTables settings object
1050	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
1051	 *  @returns {array} Array of indexes for the added rows
1052	 *  @memberof DataTable#oApi
1053	 */
1054	function _fnAddTr( settings, trs )
1055	{
1056		var row;
1057	
1058		// Allow an individual node to be passed in
1059		if ( ! (trs instanceof $) ) {
1060			trs = $(trs);
1061		}
1062	
1063		return trs.map( function (i, el) {
1064			row = _fnGetRowElements( settings, el );
1065			return _fnAddData( settings, row.data, el, row.cells );
1066		} );
1067	}
1068	
1069	
1070	/**
1071	 * Take a TR element and convert it to an index in aoData
1072	 *  @param {object} oSettings dataTables settings object
1073	 *  @param {node} n the TR element to find
1074	 *  @returns {int} index if the node is found, null if not
1075	 *  @memberof DataTable#oApi
1076	 */
1077	function _fnNodeToDataIndex( oSettings, n )
1078	{
1079		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
1080	}
1081	
1082	
1083	/**
1084	 * Take a TD element and convert it into a column data index (not the visible index)
1085	 *  @param {object} oSettings dataTables settings object
1086	 *  @param {int} iRow The row number the TD/TH can be found in
1087	 *  @param {node} n The TD/TH element to find
1088	 *  @returns {int} index if the node is found, -1 if not
1089	 *  @memberof DataTable#oApi
1090	 */
1091	function _fnNodeToColumnIndex( oSettings, iRow, n )
1092	{
1093		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
1094	}
1095	
1096	
1097	/**
1098	 * Get the data for a given cell from the internal cache, taking into account data mapping
1099	 *  @param {object} settings dataTables settings object
1100	 *  @param {int} rowIdx aoData row id
1101	 *  @param {int} colIdx Column index
1102	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
1103	 *  @returns {*} Cell data
1104	 *  @memberof DataTable#oApi
1105	 */
1106	function _fnGetCellData( settings, rowIdx, colIdx, type )
1107	{
1108		var draw           = settings.iDraw;
1109		var col            = settings.aoColumns[colIdx];
1110		var rowData        = settings.aoData[rowIdx]._aData;
1111		var defaultContent = col.sDefaultContent;
1112		var cellData       = col.fnGetData( rowData, type, {
1113			settings: settings,
1114			row:      rowIdx,
1115			col:      colIdx
1116		} );
1117	
1118		if ( cellData === undefined ) {
1119			if ( settings.iDrawError != draw && defaultContent === null ) {
1120				_fnLog( settings, 0, "Requested unknown parameter "+
1121					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
1122					" for row "+rowIdx, 4 );
1123				settings.iDrawError = draw;
1124			}
1125			return defaultContent;
1126		}
1127	
1128		/* When the data source is null, we can use default column data */
1129		if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
1130			cellData = defaultContent;
1131		}
1132		else if ( typeof cellData === 'function' ) {
1133			// If the data source is a function, then we run it and use the return,
1134			// executing in the scope of the data object (for instances)
1135			return cellData.call( rowData );
1136		}
1137	
1138		if ( cellData === null && type == 'display' ) {
1139			return '';
1140		}
1141		return cellData;
1142	}
1143	
1144	
1145	/**
1146	 * Set the value for a specific cell, into the internal data cache
1147	 *  @param {object} settings dataTables settings object
1148	 *  @param {int} rowIdx aoData row id
1149	 *  @param {int} colIdx Column index
1150	 *  @param {*} val Value to set
1151	 *  @memberof DataTable#oApi
1152	 */
1153	function _fnSetCellData( settings, rowIdx, colIdx, val )
1154	{
1155		var col     = settings.aoColumns[colIdx];
1156		var rowData = settings.aoData[rowIdx]._aData;
1157	
1158		col.fnSetData( rowData, val, {
1159			settings: settings,
1160			row:      rowIdx,
1161			col:      colIdx
1162		}  );
1163	}
1164	
1165	
1166	// Private variable that is used to match action syntax in the data property object
1167	var __reArray = /\[.*?\]$/;
1168	var __reFn = /\(\)$/;
1169	
1170	/**
1171	 * Split string on periods, taking into account escaped periods
1172	 * @param  {string} str String to split
1173	 * @return {array} Split string
1174	 */
1175	function _fnSplitObjNotation( str )
1176	{
1177		return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1178			return s.replace(/\\./g, '.');
1179		} );
1180	}
1181	
1182	
1183	/**
1184	 * Return a function that can be used to get data from a source object, taking
1185	 * into account the ability to use nested objects as a source
1186	 *  @param {string|int|function} mSource The data source for the object
1187	 *  @returns {function} Data get function
1188	 *  @memberof DataTable#oApi
1189	 */
1190	function _fnGetObjectDataFn( mSource )
1191	{
1192		if ( $.isPlainObject( mSource ) )
1193		{
1194			/* Build an object of get functions, and wrap them in a single call */
1195			var o = {};
1196			$.each( mSource, function (key, val) {
1197				if ( val ) {
1198					o[key] = _fnGetObjectDataFn( val );
1199				}
1200			} );
1201	
1202			return function (data, type, row, meta) {
1203				var t = o[type] || o._;
1204				return t !== undefined ?
1205					t(data, type, row, meta) :
1206					data;
1207			};
1208		}
1209		else if ( mSource === null )
1210		{
1211			/* Give an empty string for rendering / sorting etc */
1212			return function (data) { // type, row and meta also passed, but not used
1213				return data;
1214			};
1215		}
1216		else if ( typeof mSource === 'function' )
1217		{
1218			return function (data, type, row, meta) {
1219				return mSource( data, type, row, meta );
1220			};
1221		}
1222		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1223			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1224		{
1225			/* If there is a . in the source string then the data source is in a
1226			 * nested object so we loop over the data for each level to get the next
1227			 * level down. On each loop we test for undefined, and if found immediately
1228			 * return. This allows entire objects to be missing and sDefaultContent to
1229			 * be used if defined, rather than throwing an error
1230			 */
1231			var fetchData = function (data, type, src) {
1232				var arrayNotation, funcNotation, out, innerSrc;
1233	
1234				if ( src !== "" )
1235				{
1236					var a = _fnSplitObjNotation( src );
1237	
1238					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1239					{
1240						// Check if we are dealing with special notation
1241						arrayNotation = a[i].match(__reArray);
1242						funcNotation = a[i].match(__reFn);
1243	
1244						if ( arrayNotation )
1245						{
1246							// Array notation
1247							a[i] = a[i].replace(__reArray, '');
1248	
1249							// Condition allows simply [] to be passed in
1250							if ( a[i] !== "" ) {
1251								data = data[ a[i] ];
1252							}
1253							out = [];
1254	
1255							// Get the remainder of the nested object to get
1256							a.splice( 0, i+1 );
1257							innerSrc = a.join('.');
1258	
1259							// Traverse each entry in the array getting the properties requested
1260							for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1261								out.push( fetchData( data[j], type, innerSrc ) );
1262							}
1263	
1264							// If a string is given in between the array notation indicators, that
1265							// is used to join the strings together, otherwise an array is returned
1266							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1267							data = (join==="") ? out : out.join(join);
1268	
1269							// The inner call to fetchData has already traversed through the remainder
1270							// of the source requested, so we exit from the loop
1271							break;
1272						}
1273						else if ( funcNotation )
1274						{
1275							// Function call
1276							a[i] = a[i].replace(__reFn, '');
1277							data = data[ a[i] ]();
1278							continue;
1279						}
1280	
1281						if ( data === null || data[ a[i] ] === undefined )
1282						{
1283							return undefined;
1284						}
1285						data = data[ a[i] ];
1286					}
1287				}
1288	
1289				return data;
1290			};
1291	
1292			return function (data, type) { // row and meta also passed, but not used
1293				return fetchData( data, type, mSource );
1294			};
1295		}
1296		else
1297		{
1298			/* Array or flat object mapping */
1299			return function (data, type) { // row and meta also passed, but not used
1300				return data[mSource];
1301			};
1302		}
1303	}
1304	
1305	
1306	/**
1307	 * Return a function that can be used to set data from a source object, taking
1308	 * into account the ability to use nested objects as a source
1309	 *  @param {string|int|function} mSource The data source for the object
1310	 *  @returns {function} Data set function
1311	 *  @memberof DataTable#oApi
1312	 */
1313	function _fnSetObjectDataFn( mSource )
1314	{
1315		if ( $.isPlainObject( mSource ) )
1316		{
1317			/* Unlike get, only the underscore (global) option is used for for
1318			 * setting data since we don't know the type here. This is why an object
1319			 * option is not documented for `mData` (which is read/write), but it is
1320			 * for `mRender` which is read only.
1321			 */
1322			return _fnSetObjectDataFn( mSource._ );
1323		}
1324		else if ( mSource === null )
1325		{
1326			/* Nothing to do when the data source is null */
1327			return function () {};
1328		}
1329		else if ( typeof mSource === 'function' )
1330		{
1331			return function (data, val, meta) {
1332				mSource( data, 'set', val, meta );
1333			};
1334		}
1335		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1336			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1337		{
1338			/* Like the get, we need to get data from a nested object */
1339			var setData = function (data, val, src) {
1340				var a = _fnSplitObjNotation( src ), b;
1341				var aLast = a[a.length-1];
1342				var arrayNotation, funcNotation, o, innerSrc;
1343	
1344				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
1345				{
1346					// Check if we are dealing with an array notation request
1347					arrayNotation = a[i].match(__reArray);
1348					funcNotation = a[i].match(__reFn);
1349	
1350					if ( arrayNotation )
1351					{
1352						a[i] = a[i].replace(__reArray, '');
1353						data[ a[i] ] = [];
1354	
1355						// Get the remainder of the nested object to set so we can recurse
1356						b = a.slice();
1357						b.splice( 0, i+1 );
1358						innerSrc = b.join('.');
1359	
1360						// Traverse each entry in the array setting the properties requested
1361						for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1362						{
1363							o = {};
1364							setData( o, val[j], innerSrc );
1365							data[ a[i] ].push( o );
1366						}
1367	
1368						// The inner call to setData has already traversed through the remainder
1369						// of the source and has set the data, thus we can exit here
1370						return;
1371					}
1372					else if ( funcNotation )
1373					{
1374						// Function call
1375						a[i] = a[i].replace(__reFn, '');
1376						data = data[ a[i] ]( val );
1377					}
1378	
1379					// If the nested object doesn't currently exist - since we are
1380					// trying to set the value - create it
1381					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
1382					{
1383						data[ a[i] ] = {};
1384					}
1385					data = data[ a[i] ];
1386				}
1387	
1388				// Last item in the input - i.e, the actual set
1389				if ( aLast.match(__reFn ) )
1390				{
1391					// Function call
1392					data = data[ aLast.replace(__reFn, '') ]( val );
1393				}
1394				else
1395				{
1396					// If array notation is used, we just want to strip it and use the property name
1397					// and assign the value. If it isn't used, then we get the result we want anyway
1398					data[ aLast.replace(__reArray, '') ] = val;
1399				}
1400			};
1401	
1402			return function (data, val) { // meta is also passed in, but not used
1403				return setData( data, val, mSource );
1404			};
1405		}
1406		else
1407		{
1408			/* Array or flat object mapping */
1409			return function (data, val) { // meta is also passed in, but not used
1410				data[mSource] = val;
1411			};
1412		}
1413	}
1414	
1415	
1416	/**
1417	 * Return an array with the full table data
1418	 *  @param {object} oSettings dataTables settings object
1419	 *  @returns array {array} aData Master data array
1420	 *  @memberof DataTable#oApi
1421	 */
1422	function _fnGetDataMaster ( settings )
1423	{
1424		return _pluck( settings.aoData, '_aData' );
1425	}
1426	
1427	
1428	/**
1429	 * Nuke the table
1430	 *  @param {object} oSettings dataTables settings object
1431	 *  @memberof DataTable#oApi
1432	 */
1433	function _fnClearTable( settings )
1434	{
1435		settings.aoData.length = 0;
1436		settings.aiDisplayMaster.length = 0;
1437		settings.aiDisplay.length = 0;
1438	}
1439	
1440	
1441	 /**
1442	 * Take an array of integers (index array) and remove a target integer (value - not
1443	 * the key!)
1444	 *  @param {array} a Index array to target
1445	 *  @param {int} iTarget value to find
1446	 *  @memberof DataTable#oApi
1447	 */
1448	function _fnDeleteIndex( a, iTarget, splice )
1449	{
1450		var iTargetIndex = -1;
1451	
1452		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1453		{
1454			if ( a[i] == iTarget )
1455			{
1456				iTargetIndex = i;
1457			}
1458			else if ( a[i] > iTarget )
1459			{
1460				a[i]--;
1461			}
1462		}
1463	
1464		if ( iTargetIndex != -1 && splice === undefined )
1465		{
1466			a.splice( iTargetIndex, 1 );
1467		}
1468	}
1469	
1470	
1471	/**
1472	 * Mark cached data as invalid such that a re-read of the data will occur when
1473	 * the cached data is next requested. Also update from the data source object.
1474	 *
1475	 * @param {object} settings DataTables settings object
1476	 * @param {int}    rowIdx   Row index to invalidate
1477	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
1478	 *     or 'data'
1479	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
1480	 *     row will be invalidated
1481	 * @memberof DataTable#oApi
1482	 *
1483	 * @todo For the modularisation of v1.11 this will need to become a callback, so
1484	 *   the sort and filter methods can subscribe to it. That will required
1485	 *   initialisation options for sorting, which is why it is not already baked in
1486	 */
1487	function _fnInvalidate( settings, rowIdx, src, colIdx )
1488	{
1489		var row = settings.aoData[ rowIdx ];
1490		var i, ien;
1491		var cellWrite = function ( cell, col ) {
1492			// This is very frustrating, but in IE if you just write directly
1493			// to innerHTML, and elements that are overwritten are GC'ed,
1494			// even if there is a reference to them elsewhere
1495			while ( cell.childNodes.length ) {
1496				cell.removeChild( cell.firstChild );
1497			}
1498	
1499			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
1500		};
1501	
1502		// Are we reading last data from DOM or the data object?
1503		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1504			// Read the data from the DOM
1505			row._aData = _fnGetRowElements(
1506					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
1507				)
1508				.data;
1509		}
1510		else {
1511			// Reading from data object, update the DOM
1512			var cells = row.anCells;
1513	
1514			if ( cells ) {
1515				if ( colIdx !== undefined ) {
1516					cellWrite( cells[colIdx], colIdx );
1517				}
1518				else {
1519					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1520						cellWrite( cells[i], i );
1521					}
1522				}
1523			}
1524		}
1525	
1526		// For both row and cell invalidation, the cached data for sorting and
1527		// filtering is nulled out
1528		row._aSortData = null;
1529		row._aFilterData = null;
1530	
1531		// Invalidate the type for a specific column (if given) or all columns since
1532		// the data might have changed
1533		var cols = settings.aoColumns;
1534		if ( colIdx !== undefined ) {
1535			cols[ colIdx ].sType = null;
1536		}
1537		else {
1538			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1539				cols[i].sType = null;
1540			}
1541	
1542			// Update DataTables special `DT_*` attributes for the row
1543			_fnRowAttributes( row );
1544		}
1545	}
1546	
1547	
1548	/**
1549	 * Build a data source object from an HTML row, reading the contents of the
1550	 * cells that are in the row.
1551	 *
1552	 * @param {object} settings DataTables settings object
1553	 * @param {node|object} TR element from which to read data or existing row
1554	 *   object from which to re-read the data from the cells
1555	 * @param {int} [colIdx] Optional column index
1556	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
1557	 *   parameter should also be given and will be used to write the data into.
1558	 *   Only the column in question will be written
1559	 * @returns {object} Object with two parameters: `data` the data read, in
1560	 *   document order, and `cells` and array of nodes (they can be useful to the
1561	 *   caller, so rather than needing a second traversal to get them, just return
1562	 *   them from here).
1563	 * @memberof DataTable#oApi
1564	 */
1565	function _fnGetRowElements( settings, row, colIdx, d )
1566	{
1567		var
1568			tds = [],
1569			td = row.firstChild,
1570			name, col, o, i=0, contents,
1571			columns = settings.aoColumns,
1572			objectRead = settings._rowReadObject;
1573	
1574		// Allow the data object to be passed in, or construct
1575		d = d || objectRead ? {} : [];
1576	
1577		var attr = function ( str, td  ) {
1578			if ( typeof str === 'string' ) {
1579				var idx = str.indexOf('@');
1580	
1581				if ( idx !== -1 ) {
1582					var attr = str.substring( idx+1 );
1583					var setter = _fnSetObjectDataFn( str );
1584					setter( d, td.getAttribute( attr ) );
1585				}
1586			}
1587		};
1588	
1589		// Read data from a cell and store into the data object
1590		var cellProcess = function ( cell ) {
1591			if ( colIdx === undefined || colIdx === i ) {
1592				col = columns[i];
1593				contents = $.trim(cell.innerHTML);
1594	
1595				if ( col && col._bAttrSrc ) {
1596					var setter = _fnSetObjectDataFn( col.mData._ );
1597					setter( d, contents );
1598	
1599					attr( col.mData.sort, cell );
1600					attr( col.mData.type, cell );
1601					attr( col.mData.filter, cell );
1602				}
1603				else {
1604					// Depending on the `data` option for the columns the data can
1605					// be read to either an object or an array.
vendor: 11,503 bytes, lines 1606-2043
1606					if ( objectRead ) {
1607						if ( ! col._setter ) {
1608							// Cache the setter function
1609							col._setter = _fnSetObjectDataFn( col.mData );
1610						}
1611						col._setter( d, contents );
1612					}
1613					else {
1614						d[i] = contents;
1615					}
1616				}
1617			}
1618	
1619			i++;
1620		};
1621	
1622		if ( td ) {
1623			// `tr` element was passed in
1624			while ( td ) {
1625				name = td.nodeName.toUpperCase();
1626	
1627				if ( name == "TD" || name == "TH" ) {
1628					cellProcess( td );
1629					tds.push( td );
1630				}
1631	
1632				td = td.nextSibling;
1633			}
1634		}
1635		else {
1636			// Existing row object passed in
1637			tds = row.anCells;
1638			
1639			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1640				cellProcess( tds[j] );
1641			}
1642		}
1643	
1644		return {
1645			data: d,
1646			cells: tds
1647		};
1648	}
1649	/**
1650	 * Create a new TR element (and it's TD children) for a row
1651	 *  @param {object} oSettings dataTables settings object
1652	 *  @param {int} iRow Row to consider
1653	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1654	 *    DataTables will create a row automatically
1655	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1656	 *    if nTr is.
1657	 *  @memberof DataTable#oApi
1658	 */
1659	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
1660	{
1661		var
1662			row = oSettings.aoData[iRow],
1663			rowData = row._aData,
1664			cells = [],
1665			nTr, nTd, oCol,
1666			i, iLen;
1667	
1668		if ( row.nTr === null )
1669		{
1670			nTr = nTrIn || document.createElement('tr');
1671	
1672			row.nTr = nTr;
1673			row.anCells = cells;
1674	
1675			/* Use a private property on the node to allow reserve mapping from the node
1676			 * to the aoData array for fast look up
1677			 */
1678			nTr._DT_RowIndex = iRow;
1679	
1680			/* Special parameters can be given by the data source to be used on the row */
1681			_fnRowAttributes( row );
1682	
1683			/* Process each column */
1684			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1685			{
1686				oCol = oSettings.aoColumns[i];
1687	
1688				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1689				cells.push( nTd );
1690	
1691				// Need to create the HTML if new, or if a rendering function is defined
1692				if ( !nTrIn || oCol.mRender || oCol.mData !== i )
1693				{
1694					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
1695				}
1696	
1697				/* Add user defined class */
1698				if ( oCol.sClass )
1699				{
1700					nTd.className += ' '+oCol.sClass;
1701				}
1702	
1703				// Visibility - add or remove as required
1704				if ( oCol.bVisible && ! nTrIn )
1705				{
1706					nTr.appendChild( nTd );
1707				}
1708				else if ( ! oCol.bVisible && nTrIn )
1709				{
1710					nTd.parentNode.removeChild( nTd );
1711				}
1712	
1713				if ( oCol.fnCreatedCell )
1714				{
1715					oCol.fnCreatedCell.call( oSettings.oInstance,
1716						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
1717					);
1718				}
1719			}
1720	
1721			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
1722		}
1723	
1724		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1725		// and deployed
1726		row.nTr.setAttribute( 'role', 'row' );
1727	}
1728	
1729	
1730	/**
1731	 * Add attributes to a row based on the special `DT_*` parameters in a data
1732	 * source object.
1733	 *  @param {object} DataTables row object for the row to be modified
1734	 *  @memberof DataTable#oApi
1735	 */
1736	function _fnRowAttributes( row )
1737	{
1738		var tr = row.nTr;
1739		var data = row._aData;
1740	
1741		if ( tr ) {
1742			if ( data.DT_RowId ) {
1743				tr.id = data.DT_RowId;
1744			}
1745	
1746			if ( data.DT_RowClass ) {
1747				// Remove any classes added by DT_RowClass before
1748				var a = data.DT_RowClass.split(' ');
1749				row.__rowc = row.__rowc ?
1750					_unique( row.__rowc.concat( a ) ) :
1751					a;
1752	
1753				$(tr)
1754					.removeClass( row.__rowc.join(' ') )
1755					.addClass( data.DT_RowClass );
1756			}
1757	
1758			if ( data.DT_RowAttr ) {
1759				$(tr).attr( data.DT_RowAttr );
1760			}
1761	
1762			if ( data.DT_RowData ) {
1763				$(tr).data( data.DT_RowData );
1764			}
1765		}
1766	}
1767	
1768	
1769	/**
1770	 * Create the HTML header for the table
1771	 *  @param {object} oSettings dataTables settings object
1772	 *  @memberof DataTable#oApi
1773	 */
1774	function _fnBuildHead( oSettings )
1775	{
1776		var i, ien, cell, row, column;
1777		var thead = oSettings.nTHead;
1778		var tfoot = oSettings.nTFoot;
1779		var createHeader = $('th, td', thead).length === 0;
1780		var classes = oSettings.oClasses;
1781		var columns = oSettings.aoColumns;
1782	
1783		if ( createHeader ) {
1784			row = $('<tr/>').appendTo( thead );
1785		}
1786	
1787		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
1788			column = columns[i];
1789			cell = $( column.nTh ).addClass( column.sClass );
1790	
1791			if ( createHeader ) {
1792				cell.appendTo( row );
1793			}
1794	
1795			// 1.11 move into sorting
1796			if ( oSettings.oFeatures.bSort ) {
1797				cell.addClass( column.sSortingClass );
1798	
1799				if ( column.bSortable !== false ) {
1800					cell
1801						.attr( 'tabindex', oSettings.iTabIndex )
1802						.attr( 'aria-controls', oSettings.sTableId );
1803	
1804					_fnSortAttachListener( oSettings, column.nTh, i );
1805				}
1806			}
1807	
1808			if ( column.sTitle != cell.html() ) {
1809				cell.html( column.sTitle );
1810			}
1811	
1812			_fnRenderer( oSettings, 'header' )(
1813				oSettings, cell, column, classes
1814			);
1815		}
1816	
1817		if ( createHeader ) {
1818			_fnDetectHeader( oSettings.aoHeader, thead );
1819		}
1820		
1821		/* ARIA role for the rows */
1822	 	$(thead).find('>tr').attr('role', 'row');
1823	
1824		/* Deal with the footer - add classes if required */
1825		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
1826		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
1827	
1828		// Cache the footer cells. Note that we only take the cells from the first
1829		// row in the footer. If there is more than one row the user wants to
1830		// interact with, they need to use the table().foot() method. Note also this
1831		// allows cells to be used for multiple columns using colspan
1832		if ( tfoot !== null ) {
1833			var cells = oSettings.aoFooter[0];
1834	
1835			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1836				column = columns[i];
1837				column.nTf = cells[i].cell;
1838	
1839				if ( column.sClass ) {
1840					$(column.nTf).addClass( column.sClass );
1841				}
1842			}
1843		}
1844	}
1845	
1846	
1847	/**
1848	 * Draw the header (or footer) element based on the column visibility states. The
1849	 * methodology here is to use the layout array from _fnDetectHeader, modified for
1850	 * the instantaneous column visibility, to construct the new layout. The grid is
1851	 * traversed over cell at a time in a rows x columns grid fashion, although each
1852	 * cell insert can cover multiple elements in the grid - which is tracks using the
1853	 * aApplied array. Cell inserts in the grid will only occur where there isn't
1854	 * already a cell in that position.
1855	 *  @param {object} oSettings dataTables settings object
1856	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
1857	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1858	 *  @memberof DataTable#oApi
1859	 */
1860	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1861	{
1862		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1863		var aoLocal = [];
1864		var aApplied = [];
1865		var iColumns = oSettings.aoColumns.length;
1866		var iRowspan, iColspan;
1867	
1868		if ( ! aoSource )
1869		{
1870			return;
1871		}
1872	
1873		if (  bIncludeHidden === undefined )
1874		{
1875			bIncludeHidden = false;
1876		}
1877	
1878		/* Make a copy of the master layout array, but without the visible columns in it */
1879		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1880		{
1881			aoLocal[i] = aoSource[i].slice();
1882			aoLocal[i].nTr = aoSource[i].nTr;
1883	
1884			/* Remove any columns which are currently hidden */
1885			for ( j=iColumns-1 ; j>=0 ; j-- )
1886			{
1887				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1888				{
1889					aoLocal[i].splice( j, 1 );
1890				}
1891			}
1892	
1893			/* Prep the applied array - it needs an element for each row */
1894			aApplied.push( [] );
1895		}
1896	
1897		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1898		{
1899			nLocalTr = aoLocal[i].nTr;
1900	
1901			/* All cells are going to be replaced, so empty out the row */
1902			if ( nLocalTr )
1903			{
1904				while( (n = nLocalTr.firstChild) )
1905				{
1906					nLocalTr.removeChild( n );
1907				}
1908			}
1909	
1910			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1911			{
1912				iRowspan = 1;
1913				iColspan = 1;
1914	
1915				/* Check to see if there is already a cell (row/colspan) covering our target
1916				 * insert point. If there is, then there is nothing to do.
1917				 */
1918				if ( aApplied[i][j] === undefined )
1919				{
1920					nLocalTr.appendChild( aoLocal[i][j].cell );
1921					aApplied[i][j] = 1;
1922	
1923					/* Expand the cell to cover as many rows as needed */
1924					while ( aoLocal[i+iRowspan] !== undefined &&
1925					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1926					{
1927						aApplied[i+iRowspan][j] = 1;
1928						iRowspan++;
1929					}
1930	
1931					/* Expand the cell to cover as many columns as needed */
1932					while ( aoLocal[i][j+iColspan] !== undefined &&
1933					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1934					{
1935						/* Must update the applied array over the rows for the columns */
1936						for ( k=0 ; k<iRowspan ; k++ )
1937						{
1938							aApplied[i+k][j+iColspan] = 1;
1939						}
1940						iColspan++;
1941					}
1942	
1943					/* Do the actual expansion in the DOM */
1944					$(aoLocal[i][j].cell)
1945						.attr('rowspan', iRowspan)
1946						.attr('colspan', iColspan);
1947				}
1948			}
1949		}
1950	}
1951	
1952	
1953	/**
1954	 * Insert the required TR nodes into the table for display
1955	 *  @param {object} oSettings dataTables settings object
1956	 *  @memberof DataTable#oApi
1957	 */
1958	function _fnDraw( oSettings )
1959	{
1960		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1961		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
1962		if ( $.inArray( false, aPreDraw ) !== -1 )
1963		{
1964			_fnProcessingDisplay( oSettings, false );
1965			return;
1966		}
1967	
1968		var i, iLen, n;
1969		var anRows = [];
1970		var iRowCount = 0;
1971		var asStripeClasses = oSettings.asStripeClasses;
1972		var iStripes = asStripeClasses.length;
1973		var iOpenRows = oSettings.aoOpenRows.length;
1974		var oLang = oSettings.oLanguage;
1975		var iInitDisplayStart = oSettings.iInitDisplayStart;
1976		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
1977		var aiDisplay = oSettings.aiDisplay;
1978	
1979		oSettings.bDrawing = true;
1980	
1981		/* Check and see if we have an initial draw position from state saving */
1982		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
1983		{
1984			oSettings._iDisplayStart = bServerSide ?
1985				iInitDisplayStart :
1986				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
1987					0 :
1988					iInitDisplayStart;
1989	
1990			oSettings.iInitDisplayStart = -1;
1991		}
1992	
1993		var iDisplayStart = oSettings._iDisplayStart;
1994		var iDisplayEnd = oSettings.fnDisplayEnd();
1995	
1996		/* Server-side processing draw intercept */
1997		if ( oSettings.bDeferLoading )
1998		{
1999			oSettings.bDeferLoading = false;
2000			oSettings.iDraw++;
2001			_fnProcessingDisplay( oSettings, false );
2002		}
2003		else if ( !bServerSide )
2004		{
2005			oSettings.iDraw++;
2006		}
2007		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
2008		{
2009			return;
2010		}
2011	
2012		if ( aiDisplay.length !== 0 )
2013		{
2014			var iStart = bServerSide ? 0 : iDisplayStart;
2015			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
2016	
2017			for ( var j=iStart ; j<iEnd ; j++ )
2018			{
2019				var iDataIndex = aiDisplay[j];
2020				var aoData = oSettings.aoData[ iDataIndex ];
2021				if ( aoData.nTr === null )
2022				{
2023					_fnCreateTr( oSettings, iDataIndex );
2024				}
2025	
2026				var nRow = aoData.nTr;
2027	
2028				/* Remove the old striping classes and then add the new one */
2029				if ( iStripes !== 0 )
2030				{
2031					var sStripe = asStripeClasses[ iRowCount % iStripes ];
2032					if ( aoData._sRowStripe != sStripe )
2033					{
2034						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
2035						aoData._sRowStripe = sStripe;
2036					}
2037				}
2038	
2039				// Row callback functions - might want to manipulate the row
2040				// iRowCount and j are not currently documented. Are they at all
2041				// useful?
2042				_fnCallbackFire( oSettings, 'aoRowCallback', null,
2043					[nRow, aoData._aData, iRowCount, j
vendor: 6,302 bytes, lines 2043-2280
2043] );
2044	
2045				anRows.push( nRow );
2046				iRowCount++;
2047			}
2048		}
2049		else
2050		{
2051			/* Table is empty - create a row with an empty message in it */
2052			var sZero = oLang.sZeroRecords;
2053			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
2054			{
2055				sZero = oLang.sLoadingRecords;
2056			}
2057			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
2058			{
2059				sZero = oLang.sEmptyTable;
2060			}
2061	
2062			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
2063				.append( $('<td />', {
2064					'valign':  'top',
2065					'colSpan': _fnVisbleColumns( oSettings ),
2066					'class':   oSettings.oClasses.sRowEmpty
2067				} ).html( sZero ) )[0];
2068		}
2069	
2070		/* Header and footer callbacks */
2071		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
2072			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2073	
2074		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
2075			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2076	
2077		var body = $(oSettings.nTBody);
2078	
2079		body.children().detach();
2080		body.append( $(anRows) );
2081	
2082		/* Call all required callback functions for the end of a draw */
2083		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
2084	
2085		/* Draw is complete, sorting and filtering must be as well */
2086		oSettings.bSorted = false;
2087		oSettings.bFiltered = false;
2088		oSettings.bDrawing = false;
2089	}
2090	
2091	
2092	/**
2093	 * Redraw the table - taking account of the various features which are enabled
2094	 *  @param {object} oSettings dataTables settings object
2095	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
2096	 *    the paging is reset to the first page
2097	 *  @memberof DataTable#oApi
2098	 */
2099	function _fnReDraw( settings, holdPosition )
2100	{
2101		var
2102			features = settings.oFeatures,
2103			sort     = features.bSort,
2104			filter   = features.bFilter;
2105	
2106		if ( sort ) {
2107			_fnSort( settings );
2108		}
2109	
2110		if ( filter ) {
2111			_fnFilterComplete( settings, settings.oPreviousSearch );
2112		}
2113		else {
2114			// No filtering, so we want to just use the display master
2115			settings.aiDisplay = settings.aiDisplayMaster.slice();
2116		}
2117	
2118		if ( holdPosition !== true ) {
2119			settings._iDisplayStart = 0;
2120		}
2121	
2122		// Let any modules know about the draw hold position state (used by
2123		// scrolling internally)
2124		settings._drawHold = holdPosition;
2125	
2126		_fnDraw( settings );
2127	
2128		settings._drawHold = false;
2129	}
2130	
2131	
2132	/**
2133	 * Add the options to the page HTML for the table
2134	 *  @param {object} oSettings dataTables settings object
2135	 *  @memberof DataTable#oApi
2136	 */
2137	function _fnAddOptionsHtml ( oSettings )
2138	{
2139		var classes = oSettings.oClasses;
2140		var table = $(oSettings.nTable);
2141		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
2142		var features = oSettings.oFeatures;
2143	
2144		// All DataTables are wrapped in a div
2145		var insert = $('<div/>', {
2146			id:      oSettings.sTableId+'_wrapper',
2147			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
2148		} );
2149	
2150		oSettings.nHolding = holding[0];
2151		oSettings.nTableWrapper = insert[0];
2152		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
2153	
2154		/* Loop over the user set positioning and place the elements as needed */
2155		var aDom = oSettings.sDom.split('');
2156		var featureNode, cOption, nNewNode, cNext, sAttr, j;
2157		for ( var i=0 ; i<aDom.length ; i++ )
2158		{
2159			featureNode = null;
2160			cOption = aDom[i];
2161	
2162			if ( cOption == '<' )
2163			{
2164				/* New container div */
2165				nNewNode = $('<div/>')[0];
2166	
2167				/* Check to see if we should append an id and/or a class name to the container */
2168				cNext = aDom[i+1];
2169				if ( cNext == "'" || cNext == '"' )
2170				{
2171					sAttr = "";
2172					j = 2;
2173					while ( aDom[i+j] != cNext )
2174					{
2175						sAttr += aDom[i+j];
2176						j++;
2177					}
2178	
2179					/* Replace jQuery UI constants @todo depreciated */
2180					if ( sAttr == "H" )
2181					{
2182						sAttr = classes.sJUIHeader;
2183					}
2184					else if ( sAttr == "F" )
2185					{
2186						sAttr = classes.sJUIFooter;
2187					}
2188	
2189					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2190					 * breaks the string into parts and applies them as needed
2191					 */
2192					if ( sAttr.indexOf('.') != -1 )
2193					{
2194						var aSplit = sAttr.split('.');
2195						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
2196						nNewNode.className = aSplit[1];
2197					}
2198					else if ( sAttr.charAt(0) == "#" )
2199					{
2200						nNewNode.id = sAttr.substr(1, sAttr.length-1);
2201					}
2202					else
2203					{
2204						nNewNode.className = sAttr;
2205					}
2206	
2207					i += j; /* Move along the position array */
2208				}
2209	
2210				insert.append( nNewNode );
2211				insert = $(nNewNode);
2212			}
2213			else if ( cOption == '>' )
2214			{
2215				/* End container div */
2216				insert = insert.parent();
2217			}
2218			// @todo Move options into their own plugins?
2219			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
2220			{
2221				/* Length */
2222				featureNode = _fnFeatureHtmlLength( oSettings );
2223			}
2224			else if ( cOption == 'f' && features.bFilter )
2225			{
2226				/* Filter */
2227				featureNode = _fnFeatureHtmlFilter( oSettings );
2228			}
2229			else if ( cOption == 'r' && features.bProcessing )
2230			{
2231				/* pRocessing */
2232				featureNode = _fnFeatureHtmlProcessing( oSettings );
2233			}
2234			else if ( cOption == 't' )
2235			{
2236				/* Table */
2237				featureNode = _fnFeatureHtmlTable( oSettings );
2238			}
2239			else if ( cOption ==  'i' && features.bInfo )
2240			{
2241				/* Info */
2242				featureNode = _fnFeatureHtmlInfo( oSettings );
2243			}
2244			else if ( cOption == 'p' && features.bPaginate )
2245			{
2246				/* Pagination */
2247				featureNode = _fnFeatureHtmlPaginate( oSettings );
2248			}
2249			else if ( DataTable.ext.feature.length !== 0 )
2250			{
2251				/* Plug-in features */
2252				var aoFeatures = DataTable.ext.feature;
2253				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
2254				{
2255					if ( cOption == aoFeatures[k].cFeature )
2256					{
2257						featureNode = aoFeatures[k].fnInit( oSettings );
2258						break;
2259					}
2260				}
2261			}
2262	
2263			/* Add to the 2D features array */
2264			if ( featureNode )
2265			{
2266				var aanFeatures = oSettings.aanFeatures;
2267	
2268				if ( ! aanFeatures[cOption] )
2269				{
2270					aanFeatures[cOption] = [];
2271				}
2272	
2273				aanFeatures[cOption].push( featureNode );
2274				insert.append( featureNode );
2275			}
2276		}
2277	
2278		/* Built our DOM structure - replace the holding div with what we want */
2279		holding.replaceWith( insert );
2280	
vendor: 42,271 bytes, lines 2280-3782
2280}
2281	
2282	
2283	/**
2284	 * Use the DOM source to create up an array of header cells. The idea here is to
2285	 * create a layout grid (array) of rows x columns, which contains a reference
2286	 * to the cell that that point in the grid (regardless of col/rowspan), such that
2287	 * any column / row could be removed and the new grid constructed
2288	 *  @param array {object} aLayout Array to store the calculated layout in
2289	 *  @param {node} nThead The header/footer element for the table
2290	 *  @memberof DataTable#oApi
2291	 */
2292	function _fnDetectHeader ( aLayout, nThead )
2293	{
2294		var nTrs = $(nThead).children('tr');
2295		var nTr, nCell;
2296		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
2297		var bUnique;
2298		var fnShiftCol = function ( a, i, j ) {
2299			var k = a[i];
2300	                while ( k[j] ) {
2301				j++;
2302			}
2303			return j;
2304		};
2305	
2306		aLayout.splice( 0, aLayout.length );
2307	
2308		/* We know how many rows there are in the layout - so prep it */
2309		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2310		{
2311			aLayout.push( [] );
2312		}
2313	
2314		/* Calculate a layout array */
2315		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2316		{
2317			nTr = nTrs[i];
2318			iColumn = 0;
2319	
2320			/* For every cell in the row... */
2321			nCell = nTr.firstChild;
2322			while ( nCell ) {
2323				if ( nCell.nodeName.toUpperCase() == "TD" ||
2324				     nCell.nodeName.toUpperCase() == "TH" )
2325				{
2326					/* Get the col and rowspan attributes from the DOM and sanitise them */
2327					iColspan = nCell.getAttribute('colspan') * 1;
2328					iRowspan = nCell.getAttribute('rowspan') * 1;
2329					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
2330					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
2331	
2332					/* There might be colspan cells already in this row, so shift our target
2333					 * accordingly
2334					 */
2335					iColShifted = fnShiftCol( aLayout, i, iColumn );
2336	
2337					/* Cache calculation for unique columns */
2338					bUnique = iColspan === 1 ? true : false;
2339	
2340					/* If there is col / rowspan, copy the information into the layout grid */
2341					for ( l=0 ; l<iColspan ; l++ )
2342					{
2343						for ( k=0 ; k<iRowspan ; k++ )
2344						{
2345							aLayout[i+k][iColShifted+l] = {
2346								"cell": nCell,
2347								"unique": bUnique
2348							};
2349							aLayout[i+k].nTr = nTr;
2350						}
2351					}
2352				}
2353				nCell = nCell.nextSibling;
2354			}
2355		}
2356	}
2357	
2358	
2359	/**
2360	 * Get an array of unique th elements, one for each column
2361	 *  @param {object} oSettings dataTables settings object
2362	 *  @param {node} nHeader automatically detect the layout from this node - optional
2363	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2364	 *  @returns array {node} aReturn list of unique th's
2365	 *  @memberof DataTable#oApi
2366	 */
2367	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
2368	{
2369		var aReturn = [];
2370		if ( !aLayout )
2371		{
2372			aLayout = oSettings.aoHeader;
2373			if ( nHeader )
2374			{
2375				aLayout = [];
2376				_fnDetectHeader( aLayout, nHeader );
2377			}
2378		}
2379	
2380		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
2381		{
2382			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
2383			{
2384				if ( aLayout[i][j].unique &&
2385					 (!aReturn[j] || !oSettings.bSortCellsTop) )
2386				{
2387					aReturn[j] = aLayout[i][j].cell;
2388				}
2389			}
2390		}
2391	
2392		return aReturn;
2393	}
2394	
2395	/**
2396	 * Create an Ajax call based on the table's settings, taking into account that
2397	 * parameters can have multiple forms, and backwards compatibility.
2398	 *
2399	 * @param {object} oSettings dataTables settings object
2400	 * @param {array} data Data to send to the server, required by
2401	 *     DataTables - may be augmented by developer callbacks
2402	 * @param {function} fn Callback function to run when data is obtained
2403	 */
2404	function _fnBuildAjax( oSettings, data, fn )
2405	{
2406		// Compatibility with 1.9-, allow fnServerData and event to manipulate
2407		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
2408	
2409		// Convert to object based for 1.10+ if using the old array scheme which can
2410		// come from server-side processing or serverParams
2411		if ( data && $.isArray(data) ) {
2412			var tmp = {};
2413			var rbracket = /(.*?)\[\]$/;
2414	
2415			$.each( data, function (key, val) {
2416				var match = val.name.match(rbracket);
2417	
2418				if ( match ) {
2419					// Support for arrays
2420					var name = match[0];
2421	
2422					if ( ! tmp[ name ] ) {
2423						tmp[ name ] = [];
2424					}
2425					tmp[ name ].push( val.value );
2426				}
2427				else {
2428					tmp[val.name] = val.value;
2429				}
2430			} );
2431			data = tmp;
2432		}
2433	
2434		var ajaxData;
2435		var ajax = oSettings.ajax;
2436		var instance = oSettings.oInstance;
2437		var callback = function ( json ) {
2438			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
2439			fn( json );
2440		};
2441	
2442		if ( $.isPlainObject( ajax ) && ajax.data )
2443		{
2444			ajaxData = ajax.data;
2445	
2446			var newData = $.isFunction( ajaxData ) ?
2447				ajaxData( data, oSettings ) :  // fn can manipulate data or return
2448				ajaxData;                      // an object object or array to merge
2449	
2450			// If the function returned something, use that alone
2451			data = $.isFunction( ajaxData ) && newData ?
2452				newData :
2453				$.extend( true, data, newData );
2454	
2455			// Remove the data property as we've resolved it already and don't want
2456			// jQuery to do it again (it is restored at the end of the function)
2457			delete ajax.data;
2458		}
2459	
2460		var baseAjax = {
2461			"data": data,
2462			"success": function (json) {
2463				var error = json.error || json.sError;
2464				if ( error ) {
2465					_fnLog( oSettings, 0, error );
2466				}
2467	
2468				oSettings.json = json;
2469				callback( json );
2470			},
2471			"dataType": "json",
2472			"cache": false,
2473			"type": oSettings.sServerMethod,
2474			"error": function (xhr, error, thrown) {
2475				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
2476	
2477				if ( $.inArray( true, ret ) === -1 ) {
2478					if ( error == "parsererror" ) {
2479						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
2480					}
2481					else if ( xhr.readyState === 4 ) {
2482						_fnLog( oSettings, 0, 'Ajax error', 7 );
2483					}
2484				}
2485	
2486				_fnProcessingDisplay( oSettings, false );
2487			}
2488		};
2489	
2490		// Store the data submitted for the API
2491		oSettings.oAjaxData = data;
2492	
2493		// Allow plug-ins and external processes to modify the data
2494		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
2495	
2496		if ( oSettings.fnServerData )
2497		{
2498			// DataTables 1.9- compatibility
2499			oSettings.fnServerData.call( instance,
2500				oSettings.sAjaxSource,
2501				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2502					return { name: key, value: val };
2503				} ),
2504				callback,
2505				oSettings
2506			);
2507		}
2508		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
2509		{
2510			// DataTables 1.9- compatibility
2511			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
2512				url: ajax || oSettings.sAjaxSource
2513			} ) );
2514		}
2515		else if ( $.isFunction( ajax ) )
2516		{
2517			// Is a function - let the caller define what needs to be done
2518			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
2519		}
2520		else
2521		{
2522			// Object to extend the base settings
2523			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
2524	
2525			// Restore for next time around
2526			ajax.data = ajaxData;
2527		}
2528	}
2529	
2530	
2531	/**
2532	 * Update the table using an Ajax call
2533	 *  @param {object} settings dataTables settings object
2534	 *  @returns {boolean} Block the table drawing or not
2535	 *  @memberof DataTable#oApi
2536	 */
2537	function _fnAjaxUpdate( settings )
2538	{
2539		if ( settings.bAjaxDataGet ) {
2540			settings.iDraw++;
2541			_fnProcessingDisplay( settings, true );
2542	
2543			_fnBuildAjax(
2544				settings,
2545				_fnAjaxParameters( settings ),
2546				function(json) {
2547					_fnAjaxUpdateDraw( settings, json );
2548				}
2549			);
2550	
2551			return false;
2552		}
2553		return true;
2554	}
2555	
2556	
2557	/**
2558	 * Build up the parameters in an object needed for a server-side processing
2559	 * request. Note that this is basically done twice, is different ways - a modern
2560	 * method which is used by default in DataTables 1.10 which uses objects and
2561	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2562	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
2563	 * option is set.
2564	 *  @param {object} oSettings dataTables settings object
2565	 *  @returns {bool} block the table drawing or not
2566	 *  @memberof DataTable#oApi
2567	 */
2568	function _fnAjaxParameters( settings )
2569	{
2570		var
2571			columns = settings.aoColumns,
2572			columnCount = columns.length,
2573			features = settings.oFeatures,
2574			preSearch = settings.oPreviousSearch,
2575			preColSearch = settings.aoPreSearchCols,
2576			i, data = [], dataProp, column, columnSearch,
2577			sort = _fnSortFlatten( settings ),
2578			displayStart = settings._iDisplayStart,
2579			displayLength = features.bPaginate !== false ?
2580				settings._iDisplayLength :
2581				-1;
2582	
2583		var param = function ( name, value ) {
2584			data.push( { 'name': name, 'value': value } );
2585		};
2586	
2587		// DataTables 1.9- compatible method
2588		param( 'sEcho',          settings.iDraw );
2589		param( 'iColumns',       columnCount );
2590		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
2591		param( 'iDisplayStart',  displayStart );
2592		param( 'iDisplayLength', displayLength );
2593	
2594		// DataTables 1.10+ method
2595		var d = {
2596			draw:    settings.iDraw,
2597			columns: [],
2598			order:   [],
2599			start:   displayStart,
2600			length:  displayLength,
2601			search:  {
2602				value: preSearch.sSearch,
2603				regex: preSearch.bRegex
2604			}
2605		};
2606	
2607		for ( i=0 ; i<columnCount ; i++ ) {
2608			column = columns[i];
2609			columnSearch = preColSearch[i];
2610			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
2611	
2612			d.columns.push( {
2613				data:       dataProp,
2614				name:       column.sName,
2615				searchable: column.bSearchable,
2616				orderable:  column.bSortable,
2617				search:     {
2618					value: columnSearch.sSearch,
2619					regex: columnSearch.bRegex
2620				}
2621			} );
2622	
2623			param( "mDataProp_"+i, dataProp );
2624	
2625			if ( features.bFilter ) {
2626				param( 'sSearch_'+i,     columnSearch.sSearch );
2627				param( 'bRegex_'+i,      columnSearch.bRegex );
2628				param( 'bSearchable_'+i, column.bSearchable );
2629			}
2630	
2631			if ( features.bSort ) {
2632				param( 'bSortable_'+i, column.bSortable );
2633			}
2634		}
2635	
2636		if ( features.bFilter ) {
2637			param( 'sSearch', preSearch.sSearch );
2638			param( 'bRegex', preSearch.bRegex );
2639		}
2640	
2641		if ( features.bSort ) {
2642			$.each( sort, function ( i, val ) {
2643				d.order.push( { column: val.col, dir: val.dir } );
2644	
2645				param( 'iSortCol_'+i, val.col );
2646				param( 'sSortDir_'+i, val.dir );
2647			} );
2648	
2649			param( 'iSortingCols', sort.length );
2650		}
2651	
2652		// If the legacy.ajax parameter is null, then we automatically decide which
2653		// form to use, based on sAjaxSource
2654		var legacy = DataTable.ext.legacy.ajax;
2655		if ( legacy === null ) {
2656			return settings.sAjaxSource ? data : d;
2657		}
2658	
2659		// Otherwise, if legacy has been specified then we use that to decide on the
2660		// form
2661		return legacy ? data : d;
2662	}
2663	
2664	
2665	/**
2666	 * Data the data from the server (nuking the old) and redraw the table
2667	 *  @param {object} oSettings dataTables settings object
2668	 *  @param {object} json json data return from the server.
2669	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
2670	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2671	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2672	 *  @param {array} json.aaData The data to display on this page
2673	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
2674	 *  @memberof DataTable#oApi
2675	 */
2676	function _fnAjaxUpdateDraw ( settings, json )
2677	{
2678		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2679		// Support both
2680		var compat = function ( old, modern ) {
2681			return json[old] !== undefined ? json[old] : json[modern];
2682		};
2683	
2684		var data = _fnAjaxDataSrc( settings, json );
2685		var draw            = compat( 'sEcho',                'draw' );
2686		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
2687		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2688	
2689		if ( draw ) {
2690			// Protect against out of sequence returns
2691			if ( draw*1 < settings.iDraw ) {
2692				return;
2693			}
2694			settings.iDraw = draw * 1;
2695		}
2696	
2697		_fnClearTable( settings );
2698		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
2699		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
2700	
2701		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2702			_fnAddData( settings, data[i] );
2703		}
2704		settings.aiDisplay = settings.aiDisplayMaster.slice();
2705	
2706		settings.bAjaxDataGet = false;
2707		_fnDraw( settings );
2708	
2709		if ( ! settings._bInitComplete ) {
2710			_fnInitComplete( settings, json );
2711		}
2712	
2713		settings.bAjaxDataGet = true;
2714		_fnProcessingDisplay( settings, false );
2715	}
2716	
2717	
2718	/**
2719	 * Get the data from the JSON data source to use for drawing a table. Using
2720	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2721	 * source object, or from a processing function.
2722	 *  @param {object} oSettings dataTables settings object
2723	 *  @param  {object} json Data source object / array from the server
2724	 *  @return {array} Array of data to use
2725	 */
2726	function _fnAjaxDataSrc ( oSettings, json )
2727	{
2728		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
2729			oSettings.ajax.dataSrc :
2730			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
2731	
2732		// Compatibility with 1.9-. In order to read from aaData, check if the
2733		// default has been changed, if not, check for aaData
2734		if ( dataSrc === 'data' ) {
2735			return json.aaData || json[dataSrc];
2736		}
2737	
2738		return dataSrc !== "" ?
2739			_fnGetObjectDataFn( dataSrc )( json ) :
2740			json;
2741	}
2742	
2743	/**
2744	 * Generate the node required for filtering text
2745	 *  @returns {node} Filter control element
2746	 *  @param {object} oSettings dataTables settings object
2747	 *  @memberof DataTable#oApi
2748	 */
2749	function _fnFeatureHtmlFilter ( settings )
2750	{
2751		var classes = settings.oClasses;
2752		var tableId = settings.sTableId;
2753		var language = settings.oLanguage;
2754		var previousSearch = settings.oPreviousSearch;
2755		var features = settings.aanFeatures;
2756		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
2757	
2758		var str = language.sSearch;
2759		str = str.match(/_INPUT_/) ?
2760			str.replace('_INPUT_', input) :
2761			str+input;
2762	
2763		var filter = $('<div/>', {
2764				'id': ! features.f ? tableId+'_filter' : null,
2765				'class': classes.sFilter
2766			} )
2767			.append( $('<label/>' ).append( str ) );
2768	
2769		var searchFn = function() {
2770			/* Update all other filter input elements for the new display */
2771			var n = features.f;
2772			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
2773	
2774			/* Now do the filter */
2775			if ( val != previousSearch.sSearch ) {
2776				_fnFilterComplete( settings, {
2777					"sSearch": val,
2778					"bRegex": previousSearch.bRegex,
2779					"bSmart": previousSearch.bSmart ,
2780					"bCaseInsensitive": previousSearch.bCaseInsensitive
2781				} );
2782	
2783				// Need to redraw, without resorting
2784				settings._iDisplayStart = 0;
2785				_fnDraw( settings );
2786			}
2787		};
2788	
2789		var searchDelay = settings.searchDelay !== null ?
2790			settings.searchDelay :
2791			_fnDataSource( settings ) === 'ssp' ?
2792				400 :
2793				0;
2794	
2795		var jqFilter = $('input', filter)
2796			.val( previousSearch.sSearch )
2797			.attr( 'placeholder', language.sSearchPlaceholder )
2798			.bind(
2799				'keyup.DT search.DT input.DT paste.DT cut.DT',
2800				searchDelay ?
2801					_fnThrottle( searchFn, searchDelay ) :
2802					searchFn
2803			)
2804			.bind( 'keypress.DT', function(e) {
2805				/* Prevent form submission */
2806				if ( e.keyCode == 13 ) {
2807					return false;
2808				}
2809			} )
2810			.attr('aria-controls', tableId);
2811	
2812		// Update the input elements whenever the table is filtered
2813		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
2814			if ( settings === s ) {
2815				// IE9 throws an 'unknown error' if document.activeElement is used
2816				// inside an iframe or frame...
2817				try {
2818					if ( jqFilter[0] !== document.activeElement ) {
2819						jqFilter.val( previousSearch.sSearch );
2820					}
2821				}
2822				catch ( e ) {}
2823			}
2824		} );
2825	
2826		return filter[0];
2827	}
2828	
2829	
2830	/**
2831	 * Filter the table using both the global filter and column based filtering
2832	 *  @param {object} oSettings dataTables settings object
2833	 *  @param {object} oSearch search information
2834	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2835	 *  @memberof DataTable#oApi
2836	 */
2837	function _fnFilterComplete ( oSettings, oInput, iForce )
2838	{
2839		var oPrevSearch = oSettings.oPreviousSearch;
2840		var aoPrevSearch = oSettings.aoPreSearchCols;
2841		var fnSaveFilter = function ( oFilter ) {
2842			/* Save the filtering values */
2843			oPrevSearch.sSearch = oFilter.sSearch;
2844			oPrevSearch.bRegex = oFilter.bRegex;
2845			oPrevSearch.bSmart = oFilter.bSmart;
2846			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
2847		};
2848		var fnRegex = function ( o ) {
2849			// Backwards compatibility with the bEscapeRegex option
2850			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
2851		};
2852	
2853		// Resolve any column types that are unknown due to addition or invalidation
2854		// @todo As per sort - can this be moved into an event handler?
2855		_fnColumnTypes( oSettings );
2856	
2857		/* In server-side processing all filtering is done by the server, so no point hanging around here */
2858		if ( _fnDataSource( oSettings ) != 'ssp' )
2859		{
2860			/* Global filter */
2861			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
2862			fnSaveFilter( oInput );
2863	
2864			/* Now do the individual column filter */
2865			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
2866			{
2867				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
2868					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
2869			}
2870	
2871			/* Custom filtering */
2872			_fnFilterCustom( oSettings );
2873		}
2874		else
2875		{
2876			fnSaveFilter( oInput );
2877		}
2878	
2879		/* Tell the draw function we have been filtering */
2880		oSettings.bFiltered = true;
2881		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
2882	}
2883	
2884	
2885	/**
2886	 * Apply custom filtering functions
2887	 *  @param {object} oSettings dataTables settings object
2888	 *  @memberof DataTable#oApi
2889	 */
2890	function _fnFilterCustom( settings )
2891	{
2892		var filters = DataTable.ext.search;
2893		var displayRows = settings.aiDisplay;
2894		var row, rowIdx;
2895	
2896		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
2897			var rows = [];
2898	
2899			// Loop over each row and see if it should be included
2900			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
2901				rowIdx = displayRows[ j ];
2902				row = settings.aoData[ rowIdx ];
2903	
2904				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
2905					rows.push( rowIdx );
2906				}
2907			}
2908	
2909			// So the array reference doesn't break set the results into the
2910			// existing array
2911			displayRows.length = 0;
2912			displayRows.push.apply( displayRows, rows );
2913		}
2914	}
2915	
2916	
2917	/**
2918	 * Filter the table on a per-column basis
2919	 *  @param {object} oSettings dataTables settings object
2920	 *  @param {string} sInput string to filter on
2921	 *  @param {int} iColumn column to filter
2922	 *  @param {bool} bRegex treat search string as a regular expression or not
2923	 *  @param {bool} bSmart use smart filtering or not
2924	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
2925	 *  @memberof DataTable#oApi
2926	 */
2927	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
2928	{
2929		if ( searchStr === '' ) {
2930			return;
2931		}
2932	
2933		var data;
2934		var display = settings.aiDisplay;
2935		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
2936	
2937		for ( var i=display.length-1 ; i>=0 ; i-- ) {
2938			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
2939	
2940			if ( ! rpSearch.test( data ) ) {
2941				display.splice( i, 1 );
2942			}
2943		}
2944	}
2945	
2946	
2947	/**
2948	 * Filter the data table based on user input and draw the table
2949	 *  @param {object} settings dataTables settings object
2950	 *  @param {string} input string to filter on
2951	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
2952	 *  @param {bool} regex treat as a regular expression or not
2953	 *  @param {bool} smart perform smart filtering or not
2954	 *  @param {bool} caseInsensitive Do case insenstive matching or not
2955	 *  @memberof DataTable#oApi
2956	 */
2957	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
2958	{
2959		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
2960		var prevSearch = settings.oPreviousSearch.sSearch;
2961		var displayMaster = settings.aiDisplayMaster;
2962		var display, invalidated, i;
2963	
2964		// Need to take account of custom filtering functions - always filter
2965		if ( DataTable.ext.search.length !== 0 ) {
2966			force = true;
2967		}
2968	
2969		// Check if any of the rows were invalidated
2970		invalidated = _fnFilterData( settings );
2971	
2972		// If the input is blank - we just want the full data set
2973		if ( input.length <= 0 ) {
2974			settings.aiDisplay = displayMaster.slice();
2975		}
2976		else {
2977			// New search - start from the master array
2978			if ( invalidated ||
2979				 force ||
2980				 prevSearch.length > input.length ||
2981				 input.indexOf(prevSearch) !== 0 ||
2982				 settings.bSorted // On resort, the display master needs to be
2983				                  // re-filtered since indexes will have changed
2984			) {
2985				settings.aiDisplay = displayMaster.slice();
2986			}
2987	
2988			// Search the display array
2989			display = settings.aiDisplay;
2990	
2991			for ( i=display.length-1 ; i>=0 ; i-- ) {
2992				if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
2993					display.splice( i, 1 );
2994				}
2995			}
2996		}
2997	}
2998	
2999	
3000	/**
3001	 * Build a regular expression object suitable for searching a table
3002	 *  @param {string} sSearch string to search for
3003	 *  @param {bool} bRegex treat as a regular expression or not
3004	 *  @param {bool} bSmart perform smart filtering or not
3005	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
3006	 *  @returns {RegExp} constructed object
3007	 *  @memberof DataTable#oApi
3008	 */
3009	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
3010	{
3011		search = regex ?
3012			search :
3013			_fnEscapeRegex( search );
3014		
3015		if ( smart ) {
3016			/* For smart filtering we want to allow the search to work regardless of
3017			 * word order. We also want double quoted text to be preserved, so word
3018			 * order is important - a la google. So this is what we want to
3019			 * generate:
3020			 * 
3021			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
3022			 */
3023			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
3024				if ( word.charAt(0) === '"' ) {
3025					var m = word.match( /^"(.*)"$/ );
3026					word = m ? m[1] : word;
3027				}
3028	
3029				return word.replace('"', '');
3030			} );
3031	
3032			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
3033		}
3034	
3035		return new RegExp( search, caseInsensitive ? 'i' : '' );
3036	}
3037	
3038	
3039	/**
3040	 * Escape a string such that it can be used in a regular expression
3041	 *  @param {string} sVal string to escape
3042	 *  @returns {string} escaped string
3043	 *  @memberof DataTable#oApi
3044	 */
3045	function _fnEscapeRegex ( sVal )
3046	{
3047		return sVal.replace( _re_escape_regex, '\\$1' );
3048	}
3049	
3050	
3051	
3052	var __filter_div = $('<div>')[0];
3053	var __filter_div_textContent = __filter_div.textContent !== undefined;
3054	
3055	// Update the filtering data for each row if needed (by invalidation or first run)
3056	function _fnFilterData ( settings )
3057	{
3058		var columns = settings.aoColumns;
3059		var column;
3060		var i, j, ien, jen, filterData, cellData, row;
3061		var fomatters = DataTable.ext.type.search;
3062		var wasInvalidated = false;
3063	
3064		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
3065			row = settings.aoData[i];
3066	
3067			if ( ! row._aFilterData ) {
3068				filterData = [];
3069	
3070				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
3071					column = columns[j];
3072	
3073					if ( column.bSearchable ) {
3074						cellData = _fnGetCellData( settings, i, j, 'filter' );
3075	
3076						if ( fomatters[ column.sType ] ) {
3077							cellData = fomatters[ column.sType ]( cellData );
3078						}
3079	
3080						// Search in DataTables 1.10 is string based. In 1.11 this
3081						// should be altered to also allow strict type checking.
3082						if ( cellData === null ) {
3083							cellData = '';
3084						}
3085	
3086						if ( typeof cellData !== 'string' && cellData.toString ) {
3087							cellData = cellData.toString();
3088						}
3089					}
3090					else {
3091						cellData = '';
3092					}
3093	
3094					// If it looks like there is an HTML entity in the string,
3095					// attempt to decode it so sorting works as expected. Note that
3096					// we could use a single line of jQuery to do this, but the DOM
3097					// method used here is much faster http://jsperf.com/html-decode
3098					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
3099						__filter_div.innerHTML = cellData;
3100						cellData = __filter_div_textContent ?
3101							__filter_div.textContent :
3102							__filter_div.innerText;
3103					}
3104	
3105					if ( cellData.replace ) {
3106						cellData = cellData.replace(/[\r\n]/g, '');
3107					}
3108	
3109					filterData.push( cellData );
3110				}
3111	
3112				row._aFilterData = filterData;
3113				row._sFilterRow = filterData.join('  ');
3114				wasInvalidated = true;
3115			}
3116		}
3117	
3118		return wasInvalidated;
3119	}
3120	
3121	
3122	/**
3123	 * Convert from the internal Hungarian notation to camelCase for external
3124	 * interaction
3125	 *  @param {object} obj Object to convert
3126	 *  @returns {object} Inverted object
3127	 *  @memberof DataTable#oApi
3128	 */
3129	function _fnSearchToCamel ( obj )
3130	{
3131		return {
3132			search:          obj.sSearch,
3133			smart:           obj.bSmart,
3134			regex:           obj.bRegex,
3135			caseInsensitive: obj.bCaseInsensitive
3136		};
3137	}
3138	
3139	
3140	
3141	/**
3142	 * Convert from camelCase notation to the internal Hungarian. We could use the
3143	 * Hungarian convert function here, but this is cleaner
3144	 *  @param {object} obj Object to convert
3145	 *  @returns {object} Inverted object
3146	 *  @memberof DataTable#oApi
3147	 */
3148	function _fnSearchToHung ( obj )
3149	{
3150		return {
3151			sSearch:          obj.search,
3152			bSmart:           obj.smart,
3153			bRegex:           obj.regex,
3154			bCaseInsensitive: obj.caseInsensitive
3155		};
3156	}
3157	
3158	/**
3159	 * Generate the node required for the info display
3160	 *  @param {object} oSettings dataTables settings object
3161	 *  @returns {node} Information element
3162	 *  @memberof DataTable#oApi
3163	 */
3164	function _fnFeatureHtmlInfo ( settings )
3165	{
3166		var
3167			tid = settings.sTableId,
3168			nodes = settings.aanFeatures.i,
3169			n = $('<div/>', {
3170				'class': settings.oClasses.sInfo,
3171				'id': ! nodes ? tid+'_info' : null
3172			} );
3173	
3174		if ( ! nodes ) {
3175			// Update display on each draw
3176			settings.aoDrawCallback.push( {
3177				"fn": _fnUpdateInfo,
3178				"sName": "information"
3179			} );
3180	
3181			n
3182				.attr( 'role', 'status' )
3183				.attr( 'aria-live', 'polite' );
3184	
3185			// Table is described by our info div
3186			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
3187		}
3188	
3189		return n[0];
3190	}
3191	
3192	
3193	/**
3194	 * Update the information elements in the display
3195	 *  @param {object} settings dataTables settings object
3196	 *  @memberof DataTable#oApi
3197	 */
3198	function _fnUpdateInfo ( settings )
3199	{
3200		/* Show information about the table */
3201		var nodes = settings.aanFeatures.i;
3202		if ( nodes.length === 0 ) {
3203			return;
3204		}
3205	
3206		var
3207			lang  = settings.oLanguage,
3208			start = settings._iDisplayStart+1,
3209			end   = settings.fnDisplayEnd(),
3210			max   = settings.fnRecordsTotal(),
3211			total = settings.fnRecordsDisplay(),
3212			out   = total ?
3213				lang.sInfo :
3214				lang.sInfoEmpty;
3215	
3216		if ( total !== max ) {
3217			/* Record set after filtering */
3218			out += ' ' + lang.sInfoFiltered;
3219		}
3220	
3221		// Convert the macros
3222		out += lang.sInfoPostFix;
3223		out = _fnInfoMacros( settings, out );
3224	
3225		var callback = lang.fnInfoCallback;
3226		if ( callback !== null ) {
3227			out = callback.call( settings.oInstance,
3228				settings, start, end, max, total, out
3229			);
3230		}
3231	
3232		$(nodes).html( out );
3233	}
3234	
3235	
3236	function _fnInfoMacros ( settings, str )
3237	{
3238		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3239		// internally
3240		var
3241			formatter  = settings.fnFormatNumber,
3242			start      = settings._iDisplayStart+1,
3243			len        = settings._iDisplayLength,
3244			vis        = settings.fnRecordsDisplay(),
3245			all        = len === -1;
3246	
3247		return str.
3248			replace(/_START_/g, formatter.call( settings, start ) ).
3249			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
3250			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
3251			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
3252			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
3253			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
3254	}
3255	
3256	
3257	
3258	/**
3259	 * Draw the table for the first time, adding all required features
3260	 *  @param {object} settings dataTables settings object
3261	 *  @memberof DataTable#oApi
3262	 */
3263	function _fnInitialise ( settings )
3264	{
3265		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3266		var columns = settings.aoColumns, column;
3267		var features = settings.oFeatures;
3268	
3269		/* Ensure that the table data is fully initialised */
3270		if ( ! settings.bInitialised ) {
3271			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
3272			return;
3273		}
3274	
3275		/* Show the display HTML options */
3276		_fnAddOptionsHtml( settings );
3277	
3278		/* Build and draw the header / footer for the table */
3279		_fnBuildHead( settings );
3280		_fnDrawHead( settings, settings.aoHeader );
3281		_fnDrawHead( settings, settings.aoFooter );
3282	
3283		/* Okay to show that something is going on now */
3284		_fnProcessingDisplay( settings, true );
3285	
3286		/* Calculate sizes for columns */
3287		if ( features.bAutoWidth ) {
3288			_fnCalculateColumnWidths( settings );
3289		}
3290	
3291		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
3292			column = columns[i];
3293	
3294			if ( column.sWidth ) {
3295				column.nTh.style.width = _fnStringToCss( column.sWidth );
3296			}
3297		}
3298	
3299		// If there is default sorting required - let's do it. The sort function
3300		// will do the drawing for us. Otherwise we draw the table regardless of the
3301		// Ajax source - this allows the table to look initialised for Ajax sourcing
3302		// data (show 'loading' message possibly)
3303		_fnReDraw( settings );
3304	
3305		// Server-side processing init complete is done by _fnAjaxUpdateDraw
3306		var dataSrc = _fnDataSource( settings );
3307		if ( dataSrc != 'ssp' ) {
3308			// if there is an ajax source load the data
3309			if ( dataSrc == 'ajax' ) {
3310				_fnBuildAjax( settings, [], function(json) {
3311					var aData = _fnAjaxDataSrc( settings, json );
3312	
3313					// Got the data - add it to the table
3314					for ( i=0 ; i<aData.length ; i++ ) {
3315						_fnAddData( settings, aData[i] );
3316					}
3317	
3318					// Reset the init display for cookie saving. We've already done
3319					// a filter, and therefore cleared it before. So we need to make
3320					// it appear 'fresh'
3321					settings.iInitDisplayStart = iAjaxStart;
3322	
3323					_fnReDraw( settings );
3324	
3325					_fnProcessingDisplay( settings, false );
3326					_fnInitComplete( settings, json );
3327				}, settings );
3328			}
3329			else {
3330				_fnProcessingDisplay( settings, false );
3331				_fnInitComplete( settings );
3332			}
3333		}
3334	}
3335	
3336	
3337	/**
3338	 * Draw the table for the first time, adding all required features
3339	 *  @param {object} oSettings dataTables settings object
3340	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
3341	 *    with client-side processing (optional)
3342	 *  @memberof DataTable#oApi
3343	 */
3344	function _fnInitComplete ( settings, json )
3345	{
3346		settings._bInitComplete = true;
3347	
3348		// On an Ajax load we now have data and therefore want to apply the column
3349		// sizing
3350		if ( json ) {
3351			_fnAdjustColumnSizing( settings );
3352		}
3353	
3354		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3355	}
3356	
3357	
3358	function _fnLengthChange ( settings, val )
3359	{
3360		var len = parseInt( val, 10 );
3361		settings._iDisplayLength = len;
3362	
3363		_fnLengthOverflow( settings );
3364	
3365		// Fire length change event
3366		_fnCallbackFire( settings, null, 'length', [settings, len] );
3367	}
3368	
3369	
3370	/**
3371	 * Generate the node required for user display length changing
3372	 *  @param {object} settings dataTables settings object
3373	 *  @returns {node} Display length feature node
3374	 *  @memberof DataTable#oApi
3375	 */
3376	function _fnFeatureHtmlLength ( settings )
3377	{
3378		var
3379			classes  = settings.oClasses,
3380			tableId  = settings.sTableId,
3381			menu     = settings.aLengthMenu,
3382			d2       = $.isArray( menu[0] ),
3383			lengths  = d2 ? menu[0] : menu,
3384			language = d2 ? menu[1] : menu;
3385	
3386		var select = $('<select/>', {
3387			'name':          tableId+'_length',
3388			'aria-controls': tableId,
3389			'class':         classes.sLengthSelect
3390		} );
3391	
3392		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
3393			select[0][ i ] = new Option( language[i], lengths[i] );
3394		}
3395	
3396		var div = $('<div><label/></div>').addClass( classes.sLength );
3397		if ( ! settings.aanFeatures.l ) {
3398			div[0].id = tableId+'_length';
3399		}
3400	
3401		div.children().append(
3402			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
3403		);
3404	
3405		// Can't use `select` variable as user might provide their own and the
3406		// reference is broken by the use of outerHTML
3407		$('select', div)
3408			.val( settings._iDisplayLength )
3409			.bind( 'change.DT', function(e) {
3410				_fnLengthChange( settings, $(this).val() );
3411				_fnDraw( settings );
3412			} );
3413	
3414		// Update node value whenever anything changes the table's length
3415		$(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
3416			if ( settings === s ) {
3417				$('select', div).val( len );
3418			}
3419		} );
3420	
3421		return div[0];
3422	}
3423	
3424	
3425	
3426	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3427	 * Note that most of the paging logic is done in
3428	 * DataTable.ext.pager
3429	 */
3430	
3431	/**
3432	 * Generate the node required for default pagination
3433	 *  @param {object} oSettings dataTables settings object
3434	 *  @returns {node} Pagination feature node
3435	 *  @memberof DataTable#oApi
3436	 */
3437	function _fnFeatureHtmlPaginate ( settings )
3438	{
3439		var
3440			type   = settings.sPaginationType,
3441			plugin = DataTable.ext.pager[ type ],
3442			modern = typeof plugin === 'function',
3443			redraw = function( settings ) {
3444				_fnDraw( settings );
3445			},
3446			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
3447			features = settings.aanFeatures;
3448	
3449		if ( ! modern ) {
3450			plugin.fnInit( settings, node, redraw );
3451		}
3452	
3453		/* Add a draw callback for the pagination on first instance, to update the paging display */
3454		if ( ! features.p )
3455		{
3456			node.id = settings.sTableId+'_paginate';
3457	
3458			settings.aoDrawCallback.push( {
3459				"fn": function( settings ) {
3460					if ( modern ) {
3461						var
3462							start      = settings._iDisplayStart,
3463							len        = settings._iDisplayLength,
3464							visRecords = settings.fnRecordsDisplay(),
3465							all        = len === -1,
3466							page = all ? 0 : Math.ceil( start / len ),
3467							pages = all ? 1 : Math.ceil( visRecords / len ),
3468							buttons = plugin(page, pages),
3469							i, ien;
3470	
3471						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
3472							_fnRenderer( settings, 'pageButton' )(
3473								settings, features.p[i], i, buttons, page, pages
3474							);
3475						}
3476					}
3477					else {
3478						plugin.fnUpdate( settings, redraw );
3479					}
3480				},
3481				"sName": "pagination"
3482			} );
3483		}
3484	
3485		return node;
3486	}
3487	
3488	
3489	/**
3490	 * Alter the display settings to change the page
3491	 *  @param {object} settings DataTables settings object
3492	 *  @param {string|int} action Paging action to take: "first", "previous",
3493	 *    "next" or "last" or page number to jump to (integer)
3494	 *  @param [bool] redraw Automatically draw the update or not
3495	 *  @returns {bool} true page has changed, false - no change
3496	 *  @memberof DataTable#oApi
3497	 */
3498	function _fnPageChange ( settings, action, redraw )
3499	{
3500		var
3501			start     = settings._iDisplayStart,
3502			len       = settings._iDisplayLength,
3503			records   = settings.fnRecordsDisplay();
3504	
3505		if ( records === 0 || len === -1 )
3506		{
3507			start = 0;
3508		}
3509		else if ( typeof action === "number" )
3510		{
3511			start = action * len;
3512	
3513			if ( start > records )
3514			{
3515				start = 0;
3516			}
3517		}
3518		else if ( action == "first" )
3519		{
3520			start = 0;
3521		}
3522		else if ( action == "previous" )
3523		{
3524			start = len >= 0 ?
3525				start - len :
3526				0;
3527	
3528			if ( start < 0 )
3529			{
3530			  start = 0;
3531			}
3532		}
3533		else if ( action == "next" )
3534		{
3535			if ( start + len < records )
3536			{
3537				start += len;
3538			}
3539		}
3540		else if ( action == "last" )
3541		{
3542			start = Math.floor( (records-1) / len) * len;
3543		}
3544		else
3545		{
3546			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
3547		}
3548	
3549		var changed = settings._iDisplayStart !== start;
3550		settings._iDisplayStart = start;
3551	
3552		if ( changed ) {
3553			_fnCallbackFire( settings, null, 'page', [settings] );
3554	
3555			if ( redraw ) {
3556				_fnDraw( settings );
3557			}
3558		}
3559	
3560		return changed;
3561	}
3562	
3563	
3564	
3565	/**
3566	 * Generate the node required for the processing node
3567	 *  @param {object} settings dataTables settings object
3568	 *  @returns {node} Processing element
3569	 *  @memberof DataTable#oApi
3570	 */
3571	function _fnFeatureHtmlProcessing ( settings )
3572	{
3573		return $('<div/>', {
3574				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
3575				'class': settings.oClasses.sProcessing
3576			} )
3577			.html( settings.oLanguage.sProcessing )
3578			.insertBefore( settings.nTable )[0];
3579	}
3580	
3581	
3582	/**
3583	 * Display or hide the processing indicator
3584	 *  @param {object} settings dataTables settings object
3585	 *  @param {bool} show Show the processing indicator (true) or not (false)
3586	 *  @memberof DataTable#oApi
3587	 */
3588	function _fnProcessingDisplay ( settings, show )
3589	{
3590		if ( settings.oFeatures.bProcessing ) {
3591			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
3592		}
3593	
3594		_fnCallbackFire( settings, null, 'processing', [settings, show] );
3595	}
3596	
3597	/**
3598	 * Add any control elements for the table - specifically scrolling
3599	 *  @param {object} settings dataTables settings object
3600	 *  @returns {node} Node to add to the DOM
3601	 *  @memberof DataTable#oApi
3602	 */
3603	function _fnFeatureHtmlTable ( settings )
3604	{
3605		var table = $(settings.nTable);
3606	
3607		// Add the ARIA grid role to the table
3608		table.attr( 'role', 'grid' );
3609	
3610		// Scrolling from here on in
3611		var scroll = settings.oScroll;
3612	
3613		if ( scroll.sX === '' && scroll.sY === '' ) {
3614			return settings.nTable;
3615		}
3616	
3617		var scrollX = scroll.sX;
3618		var scrollY = scroll.sY;
3619		var classes = settings.oClasses;
3620		var caption = table.children('caption');
3621		var captionSide = caption.length ? caption[0]._captionSide : null;
3622		var headerClone = $( table[0].cloneNode(false) );
3623		var footerClone = $( table[0].cloneNode(false) );
3624		var footer = table.children('tfoot');
3625		var _div = '<div/>';
3626		var size = function ( s ) {
3627			return !s ? null : _fnStringToCss( s );
3628		};
3629	
3630		// This is fairly messy, but with x scrolling enabled, if the table has a
3631		// width attribute, regardless of any width applied using the column width
3632		// options, the browser will shrink or grow the table as needed to fit into
3633		// that 100%. That would make the width options useless. So we remove it.
3634		// This is okay, under the assumption that width:100% is applied to the
3635		// table in CSS (it is in the default stylesheet) which will set the table
3636		// width as appropriate (the attribute and css behave differently...)
3637		if ( scroll.sX && table.attr('width') === '100%' ) {
3638			table.removeAttr('width');
3639		}
3640	
3641		if ( ! footer.length ) {
3642			footer = null;
3643		}
3644	
3645		/*
3646		 * The HTML structure that we want to generate in this function is:
3647		 *  div - scroller
3648		 *    div - scroll head
3649		 *      div - scroll head inner
3650		 *        table - scroll head table
3651		 *          thead - thead
3652		 *    div - scroll body
3653		 *      table - table (master table)
3654		 *        thead - thead clone for sizing
3655		 *        tbody - tbody
3656		 *    div - scroll foot
3657		 *      div - scroll foot inner
3658		 *        table - scroll foot table
3659		 *          tfoot - tfoot
3660		 */
3661		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
3662			.append(
3663				$(_div, { 'class': classes.sScrollHead } )
3664					.css( {
3665						overflow: 'hidden',
3666						position: 'relative',
3667						border: 0,
3668						width: scrollX ? size(scrollX) : '100%'
3669					} )
3670					.append(
3671						$(_div, { 'class': classes.sScrollHeadInner } )
3672							.css( {
3673								'box-sizing': 'content-box',
3674								width: scroll.sXInner || '100%'
3675							} )
3676							.append(
3677								headerClone
3678									.removeAttr('id')
3679									.css( 'margin-left', 0 )
3680									.append( captionSide === 'top' ? caption : null )
3681									.append(
3682										table.children('thead')
3683									)
3684							)
3685					)
3686			)
3687			.append(
3688				$(_div, { 'class': classes.sScrollBody } )
3689					.css( {
3690						overflow: 'auto',
3691						height: size( scrollY ),
3692						width: size( scrollX )
3693					} )
3694					.append( table )
3695			);
3696	
3697		if ( footer ) {
3698			scroller.append(
3699				$(_div, { 'class': classes.sScrollFoot } )
3700					.css( {
3701						overflow: 'hidden',
3702						border: 0,
3703						width: scrollX ? size(scrollX) : '100%'
3704					} )
3705					.append(
3706						$(_div, { 'class': classes.sScrollFootInner } )
3707							.append(
3708								footerClone
3709									.removeAttr('id')
3710									.css( 'margin-left', 0 )
3711									.append( captionSide === 'bottom' ? caption : null )
3712									.append(
3713										table.children('tfoot')
3714									)
3715							)
3716					)
3717			);
3718		}
3719	
3720		var children = scroller.children();
3721		var scrollHead = children[0];
3722		var scrollBody = children[1];
3723		var scrollFoot = footer ? children[2] : null;
3724	
3725		// When the body is scrolled, then we also want to scroll the headers
3726		if ( scrollX ) {
3727			$(scrollBody).on( 'scroll.DT', function (e) {
3728				var scrollLeft = this.scrollLeft;
3729	
3730				scrollHead.scrollLeft = scrollLeft;
3731	
3732				if ( footer ) {
3733					scrollFoot.scrollLeft = scrollLeft;
3734				}
3735			} );
3736		}
3737	
3738		settings.nScrollHead = scrollHead;
3739		settings.nScrollBody = scrollBody;
3740		settings.nScrollFoot = scrollFoot;
3741	
3742		// On redraw - align columns
3743		settings.aoDrawCallback.push( {
3744			"fn": _fnScrollDraw,
3745			"sName": "scrolling"
3746		} );
3747	
3748		return scroller[0];
3749	}
3750	
3751	
3752	
3753	/**
3754	 * Update the header, footer and body tables for resizing - i.e. column
3755	 * alignment.
3756	 *
3757	 * Welcome to the most horrible function DataTables. The process that this
3758	 * function follows is basically:
3759	 *   1. Re-create the table inside the scrolling div
3760	 *   2. Take live measurements from the DOM
3761	 *   3. Apply the measurements to align the columns
3762	 *   4. Clean up
3763	 *
3764	 *  @param {object} settings dataTables settings object
3765	 *  @memberof DataTable#oApi
3766	 */
3767	function _fnScrollDraw ( settings )
3768	{
3769		// Given that this is such a monster function, a lot of variables are use
3770		// to try and keep the minimised size as small as possible
3771		var
3772			scroll         = settings.oScroll,
3773			scrollX        = scroll.sX,
3774			scrollXInner   = scroll.sXInner,
3775			scrollY        = scroll.sY,
3776			barWidth       = scroll.iBarWidth,
3777			divHeader      = $(settings.nScrollHead),
3778			divHeaderStyle = divHeader[0].style,
3779			divHeaderInner = divHeader.children('div'),
3780			divHeaderInnerStyle = divHeaderInner[0].style,
3781			divHeaderTable = divHeaderInner.children('table'),
3782			divBodyEl      = settings.nScrollBody,
3783			divBody        = $(divBodyEl),
3784			divBodyStyle   = divBodyEl.style,
3785			divFooter      = $(settings.nScrollFoot),
3786			divFooterInner = divFooter.children('div'),
3787			divFooterTable = divFooterInner.children('table'),
3788			header         = $(settings.nTHead),
3789			table          = $(settings.nTable),
3790			tableEl        = table[0],
3791			tableStyle     = tableEl.style,
3792			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
3793			browser        = settings.oBrowser,
3794			ie67           = browser.bScrollOversize,
3795			headerTrgEls, footerTrgEls,
3796			headerSrcEls, footerSrcEls,
3797			headerCopy, footerCopy,
3798			headerWidths=[], footerWidths=[],
3799			headerContent=[],
3800			idx, correction, sanityWidth,
3801			zeroOut = function(nSizer) {
3802				var style = nSizer.style;
3803				style.paddingTop = "0";
3804				style.paddingBottom = "0";
3805				style.borderTopWidth = "0";
3806				style.borderBottomWidth = "0";
3807				style.height = 0;
3808			};
3809	
3810		/*
3811		 * 1. Re-create the table inside the scrolling div
3812		 */
3813	
3814		// Remove the old minimised thead and tfoot elements in the inner table
3815		table.children('thead, tfoot').remove();
3816	
3817		// Clone the current header and footer elements and then place it into the inner table
3818		headerCopy = header.clone().prependTo( table );
3819		headerTrgEls = header.find('tr'); // original header is in its own table
3820		headerSrcEls = headerCopy.find('tr');
3821		headerCopy.find('th, td').removeAttr('tabindex');
3822	
3823		if ( footer ) {
3824			footerCopy = footer.clone().prependTo( table );
3825			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
3826			footerSrcEls = footerCopy.find('tr');
3827		}
3828	
3829	
3830		/*
3831		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
3832		 */
3833	
3834		// Remove old sizing and apply the calculated column widths
3835		// Get the unique column headers in the newly created (cloned) header. We want to apply the
3836		// calculated sizes to this header
3837		if ( ! scrollX )
3838		{
3839			divBodyStyle.width = '100%';
3840			divHeader[0].style.width = '100%';
3841		}
3842	
3843		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
3844			idx = _fnVisibleToColumnIndex( settings, i );
3845			el.style.width = settings.aoColumns[idx].sWidth;
3846		} );
3847	
3848		if ( footer ) {
3849			_fnApplyToChildren( function(n) {
3850				n.style.width = "";
3851			}, footerSrcEls );
3852		}
3853	
3854		// If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3855		// will end up forcing the scrollbar to appear, making our measurements wrong for when we
3856		// then hide it (end of this function), so add the header height to the body scroller.
3857		if ( scroll.bCollapse && scrollY !== "" ) {
3858			divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3859		}
3860	
3861		// Size the table as a whole
3862		sanityWidth = table.outerWidth();
3863		if ( scrollX === "" ) {
3864			// No x scrolling
3865			tableStyle.width = "100%";
3866	
3867			// IE7 will make the width of the table when 100% include the scrollbar
3868			// - which is shouldn't. When there is a scrollbar we need to take this
3869			// into account.
3870			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
3871				divBody.css('overflow-y') == "scroll")
3872			) {
3873				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3874			}
3875		}
3876		else
3877		{
3878			// x scrolling
3879			if ( scrollXInner !== "" ) {
3880				// x scroll inner has been given - use it
3881				tableStyle.width = _fnStringToCss(scrollXInner);
3882			}
3883			else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3884				// There is y-scrolling - try to take account of the y scroll bar
3885				tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3886				if ( table.outerWidth() > sanityWidth-barWidth ) {
3887					// Not possible to take account of it
3888					tableStyle.width = _fnStringToCss( sanityWidth );
3889				}
3890			}
3891			else {
3892				// When all else fails
3893				tableStyle.width = _fnStringToCss( sanityWidth );
3894			}
3895		}
3896	
3897		// Recalculate the sanity width - now that we've applied the required width,
3898		// before it was a temporary variable. This is required because the column
3899		// width calculation is done before this table DOM is created.
3900		sanityWidth = table.outerWidth();
3901	
3902		// Hidden header should have zero height, so remove padding and borders. Then
3903		// set the width based on the real headers
3904	
3905		// Apply all styles in one pass
3906		_fnApplyToChildren( zeroOut, headerSrcEls );
3907	
3908		// Read all widths in next pass
3909		_fnApplyToChildren( function(nSizer) {
3910			headerContent.push( nSizer.innerHTML );
3911			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3912		}, headerSrcEls );
3913	
3914		// Apply all widths in final pass
3915		_fnApplyToChildren( function(nToSize, i) {
3916			nToSize.style.width = headerWidths[i];
3917		}, headerTrgEls );
3918	
3919		$(headerSrcEls).height(0);
3920	
3921		/* Same again with the footer if we have one */
3922		if ( footer )
3923		{
3924			_fnApplyToChildren( zeroOut, footerSrcEls );
3925	
3926			_fnApplyToChildren( function(nSizer) {
vendor: 6,846 bytes, lines 3927-4145
3927				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3928			}, footerSrcEls );
3929	
3930			_fnApplyToChildren( function(nToSize, i) {
3931				nToSize.style.width = footerWidths[i];
3932			}, footerTrgEls );
3933	
3934			$(footerSrcEls).height(0);
3935		}
3936	
3937	
3938		/*
3939		 * 3. Apply the measurements
3940		 */
3941	
3942		// "Hide" the header and footer that we used for the sizing. We need to keep
3943		// the content of the cell so that the width applied to the header and body
3944		// both match, but we want to hide it completely. We want to also fix their
3945		// width to what they currently are
3946		_fnApplyToChildren( function(nSizer, i) {
3947			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
3948			nSizer.style.width = headerWidths[i];
3949		}, headerSrcEls );
3950	
3951		if ( footer )
3952		{
3953			_fnApplyToChildren( function(nSizer, i) {
3954				nSizer.innerHTML = "";
3955				nSizer.style.width = footerWidths[i];
3956			}, footerSrcEls );
3957		}
3958	
3959		// Sanity check that the table is of a sensible width. If not then we are going to get
3960		// misalignment - try to prevent this by not allowing the table to shrink below its min width
3961		if ( table.outerWidth() < sanityWidth )
3962		{
3963			// The min width depends upon if we have a vertical scrollbar visible or not */
3964			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
3965				divBody.css('overflow-y') == "scroll")) ?
3966					sanityWidth+barWidth :
3967					sanityWidth;
3968	
3969			// IE6/7 are a law unto themselves...
3970			if ( ie67 && (divBodyEl.scrollHeight >
3971				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
3972			) {
3973				tableStyle.width = _fnStringToCss( correction-barWidth );
3974			}
3975	
3976			// And give the user a warning that we've stopped the table getting too small
3977			if ( scrollX === "" || scrollXInner !== "" ) {
3978				_fnLog( settings, 1, 'Possible column misalignment', 6 );
3979			}
3980		}
3981		else
3982		{
3983			correction = '100%';
3984		}
3985	
3986		// Apply to the container elements
3987		divBodyStyle.width = _fnStringToCss( correction );
3988		divHeaderStyle.width = _fnStringToCss( correction );
3989	
3990		if ( footer ) {
3991			settings.nScrollFoot.style.width = _fnStringToCss( correction );
3992		}
3993	
3994	
3995		/*
3996		 * 4. Clean up
3997		 */
3998		if ( ! scrollY ) {
3999			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
4000			 * the scrollbar height from the visible display, rather than adding it on. We need to
4001			 * set the height in order to sort this. Don't want to do it in any other browsers.
4002			 */
4003			if ( ie67 ) {
4004				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
4005			}
4006		}
4007	
4008		if ( scrollY && scroll.bCollapse ) {
4009			divBodyStyle.height = _fnStringToCss( scrollY );
4010	
4011			var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
4012				barWidth :
4013				0;
4014	
4015			if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
4016				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
4017			}
4018		}
4019	
4020		/* Finally set the width's of the header and footer tables */
4021		var iOuterWidth = table.outerWidth();
4022		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
4023		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
4024	
4025		// Figure out if there are scrollbar present - if so then we need a the header and footer to
4026		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
4027		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
4028		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
4029		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
4030	
4031		if ( footer ) {
4032			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
4033			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
4034			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
4035		}
4036	
4037		/* Adjust the position of the header in case we loose the y-scrollbar */
4038		divBody.scroll();
4039	
4040		// If sorting or filtering has occurred, jump the scrolling back to the top
4041		// only if we aren't holding the position
4042		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
4043			divBodyEl.scrollTop = 0;
4044		}
4045	}
4046	
4047	
4048	
4049	/**
4050	 * Apply a given function to the display child nodes of an element array (typically
4051	 * TD children of TR rows
4052	 *  @param {function} fn Method to apply to the objects
4053	 *  @param array {nodes} an1 List of elements to look through for display children
4054	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
4055	 *  @memberof DataTable#oApi
4056	 */
4057	function _fnApplyToChildren( fn, an1, an2 )
4058	{
4059		var index=0, i=0, iLen=an1.length;
4060		var nNode1, nNode2;
4061	
4062		while ( i < iLen ) {
4063			nNode1 = an1[i].firstChild;
4064			nNode2 = an2 ? an2[i].firstChild : null;
4065	
4066			while ( nNode1 ) {
4067				if ( nNode1.nodeType === 1 ) {
4068					if ( an2 ) {
4069						fn( nNode1, nNode2, index );
4070					}
4071					else {
4072						fn( nNode1, index );
4073					}
4074	
4075					index++;
4076				}
4077	
4078				nNode1 = nNode1.nextSibling;
4079				nNode2 = an2 ? nNode2.nextSibling : null;
4080			}
4081	
4082			i++;
4083		}
4084	}
4085	
4086	
4087	
4088	var __re_html_remove = /<.*?>/g;
4089	
4090	
4091	/**
4092	 * Calculate the width of columns for the table
4093	 *  @param {object} oSettings dataTables settings object
4094	 *  @memberof DataTable#oApi
4095	 */
4096	function _fnCalculateColumnWidths ( oSettings )
4097	{
4098		var
4099			table = oSettings.nTable,
4100			columns = oSettings.aoColumns,
4101			scroll = oSettings.oScroll,
4102			scrollY = scroll.sY,
4103			scrollX = scroll.sX,
4104			scrollXInner = scroll.sXInner,
4105			columnCount = columns.length,
4106			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
4107			headerCells = $('th', oSettings.nTHead),
4108			tableWidthAttr = table.getAttribute('width'), // from DOM element
4109			tableContainer = table.parentNode,
4110			userInputs = false,
4111			i, column, columnIdx, width, outerWidth;
4112	
4113		var styleWidth = table.style.width;
4114		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
4115			tableWidthAttr = styleWidth;
4116		}
4117	
4118		/* Convert any user input sizes into pixel sizes */
4119		for ( i=0 ; i<visibleColumns.length ; i++ ) {
4120			column = columns[ visibleColumns[i] ];
4121	
4122			if ( column.sWidth !== null ) {
4123				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
4124	
4125				userInputs = true;
4126			}
4127		}
4128	
4129		/* If the number of columns in the DOM equals the number that we have to
4130		 * process in DataTables, then we can use the offsets that are created by
4131		 * the web- browser. No custom sizes can be set in order for this to happen,
4132		 * nor scrolling used
4133		 */
4134		if ( ! userInputs && ! scrollX && ! scrollY &&
4135		    columnCount == _fnVisbleColumns( oSettings ) &&
4136			columnCount == headerCells.length
4137		) {
4138			for ( i=0 ; i<columnCount ; i++ ) {
4139				columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
4140			}
4141		}
4142		else
4143		{
4144			// Otherwise construct a single row, worst case, table with the widest
4145			// node in the data, assign any user defined widths, then insert it into
4146			// the DOM and allow the browser to do all the hard work of calculating
4147			// table widths
4148			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
4149				.css( 'visibility', 'hidden' )
4150				.removeAttr( 'id' );
4151	
4152			// Clean up the table body
4153			tmpTable.find('tbody tr').remove();
4154			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
4155	
4156			// Remove any assigned widths from the footer (from scrolling)
4157			tmpTable.find('tfoot th, tfoot td').css('width', '');
4158	
4159			// Apply custom sizing to the cloned header
4160			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
4161	
4162			for ( i=0 ; i<visibleColumns.length ; i++ ) {
4163				column = columns[ visibleColumns[i] ];
4164	
4165				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
4166					_fnStringToCss( column.sWidthOrig ) :
4167					'';
4168			}
4169	
4170			// Find the widest cell for each column and put it into the table
4171			if ( oSettings.aoData.length ) {
4172				for ( i=0 ; i<visibleColumns.length ; i++ ) {
4173					columnIdx = visibleColumns[i];
4174					column = columns[ columnIdx ];
4175	
4176					$( _fnGetWidestNode( oSettings, columnIdx ) )
4177						.clone( false )
4178						.append( column.sContentPadding )
4179						.appendTo( tr );
4180				}
4181			}
4182	
4183			// Table has been built, attach to the document so we can work with it
4184			tmpTable.appendTo( tableContainer );
4185	
4186			// When scrolling (X or Y) we want to set the width of the table as 
4187			// appropriate. However, when not scrolling leave the table width as it
4188			// is. This results in slightly different, but I think correct behaviour
4189			if ( scrollX && scrollXInner ) {
4190				tmpTable.width( scrollXInner );
4191			}
4192			else if ( scrollX ) {
4193				tmpTable.css( 'width', 'auto' );
4194	
4195				if ( tmpTable.width() < tableContainer.offsetWidth ) {
4196					tmpTable.width( tableContainer.offsetWidth );
4197				}
4198			}
4199			else if ( scrollY ) {
4200				tmpTable.width( tableContainer.offsetWidth );
4201			}
4202			else if ( tableWidthAttr ) {
4203				tmpTable.width( tableWidthAttr );
4204			}
4205	
4206			// Take into account the y scrollbar
4207			_fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4208	
4209			// Browsers need a bit of a hand when a width is assigned to any columns
4210			// when x-scrolling as they tend to collapse the table to the min-width,
4211			// even if we sent the column widths. So we need to keep track of what
4212			// the table width should be by summing the user given values, and the
4213			// automatic values
4214			if ( scrollX )
4215			{
4216				var total = 0;
4217	
4218				for ( i=0 ; i<visibleColumns.length ; i++ ) {
4219					column = columns[ visibleColumns[i] ];
4220					outerWidth = $(headerCells[i]).outerWidth();
4221	
4222					total += column.sWidthOrig === null ?
4223						outerWidth :
4224						parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4225				}
4226	
4227				tmpTable.width( _fnStringToCss( total ) );
4228				table.style.width = _fnStringToCss( total );
4229			}
4230	
4231			// Get the width of each column in the constructed table
4232			for ( i=0 ; i<visibleColumns.length ; i++ ) {
4233				column = columns[ visibleColumns[i] ];
4234				width = $(headerCells[i]).width();
4235	
4236				if ( width ) {
4237					column.sWidth = _fnStringToCss( width );
4238				}
4239			}
4240	
4241			table.style.width = _fnStringToCss( tmpTable.css('width') );
4242	
4243			// Finished with the table - ditch it
4244			tmpTable.remove();
4245		}
4246	
4247		// If there is a width attr, we want to attach an event listener which
4248		// allows the table sizing to automatically adjust when the window is
4249		// resized. Use the width attr rather than CSS, since we can't know if the
4250		// CSS is a relative value or absolute - DOM read is always px.
4251		if ( tableWidthAttr ) {
4252			table.style.width = _fnStringToCss( tableWidthAttr );
4253		}
4254	
4255		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4256			var bindResize = function () {
4257				$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4258					_fnAdjustColumnSizing( oSettings );
4259				} ) );
4260			};
4261	
4262			// IE6/7 will crash if we bind a resize event handler on page load.
4263			// To be removed in 1.11 which drops IE6/7 support
4264			if ( oSettings.oBrowser.bScrollOversize ) {
4265				setTimeout( bindResize, 1000 );
4266			}
4267			else {
4268				bindResize();
4269			}
4270	
4271			oSettings._reszEvt = true;
4272		}
4273	}
4274	
4275	
4276	/**
4277	 * Throttle the calls to a function. Arguments and context are maintained for
4278	 * the throttled function
4279	 *  @param {function} fn Function to be called
4280	 *  @param {int} [freq=200] call frequency in mS
4281	 *  @returns {function} wrapped function
4282	 *  @memberof DataTable#oApi
4283	 */
4284	function _fnThrottle( fn, freq ) {
4285		var
4286			frequency = freq !== undefined ? freq : 200,
4287			last,
4288			timer;
4289	
4290		return function () {
4291			var
4292				that = this,
4293				now  = +new Date(),
4294				args = arguments;
4295	
4296			if ( last && now < last + frequency ) {
4297				clearTimeout( timer );
4298	
4299				timer = setTimeout( function () {
4300					last = undefined;
4301					fn.apply( that, args );
4302				}, frequency );
4303			}
4304			else {
4305				last = now;
4306				fn.apply( that, args );
4307			}
4308		};
4309	}
4310	
4311	
4312	/**
4313	 * Convert a CSS unit width to pixels (e.g. 2em)
4314	 *  @param {string} width width to be converted
4315	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
4316	 *  @returns {int} width in pixels
4317	 *  @memberof DataTable#oApi
4318	 */
4319	function _fnConvertToWidth ( width, parent )
4320	{
4321		if ( ! width ) {
4322			return 0;
4323		}
4324	
4325		var n = $('<div/>')
4326			.css( 'width', _fnStringToCss( width ) )
4327			.appendTo( parent || document.body );
4328	
4329		var val = n[0].offsetWidth;
4330		n.remove();
4331	
4332		return val;
4333	}
4334	
4335	
4336	/**
4337	 * Adjust a table's width to take account of vertical scroll bar
4338	 *  @param {object} oSettings dataTables settings object
4339	 *  @param {node} n table node
4340	 *  @memberof DataTable#oApi
4341	 */
4342	
4343	function _fnScrollingWidthAdjust ( settings, n )
4344	{
4345		var scroll = settings.oScroll;
4346	
vendor: 56,525 bytes, lines 4347-6254
4347		if ( scroll.sX || scroll.sY ) {
4348			// When y-scrolling only, we want to remove the width of the scroll bar
4349			// so the table + scroll bar will fit into the area available, otherwise
4350			// we fix the table at its current size with no adjustment
4351			var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4352			n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4353		}
4354	}
4355	
4356	
4357	/**
4358	 * Get the widest node
4359	 *  @param {object} settings dataTables settings object
4360	 *  @param {int} colIdx column of interest
4361	 *  @returns {node} widest table node
4362	 *  @memberof DataTable#oApi
4363	 */
4364	function _fnGetWidestNode( settings, colIdx )
4365	{
4366		var idx = _fnGetMaxLenString( settings, colIdx );
4367		if ( idx < 0 ) {
4368			return null;
4369		}
4370	
4371		var data = settings.aoData[ idx ];
4372		return ! data.nTr ? // Might not have been created when deferred rendering
4373			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
4374			data.anCells[ colIdx ];
4375	}
4376	
4377	
4378	/**
4379	 * Get the maximum strlen for each data column
4380	 *  @param {object} settings dataTables settings object
4381	 *  @param {int} colIdx column of interest
4382	 *  @returns {string} max string length for each column
4383	 *  @memberof DataTable#oApi
4384	 */
4385	function _fnGetMaxLenString( settings, colIdx )
4386	{
4387		var s, max=-1, maxIdx = -1;
4388	
4389		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4390			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4391			s = s.replace( __re_html_remove, '' );
4392	
4393			if ( s.length > max ) {
4394				max = s.length;
4395				maxIdx = i;
4396			}
4397		}
4398	
4399		return maxIdx;
4400	}
4401	
4402	
4403	/**
4404	 * Append a CSS unit (only if required) to a string
4405	 *  @param {string} value to css-ify
4406	 *  @returns {string} value with css unit
4407	 *  @memberof DataTable#oApi
4408	 */
4409	function _fnStringToCss( s )
4410	{
4411		if ( s === null ) {
4412			return '0px';
4413		}
4414	
4415		if ( typeof s == 'number' ) {
4416			return s < 0 ?
4417				'0px' :
4418				s+'px';
4419		}
4420	
4421		// Check it has a unit character already
4422		return s.match(/\d$/) ?
4423			s+'px' :
4424			s;
4425	}
4426	
4427	
4428	/**
4429	 * Get the width of a scroll bar in this browser being used
4430	 *  @returns {int} width in pixels
4431	 *  @memberof DataTable#oApi
4432	 */
4433	function _fnScrollBarWidth ()
4434	{
4435		// On first run a static variable is set, since this is only needed once.
4436		// Subsequent runs will just use the previously calculated value
4437		var width = DataTable.__scrollbarWidth;
4438	
4439		if ( width === undefined ) {
4440			var sizer = $('<p/>').css( {
4441					position: 'absolute',
4442					top: 0,
4443					left: 0,
4444					width: '100%',
4445					height: 150,
4446					padding: 0,
4447					overflow: 'scroll',
4448					visibility: 'hidden'
4449				} )
4450				.appendTo('body');
4451	
4452			width = sizer[0].offsetWidth - sizer[0].clientWidth;
4453			DataTable.__scrollbarWidth = width;
4454	
4455			sizer.remove();
4456		}
4457	
4458		return width;
4459	}
4460	
4461	
4462	
4463	function _fnSortFlatten ( settings )
4464	{
4465		var
4466			i, iLen, k, kLen,
4467			aSort = [],
4468			aiOrig = [],
4469			aoColumns = settings.aoColumns,
4470			aDataSort, iCol, sType, srcCol,
4471			fixed = settings.aaSortingFixed,
4472			fixedObj = $.isPlainObject( fixed ),
4473			nestedSort = [],
4474			add = function ( a ) {
4475				if ( a.length && ! $.isArray( a[0] ) ) {
4476					// 1D array
4477					nestedSort.push( a );
4478				}
4479				else {
4480					// 2D array
4481					nestedSort.push.apply( nestedSort, a );
4482				}
4483			};
4484	
4485		// Build the sort array, with pre-fix and post-fix options if they have been
4486		// specified
4487		if ( $.isArray( fixed ) ) {
4488			add( fixed );
4489		}
4490	
4491		if ( fixedObj && fixed.pre ) {
4492			add( fixed.pre );
4493		}
4494	
4495		add( settings.aaSorting );
4496	
4497		if (fixedObj && fixed.post ) {
4498			add( fixed.post );
4499		}
4500	
4501		for ( i=0 ; i<nestedSort.length ; i++ )
4502		{
4503			srcCol = nestedSort[i][0];
4504			aDataSort = aoColumns[ srcCol ].aDataSort;
4505	
4506			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
4507			{
4508				iCol = aDataSort[k];
4509				sType = aoColumns[ iCol ].sType || 'string';
4510	
4511				if ( nestedSort[i]._idx === undefined ) {
4512					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
4513				}
4514	
4515				aSort.push( {
4516					src:       srcCol,
4517					col:       iCol,
4518					dir:       nestedSort[i][1],
4519					index:     nestedSort[i]._idx,
4520					type:      sType,
4521					formatter: DataTable.ext.type.order[ sType+"-pre" ]
4522				} );
4523			}
4524		}
4525	
4526		return aSort;
4527	}
4528	
4529	/**
4530	 * Change the order of the table
4531	 *  @param {object} oSettings dataTables settings object
4532	 *  @memberof DataTable#oApi
4533	 *  @todo This really needs split up!
4534	 */
4535	function _fnSort ( oSettings )
4536	{
4537		var
4538			i, ien, iLen, j, jLen, k, kLen,
4539			sDataType, nTh,
4540			aiOrig = [],
4541			oExtSort = DataTable.ext.type.order,
4542			aoData = oSettings.aoData,
4543			aoColumns = oSettings.aoColumns,
4544			aDataSort, data, iCol, sType, oSort,
4545			formatters = 0,
4546			sortCol,
4547			displayMaster = oSettings.aiDisplayMaster,
4548			aSort;
4549	
4550		// Resolve any column types that are unknown due to addition or invalidation
4551		// @todo Can this be moved into a 'data-ready' handler which is called when
4552		//   data is going to be used in the table?
4553		_fnColumnTypes( oSettings );
4554	
4555		aSort = _fnSortFlatten( oSettings );
4556	
4557		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
4558			sortCol = aSort[i];
4559	
4560			// Track if we can use the fast sort algorithm
4561			if ( sortCol.formatter ) {
4562				formatters++;
4563			}
4564	
4565			// Load the data needed for the sort, for each cell
4566			_fnSortData( oSettings, sortCol.col );
4567		}
4568	
4569		/* No sorting required if server-side or no sorting array */
4570		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
4571		{
4572			// Create a value - key array of the current row positions such that we can use their
4573			// current position during the sort, if values match, in order to perform stable sorting
4574			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
4575				aiOrig[ displayMaster[i] ] = i;
4576			}
4577	
4578			/* Do the sort - here we want multi-column sorting based on a given data source (column)
4579			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4580			 * follow on it's own, but this is what we want (example two column sorting):
4581			 *  fnLocalSorting = function(a,b){
4582			 *    var iTest;
4583			 *    iTest = oSort['string-asc']('data11', 'data12');
4584			 *      if (iTest !== 0)
4585			 *        return iTest;
4586			 *    iTest = oSort['numeric-desc']('data21', 'data22');
4587			 *    if (iTest !== 0)
4588			 *      return iTest;
4589			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4590			 *  }
4591			 * Basically we have a test for each sorting column, if the data in that column is equal,
4592			 * test the next column. If all columns match, then we use a numeric sort on the row
4593			 * positions in the original data array to provide a stable sort.
4594			 *
4595			 * Note - I know it seems excessive to have two sorting methods, but the first is around
4596			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
4597			 * methods which do not have a pre-sort formatting function.
4598			 */
4599			if ( formatters === aSort.length ) {
4600				// All sort types have formatting functions
4601				displayMaster.sort( function ( a, b ) {
4602					var
4603						x, y, k, test, sort,
4604						len=aSort.length,
4605						dataA = aoData[a]._aSortData,
4606						dataB = aoData[b]._aSortData;
4607	
4608					for ( k=0 ; k<len ; k++ ) {
4609						sort = aSort[k];
4610	
4611						x = dataA[ sort.col ];
4612						y = dataB[ sort.col ];
4613	
4614						test = x<y ? -1 : x>y ? 1 : 0;
4615						if ( test !== 0 ) {
4616							return sort.dir === 'asc' ? test : -test;
4617						}
4618					}
4619	
4620					x = aiOrig[a];
4621					y = aiOrig[b];
4622					return x<y ? -1 : x>y ? 1 : 0;
4623				} );
4624			}
4625			else {
4626				// Depreciated - remove in 1.11 (providing a plug-in option)
4627				// Not all sort types have formatting methods, so we have to call their sorting
4628				// methods.
4629				displayMaster.sort( function ( a, b ) {
4630					var
4631						x, y, k, l, test, sort, fn,
4632						len=aSort.length,
4633						dataA = aoData[a]._aSortData,
4634						dataB = aoData[b]._aSortData;
4635	
4636					for ( k=0 ; k<len ; k++ ) {
4637						sort = aSort[k];
4638	
4639						x = dataA[ sort.col ];
4640						y = dataB[ sort.col ];
4641	
4642						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
4643						test = fn( x, y );
4644						if ( test !== 0 ) {
4645							return test;
4646						}
4647					}
4648	
4649					x = aiOrig[a];
4650					y = aiOrig[b];
4651					return x<y ? -1 : x>y ? 1 : 0;
4652				} );
4653			}
4654		}
4655	
4656		/* Tell the draw function that we have sorted the data */
4657		oSettings.bSorted = true;
4658	}
4659	
4660	
4661	function _fnSortAria ( settings )
4662	{
4663		var label;
4664		var nextSort;
4665		var columns = settings.aoColumns;
4666		var aSort = _fnSortFlatten( settings );
4667		var oAria = settings.oLanguage.oAria;
4668	
4669		// ARIA attributes - need to loop all columns, to update all (removing old
4670		// attributes as needed)
4671		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4672		{
4673			var col = columns[i];
4674			var asSorting = col.asSorting;
4675			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
4676			var th = col.nTh;
4677	
4678			// IE7 is throwing an error when setting these properties with jQuery's
4679			// attr() and removeAttr() methods...
4680			th.removeAttribute('aria-sort');
4681	
4682			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4683			if ( col.bSortable ) {
4684				if ( aSort.length > 0 && aSort[0].col == i ) {
4685					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
4686					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
4687				}
4688				else {
4689					nextSort = asSorting[0];
4690				}
4691	
4692				label = sTitle + ( nextSort === "asc" ?
4693					oAria.sSortAscending :
4694					oAria.sSortDescending
4695				);
4696			}
4697			else {
4698				label = sTitle;
4699			}
4700	
4701			th.setAttribute('aria-label', label);
4702		}
4703	}
4704	
4705	
4706	/**
4707	 * Function to run on user sort request
4708	 *  @param {object} settings dataTables settings object
4709	 *  @param {node} attachTo node to attach the handler to
4710	 *  @param {int} colIdx column sorting index
4711	 *  @param {boolean} [append=false] Append the requested sort to the existing
4712	 *    sort if true (i.e. multi-column sort)
4713	 *  @param {function} [callback] callback function
4714	 *  @memberof DataTable#oApi
4715	 */
4716	function _fnSortListener ( settings, colIdx, append, callback )
4717	{
4718		var col = settings.aoColumns[ colIdx ];
4719		var sorting = settings.aaSorting;
4720		var asSorting = col.asSorting;
4721		var nextSortIdx;
4722		var next = function ( a, overflow ) {
4723			var idx = a._idx;
4724			if ( idx === undefined ) {
4725				idx = $.inArray( a[1], asSorting );
4726			}
4727	
4728			return idx+1 < asSorting.length ?
4729				idx+1 :
4730				overflow ?
4731					null :
4732					0;
4733		};
4734	
4735		// Convert to 2D array if needed
4736		if ( typeof sorting[0] === 'number' ) {
4737			sorting = settings.aaSorting = [ sorting ];
4738		}
4739	
4740		// If appending the sort then we are multi-column sorting
4741		if ( append && settings.oFeatures.bSortMulti ) {
4742			// Are we already doing some kind of sort on this column?
4743			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
4744	
4745			if ( sortIdx !== -1 ) {
4746				// Yes, modify the sort
4747				nextSortIdx = next( sorting[sortIdx], true );
4748	
4749				if ( nextSortIdx === null && sorting.length === 1 ) {
4750					nextSortIdx = 0; // can't remove sorting completely
4751				}
4752	
4753				if ( nextSortIdx === null ) {
4754					sorting.splice( sortIdx, 1 );
4755				}
4756				else {
4757					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
4758					sorting[sortIdx]._idx = nextSortIdx;
4759				}
4760			}
4761			else {
4762				// No sort on this column yet
4763				sorting.push( [ colIdx, asSorting[0], 0 ] );
4764				sorting[sorting.length-1]._idx = 0;
4765			}
4766		}
4767		else if ( sorting.length && sorting[0][0] == colIdx ) {
4768			// Single column - already sorting on this column, modify the sort
4769			nextSortIdx = next( sorting[0] );
4770	
4771			sorting.length = 1;
4772			sorting[0][1] = asSorting[ nextSortIdx ];
4773			sorting[0]._idx = nextSortIdx;
4774		}
4775		else {
4776			// Single column - sort only on this column
4777			sorting.length = 0;
4778			sorting.push( [ colIdx, asSorting[0] ] );
4779			sorting[0]._idx = 0;
4780		}
4781	
4782		// Run the sort by calling a full redraw
4783		_fnReDraw( settings );
4784	
4785		// callback used for async user interaction
4786		if ( typeof callback == 'function' ) {
4787			callback( settings );
4788		}
4789	}
4790	
4791	
4792	/**
4793	 * Attach a sort handler (click) to a node
4794	 *  @param {object} settings dataTables settings object
4795	 *  @param {node} attachTo node to attach the handler to
4796	 *  @param {int} colIdx column sorting index
4797	 *  @param {function} [callback] callback function
4798	 *  @memberof DataTable#oApi
4799	 */
4800	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
4801	{
4802		var col = settings.aoColumns[ colIdx ];
4803	
4804		_fnBindAction( attachTo, {}, function (e) {
4805			/* If the column is not sortable - don't to anything */
4806			if ( col.bSortable === false ) {
4807				return;
4808			}
4809	
4810			// If processing is enabled use a timeout to allow the processing
4811			// display to be shown - otherwise to it synchronously
4812			if ( settings.oFeatures.bProcessing ) {
4813				_fnProcessingDisplay( settings, true );
4814	
4815				setTimeout( function() {
4816					_fnSortListener( settings, colIdx, e.shiftKey, callback );
4817	
4818					// In server-side processing, the draw callback will remove the
4819					// processing display
4820					if ( _fnDataSource( settings ) !== 'ssp' ) {
4821						_fnProcessingDisplay( settings, false );
4822					}
4823				}, 0 );
4824			}
4825			else {
4826				_fnSortListener( settings, colIdx, e.shiftKey, callback );
4827			}
4828		} );
4829	}
4830	
4831	
4832	/**
4833	 * Set the sorting classes on table's body, Note: it is safe to call this function
4834	 * when bSort and bSortClasses are false
4835	 *  @param {object} oSettings dataTables settings object
4836	 *  @memberof DataTable#oApi
4837	 */
4838	function _fnSortingClasses( settings )
4839	{
4840		var oldSort = settings.aLastSort;
4841		var sortClass = settings.oClasses.sSortColumn;
4842		var sort = _fnSortFlatten( settings );
4843		var features = settings.oFeatures;
4844		var i, ien, colIdx;
4845	
4846		if ( features.bSort && features.bSortClasses ) {
4847			// Remove old sorting classes
4848			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
4849				colIdx = oldSort[i].src;
4850	
4851				// Remove column sorting
4852				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4853					.removeClass( sortClass + (i<2 ? i+1 : 3) );
4854			}
4855	
4856			// Add new column sorting
4857			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
4858				colIdx = sort[i].src;
4859	
4860				$( _pluck( settings.aoData, 'anCells', colIdx ) )
4861					.addClass( sortClass + (i<2 ? i+1 : 3) );
4862			}
4863		}
4864	
4865		settings.aLastSort = sort;
4866	}
4867	
4868	
4869	// Get the data to sort a column, be it from cache, fresh (populating the
4870	// cache), or from a sort formatter
4871	function _fnSortData( settings, idx )
4872	{
4873		// Custom sorting function - provided by the sort data type
4874		var column = settings.aoColumns[ idx ];
4875		var customSort = DataTable.ext.order[ column.sSortDataType ];
4876		var customData;
4877	
4878		if ( customSort ) {
4879			customData = customSort.call( settings.oInstance, settings, idx,
4880				_fnColumnIndexToVisible( settings, idx )
4881			);
4882		}
4883	
4884		// Use / populate cache
4885		var row, cellData;
4886		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
4887	
4888		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4889			row = settings.aoData[i];
4890	
4891			if ( ! row._aSortData ) {
4892				row._aSortData = [];
4893			}
4894	
4895			if ( ! row._aSortData[idx] || customSort ) {
4896				cellData = customSort ?
4897					customData[i] : // If there was a custom sort function, use data from there
4898					_fnGetCellData( settings, i, idx, 'sort' );
4899	
4900				row._aSortData[ idx ] = formatter ?
4901					formatter( cellData ) :
4902					cellData;
4903			}
4904		}
4905	}
4906	
4907	
4908	
4909	/**
4910	 * Save the state of a table
4911	 *  @param {object} oSettings dataTables settings object
4912	 *  @memberof DataTable#oApi
4913	 */
4914	function _fnSaveState ( settings )
4915	{
4916		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
4917		{
4918			return;
4919		}
4920	
4921		/* Store the interesting variables */
4922		var state = {
4923			time:    +new Date(),
4924			start:   settings._iDisplayStart,
4925			length:  settings._iDisplayLength,
4926			order:   $.extend( true, [], settings.aaSorting ),
4927			search:  _fnSearchToCamel( settings.oPreviousSearch ),
4928			columns: $.map( settings.aoColumns, function ( col, i ) {
4929				return {
4930					visible: col.bVisible,
4931					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
4932				};
4933			} )
4934		};
4935	
4936		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
4937	
4938		settings.oSavedState = state;
4939		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
4940	}
4941	
4942	
4943	/**
4944	 * Attempt to load a saved table state
4945	 *  @param {object} oSettings dataTables settings object
4946	 *  @param {object} oInit DataTables init object so we can override settings
4947	 *  @memberof DataTable#oApi
4948	 */
4949	function _fnLoadState ( settings, oInit )
4950	{
4951		var i, ien;
4952		var columns = settings.aoColumns;
4953	
4954		if ( ! settings.oFeatures.bStateSave ) {
4955			return;
4956		}
4957	
4958		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
4959		if ( ! state || ! state.time ) {
4960			return;
4961		}
4962	
4963		/* Allow custom and plug-in manipulation functions to alter the saved data set and
4964		 * cancelling of loading by returning false
4965		 */
4966		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
4967		if ( $.inArray( false, abStateLoad ) !== -1 ) {
4968			return;
4969		}
4970	
4971		/* Reject old data */
4972		var duration = settings.iStateDuration;
4973		if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
4974			return;
4975		}
4976	
4977		// Number of columns have changed - all bets are off, no restore of settings
4978		if ( columns.length !== state.columns.length ) {
4979			return;
4980		}
4981	
4982		// Store the saved state so it might be accessed at any time
4983		settings.oLoadedState = $.extend( true, {}, state );
4984	
4985		// Restore key features - todo - for 1.11 this needs to be done by
4986		// subscribed events
4987		if ( state.start !== undefined ) {
4988			settings._iDisplayStart    = state.start;
4989			settings.iInitDisplayStart = state.start;
4990		}
4991		if ( state.length !== undefined ) {
4992			settings._iDisplayLength   = state.length;
4993		}
4994	
4995		// Order
4996		if ( state.order !== undefined ) {
4997			settings.aaSorting = [];
4998			$.each( state.order, function ( i, col ) {
4999				settings.aaSorting.push( col[0] >= columns.length ?
5000					[ 0, col[1] ] :
5001					col
5002				);
5003			} );
5004		}
5005	
5006		// Search
5007		if ( state.search !== undefined ) {
5008			$.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
5009		}
5010	
5011		// Columns
5012		for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
5013			var col = state.columns[i];
5014	
5015			// Visibility
5016			if ( col.visible !== undefined ) {
5017				columns[i].bVisible = col.visible;
5018			}
5019	
5020			// Search
5021			if ( col.search !== undefined ) {
5022				$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
5023			}
5024		}
5025	
5026		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
5027	}
5028	
5029	
5030	/**
5031	 * Return the settings object for a particular table
5032	 *  @param {node} table table we are using as a dataTable
5033	 *  @returns {object} Settings object - or null if not found
5034	 *  @memberof DataTable#oApi
5035	 */
5036	function _fnSettingsFromNode ( table )
5037	{
5038		var settings = DataTable.settings;
5039		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
5040	
5041		return idx !== -1 ?
5042			settings[ idx ] :
5043			null;
5044	}
5045	
5046	
5047	/**
5048	 * Log an error message
5049	 *  @param {object} settings dataTables settings object
5050	 *  @param {int} level log error messages, or display them to the user
5051	 *  @param {string} msg error message
5052	 *  @param {int} tn Technical note id to get more information about the error.
5053	 *  @memberof DataTable#oApi
5054	 */
5055	function _fnLog( settings, level, msg, tn )
5056	{
5057		msg = 'DataTables warning: '+
5058			(settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
5059	
5060		if ( tn ) {
5061			msg += '. For more information about this error, please see '+
5062			'http://datatables.net/tn/'+tn;
5063		}
5064	
5065		if ( ! level  ) {
5066			// Backwards compatibility pre 1.10
5067			var ext = DataTable.ext;
5068			var type = ext.sErrMode || ext.errMode;
5069	
5070			_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
5071	
5072			if ( type == 'alert' ) {
5073				alert( msg );
5074			}
5075			else if ( type == 'throw' ) {
5076				throw new Error(msg);
5077			}
5078			else if ( typeof type == 'function' ) {
5079				type( settings, tn, msg );
5080			}
5081		}
5082		else if ( window.console && console.log ) {
5083			console.log( msg );
5084		}
5085	}
5086	
5087	
5088	/**
5089	 * See if a property is defined on one object, if so assign it to the other object
5090	 *  @param {object} ret target object
5091	 *  @param {object} src source object
5092	 *  @param {string} name property
5093	 *  @param {string} [mappedName] name to map too - optional, name used if not given
5094	 *  @memberof DataTable#oApi
5095	 */
5096	function _fnMap( ret, src, name, mappedName )
5097	{
5098		if ( $.isArray( name ) ) {
5099			$.each( name, function (i, val) {
5100				if ( $.isArray( val ) ) {
5101					_fnMap( ret, src, val[0], val[1] );
5102				}
5103				else {
5104					_fnMap( ret, src, val );
5105				}
5106			} );
5107	
5108			return;
5109		}
5110	
5111		if ( mappedName === undefined ) {
5112			mappedName = name;
5113		}
5114	
5115		if ( src[name] !== undefined ) {
5116			ret[mappedName] = src[name];
5117		}
5118	}
5119	
5120	
5121	/**
5122	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
5123	 * shallow copy arrays. The reason we need to do this, is that we don't want to
5124	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
5125	 * able to override them, but we do want to deep copy arrays.
5126	 *  @param {object} out Object to extend
5127	 *  @param {object} extender Object from which the properties will be applied to
5128	 *      out
5129	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
5130	 *      independent copy with the exception of the `data` or `aaData` parameters
5131	 *      if they are present. This is so you can pass in a collection to
5132	 *      DataTables and have that used as your data source without breaking the
5133	 *      references
5134	 *  @returns {object} out Reference, just for convenience - out === the return.
5135	 *  @memberof DataTable#oApi
5136	 *  @todo This doesn't take account of arrays inside the deep copied objects.
5137	 */
5138	function _fnExtend( out, extender, breakRefs )
5139	{
5140		var val;
5141	
5142		for ( var prop in extender ) {
5143			if ( extender.hasOwnProperty(prop) ) {
5144				val = extender[prop];
5145	
5146				if ( $.isPlainObject( val ) ) {
5147					if ( ! $.isPlainObject( out[prop] ) ) {
5148						out[prop] = {};
5149					}
5150					$.extend( true, out[prop], val );
5151				}
5152				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
5153					out[prop] = val.slice();
5154				}
5155				else {
5156					out[prop] = val;
5157				}
5158			}
5159		}
5160	
5161		return out;
5162	}
5163	
5164	
5165	/**
5166	 * Bind an event handers to allow a click or return key to activate the callback.
5167	 * This is good for accessibility since a return on the keyboard will have the
5168	 * same effect as a click, if the element has focus.
5169	 *  @param {element} n Element to bind the action to
5170	 *  @param {object} oData Data object to pass to the triggered function
5171	 *  @param {function} fn Callback function for when the event is triggered
5172	 *  @memberof DataTable#oApi
5173	 */
5174	function _fnBindAction( n, oData, fn )
5175	{
5176		$(n)
5177			.bind( 'click.DT', oData, function (e) {
5178					n.blur(); // Remove focus outline for mouse users
5179					fn(e);
5180				} )
5181			.bind( 'keypress.DT', oData, function (e){
5182					if ( e.which === 13 ) {
5183						e.preventDefault();
5184						fn(e);
5185					}
5186				} )
5187			.bind( 'selectstart.DT', function () {
5188					/* Take the brutal approach to cancelling text selection */
5189					return false;
5190				} );
5191	}
5192	
5193	
5194	/**
5195	 * Register a callback function. Easily allows a callback function to be added to
5196	 * an array store of callback functions that can then all be called together.
5197	 *  @param {object} oSettings dataTables settings object
5198	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
5199	 *  @param {function} fn Function to be called back
5200	 *  @param {string} sName Identifying name for the callback (i.e. a label)
5201	 *  @memberof DataTable#oApi
5202	 */
5203	function _fnCallbackReg( oSettings, sStore, fn, sName )
5204	{
5205		if ( fn )
5206		{
5207			oSettings[sStore].push( {
5208				"fn": fn,
5209				"sName": sName
5210			} );
5211		}
5212	}
5213	
5214	
5215	/**
5216	 * Fire callback functions and trigger events. Note that the loop over the
5217	 * callback array store is done backwards! Further note that you do not want to
5218	 * fire off triggers in time sensitive applications (for example cell creation)
5219	 * as its slow.
5220	 *  @param {object} settings dataTables settings object
5221	 *  @param {string} callbackArr Name of the array storage for the callbacks in
5222	 *      oSettings
5223	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
5224	 *      null no trigger is fired
5225	 *  @param {array} args Array of arguments to pass to the callback function /
5226	 *      trigger
5227	 *  @memberof DataTable#oApi
5228	 */
5229	function _fnCallbackFire( settings, callbackArr, eventName, args )
5230	{
5231		var ret = [];
5232	
5233		if ( callbackArr ) {
5234			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
5235				return val.fn.apply( settings.oInstance, args );
5236			} );
5237		}
5238	
5239		if ( eventName !== null ) {
5240			var e = $.Event( eventName+'.dt' );
5241	
5242			$(settings.nTable).trigger( e, args );
5243	
5244			ret.push( e.result );
5245		}
5246	
5247		return ret;
5248	}
5249	
5250	
5251	function _fnLengthOverflow ( settings )
5252	{
5253		var
5254			start = settings._iDisplayStart,
5255			end = settings.fnDisplayEnd(),
5256			len = settings._iDisplayLength;
5257	
5258		/* If we have space to show extra rows (backing up from the end point - then do so */
5259		if ( start >= end )
5260		{
5261			start = end - len;
5262		}
5263	
5264		// Keep the start record on the current page
5265		start -= (start % len);
5266	
5267		if ( len === -1 || start < 0 )
5268		{
5269			start = 0;
5270		}
5271	
5272		settings._iDisplayStart = start;
5273	}
5274	
5275	
5276	function _fnRenderer( settings, type )
5277	{
5278		var renderer = settings.renderer;
5279		var host = DataTable.ext.renderer[type];
5280	
5281		if ( $.isPlainObject( renderer ) && renderer[type] ) {
5282			// Specific renderer for this type. If available use it, otherwise use
5283			// the default.
5284			return host[renderer[type]] || host._;
5285		}
5286		else if ( typeof renderer === 'string' ) {
5287			// Common renderer - if there is one available for this type use it,
5288			// otherwise use the default
5289			return host[renderer] || host._;
5290		}
5291	
5292		// Use the default
5293		return host._;
5294	}
5295	
5296	
5297	/**
5298	 * Detect the data source being used for the table. Used to simplify the code
5299	 * a little (ajax) and to make it compress a little smaller.
5300	 *
5301	 *  @param {object} settings dataTables settings object
5302	 *  @returns {string} Data source
5303	 *  @memberof DataTable#oApi
5304	 */
5305	function _fnDataSource ( settings )
5306	{
5307		if ( settings.oFeatures.bServerSide ) {
5308			return 'ssp';
5309		}
5310		else if ( settings.ajax || settings.sAjaxSource ) {
5311			return 'ajax';
5312		}
5313		return 'dom';
5314	}
5315	
5316
5317	DataTable = function( options )
5318	{
5319		/**
5320		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5321		 * return the resulting jQuery object.
5322		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5323		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5324		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5325		 *    criterion ("applied") or all TR elements (i.e. no filter).
5326		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5327		 *    Can be either 'current', whereby the current sorting of the table is used, or
5328		 *    'original' whereby the original order the data was read into the table is used.
5329		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5330		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5331		 *    'current' and filter is 'applied', regardless of what they might be given as.
5332		 *  @returns {object} jQuery object, filtered by the given selector.
5333		 *  @dtopt API
5334		 *  @deprecated Since v1.10
5335		 *
5336		 *  @example
5337		 *    $(document).ready(function() {
5338		 *      var oTable = $('#example').dataTable();
5339		 *
5340		 *      // Highlight every second row
5341		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
5342		 *    } );
5343		 *
5344		 *  @example
5345		 *    $(document).ready(function() {
5346		 *      var oTable = $('#example').dataTable();
5347		 *
5348		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
5349		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
5350		 *      oTable.fnFilter('Webkit');
5351		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5352		 *      oTable.fnFilter('');
5353		 *    } );
5354		 */
5355		this.$ = function ( sSelector, oOpts )
5356		{
5357			return this.api(true).$( sSelector, oOpts );
5358		};
5359		
5360		
5361		/**
5362		 * Almost identical to $ in operation, but in this case returns the data for the matched
5363		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5364		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
5365		 * rows are found, the data returned is the original data array/object that was used to
5366		 * create the row (or a generated array if from a DOM source).
5367		 *
5368		 * This method is often useful in-combination with $ where both functions are given the
5369		 * same parameters and the array indexes will match identically.
5370		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5371		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5372		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
5373		 *    criterion ("applied") or all elements (i.e. no filter).
5374		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
5375		 *    Can be either 'current', whereby the current sorting of the table is used, or
5376		 *    'original' whereby the original order the data was read into the table is used.
5377		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5378		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5379		 *    'current' and filter is 'applied', regardless of what they might be given as.
5380		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
5381		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
5382		 *    entry in the array.
5383		 *  @dtopt API
5384		 *  @deprecated Since v1.10
5385		 *
5386		 *  @example
5387		 *    $(document).ready(function() {
5388		 *      var oTable = $('#example').dataTable();
5389		 *
5390		 *      // Get the data from the first row in the table
5391		 *      var data = oTable._('tr:first');
5392		 *
5393		 *      // Do something useful with the data
5394		 *      alert( "First cell is: "+data[0] );
5395		 *    } );
5396		 *
5397		 *  @example
5398		 *    $(document).ready(function() {
5399		 *      var oTable = $('#example').dataTable();
5400		 *
5401		 *      // Filter to 'Webkit' and get all data for
5402		 *      oTable.fnFilter('Webkit');
5403		 *      var data = oTable._('tr', {"search": "applied"});
5404		 *
5405		 *      // Do something with the data
5406		 *      alert( data.length+" rows matched the search" );
5407		 *    } );
5408		 */
5409		this._ = function ( sSelector, oOpts )
5410		{
5411			return this.api(true).rows( sSelector, oOpts ).data();
5412		};
5413		
5414		
5415		/**
5416		 * Create a DataTables Api instance, with the currently selected tables for
5417		 * the Api's context.
5418		 * @param {boolean} [traditional=false] Set the API instance's context to be
5419		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5420		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5421		 *   or if all tables captured in the jQuery object should be used.
5422		 * @return {DataTables.Api}
5423		 */
5424		this.api = function ( traditional )
5425		{
5426			return traditional ?
5427				new _Api(
5428					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
5429				) :
5430				new _Api( this );
5431		};
5432		
5433		
5434		/**
5435		 * Add a single new row or multiple rows of data to the table. Please note
5436		 * that this is suitable for client-side processing only - if you are using
5437		 * server-side processing (i.e. "bServerSide": true), then to add data, you
5438		 * must add it to the data source, i.e. the server-side, through an Ajax call.
5439		 *  @param {array|object} data The data to be added to the table. This can be:
5440		 *    <ul>
5441		 *      <li>1D array of data - add a single row with the data provided</li>
5442		 *      <li>2D array of arrays - add multiple rows in a single call</li>
5443		 *      <li>object - data object when using <i>mData</i></li>
5444		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
5445		 *    </ul>
5446		 *  @param {bool} [redraw=true] redraw the table or not
5447		 *  @returns {array} An array of integers, representing the list of indexes in
5448		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5449		 *    the table.
5450		 *  @dtopt API
5451		 *  @deprecated Since v1.10
5452		 *
5453		 *  @example
5454		 *    // Global var for counter
5455		 *    var giCount = 2;
5456		 *
5457		 *    $(document).ready(function() {
5458		 *      $('#example').dataTable();
5459		 *    } );
5460		 *
5461		 *    function fnClickAddRow() {
5462		 *      $('#example').dataTable().fnAddData( [
5463		 *        giCount+".1",
5464		 *        giCount+".2",
5465		 *        giCount+".3",
5466		 *        giCount+".4" ]
5467		 *      );
5468		 *
5469		 *      giCount++;
5470		 *    }
5471		 */
5472		this.fnAddData = function( data, redraw )
5473		{
5474			var api = this.api( true );
5475		
5476			/* Check if we want to add multiple rows or not */
5477			var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
5478				api.rows.add( data ) :
5479				api.row.add( data );
5480		
5481			if ( redraw === undefined || redraw ) {
5482				api.draw();
5483			}
5484		
5485			return rows.flatten().toArray();
5486		};
5487		
5488		
5489		/**
5490		 * This function will make DataTables recalculate the column sizes, based on the data
5491		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5492		 * through the sWidth parameter). This can be useful when the width of the table's
5493		 * parent element changes (for example a window resize).
5494		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5495		 *  @dtopt API
5496		 *  @deprecated Since v1.10
5497		 *
5498		 *  @example
5499		 *    $(document).ready(function() {
5500		 *      var oTable = $('#example').dataTable( {
5501		 *        "sScrollY": "200px",
5502		 *        "bPaginate": false
5503		 *      } );
5504		 *
5505		 *      $(window).bind('resize', function () {
5506		 *        oTable.fnAdjustColumnSizing();
5507		 *      } );
5508		 *    } );
5509		 */
5510		this.fnAdjustColumnSizing = function ( bRedraw )
5511		{
5512			var api = this.api( true ).columns.adjust();
5513			var settings = api.settings()[0];
5514			var scroll = settings.oScroll;
5515		
5516			if ( bRedraw === undefined || bRedraw ) {
5517				api.draw( false );
5518			}
5519			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
5520				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5521				_fnScrollDraw( settings );
5522			}
5523		};
5524		
5525		
5526		/**
5527		 * Quickly and simply clear a table
5528		 *  @param {bool} [bRedraw=true] redraw the table or not
5529		 *  @dtopt API
5530		 *  @deprecated Since v1.10
5531		 *
5532		 *  @example
5533		 *    $(document).ready(function() {
5534		 *      var oTable = $('#example').dataTable();
5535		 *
5536		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5537		 *      oTable.fnClearTable();
5538		 *    } );
5539		 */
5540		this.fnClearTable = function( bRedraw )
5541		{
5542			var api = this.api( true ).clear();
5543		
5544			if ( bRedraw === undefined || bRedraw ) {
5545				api.draw();
5546			}
5547		};
5548		
5549		
5550		/**
5551		 * The exact opposite of 'opening' a row, this function will close any rows which
5552		 * are currently 'open'.
5553		 *  @param {node} nTr the table row to 'close'
5554		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
5555		 *  @dtopt API
5556		 *  @deprecated Since v1.10
5557		 *
5558		 *  @example
5559		 *    $(document).ready(function() {
5560		 *      var oTable;
5561		 *
5562		 *      // 'open' an information row when a row is clicked on
5563		 *      $('#example tbody tr').click( function () {
5564		 *        if ( oTable.fnIsOpen(this) ) {
5565		 *          oTable.fnClose( this );
5566		 *        } else {
5567		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5568		 *        }
5569		 *      } );
5570		 *
5571		 *      oTable = $('#example').dataTable();
5572		 *    } );
5573		 */
5574		this.fnClose = function( nTr )
5575		{
5576			this.api( true ).row( nTr ).child.hide();
5577		};
5578		
5579		
5580		/**
5581		 * Remove a row for the table
5582		 *  @param {mixed} target The index of the row from aoData to be deleted, or
5583		 *    the TR element you want to delete
5584		 *  @param {function|null} [callBack] Callback function
5585		 *  @param {bool} [redraw=true] Redraw the table or not
5586		 *  @returns {array} The row that was deleted
5587		 *  @dtopt API
5588		 *  @deprecated Since v1.10
5589		 *
5590		 *  @example
5591		 *    $(document).ready(function() {
5592		 *      var oTable = $('#example').dataTable();
5593		 *
5594		 *      // Immediately remove the first row
5595		 *      oTable.fnDeleteRow( 0 );
5596		 *    } );
5597		 */
5598		this.fnDeleteRow = function( target, callback, redraw )
5599		{
5600			var api = this.api( true );
5601			var rows = api.rows( target );
5602			var settings = rows.settings()[0];
5603			var data = settings.aoData[ rows[0][0] ];
5604		
5605			rows.remove();
5606		
5607			if ( callback ) {
5608				callback.call( this, settings, data );
5609			}
5610		
5611			if ( redraw === undefined || redraw ) {
5612				api.draw();
5613			}
5614		
5615			return data;
5616		};
5617		
5618		
5619		/**
5620		 * Restore the table to it's original state in the DOM by removing all of DataTables
5621		 * enhancements, alterations to the DOM structure of the table and event listeners.
5622		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
5623		 *  @dtopt API
5624		 *  @deprecated Since v1.10
5625		 *
5626		 *  @example
5627		 *    $(document).ready(function() {
5628		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
5629		 *      var oTable = $('#example').dataTable();
5630		 *      oTable.fnDestroy();
5631		 *    } );
5632		 */
5633		this.fnDestroy = function ( remove )
5634		{
5635			this.api( true ).destroy( remove );
5636		};
5637		
5638		
5639		/**
5640		 * Redraw the table
5641		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5642		 *  @dtopt API
5643		 *  @deprecated Since v1.10
5644		 *
5645		 *  @example
5646		 *    $(document).ready(function() {
5647		 *      var oTable = $('#example').dataTable();
5648		 *
5649		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5650		 *      oTable.fnDraw();
5651		 *    } );
5652		 */
5653		this.fnDraw = function( complete )
5654		{
5655			// Note that this isn't an exact match to the old call to _fnDraw - it takes
5656			// into account the new data, but can hold position.
5657			this.api( true ).draw( complete );
5658		};
5659		
5660		
5661		/**
5662		 * Filter the input based on data
5663		 *  @param {string} sInput String to filter the table on
5664		 *  @param {int|null} [iColumn] Column to limit filtering to
5665		 *  @param {bool} [bRegex=false] Treat as regular expression or not
5666		 *  @param {bool} [bSmart=true] Perform smart filtering or not
5667		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5668		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5669		 *  @dtopt API
5670		 *  @deprecated Since v1.10
5671		 *
5672		 *  @example
5673		 *    $(document).ready(function() {
5674		 *      var oTable = $('#example').dataTable();
5675		 *
5676		 *      // Sometime later - filter...
5677		 *      oTable.fnFilter( 'test string' );
5678		 *    } );
5679		 */
5680		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
5681		{
5682			var api = this.api( true );
5683		
5684			if ( iColumn === null || iColumn === undefined ) {
5685				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
5686			}
5687			else {
5688				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
5689			}
5690		
5691			api.draw();
5692		};
5693		
5694		
5695		/**
5696		 * Get the data for the whole table, an individual row or an individual cell based on the
5697		 * provided parameters.
5698		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5699		 *    a TR node then the data source for the whole row will be returned. If given as a
5700		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
5701		 *    cell returned. If given as an integer, then this is treated as the aoData internal
5702		 *    data index for the row (see fnGetPosition) and the data for that row used.
5703		 *  @param {int} [col] Optional column index that you want the data of.
5704		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
5705		 *    returned. If mRow is defined, just data for that row, and is iCol is
5706		 *    defined, only data for the designated cell is returned.
5707		 *  @dtopt API
5708		 *  @deprecated Since v1.10
5709		 *
5710		 *  @example
5711		 *    // Row data
5712		 *    $(document).ready(function() {
5713		 *      oTable = $('#example').dataTable();
5714		 *
5715		 *      oTable.$('tr').click( function () {
5716		 *        var data = oTable.fnGetData( this );
5717		 *        // ... do something with the array / object of data for the row
5718		 *      } );
5719		 *    } );
5720		 *
5721		 *  @example
5722		 *    // Individual cell data
5723		 *    $(document).ready(function() {
5724		 *      oTable = $('#example').dataTable();
5725		 *
5726		 *      oTable.$('td').click( function () {
5727		 *        var sData = oTable.fnGetData( this );
5728		 *        alert( 'The cell clicked on had the value of '+sData );
5729		 *      } );
5730		 *    } );
5731		 */
5732		this.fnGetData = function( src, col )
5733		{
5734			var api = this.api( true );
5735		
5736			if ( src !== undefined ) {
5737				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
5738		
5739				return col !== undefined || type == 'td' || type == 'th' ?
5740					api.cell( src, col ).data() :
5741					api.row( src ).data() || null;
5742			}
5743		
5744			return api.data().toArray();
5745		};
5746		
5747		
5748		/**
5749		 * Get an array of the TR nodes that are used in the table's body. Note that you will
5750		 * typically want to use the '$' API method in preference to this as it is more
5751		 * flexible.
5752		 *  @param {int} [iRow] Optional row index for the TR element you want
5753		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
5754		 *    in the table's body, or iRow is defined, just the TR element requested.
5755		 *  @dtopt API
5756		 *  @deprecated Since v1.10
5757		 *
5758		 *  @example
5759		 *    $(document).ready(function() {
5760		 *      var oTable = $('#example').dataTable();
5761		 *
5762		 *      // Get the nodes from the table
5763		 *      var nNodes = oTable.fnGetNodes( );
5764		 *    } );
5765		 */
5766		this.fnGetNodes = function( iRow )
5767		{
5768			var api = this.api( true );
5769		
5770			return iRow !== undefined ?
5771				api.row( iRow ).node() :
5772				api.rows().nodes().flatten().toArray();
5773		};
5774		
5775		
5776		/**
5777		 * Get the array indexes of a particular cell from it's DOM element
5778		 * and column index including hidden columns
5779		 *  @param {node} node this can either be a TR, TD or TH in the table's body
5780		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
5781		 *    if given as a cell, an array of [row index, column index (visible),
5782		 *    column index (all)] is given.
5783		 *  @dtopt API
5784		 *  @deprecated Since v1.10
5785		 *
5786		 *  @example
5787		 *    $(document).ready(function() {
5788		 *      $('#example tbody td').click( function () {
5789		 *        // Get the position of the current data from the node
5790		 *        var aPos = oTable.fnGetPosition( this );
5791		 *
5792		 *        // Get the data array for this row
5793		 *        var aData = oTable.fnGetData( aPos[0] );
5794		 *
5795		 *        // Update the data array and return the value
5796		 *        aData[ aPos[1] ] = 'clicked';
5797		 *        this.innerHTML = 'clicked';
5798		 *      } );
5799		 *
5800		 *      // Init DataTables
5801		 *      oTable = $('#example').dataTable();
5802		 *    } );
5803		 */
5804		this.fnGetPosition = function( node )
5805		{
5806			var api = this.api( true );
5807			var nodeName = node.nodeName.toUpperCase();
5808		
5809			if ( nodeName == 'TR' ) {
5810				return api.row( node ).index();
5811			}
5812			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
5813				var cell = api.cell( node ).index();
5814		
5815				return [
5816					cell.row,
5817					cell.columnVisible,
5818					cell.column
5819				];
5820			}
5821			return null;
5822		};
5823		
5824		
5825		/**
5826		 * Check to see if a row is 'open' or not.
5827		 *  @param {node} nTr the table row to check
5828		 *  @returns {boolean} true if the row is currently open, false otherwise
5829		 *  @dtopt API
5830		 *  @deprecated Since v1.10
5831		 *
5832		 *  @example
5833		 *    $(document).ready(function() {
5834		 *      var oTable;
5835		 *
5836		 *      // 'open' an information row when a row is clicked on
5837		 *      $('#example tbody tr').click( function () {
5838		 *        if ( oTable.fnIsOpen(this) ) {
5839		 *          oTable.fnClose( this );
5840		 *        } else {
5841		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5842		 *        }
5843		 *      } );
5844		 *
5845		 *      oTable = $('#example').dataTable();
5846		 *    } );
5847		 */
5848		this.fnIsOpen = function( nTr )
5849		{
5850			return this.api( true ).row( nTr ).child.isShown();
5851		};
5852		
5853		
5854		/**
5855		 * This function will place a new row directly after a row which is currently
5856		 * on display on the page, with the HTML contents that is passed into the
5857		 * function. This can be used, for example, to ask for confirmation that a
5858		 * particular record should be deleted.
5859		 *  @param {node} nTr The table row to 'open'
5860		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
5861		 *  @param {string} sClass Class to give the new TD cell
5862		 *  @returns {node} The row opened. Note that if the table row passed in as the
5863		 *    first parameter, is not found in the table, this method will silently
5864		 *    return.
5865		 *  @dtopt API
5866		 *  @deprecated Since v1.10
5867		 *
5868		 *  @example
5869		 *    $(document).ready(function() {
5870		 *      var oTable;
5871		 *
5872		 *      // 'open' an information row when a row is clicked on
5873		 *      $('#example tbody tr').click( function () {
5874		 *        if ( oTable.fnIsOpen(this) ) {
5875		 *          oTable.fnClose( this );
5876		 *        } else {
5877		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5878		 *        }
5879		 *      } );
5880		 *
5881		 *      oTable = $('#example').dataTable();
5882		 *    } );
5883		 */
5884		this.fnOpen = function( nTr, mHtml, sClass )
5885		{
5886			return this.api( true )
5887				.row( nTr )
5888				.child( mHtml, sClass )
5889				.show()
5890				.child()[0];
5891		};
5892		
5893		
5894		/**
5895		 * Change the pagination - provides the internal logic for pagination in a simple API
5896		 * function. With this function you can have a DataTables table go to the next,
5897		 * previous, first or last pages.
5898		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5899		 *    or page number to jump to (integer), note that page 0 is the first page.
5900		 *  @param {bool} [bRedraw=true] Redraw the table or not
5901		 *  @dtopt API
5902		 *  @deprecated Since v1.10
5903		 *
5904		 *  @example
5905		 *    $(document).ready(function() {
5906		 *      var oTable = $('#example').dataTable();
5907		 *      oTable.fnPageChange( 'next' );
5908		 *    } );
5909		 */
5910		this.fnPageChange = function ( mAction, bRedraw )
5911		{
5912			var api = this.api( true ).page( mAction );
5913		
5914			if ( bRedraw === undefined || bRedraw ) {
5915				api.draw(false);
5916			}
5917		};
5918		
5919		
5920		/**
5921		 * Show a particular column
5922		 *  @param {int} iCol The column whose display should be changed
5923		 *  @param {bool} bShow Show (true) or hide (false) the column
5924		 *  @param {bool} [bRedraw=true] Redraw the table or not
5925		 *  @dtopt API
5926		 *  @deprecated Since v1.10
5927		 *
5928		 *  @example
5929		 *    $(document).ready(function() {
5930		 *      var oTable = $('#example').dataTable();
5931		 *
5932		 *      // Hide the second column after initialisation
5933		 *      oTable.fnSetColumnVis( 1, false );
5934		 *    } );
5935		 */
5936		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
5937		{
5938			var api = this.api( true ).column( iCol ).visible( bShow );
5939		
5940			if ( bRedraw === undefined || bRedraw ) {
5941				api.columns.adjust().draw();
5942			}
5943		};
5944		
5945		
5946		/**
5947		 * Get the settings for a particular table for external manipulation
5948		 *  @returns {object} DataTables settings object. See
5949		 *    {@link DataTable.models.oSettings}
5950		 *  @dtopt API
5951		 *  @deprecated Since v1.10
5952		 *
5953		 *  @example
5954		 *    $(document).ready(function() {
5955		 *      var oTable = $('#example').dataTable();
5956		 *      var oSettings = oTable.fnSettings();
5957		 *
5958		 *      // Show an example parameter from the settings
5959		 *      alert( oSettings._iDisplayStart );
5960		 *    } );
5961		 */
5962		this.fnSettings = function()
5963		{
5964			return _fnSettingsFromNode( this[_ext.iApiIndex] );
5965		};
5966		
5967		
5968		/**
5969		 * Sort the table by a particular column
5970		 *  @param {int} iCol the data index to sort on. Note that this will not match the
5971		 *    'display index' if you have hidden data entries
5972		 *  @dtopt API
5973		 *  @deprecated Since v1.10
5974		 *
5975		 *  @example
5976		 *    $(document).ready(function() {
5977		 *      var oTable = $('#example').dataTable();
5978		 *
5979		 *      // Sort immediately with columns 0 and 1
5980		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
5981		 *    } );
5982		 */
5983		this.fnSort = function( aaSort )
5984		{
5985			this.api( true ).order( aaSort ).draw();
5986		};
5987		
5988		
5989		/**
5990		 * Attach a sort listener to an element for a given column
5991		 *  @param {node} nNode the element to attach the sort listener to
5992		 *  @param {int} iColumn the column that a click on this node will sort on
5993		 *  @param {function} [fnCallback] callback function when sort is run
5994		 *  @dtopt API
5995		 *  @deprecated Since v1.10
5996		 *
5997		 *  @example
5998		 *    $(document).ready(function() {
5999		 *      var oTable = $('#example').dataTable();
6000		 *
6001		 *      // Sort on column 1, when 'sorter' is clicked on
6002		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
6003		 *    } );
6004		 */
6005		this.fnSortListener = function( nNode, iColumn, fnCallback )
6006		{
6007			this.api( true ).order.listener( nNode, iColumn, fnCallback );
6008		};
6009		
6010		
6011		/**
6012		 * Update a table cell or row - this method will accept either a single value to
6013		 * update the cell with, an array of values with one element for each column or
6014		 * an object in the same format as the original data source. The function is
6015		 * self-referencing in order to make the multi column updates easier.
6016		 *  @param {object|array|string} mData Data to update the cell/row with
6017		 *  @param {node|int} mRow TR element you want to update or the aoData index
6018		 *  @param {int} [iColumn] The column to update, give as null or undefined to
6019		 *    update a whole row.
6020		 *  @param {bool} [bRedraw=true] Redraw the table or not
6021		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
6022		 *  @returns {int} 0 on success, 1 on error
6023		 *  @dtopt API
6024		 *  @deprecated Since v1.10
6025		 *
6026		 *  @example
6027		 *    $(document).ready(function() {
6028		 *      var oTable = $('#example').dataTable();
6029		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
6030		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
6031		 *    } );
6032		 */
6033		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
6034		{
6035			var api = this.api( true );
6036		
6037			if ( iColumn === undefined || iColumn === null ) {
6038				api.row( mRow ).data( mData );
6039			}
6040			else {
6041				api.cell( mRow, iColumn ).data( mData );
6042			}
6043		
6044			if ( bAction === undefined || bAction ) {
6045				api.columns.adjust();
6046			}
6047		
6048			if ( bRedraw === undefined || bRedraw ) {
6049				api.draw();
6050			}
6051			return 0;
6052		};
6053		
6054		
6055		/**
6056		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
6057		 * to ensure compatibility.
6058		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
6059		 *    formats "X" and "X.Y" are also acceptable.
6060		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
6061		 *    version, or false if this version of DataTales is not suitable
6062		 *  @method
6063		 *  @dtopt API
6064		 *  @deprecated Since v1.10
6065		 *
6066		 *  @example
6067		 *    $(document).ready(function() {
6068		 *      var oTable = $('#example').dataTable();
6069		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
6070		 *    } );
6071		 */
6072		this.fnVersionCheck = _ext.fnVersionCheck;
6073		
6074
6075		var _that = this;
6076		var emptyInit = options === undefined;
6077		var len = this.length;
6078
6079		if ( emptyInit ) {
6080			options = {};
6081		}
6082
6083		this.oApi = this.internal = _ext.internal;
6084
6085		// Extend with old style plug-in API methods
6086		for ( var fn in DataTable.ext.internal ) {
6087			if ( fn ) {
6088				this[fn] = _fnExternApiFunc(fn);
6089			}
6090		}
6091
6092		this.each(function() {
6093			// For each initialisation we want to give it a clean initialisation
6094			// object that can be bashed around
6095			var o = {};
6096			var oInit = len > 1 ? // optimisation for single table case
6097				_fnExtend( o, options, true ) :
6098				options;
6099
6100			/*global oInit,_that,emptyInit*/
6101			var i=0, iLen, j, jLen, k, kLen;
6102			var sId = this.getAttribute( 'id' );
6103			var bInitHandedOff = false;
6104			var defaults = DataTable.defaults;
6105			var $this = $(this);
6106			
6107			
6108			/* Sanity check */
6109			if ( this.nodeName.toLowerCase() != 'table' )
6110			{
6111				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
6112				return;
6113			}
6114			
6115			/* Backwards compatibility for the defaults */
6116			_fnCompatOpts( defaults );
6117			_fnCompatCols( defaults.column );
6118			
6119			/* Convert the camel-case defaults to Hungarian */
6120			_fnCamelToHungarian( defaults, defaults, true );
6121			_fnCamelToHungarian( defaults.column, defaults.column, true );
6122			
6123			/* Setting up the initialisation object */
6124			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
6125			
6126			
6127			
6128			/* Check to see if we are re-initialising a table */
6129			var allSettings = DataTable.settings;
6130			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
6131			{
6132				var s = allSettings[i];
6133			
6134				/* Base check on table node */
6135				if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
6136				{
6137					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
6138					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
6139			
6140					if ( emptyInit || bRetrieve )
6141					{
6142						return s.oInstance;
6143					}
6144					else if ( bDestroy )
6145					{
6146						s.oInstance.fnDestroy();
6147						break;
6148					}
6149					else
6150					{
6151						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
6152						return;
6153					}
6154				}
6155			
6156				/* If the element we are initialising has the same ID as a table which was previously
6157				 * initialised, but the table nodes don't match (from before) then we destroy the old
6158				 * instance by simply deleting it. This is under the assumption that the table has been
6159				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6160				 */
6161				if ( s.sTableId == this.id )
6162				{
6163					allSettings.splice( i, 1 );
6164					break;
6165				}
6166			}
6167			
6168			/* Ensure the table has an ID - required for accessibility */
6169			if ( sId === null || sId === "" )
6170			{
6171				sId = "DataTables_Table_"+(DataTable.ext._unique++);
6172				this.id = sId;
6173			}
6174			
6175			/* Create the settings object for this table and set some of the default parameters */
6176			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
6177				"sDestroyWidth": $this[0].style.width,
6178				"sInstance":     sId,
6179				"sTableId":      sId
6180			} );
6181			oSettings.nTable = this;
6182			oSettings.oApi   = _that.internal;
6183			oSettings.oInit  = oInit;
6184			
6185			allSettings.push( oSettings );
6186			
6187			// Need to add the instance after the instance after the settings object has been added
6188			// to the settings array, so we can self reference the table instance if more than one
6189			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
6190			
6191			// Backwards compatibility, before we apply all the defaults
6192			_fnCompatOpts( oInit );
6193			
6194			if ( oInit.oLanguage )
6195			{
6196				_fnLanguageCompat( oInit.oLanguage );
6197			}
6198			
6199			// If the length menu is given, but the init display length is not, use the length menu
6200			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
6201			{
6202				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
6203					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
6204			}
6205			
6206			// Apply the defaults and init options to make a single init object will all
6207			// options defined from defaults and instance options.
6208			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
6209			
6210			
6211			// Map the initialisation options onto the settings object
6212			_fnMap( oSettings.oFeatures, oInit, [
6213				"bPaginate",
6214				"bLengthChange",
6215				"bFilter",
6216				"bSort",
6217				"bSortMulti",
6218				"bInfo",
6219				"bProcessing",
6220				"bAutoWidth",
6221				"bSortClasses",
6222				"bServerSide",
6223				"bDeferRender"
6224			] );
6225			_fnMap( oSettings, oInit, [
6226				"asStripeClasses",
6227				"ajax",
6228				"fnServerData",
6229				"fnFormatNumber",
6230				"sServerMethod",
6231				"aaSorting",
6232				"aaSortingFixed",
6233				"aLengthMenu",
6234				"sPaginationType",
6235				"sAjaxSource",
6236				"sAjaxDataProp",
6237				"iStateDuration",
6238				"sDom",
6239				"bSortCellsTop",
6240				"iTabIndex",
6241				"fnStateLoadCallback",
6242				"fnStateSaveCallback",
6243				"renderer",
6244				"searchDelay",
6245				[ "iCookieDuration", "iStateDuration" ], // backwards compat
6246				[ "oSearch", "oPreviousSearch" ],
6247				[ "aoSearchCols", "aoPreSearchCols" ],
6248				[ "iDisplayLength", "_iDisplayLength" ],
6249				[ "bJQueryUI", "bJUI" ]
6250			] );
6251			_fnMap( oSettings.oScroll, oInit, [
6252				[ "sScrollX", "sX" ],
6253				[ "sScrollXInner", "sXInner" ],
6254				[ "sScrollY", "sY" ],
6255				[ "bScrollCollapse", "bCollapse" ]
6256			] );
6257			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
6258			
6259			/* Callback functions which are array driven */
6260			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
6261			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
6262			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
6263			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
6264			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
6265			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
6266			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
6267			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
6268			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
6269			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
6270			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
6271			
6272			var oClasses = oSettings.oClasses;
6273			
6274			// @todo Remove in 1.11
6275			if ( oInit.bJQueryUI )
6276			{
6277				/* Use the JUI classes object for display. You could clone the oStdClasses object if
6278				 * you want to have multiple tables with multiple independent classes
6279				 */
6280				$.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
6281			
6282				if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
6283				{
6284					/* Set the DOM to use a layout suitable for jQuery UI's theming */
6285					oSettings.sDom = '<"H"lfr>t<"F"ip>';
6286				}
6287			
6288				if ( ! oSettings.renderer ) {
6289					oSettings.renderer = 'jqueryui';
6290				}
6291				else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
6292					oSettings.renderer.header = 'jqueryui';
6293				}
6294			}
6295			else
6296			{
6297				$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6298			}
6299			$this.addClass( oClasses.sTable );
6300			
6301			/* Calculate the scroll bar width and cache it for use later on */
6302			if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6303			{
6304				oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6305			}
6306			if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6307				oSettings.oScroll.sX = '100%';
6308			}
6309			
6310			if ( oSettings.iInitDisplayStart === undefined )
6311			{
6312				/* Display start point, taking into account the save saving */
6313				oSettings.iInitDisplayStart = oInit.iDisplayStart;
6314				oSettings._iDisplayStart = oInit.iDisplayStart;
6315			}
6316			
6317			if ( oInit.iDeferLoading !== null )
6318			{
6319				oSettings.bDeferLoading = true;
6320				var tmp = $.isArray( oInit.iDeferLoading );
6321				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
6322				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
6323			}
6324			
6325			/* Language definitions */
6326			var oLanguage = oSettings.oLanguage;
6327			$.extend( true, oLanguage, oInit.oLanguage );
6328			
6329			if ( oLanguage.sUrl !== "" )
6330			{
6331				/* Get the language definitions from a file - because this Ajax call makes the language
6332				 * get async to the remainder of this function we use bInitHandedOff to indicate that
6333				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6334				 */
6335				$.ajax( {
6336					dataType: 'json',
6337					url: oLanguage.sUrl,
6338					success: function ( json ) {
6339						_fnLanguageCompat( json );
6340						_fnCamelToHungarian( defaults.oLanguage, json );
6341						$.extend( true, oLanguage, json );
6342						_fnInitialise( oSettings );
6343					},
6344					error: function () {
6345						// Error occurred loading language file, continue on as best we can
6346						_fnInitialise( oSettings );
6347					}
6348				} );
6349				bInitHandedOff = true;
6350			}
6351			
6352			/*
6353			 * Stripes
6354			 */
6355			if ( oInit.asStripeClasses === null )
6356			{
6357				oSettings.asStripeClasses =[
6358					oClasses.sStripeOdd,
6359					oClasses.sStripeEven
6360				];
6361			}
6362			
6363			/* Remove row stripe classes if they are already on the table row */
6364			var stripeClasses = oSettings.asStripeClasses;
6365			var rowOne = $this.children('tbody').find('tr').eq(0);
6366			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6367				return rowOne.hasClass(el);
6368			} ) ) !== -1 ) {
6369				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
6370				oSettings.asDestroyStripes = stripeClasses.slice();
6371			}
6372			
6373			/*
6374			 * Columns
6375			 * See if we should load columns automatically or use defined ones
6376			 */
6377			var anThs = [];
6378			var aoColumnsInit;
6379			var nThead = this.getElementsByTagName('thead');
6380			if ( nThead.length !== 0 )
6381			{
6382				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
6383				anThs = _fnGetUniqueThs( oSettings );
6384			}
6385			
6386			/* If not given a column array, generate one with nulls */
6387			if ( oInit.aoColumns === null )
6388			{
6389				aoColumnsInit = [];
6390				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6391				{
6392					aoColumnsInit.push( null );
6393				}
6394			}
6395			else
6396			{
vendor: 62,586 bytes, lines 6397-8792
6397				aoColumnsInit = oInit.aoColumns;
6398			}
6399			
6400			/* Add the columns */
6401			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6402			{
6403				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
6404			}
6405			
6406			/* Apply the column definitions */
6407			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
6408				_fnColumnOptions( oSettings, iCol, oDef );
6409			} );
6410			
6411			/* HTML5 attribute detection - build an mData object automatically if the
6412			 * attributes are found
6413			 */
6414			if ( rowOne.length ) {
6415				var a = function ( cell, name ) {
6416					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
6417				};
6418			
6419				$.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
6420					var col = oSettings.aoColumns[i];
6421			
6422					if ( col.mData === i ) {
6423						var sort = a( cell, 'sort' ) || a( cell, 'order' );
6424						var filter = a( cell, 'filter' ) || a( cell, 'search' );
6425			
6426						if ( sort !== null || filter !== null ) {
6427							col.mData = {
6428								_:      i+'.display',
6429								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
6430								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
6431								filter: filter !== null ? i+'.@data-'+filter : undefined
6432							};
6433			
6434							_fnColumnOptions( oSettings, i );
6435						}
6436					}
6437				} );
6438			}
6439			
6440			var features = oSettings.oFeatures;
6441			
6442			/* Must be done after everything which can be overridden by the state saving! */
6443			if ( oInit.bStateSave )
6444			{
6445				features.bStateSave = true;
6446				_fnLoadState( oSettings, oInit );
6447				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
6448			}
6449			
6450			
6451			/*
6452			 * Sorting
6453			 * @todo For modularisation (1.11) this needs to do into a sort start up handler
6454			 */
6455			
6456			// If aaSorting is not defined, then we use the first indicator in asSorting
6457			// in case that has been altered, so the default sort reflects that option
6458			if ( oInit.aaSorting === undefined )
6459			{
6460				var sorting = oSettings.aaSorting;
6461				for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
6462				{
6463					sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
6464				}
6465			}
6466			
6467			/* Do a first pass on the sorting classes (allows any size changes to be taken into
6468			 * account, and also will apply sorting disabled classes if disabled
6469			 */
6470			_fnSortingClasses( oSettings );
6471			
6472			if ( features.bSort )
6473			{
6474				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6475					if ( oSettings.bSorted ) {
6476						var aSort = _fnSortFlatten( oSettings );
6477						var sortedColumns = {};
6478			
6479						$.each( aSort, function (i, val) {
6480							sortedColumns[ val.src ] = val.dir;
6481						} );
6482			
6483						_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
6484						_fnSortAria( oSettings );
6485					}
6486				} );
6487			}
6488			
6489			_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6490				if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
6491					_fnSortingClasses( oSettings );
6492				}
6493			}, 'sc' );
6494			
6495			
6496			/*
6497			 * Final init
6498			 * Cache the header, body and footer as required, creating them if needed
6499			 */
6500			
6501			/* Browser support detection */
6502			_fnBrowserDetect( oSettings );
6503			
6504			// Work around for Webkit bug 83867 - store the caption-side before removing from doc
6505			var captions = $this.children('caption').each( function () {
6506				this._captionSide = $this.css('caption-side');
6507			} );
6508			
6509			var thead = $this.children('thead');
6510			if ( thead.length === 0 )
6511			{
6512				thead = $('<thead/>').appendTo(this);
6513			}
6514			oSettings.nTHead = thead[0];
6515			
6516			var tbody = $this.children('tbody');
6517			if ( tbody.length === 0 )
6518			{
6519				tbody = $('<tbody/>').appendTo(this);
6520			}
6521			oSettings.nTBody = tbody[0];
6522			
6523			var tfoot = $this.children('tfoot');
6524			if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6525			{
6526				// If we are a scrolling table, and no footer has been given, then we need to create
6527				// a tfoot element for the caption element to be appended to
6528				tfoot = $('<tfoot/>').appendTo(this);
6529			}
6530			
6531			if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6532				$this.addClass( oClasses.sNoFooter );
6533			}
6534			else if ( tfoot.length > 0 ) {
6535				oSettings.nTFoot = tfoot[0];
6536				_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
6537			}
6538			
6539			/* Check if there is data passing into the constructor */
6540			if ( oInit.aaData )
6541			{
6542				for ( i=0 ; i<oInit.aaData.length ; i++ )
6543				{
6544					_fnAddData( oSettings, oInit.aaData[ i ] );
6545				}
6546			}
6547			else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
6548			{
6549				/* Grab the data from the page - only do this when deferred loading or no Ajax
6550				 * source since there is no point in reading the DOM data if we are then going
6551				 * to replace it with Ajax data
6552				 */
6553				_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
6554			}
6555			
6556			/* Copy the data index array */
6557			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6558			
6559			/* Initialisation complete - table can be drawn */
6560			oSettings.bInitialised = true;
6561			
6562			/* Check if we need to initialise the table (it might not have been handed off to the
6563			 * language processor)
6564			 */
6565			if ( bInitHandedOff === false )
6566			{
6567				_fnInitialise( oSettings );
6568			}
6569		} );
6570		_that = null;
6571		return this;
6572	};
6573
6574	
6575	
6576	/**
6577	 * Computed structure of the DataTables API, defined by the options passed to
6578	 * `DataTable.Api.register()` when building the API.
6579	 *
6580	 * The structure is built in order to speed creation and extension of the Api
6581	 * objects since the extensions are effectively pre-parsed.
6582	 *
6583	 * The array is an array of objects with the following structure, where this
6584	 * base array represents the Api prototype base:
6585	 *
6586	 *     [
6587	 *       {
6588	 *         name:      'data'                -- string   - Property name
6589	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6590	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6591	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6592	 *       },
6593	 *       {
6594	 *         name:     'row'
6595	 *         val:       {},
6596	 *         methodExt: [ ... ],
6597	 *         propExt:   [
6598	 *           {
6599	 *             name:      'data'
6600	 *             val:       function () {},
6601	 *             methodExt: [ ... ],
6602	 *             propExt:   [ ... ]
6603	 *           },
6604	 *           ...
6605	 *         ]
6606	 *       }
6607	 *     ]
6608	 *
6609	 * @type {Array}
6610	 * @ignore
6611	 */
6612	var __apiStruct = [];
6613	
6614	
6615	/**
6616	 * `Array.prototype` reference.
6617	 *
6618	 * @type object
6619	 * @ignore
6620	 */
6621	var __arrayProto = Array.prototype;
6622	
6623	
6624	/**
6625	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6626	 * take several different forms for ease of use.
6627	 *
6628	 * Each of the input parameter types will be converted to a DataTables settings
6629	 * object where possible.
6630	 *
6631	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6632	 *   of:
6633	 *
6634	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6635	 *     with be found and used.
6636	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6637	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6638	 *   * `object` - DataTables settings object
6639	 *   * `DataTables.Api` - API instance
6640	 * @return {array|null} Matching DataTables settings objects. `null` or
6641	 *   `undefined` is returned if no matching DataTable is found.
6642	 * @ignore
6643	 */
6644	var _toSettings = function ( mixed )
6645	{
6646		var idx, jq;
6647		var settings = DataTable.settings;
6648		var tables = $.map( settings, function (el, i) {
6649			return el.nTable;
6650		} );
6651	
6652		if ( ! mixed ) {
6653			return [];
6654		}
6655		else if ( mixed.nTable && mixed.oApi ) {
6656			// DataTables settings object
6657			return [ mixed ];
6658		}
6659		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6660			// Table node
6661			idx = $.inArray( mixed, tables );
6662			return idx !== -1 ? [ settings[idx] ] : null;
6663		}
6664		else if ( mixed && typeof mixed.settings === 'function' ) {
6665			return mixed.settings().toArray();
6666		}
6667		else if ( typeof mixed === 'string' ) {
6668			// jQuery selector
6669			jq = $(mixed);
6670		}
6671		else if ( mixed instanceof $ ) {
6672			// jQuery object (also DataTables instance)
6673			jq = mixed;
6674		}
6675	
6676		if ( jq ) {
6677			return jq.map( function(i) {
6678				idx = $.inArray( this, tables );
6679				return idx !== -1 ? settings[idx] : null;
6680			} ).toArray();
6681		}
6682	};
6683	
6684	
6685	/**
6686	 * DataTables API class - used to control and interface with  one or more
6687	 * DataTables enhanced tables.
6688	 *
6689	 * The API class is heavily based on jQuery, presenting a chainable interface
6690	 * that you can use to interact with tables. Each instance of the API class has
6691	 * a "context" - i.e. the tables that it will operate on. This could be a single
6692	 * table, all tables on a page or a sub-set thereof.
6693	 *
6694	 * Additionally the API is designed to allow you to easily work with the data in
6695	 * the tables, retrieving and manipulating it as required. This is done by
6696	 * presenting the API class as an array like interface. The contents of the
6697	 * array depend upon the actions requested by each method (for example
6698	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6699	 * return an array of objects or arrays depending upon your table's
6700	 * configuration). The API object has a number of array like methods (`push`,
6701	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6702	 * `unique` etc) to assist your working with the data held in a table.
6703	 *
6704	 * Most methods (those which return an Api instance) are chainable, which means
6705	 * the return from a method call also has all of the methods available that the
6706	 * top level object had. For example, these two calls are equivalent:
6707	 *
6708	 *     // Not chained
6709	 *     api.row.add( {...} );
6710	 *     api.draw();
6711	 *
6712	 *     // Chained
6713	 *     api.row.add( {...} ).draw();
6714	 *
6715	 * @class DataTable.Api
6716	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6717	 *   used to define which DataTables enhanced tables this API will operate on.
6718	 *   Can be one of:
6719	 *
6720	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6721	 *     with be found and used.
6722	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6723	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6724	 *   * `object` - DataTables settings object
6725	 * @param {array} [data] Data to initialise the Api instance with.
6726	 *
6727	 * @example
6728	 *   // Direct initialisation during DataTables construction
6729	 *   var api = $('#example').DataTable();
6730	 *
6731	 * @example
6732	 *   // Initialisation using a DataTables jQuery object
6733	 *   var api = $('#example').dataTable().api();
6734	 *
6735	 * @example
6736	 *   // Initialisation as a constructor
6737	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6738	 */
6739	_Api = function ( context, data )
6740	{
6741		if ( ! (this instanceof _Api) ) {
6742			return new _Api( context, data );
6743		}
6744	
6745		var settings = [];
6746		var ctxSettings = function ( o ) {
6747			var a = _toSettings( o );
6748			if ( a ) {
6749				settings.push.apply( settings, a );
6750			}
6751		};
6752	
6753		if ( $.isArray( context ) ) {
6754			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6755				ctxSettings( context[i] );
6756			}
6757		}
6758		else {
6759			ctxSettings( context );
6760		}
6761	
6762		// Remove duplicates
6763		this.context = _unique( settings );
6764	
6765		// Initial data
6766		if ( data ) {
6767			this.push.apply( this, data.toArray ? data.toArray() : data );
6768		}
6769	
6770		// selector
6771		this.selector = {
6772			rows: null,
6773			cols: null,
6774			opts: null
6775		};
6776	
6777		_Api.extend( this, this, __apiStruct );
6778	};
6779	
6780	DataTable.Api = _Api;
6781	
6782	_Api.prototype = /** @lends DataTables.Api */{
6783		any: function ()
6784		{
6785			return this.flatten().length !== 0;
6786		},
6787	
6788	
6789		concat:  __arrayProto.concat,
6790	
6791	
6792		context: [], // array of table settings objects
6793	
6794	
6795		each: function ( fn )
6796		{
6797			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6798				fn.call( this, this[i], i, this );
6799			}
6800	
6801			return this;
6802		},
6803	
6804	
6805		eq: function ( idx )
6806		{
6807			var ctx = this.context;
6808	
6809			return ctx.length > idx ?
6810				new _Api( ctx[idx], this[idx] ) :
6811				null;
6812		},
6813	
6814	
6815		filter: function ( fn )
6816		{
6817			var a = [];
6818	
6819			if ( __arrayProto.filter ) {
6820				a = __arrayProto.filter.call( this, fn, this );
6821			}
6822			else {
6823				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6824				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6825					if ( fn.call( this, this[i], i, this ) ) {
6826						a.push( this[i] );
6827					}
6828				}
6829			}
6830	
6831			return new _Api( this.context, a );
6832		},
6833	
6834	
6835		flatten: function ()
6836		{
6837			var a = [];
6838			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6839		},
6840	
6841	
6842		join:    __arrayProto.join,
6843	
6844	
6845		indexOf: __arrayProto.indexOf || function (obj, start)
6846		{
6847			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6848				if ( this[i] === obj ) {
6849					return i;
6850				}
6851			}
6852			return -1;
6853		},
6854	
6855		iterator: function ( flatten, type, fn, alwaysNew ) {
6856			var
6857				a = [], ret,
6858				i, ien, j, jen,
6859				context = this.context,
6860				rows, items, item,
6861				selector = this.selector;
6862	
6863			// Argument shifting
6864			if ( typeof flatten === 'string' ) {
6865				alwaysNew = fn;
6866				fn = type;
6867				type = flatten;
6868				flatten = false;
6869			}
6870	
6871			for ( i=0, ien=context.length ; i<ien ; i++ ) {
6872				var apiInst = new _Api( context[i] );
6873	
6874				if ( type === 'table' ) {
6875					ret = fn.call( apiInst, context[i], i );
6876	
6877					if ( ret !== undefined ) {
6878						a.push( ret );
6879					}
6880				}
6881				else if ( type === 'columns' || type === 'rows' ) {
6882					// this has same length as context - one entry for each table
6883					ret = fn.call( apiInst, context[i], this[i], i );
6884	
6885					if ( ret !== undefined ) {
6886						a.push( ret );
6887					}
6888				}
6889				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6890					// columns and rows share the same structure.
6891					// 'this' is an array of column indexes for each context
6892					items = this[i];
6893	
6894					if ( type === 'column-rows' ) {
6895						rows = _selector_row_indexes( context[i], selector.opts );
6896					}
6897	
6898					for ( j=0, jen=items.length ; j<jen ; j++ ) {
6899						item = items[j];
6900	
6901						if ( type === 'cell' ) {
6902							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
6903						}
6904						else {
6905							ret = fn.call( apiInst, context[i], item, i, j, rows );
6906						}
6907	
6908						if ( ret !== undefined ) {
6909							a.push( ret );
6910						}
6911					}
6912				}
6913			}
6914	
6915			if ( a.length || alwaysNew ) {
6916				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6917				var apiSelector = api.selector;
6918				apiSelector.rows = selector.rows;
6919				apiSelector.cols = selector.cols;
6920				apiSelector.opts = selector.opts;
6921				return api;
6922			}
6923			return this;
6924		},
6925	
6926	
6927		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
6928		{
6929			// Bit cheeky...
6930			return this.indexOf.apply( this.toArray.reverse(), arguments );
6931		},
6932	
6933	
6934		length:  0,
6935	
6936	
6937		map: function ( fn )
6938		{
6939			var a = [];
6940	
6941			if ( __arrayProto.map ) {
6942				a = __arrayProto.map.call( this, fn, this );
6943			}
6944			else {
6945				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6946				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6947					a.push( fn.call( this, this[i], i ) );
6948				}
6949			}
6950	
6951			return new _Api( this.context, a );
6952		},
6953	
6954	
6955		pluck: function ( prop )
6956		{
6957			return this.map( function ( el ) {
6958				return el[ prop ];
6959			} );
6960		},
6961	
6962		pop:     __arrayProto.pop,
6963	
6964	
6965		push:    __arrayProto.push,
6966	
6967	
6968		// Does not return an API instance
6969		reduce: __arrayProto.reduce || function ( fn, init )
6970		{
6971			return _fnReduce( this, fn, init, 0, this.length, 1 );
6972		},
6973	
6974	
6975		reduceRight: __arrayProto.reduceRight || function ( fn, init )
6976		{
6977			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
6978		},
6979	
6980	
6981		reverse: __arrayProto.reverse,
6982	
6983	
6984		// Object with rows, columns and opts
6985		selector: null,
6986	
6987	
6988		shift:   __arrayProto.shift,
6989	
6990	
6991		sort:    __arrayProto.sort, // ? name - order?
6992	
6993	
6994		splice:  __arrayProto.splice,
6995	
6996	
6997		toArray: function ()
6998		{
6999			return __arrayProto.slice.call( this );
7000		},
7001	
7002	
7003		to$: function ()
7004		{
7005			return $( this );
7006		},
7007	
7008	
7009		toJQuery: function ()
7010		{
7011			return $( this );
7012		},
7013	
7014	
7015		unique: function ()
7016		{
7017			return new _Api( this.context, _unique(this) );
7018		},
7019	
7020	
7021		unshift: __arrayProto.unshift
7022	};
7023	
7024	
7025	_Api.extend = function ( scope, obj, ext )
7026	{
7027		// Only extend API instances and static properties of the API
7028		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7029			return;
7030		}
7031	
7032		var
7033			i, ien,
7034			j, jen,
7035			struct, inner,
7036			methodScoping = function ( scope, fn, struc ) {
7037				return function () {
7038					var ret = fn.apply( scope, arguments );
7039	
7040					// Method extension
7041					_Api.extend( ret, ret, struc.methodExt );
7042					return ret;
7043				};
7044			};
7045	
7046		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7047			struct = ext[i];
7048	
7049			// Value
7050			obj[ struct.name ] = typeof struct.val === 'function' ?
7051				methodScoping( scope, struct.val, struct ) :
7052				$.isPlainObject( struct.val ) ?
7053					{} :
7054					struct.val;
7055	
7056			obj[ struct.name ].__dt_wrapper = true;
7057	
7058			// Property extension
7059			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7060		}
7061	};
7062	
7063	
7064	// @todo - Is there need for an augment function?
7065	// _Api.augment = function ( inst, name )
7066	// {
7067	// 	// Find src object in the structure from the name
7068	// 	var parts = name.split('.');
7069	
7070	// 	_Api.extend( inst, obj );
7071	// };
7072	
7073	
7074	//     [
7075	//       {
7076	//         name:      'data'                -- string   - Property name
7077	//         val:       function () {},       -- function - Api method (or undefined if just an object
7078	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7079	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7080	//       },
7081	//       {
7082	//         name:     'row'
7083	//         val:       {},
7084	//         methodExt: [ ... ],
7085	//         propExt:   [
7086	//           {
7087	//             name:      'data'
7088	//             val:       function () {},
7089	//             methodExt: [ ... ],
7090	//             propExt:   [ ... ]
7091	//           },
7092	//           ...
7093	//         ]
7094	//       }
7095	//     ]
7096	
7097	_Api.register = _api_register = function ( name, val )
7098	{
7099		if ( $.isArray( name ) ) {
7100			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7101				_Api.register( name[j], val );
7102			}
7103			return;
7104		}
7105	
7106		var
7107			i, ien,
7108			heir = name.split('.'),
7109			struct = __apiStruct,
7110			key, method;
7111	
7112		var find = function ( src, name ) {
7113			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7114				if ( src[i].name === name ) {
7115					return src[i];
7116				}
7117			}
7118			return null;
7119		};
7120	
7121		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7122			method = heir[i].indexOf('()') !== -1;
7123			key = method ?
7124				heir[i].replace('()', '') :
7125				heir[i];
7126	
7127			var src = find( struct, key );
7128			if ( ! src ) {
7129				src = {
7130					name:      key,
7131					val:       {},
7132					methodExt: [],
7133					propExt:   []
7134				};
7135				struct.push( src );
7136			}
7137	
7138			if ( i === ien-1 ) {
7139				src.val = val;
7140			}
7141			else {
7142				struct = method ?
7143					src.methodExt :
7144					src.propExt;
7145			}
7146		}
7147	};
7148	
7149	
7150	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7151		_Api.register( pluralName, val );
7152	
7153		_Api.register( singularName, function () {
7154			var ret = val.apply( this, arguments );
7155	
7156			if ( ret === this ) {
7157				// Returned item is the API instance that was passed in, return it
7158				return this;
7159			}
7160			else if ( ret instanceof _Api ) {
7161				// New API instance returned, want the value from the first item
7162				// in the returned array for the singular result.
7163				return ret.length ?
7164					$.isArray( ret[0] ) ?
7165						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7166						ret[0] :
7167					undefined;
7168			}
7169	
7170			// Non-API return - just fire it back
7171			return ret;
7172		} );
7173	};
7174	
7175	
7176	/**
7177	 * Selector for HTML tables. Apply the given selector to the give array of
7178	 * DataTables settings objects.
7179	 *
7180	 * @param {string|integer} [selector] jQuery selector string or integer
7181	 * @param  {array} Array of DataTables settings objects to be filtered
7182	 * @return {array}
7183	 * @ignore
7184	 */
7185	var __table_selector = function ( selector, a )
7186	{
7187		// Integer is used to pick out a table by index
7188		if ( typeof selector === 'number' ) {
7189			return [ a[ selector ] ];
7190		}
7191	
7192		// Perform a jQuery selector on the table nodes
7193		var nodes = $.map( a, function (el, i) {
7194			return el.nTable;
7195		} );
7196	
7197		return $(nodes)
7198			.filter( selector )
7199			.map( function (i) {
7200				// Need to translate back from the table node to the settings
7201				var idx = $.inArray( this, nodes );
7202				return a[ idx ];
7203			} )
7204			.toArray();
7205	};
7206	
7207	
7208	
7209	/**
7210	 * Context selector for the API's context (i.e. the tables the API instance
7211	 * refers to.
7212	 *
7213	 * @name    DataTable.Api#tables
7214	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7215	 *   should operate on. If not given, all tables in the current context are
7216	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7217	 *   select multiple tables or as an integer to select a single table.
7218	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7219	 */
7220	_api_register( 'tables()', function ( selector ) {
7221		// A new instance is created if there was a selector specified
7222		return selector ?
7223			new _Api( __table_selector( selector, this.context ) ) :
7224			this;
7225	} );
7226	
7227	
7228	_api_register( 'table()', function ( selector ) {
7229		var tables = this.tables( selector );
7230		var ctx = tables.context;
7231	
7232		// Truncate to the first matched table
7233		return ctx.length ?
7234			new _Api( ctx[0] ) :
7235			tables;
7236	} );
7237	
7238	
7239	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7240		return this.iterator( 'table', function ( ctx ) {
7241			return ctx.nTable;
7242		}, 1 );
7243	} );
7244	
7245	
7246	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7247		return this.iterator( 'table', function ( ctx ) {
7248			return ctx.nTBody;
7249		}, 1 );
7250	} );
7251	
7252	
7253	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7254		return this.iterator( 'table', function ( ctx ) {
7255			return ctx.nTHead;
7256		}, 1 );
7257	} );
7258	
7259	
7260	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7261		return this.iterator( 'table', function ( ctx ) {
7262			return ctx.nTFoot;
7263		}, 1 );
7264	} );
7265	
7266	
7267	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7268		return this.iterator( 'table', function ( ctx ) {
7269			return ctx.nTableWrapper;
7270		}, 1 );
7271	} );
7272	
7273	
7274	
7275	/**
7276	 * Redraw the tables in the current context.
7277	 *
7278	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7279	 *   position. A full re-sort and re-filter is performed when this method is
7280	 *   called, which is why the pagination reset is the default action.
7281	 * @returns {DataTables.Api} this
7282	 */
7283	_api_register( 'draw()', function ( resetPaging ) {
7284		return this.iterator( 'table', function ( settings ) {
7285			_fnReDraw( settings, resetPaging===false );
7286		} );
7287	} );
7288	
7289	
7290	
7291	/**
7292	 * Get the current page index.
7293	 *
7294	 * @return {integer} Current page index (zero based)
7295	 *//**
7296	 * Set the current page.
7297	 *
7298	 * Note that if you attempt to show a page which does not exist, DataTables will
7299	 * not throw an error, but rather reset the paging.
7300	 *
7301	 * @param {integer|string} action The paging action to take. This can be one of:
7302	 *  * `integer` - The page index to jump to
7303	 *  * `string` - An action to take:
7304	 *    * `first` - Jump to first page.
7305	 *    * `next` - Jump to the next page
7306	 *    * `previous` - Jump to previous page
7307	 *    * `last` - Jump to the last page.
7308	 * @returns {DataTables.Api} this
7309	 */
7310	_api_register( 'page()', function ( action ) {
7311		if ( action === undefined ) {
7312			return this.page.info().page; // not an expensive call
7313		}
7314	
7315		// else, have an action to take on all tables
7316		return this.iterator( 'table', function ( settings ) {
7317			_fnPageChange( settings, action );
7318		} );
7319	} );
7320	
7321	
7322	/**
7323	 * Paging information for the first table in the current context.
7324	 *
7325	 * If you require paging information for another table, use the `table()` method
7326	 * with a suitable selector.
7327	 *
7328	 * @return {object} Object with the following properties set:
7329	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7330	 *  * `pages` - Total number of pages
7331	 *  * `start` - Display index for the first record shown on the current page
7332	 *  * `end` - Display index for the last record shown on the current page
7333	 *  * `length` - Display length (number of records). Note that generally `start
7334	 *    + length = end`, but this is not always true, for example if there are
7335	 *    only 2 records to show on the final page, with a length of 10.
7336	 *  * `recordsTotal` - Full data set length
7337	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7338	 *    are applied.
7339	 */
7340	_api_register( 'page.info()', function ( action ) {
7341		if ( this.context.length === 0 ) {
7342			return undefined;
7343		}
7344	
7345		var
7346			settings   = this.context[0],
7347			start      = settings._iDisplayStart,
7348			len        = settings._iDisplayLength,
7349			visRecords = settings.fnRecordsDisplay(),
7350			all        = len === -1;
7351	
7352		return {
7353			"page":           all ? 0 : Math.floor( start / len ),
7354			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7355			"start":          start,
7356			"end":            settings.fnDisplayEnd(),
7357			"length":         len,
7358			"recordsTotal":   settings.fnRecordsTotal(),
7359			"recordsDisplay": visRecords
7360		};
7361	} );
7362	
7363	
7364	/**
7365	 * Get the current page length.
7366	 *
7367	 * @return {integer} Current page length. Note `-1` indicates that all records
7368	 *   are to be shown.
7369	 *//**
7370	 * Set the current page length.
7371	 *
7372	 * @param {integer} Page length to set. Use `-1` to show all records.
7373	 * @returns {DataTables.Api} this
7374	 */
7375	_api_register( 'page.len()', function ( len ) {
7376		// Note that we can't call this function 'length()' because `length`
7377		// is a Javascript property of functions which defines how many arguments
7378		// the function expects.
7379		if ( len === undefined ) {
7380			return this.context.length !== 0 ?
7381				this.context[0]._iDisplayLength :
7382				undefined;
7383		}
7384	
7385		// else, set the page length
7386		return this.iterator( 'table', function ( settings ) {
7387			_fnLengthChange( settings, len );
7388		} );
7389	} );
7390	
7391	
7392	
7393	var __reload = function ( settings, holdPosition, callback ) {
7394		// Use the draw event to trigger a callback
7395		if ( callback ) {
7396			var api = new _Api( settings );
7397	
7398			api.one( 'draw', function () {
7399				callback( api.ajax.json() );
7400			} );
7401		}
7402	
7403		if ( _fnDataSource( settings ) == 'ssp' ) {
7404			_fnReDraw( settings, holdPosition );
7405		}
7406		else {
7407			// Trigger xhr
7408			_fnProcessingDisplay( settings, true );
7409	
7410			_fnBuildAjax( settings, [], function( json ) {
7411				_fnClearTable( settings );
7412	
7413				var data = _fnAjaxDataSrc( settings, json );
7414				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7415					_fnAddData( settings, data[i] );
7416				}
7417	
7418				_fnReDraw( settings, holdPosition );
7419				_fnProcessingDisplay( settings, false );
7420			} );
7421		}
7422	};
7423	
7424	
7425	/**
7426	 * Get the JSON response from the last Ajax request that DataTables made to the
7427	 * server. Note that this returns the JSON from the first table in the current
7428	 * context.
7429	 *
7430	 * @return {object} JSON received from the server.
7431	 */
7432	_api_register( 'ajax.json()', function () {
7433		var ctx = this.context;
7434	
7435		if ( ctx.length > 0 ) {
7436			return ctx[0].json;
7437		}
7438	
7439		// else return undefined;
7440	} );
7441	
7442	
7443	/**
7444	 * Get the data submitted in the last Ajax request
7445	 */
7446	_api_register( 'ajax.params()', function () {
7447		var ctx = this.context;
7448	
7449		if ( ctx.length > 0 ) {
7450			return ctx[0].oAjaxData;
7451		}
7452	
7453		// else return undefined;
7454	} );
7455	
7456	
7457	/**
7458	 * Reload tables from the Ajax data source. Note that this function will
7459	 * automatically re-draw the table when the remote data has been loaded.
7460	 *
7461	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7462	 *   position. A full re-sort and re-filter is performed when this method is
7463	 *   called, which is why the pagination reset is the default action.
7464	 * @returns {DataTables.Api} this
7465	 */
7466	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7467		return this.iterator( 'table', function (settings) {
7468			__reload( settings, resetPaging===false, callback );
7469		} );
7470	} );
7471	
7472	
7473	/**
7474	 * Get the current Ajax URL. Note that this returns the URL from the first
7475	 * table in the current context.
7476	 *
7477	 * @return {string} Current Ajax source URL
7478	 *//**
7479	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7480	 * current context.
7481	 *
7482	 * @param {string} url URL to set.
7483	 * @returns {DataTables.Api} this
7484	 */
7485	_api_register( 'ajax.url()', function ( url ) {
7486		var ctx = this.context;
7487	
7488		if ( url === undefined ) {
7489			// get
7490			if ( ctx.length === 0 ) {
7491				return undefined;
7492			}
7493			ctx = ctx[0];
7494	
7495			return ctx.ajax ?
7496				$.isPlainObject( ctx.ajax ) ?
7497					ctx.ajax.url :
7498					ctx.ajax :
7499				ctx.sAjaxSource;
7500		}
7501	
7502		// set
7503		return this.iterator( 'table', function ( settings ) {
7504			if ( $.isPlainObject( settings.ajax ) ) {
7505				settings.ajax.url = url;
7506			}
7507			else {
7508				settings.ajax = url;
7509			}
7510			// No need to consider sAjaxSource here since DataTables gives priority
7511			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7512			// value of `sAjaxSource` redundant.
7513		} );
7514	} );
7515	
7516	
7517	/**
7518	 * Load data from the newly set Ajax URL. Note that this method is only
7519	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7520	 * has the same effect as calling `ajax.reload()` but is provided for
7521	 * convenience when setting a new URL. Like `ajax.reload()` it will
7522	 * automatically redraw the table once the remote data has been loaded.
7523	 *
7524	 * @returns {DataTables.Api} this
7525	 */
7526	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7527		// Same as a reload, but makes sense to present it for easy access after a
7528		// url change
7529		return this.iterator( 'table', function ( ctx ) {
7530			__reload( ctx, resetPaging===false, callback );
7531		} );
7532	} );
7533	
7534	
7535	
7536	
7537	var _selector_run = function ( type, selector, selectFn, settings, opts )
7538	{
7539		var
7540			out = [], res,
7541			a, i, ien, j, jen,
7542			selectorType = typeof selector;
7543	
7544		// Can't just check for isArray here, as an API or jQuery instance might be
7545		// given with their array like look
7546		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7547			selector = [ selector ];
7548		}
7549	
7550		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7551			a = selector[i] && selector[i].split ?
7552				selector[i].split(',') :
7553				[ selector[i] ];
7554	
7555			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7556				res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7557	
7558				if ( res && res.length ) {
7559					out.push.apply( out, res );
7560				}
7561			}
7562		}
7563	
7564		// selector extensions
7565		var ext = _ext.selector[ type ];
7566		if ( ext.length ) {
7567			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7568				out = ext[i]( settings, opts, out );
7569			}
7570		}
7571	
7572		return out;
7573	};
7574	
7575	
7576	var _selector_opts = function ( opts )
7577	{
7578		if ( ! opts ) {
7579			opts = {};
7580		}
7581	
7582		// Backwards compatibility for 1.9- which used the terminology filter rather
7583		// than search
7584		if ( opts.filter && opts.search === undefined ) {
7585			opts.search = opts.filter;
7586		}
7587	
7588		return $.extend( {
7589			search: 'none',
7590			order: 'current',
7591			page: 'all'
7592		}, opts );
7593	};
7594	
7595	
7596	var _selector_first = function ( inst )
7597	{
7598		// Reduce the API instance to the first item found
7599		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7600			if ( inst[i].length > 0 ) {
7601				// Assign the first element to the first item in the instance
7602				// and truncate the instance and context
7603				inst[0] = inst[i];
7604				inst[0].length = 1;
7605				inst.length = 1;
7606				inst.context = [ inst.context[i] ];
7607	
7608				return inst;
7609			}
7610		}
7611	
7612		// Not found - return an empty instance
7613		inst.length = 0;
7614		return inst;
7615	};
7616	
7617	
7618	var _selector_row_indexes = function ( settings, opts )
7619	{
7620		var
7621			i, ien, tmp, a=[],
7622			displayFiltered = settings.aiDisplay,
7623			displayMaster = settings.aiDisplayMaster;
7624	
7625		var
7626			search = opts.search,  // none, applied, removed
7627			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7628			page   = opts.page;    // all, current
7629	
7630		if ( _fnDataSource( settings ) == 'ssp' ) {
7631			// In server-side processing mode, most options are irrelevant since
7632			// rows not shown don't exist and the index order is the applied order
7633			// Removed is a special case - for consistency just return an empty
7634			// array
7635			return search === 'removed' ?
7636				[] :
7637				_range( 0, displayMaster.length );
7638		}
7639		else if ( page == 'current' ) {
7640			// Current page implies that order=current and fitler=applied, since it is
7641			// fairly senseless otherwise, regardless of what order and search actually
7642			// are
7643			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7644				a.push( displayFiltered[i] );
7645			}
7646		}
7647		else if ( order == 'current' || order == 'applied' ) {
7648			a = search == 'none' ?
7649				displayMaster.slice() :                      // no search
7650				search == 'applied' ?
7651					displayFiltered.slice() :                // applied search
7652					$.map( displayMaster, function (el, i) { // removed search
7653						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7654					} );
7655		}
7656		else if ( order == 'index' || order == 'original' ) {
7657			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7658				if ( search == 'none' ) {
7659					a.push( i );
7660				}
7661				else { // applied | removed
7662					tmp = $.inArray( i, displayFiltered );
7663	
7664					if ((tmp === -1 && search == 'removed') ||
7665						(tmp >= 0   && search == 'applied') )
7666					{
7667						a.push( i );
7668					}
7669				}
7670			}
7671		}
7672	
7673		return a;
7674	};
7675	
7676	
7677	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7678	 * Rows
7679	 *
7680	 * {}          - no selector - use all available rows
7681	 * {integer}   - row aoData index
7682	 * {node}      - TR node
7683	 * {string}    - jQuery selector to apply to the TR elements
7684	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7685	 *
7686	 */
7687	
7688	
7689	var __row_selector = function ( settings, selector, opts )
7690	{
7691		var run = function ( sel ) {
7692			var selInt = _intVal( sel );
7693			var i, ien;
7694	
7695			// Short cut - selector is a number and no options provided (default is
7696			// all records, so no need to check if the index is in there, since it
7697			// must be - dev error if the index doesn't exist).
7698			if ( selInt !== null && ! opts ) {
7699				return [ selInt ];
7700			}
7701	
7702			var rows = _selector_row_indexes( settings, opts );
7703	
7704			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7705				// Selector - integer
7706				return [ selInt ];
7707			}
7708			else if ( ! sel ) {
7709				// Selector - none
7710				return rows;
7711			}
7712	
7713			// Selector - function
7714			if ( typeof sel === 'function' ) {
7715				return $.map( rows, function (idx) {
7716					var row = settings.aoData[ idx ];
7717					return sel( idx, row._aData, row.nTr ) ? idx : null;
7718				} );
7719			}
7720	
7721			// Get nodes in the order from the `rows` array with null values removed
7722			var nodes = _removeEmpty(
7723				_pluck_order( settings.aoData, rows, 'nTr' )
7724			);
7725	
7726			// Selector - node
7727			if ( sel.nodeName ) {
7728				if ( $.inArray( sel, nodes ) !== -1 ) {
7729					return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table
7730					                             // and DataTables adds a prop for fast lookup
7731				}
7732			}
7733	
7734			// Selector - jQuery selector string, array of nodes or jQuery object/
7735			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7736			// it also allows arrays, so this will cope with all three options
7737			return $(nodes)
7738				.filter( sel )
7739				.map( function () {
7740					return this._DT_RowIndex;
7741				} )
7742				.toArray();
7743		};
7744	
7745		return _selector_run( 'row', selector, run, settings, opts );
7746	};
7747	
7748	
7749	_api_register( 'rows()', function ( selector, opts ) {
7750		// argument shifting
7751		if ( selector === undefined ) {
7752			selector = '';
7753		}
7754		else if ( $.isPlainObject( selector ) ) {
7755			opts = selector;
7756			selector = '';
7757		}
7758	
7759		opts = _selector_opts( opts );
7760	
7761		var inst = this.iterator( 'table', function ( settings ) {
7762			return __row_selector( settings, selector, opts );
7763		}, 1 );
7764	
7765		// Want argument shifting here and in __row_selector?
7766		inst.selector.rows = selector;
7767		inst.selector.opts = opts;
7768	
7769		return inst;
7770	} );
7771	
7772	_api_register( 'rows().nodes()', function () {
7773		return this.iterator( 'row', function ( settings, row ) {
7774			return settings.aoData[ row ].nTr || undefined;
7775		}, 1 );
7776	} );
7777	
7778	_api_register( 'rows().data()', function () {
7779		return this.iterator( true, 'rows', function ( settings, rows ) {
7780			return _pluck_order( settings.aoData, rows, '_aData' );
7781		}, 1 );
7782	} );
7783	
7784	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7785		return this.iterator( 'row', function ( settings, row ) {
7786			var r = settings.aoData[ row ];
7787			return type === 'search' ? r._aFilterData : r._aSortData;
7788		}, 1 );
7789	} );
7790	
7791	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7792		return this.iterator( 'row', function ( settings, row ) {
7793			_fnInvalidate( settings, row, src );
7794		} );
7795	} );
7796	
7797	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7798		return this.iterator( 'row', function ( settings, row ) {
7799			return row;
7800		}, 1 );
7801	} );
7802	
7803	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7804		var that = this;
7805	
7806		return this.iterator( 'row', function ( settings, row, thatIdx ) {
7807			var data = settings.aoData;
7808	
7809			data.splice( row, 1 );
7810	
7811			// Update the _DT_RowIndex parameter on all rows in the table
7812			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7813				if ( data[i].nTr !== null ) {
7814					data[i].nTr._DT_RowIndex = i;
7815				}
7816			}
7817	
7818			// Remove the target row from the search array
7819			var displayIndex = $.inArray( row, settings.aiDisplay );
7820	
7821			// Delete from the display arrays
7822			_fnDeleteIndex( settings.aiDisplayMaster, row );
7823			_fnDeleteIndex( settings.aiDisplay, row );
7824			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7825	
7826			// Check for an 'overflow' they case for displaying the table
7827			_fnLengthOverflow( settings );
7828		} );
7829	} );
7830	
7831	
7832	_api_register( 'rows.add()', function ( rows ) {
7833		var newRows = this.iterator( 'table', function ( settings ) {
7834				var row, i, ien;
7835				var out = [];
7836	
7837				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
7838					row = rows[i];
7839	
7840					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7841						out.push( _fnAddTr( settings, row )[0] );
7842					}
7843					else {
7844						out.push( _fnAddData( settings, row ) );
7845					}
7846				}
7847	
7848				return out;
7849			}, 1 );
7850	
7851		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
7852		var modRows = this.rows( -1 );
7853		modRows.pop();
7854		modRows.push.apply( modRows, newRows.toArray() );
7855	
7856		return modRows;
7857	} );
7858	
7859	
7860	
7861	
7862	
7863	/**
7864	 *
7865	 */
7866	_api_register( 'row()', function ( selector, opts ) {
7867		return _selector_first( this.rows( selector, opts ) );
7868	} );
7869	
7870	
7871	_api_register( 'row().data()', function ( data ) {
7872		var ctx = this.context;
7873	
7874		if ( data === undefined ) {
7875			// Get
7876			return ctx.length && this.length ?
7877				ctx[0].aoData[ this[0] ]._aData :
7878				undefined;
7879		}
7880	
7881		// Set
7882		ctx[0].aoData[ this[0] ]._aData = data;
7883	
7884		// Automatically invalidate
7885		_fnInvalidate( ctx[0], this[0], 'data' );
7886	
7887		return this;
7888	} );
7889	
7890	
7891	_api_register( 'row().node()', function () {
7892		var ctx = this.context;
7893	
7894		return ctx.length && this.length ?
7895			ctx[0].aoData[ this[0] ].nTr || null :
7896			null;
7897	} );
7898	
7899	
7900	_api_register( 'row.add()', function ( row ) {
7901		// Allow a jQuery object to be passed in - only a single row is added from
7902		// it though - the first element in the set
7903		if ( row instanceof $ && row.length ) {
7904			row = row[0];
7905		}
7906	
7907		var rows = this.iterator( 'table', function ( settings ) {
7908			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7909				return _fnAddTr( settings, row )[0];
7910			}
7911			return _fnAddData( settings, row );
7912		} );
7913	
7914		// Return an Api.rows() extended instance, with the newly added row selected
7915		return this.row( rows[0] );
7916	} );
7917	
7918	
7919	
7920	var __details_add = function ( ctx, row, data, klass )
7921	{
7922		// Convert to array of TR elements
7923		var rows = [];
7924		var addRow = function ( r, k ) {
7925			// Recursion to allow for arrays of jQuery objects
7926			if ( $.isArray( r ) || r instanceof $ ) {
7927				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
7928					addRow( r[i], k );
7929				}
7930				return;
7931			}
7932	
7933			// If we get a TR element, then just add it directly - up to the dev
7934			// to add the correct number of columns etc
7935			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
7936				rows.push( r );
7937			}
7938			else {
7939				// Otherwise create a row with a wrapper
7940				var created = $('<tr><td/></tr>').addClass( k );
7941				$('td', created)
7942					.addClass( k )
7943					.html( r )
7944					[0].colSpan = _fnVisbleColumns( ctx );
7945	
7946				rows.push( created[0] );
7947			}
7948		};
7949	
7950		addRow( data, klass );
7951	
7952		if ( row._details ) {
7953			row._details.remove();
7954		}
7955	
7956		row._details = $(rows);
7957	
7958		// If the children were already shown, that state should be retained
7959		if ( row._detailsShow ) {
7960			row._details.insertAfter( row.nTr );
7961		}
7962	};
7963	
7964	
7965	var __details_remove = function ( api, idx )
7966	{
7967		var ctx = api.context;
7968	
7969		if ( ctx.length ) {
7970			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
7971	
7972			if ( row._details ) {
7973				row._details.remove();
7974	
7975				row._detailsShow = undefined;
7976				row._details = undefined;
7977			}
7978		}
7979	};
7980	
7981	
7982	var __details_display = function ( api, show ) {
7983		var ctx = api.context;
7984	
7985		if ( ctx.length && api.length ) {
7986			var row = ctx[0].aoData[ api[0] ];
7987	
7988			if ( row._details ) {
7989				row._detailsShow = show;
7990	
7991				if ( show ) {
7992					row._details.insertAfter( row.nTr );
7993				}
7994				else {
7995					row._details.detach();
7996				}
7997	
7998				__details_events( ctx[0] );
7999			}
8000		}
8001	};
8002	
8003	
8004	var __details_events = function ( settings )
8005	{
8006		var api = new _Api( settings );
8007		var namespace = '.dt.DT_details';
8008		var drawEvent = 'draw'+namespace;
8009		var colvisEvent = 'column-visibility'+namespace;
8010		var destroyEvent = 'destroy'+namespace;
8011		var data = settings.aoData;
8012	
8013		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8014	
8015		if ( _pluck( data, '_details' ).length > 0 ) {
8016			// On each draw, insert the required elements into the document
8017			api.on( drawEvent, function ( e, ctx ) {
8018				if ( settings !== ctx ) {
8019					return;
8020				}
8021	
8022				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8023					// Internal data grab
8024					var row = data[ idx ];
8025	
8026					if ( row._detailsShow ) {
8027						row._details.insertAfter( row.nTr );
8028					}
8029				} );
8030			} );
8031	
8032			// Column visibility change - update the colspan
8033			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8034				if ( settings !== ctx ) {
8035					return;
8036				}
8037	
8038				// Update the colspan for the details rows (note, only if it already has
8039				// a colspan)
8040				var row, visible = _fnVisbleColumns( ctx );
8041	
8042				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8043					row = data[i];
8044	
8045					if ( row._details ) {
8046						row._details.children('td[colspan]').attr('colspan', visible );
8047					}
8048				}
8049			} );
8050	
8051			// Table destroyed - nuke any child rows
8052			api.on( destroyEvent, function ( e, ctx ) {
8053				if ( settings !== ctx ) {
8054					return;
8055				}
8056	
8057				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8058					if ( data[i]._details ) {
8059						__details_remove( api, i );
8060					}
8061				}
8062			} );
8063		}
8064	};
8065	
8066	// Strings for the method names to help minification
8067	var _emp = '';
8068	var _child_obj = _emp+'row().child';
8069	var _child_mth = _child_obj+'()';
8070	
8071	// data can be:
8072	//  tr
8073	//  string
8074	//  jQuery or array of any of the above
8075	_api_register( _child_mth, function ( data, klass ) {
8076		var ctx = this.context;
8077	
8078		if ( data === undefined ) {
8079			// get
8080			return ctx.length && this.length ?
8081				ctx[0].aoData[ this[0] ]._details :
8082				undefined;
8083		}
8084		else if ( data === true ) {
8085			// show
8086			this.child.show();
8087		}
8088		else if ( data === false ) {
8089			// remove
8090			__details_remove( this );
8091		}
8092		else if ( ctx.length && this.length ) {
8093			// set
8094			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8095		}
8096	
8097		return this;
8098	} );
8099	
8100	
8101	_api_register( [
8102		_child_obj+'.show()',
8103		_child_mth+'.show()' // only when `child()` was called with parameters (without
8104	], function ( show ) {   // it returns an object and this method is not executed)
8105		__details_display( this, true );
8106		return this;
8107	} );
8108	
8109	
8110	_api_register( [
8111		_child_obj+'.hide()',
8112		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8113	], function () {         // it returns an object and this method is not executed)
8114		__details_display( this, false );
8115		return this;
8116	} );
8117	
8118	
8119	_api_register( [
8120		_child_obj+'.remove()',
8121		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8122	], function () {           // it returns an object and this method is not executed)
8123		__details_remove( this );
8124		return this;
8125	} );
8126	
8127	
8128	_api_register( _child_obj+'.isShown()', function () {
8129		var ctx = this.context;
8130	
8131		if ( ctx.length && this.length ) {
8132			// _detailsShown as false or undefined will fall through to return false
8133			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8134		}
8135		return false;
8136	} );
8137	
8138	
8139	
8140	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8141	 * Columns
8142	 *
8143	 * {integer}           - column index (>=0 count from left, <0 count from right)
8144	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8145	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8146	 * "{string}:name"     - column name
8147	 * "{string}"          - jQuery selector on column header nodes
8148	 *
8149	 */
8150	
8151	// can be an array of these items, comma separated list, or an array of comma
8152	// separated lists
8153	
8154	var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
8155	
8156	
8157	// r1 and r2 are redundant - but it means that the parameters match for the
8158	// iterator callback in columns().data()
8159	var __columnData = function ( settings, column, r1, r2, rows ) {
8160		var a = [];
8161		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8162			a.push( _fnGetCellData( settings, rows[row], column ) );
8163		}
8164		return a;
8165	};
8166	
8167	
8168	var __column_selector = function ( settings, selector, opts )
8169	{
8170		var
8171			columns = settings.aoColumns,
8172			names = _pluck( columns, 'sName' ),
8173			nodes = _pluck( columns, 'nTh' );
8174	
8175		var run = function ( s ) {
8176			var selInt = _intVal( s );
8177	
8178			// Selector - all
8179			if ( s === '' ) {
8180				return _range( columns.length );
8181			}
8182			
8183			// Selector - index
8184			if ( selInt !== null ) {
8185				return [ selInt >= 0 ?
8186					selInt : // Count from left
8187					columns.length + selInt // Count from right (+ because its a negative value)
8188				];
8189			}
8190			
8191			// Selector = function
8192			if ( typeof s === 'function' ) {
8193				var rows = _selector_row_indexes( settings, opts );
8194	
8195				return $.map( columns, function (col, idx) {
8196					return s(
8197							idx,
8198							__columnData( settings, idx, 0, 0, rows ),
8199							nodes[ idx ]
8200						) ? idx : null;
8201				} );
8202			}
8203	
8204			// jQuery or string selector
8205			var match = typeof s === 'string' ?
8206				s.match( __re_column_selector ) :
8207				'';
8208	
8209			if ( match ) {
8210				switch( match[2] ) {
8211					case 'visIdx':
8212					case 'visible':
8213						var idx = parseInt( match[1], 10 );
8214						// Visible index given, convert to column index
8215						if ( idx < 0 ) {
8216							// Counting from the right
8217							var visColumns = $.map( columns, function (col,i) {
8218								return col.bVisible ? i : null;
8219							} );
8220							return [ visColumns[ visColumns.length + idx ] ];
8221						}
8222						// Counting from the left
8223						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8224	
8225					case 'name':
8226						// match by name. `names` is column index complete and in order
8227						return $.map( names, function (name, i) {
8228							return name === match[1] ? i : null;
8229						} );
8230				}
8231			}
8232			else {
8233				// jQuery selector on the TH elements for the columns
8234				return $( nodes )
8235					.filter( s )
8236					.map( function () {
8237						return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8238					} )
8239					.toArray();
8240			}
8241		};
8242	
8243		return _selector_run( 'column', selector, run, settings, opts );
8244	};
8245	
8246	
8247	var __setColumnVis = function ( settings, column, vis, recalc ) {
8248		var
8249			cols = settings.aoColumns,
8250			col  = cols[ column ],
8251			data = settings.aoData,
8252			row, cells, i, ien, tr;
8253	
8254		// Get
8255		if ( vis === undefined ) {
8256			return col.bVisible;
8257		}
8258	
8259		// Set
8260		// No change
8261		if ( col.bVisible === vis ) {
8262			return;
8263		}
8264	
8265		if ( vis ) {
8266			// Insert column
8267			// Need to decide if we should use appendChild or insertBefore
8268			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8269	
8270			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8271				tr = data[i].nTr;
8272				cells = data[i].anCells;
8273	
8274				if ( tr ) {
8275					// insertBefore can act like appendChild if 2nd arg is null
8276					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8277				}
8278			}
8279		}
8280		else {
8281			// Remove column
8282			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8283		}
8284	
8285		// Common actions
8286		col.bVisible = vis;
8287		_fnDrawHead( settings, settings.aoHeader );
8288		_fnDrawHead( settings, settings.aoFooter );
8289	
8290		if ( recalc === undefined || recalc ) {
8291			// Automatically adjust column sizing
8292			_fnAdjustColumnSizing( settings );
8293	
8294			// Realign columns for scrolling
8295			if ( settings.oScroll.sX || settings.oScroll.sY ) {
8296				_fnScrollDraw( settings );
8297			}
8298		}
8299	
8300		_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
8301	
8302		_fnSaveState( settings );
8303	};
8304	
8305	
8306	_api_register( 'columns()', function ( selector, opts ) {
8307		// argument shifting
8308		if ( selector === undefined ) {
8309			selector = '';
8310		}
8311		else if ( $.isPlainObject( selector ) ) {
8312			opts = selector;
8313			selector = '';
8314		}
8315	
8316		opts = _selector_opts( opts );
8317	
8318		var inst = this.iterator( 'table', function ( settings ) {
8319			return __column_selector( settings, selector, opts );
8320		}, 1 );
8321	
8322		// Want argument shifting here and in _row_selector?
8323		inst.selector.cols = selector;
8324		inst.selector.opts = opts;
8325	
8326		return inst;
8327	} );
8328	
8329	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8330		return this.iterator( 'column', function ( settings, column ) {
8331			return settings.aoColumns[column].nTh;
8332		}, 1 );
8333	} );
8334	
8335	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8336		return this.iterator( 'column', function ( settings, column ) {
8337			return settings.aoColumns[column].nTf;
8338		}, 1 );
8339	} );
8340	
8341	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8342		return this.iterator( 'column-rows', __columnData, 1 );
8343	} );
8344	
8345	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8346		return this.iterator( 'column', function ( settings, column ) {
8347			return settings.aoColumns[column].mData;
8348		}, 1 );
8349	} );
8350	
8351	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8352		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8353			return _pluck_order( settings.aoData, rows,
8354				type === 'search' ? '_aFilterData' : '_aSortData', column
8355			);
8356		}, 1 );
8357	} );
8358	
8359	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8360		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8361			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8362		}, 1 );
8363	} );
8364	
8365	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8366		return this.iterator( 'column', function ( settings, column ) {
8367			if ( vis === undefined ) {
8368				return settings.aoColumns[ column ].bVisible;
8369			} // else
8370			__setColumnVis( settings, column, vis, calc );
8371		} );
8372	} );
8373	
8374	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8375		return this.iterator( 'column', function ( settings, column ) {
8376			return type === 'visible' ?
8377				_fnColumnIndexToVisible( settings, column ) :
8378				column;
8379		}, 1 );
8380	} );
8381	
8382	_api_register( 'columns.adjust()', function () {
8383		return this.iterator( 'table', function ( settings ) {
8384			_fnAdjustColumnSizing( settings );
8385		}, 1 );
8386	} );
8387	
8388	_api_register( 'column.index()', function ( type, idx ) {
8389		if ( this.context.length !== 0 ) {
8390			var ctx = this.context[0];
8391	
8392			if ( type === 'fromVisible' || type === 'toData' ) {
8393				return _fnVisibleToColumnIndex( ctx, idx );
8394			}
8395			else if ( type === 'fromData' || type === 'toVisible' ) {
8396				return _fnColumnIndexToVisible( ctx, idx );
8397			}
8398		}
8399	} );
8400	
8401	_api_register( 'column()', function ( selector, opts ) {
8402		return _selector_first( this.columns( selector, opts ) );
8403	} );
8404	
8405	
8406	
8407	
8408	var __cell_selector = function ( settings, selector, opts )
8409	{
8410		var data = settings.aoData;
8411		var rows = _selector_row_indexes( settings, opts );
8412		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8413		var allCells = $( [].concat.apply([], cells) );
8414		var row;
8415		var columns = settings.aoColumns.length;
8416		var a, i, ien, j, o, host;
8417	
8418		var run = function ( s ) {
8419			var fnSelector = typeof s === 'function';
8420	
8421			if ( s === null || s === undefined || fnSelector ) {
8422				// All cells and function selectors
8423				a = [];
8424	
8425				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8426					row = rows[i];
8427	
8428					for ( j=0 ; j<columns ; j++ ) {
8429						o = {
8430							row: row,
8431							column: j
8432						};
8433	
8434						if ( fnSelector ) {
8435							// Selector - function
8436							host = settings.aoData[ row ];
8437	
8438							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8439								a.push( o );
8440							}
8441						}
8442						else {
8443							// Selector - all
8444							a.push( o );
8445						}
8446					}
8447				}
8448	
8449				return a;
8450			}
8451			
8452			// Selector - index
8453			if ( $.isPlainObject( s ) ) {
8454				return [s];
8455			}
8456	
8457			// Selector - jQuery filtered cells
8458			return allCells
8459				.filter( s )
8460				.map( function (i, el) {
8461					row = el.parentNode._DT_RowIndex;
8462	
8463					return {
8464						row: row,
8465						column: $.inArray( el, data[ row ].anCells )
8466					};
8467				} )
8468				.toArray();
8469		};
8470	
8471		return _selector_run( 'cell', selector, run, settings, opts );
8472	};
8473	
8474	
8475	
8476	
8477	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8478		// Argument shifting
8479		if ( $.isPlainObject( rowSelector ) ) {
8480			// Indexes
8481			if ( rowSelector.row === undefined ) {
8482				// Selector options in first parameter
8483				opts = rowSelector;
8484				rowSelector = null;
8485			}
8486			else {
8487				// Cell index objects in first parameter
8488				opts = columnSelector;
8489				columnSelector = null;
8490			}
8491		}
8492		if ( $.isPlainObject( columnSelector ) ) {
8493			opts = columnSelector;
8494			columnSelector = null;
8495		}
8496	
8497		// Cell selector
8498		if ( columnSelector === null || columnSelector === undefined ) {
8499			return this.iterator( 'table', function ( settings ) {
8500				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8501			} );
8502		}
8503	
8504		// Row + column selector
8505		var columns = this.columns( columnSelector, opts );
8506		var rows = this.rows( rowSelector, opts );
8507		var a, i, ien, j, jen;
8508	
8509		var cells = this.iterator( 'table', function ( settings, idx ) {
8510			a = [];
8511	
8512			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8513				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8514					a.push( {
8515						row:    rows[idx][i],
8516						column: columns[idx][j]
8517					} );
8518				}
8519			}
8520	
8521			return a;
8522		}, 1 );
8523	
8524		$.extend( cells.selector, {
8525			cols: columnSelector,
8526			rows: rowSelector,
8527			opts: opts
8528		} );
8529	
8530		return cells;
8531	} );
8532	
8533	
8534	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8535		return this.iterator( 'cell', function ( settings, row, column ) {
8536			var cells = settings.aoData[ row ].anCells;
8537			return cells ?
8538				cells[ column ] :
8539				undefined;
8540		}, 1 );
8541	} );
8542	
8543	
8544	_api_register( 'cells().data()', function () {
8545		return this.iterator( 'cell', function ( settings, row, column ) {
8546			return _fnGetCellData( settings, row, column );
8547		}, 1 );
8548	} );
8549	
8550	
8551	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8552		type = type === 'search' ? '_aFilterData' : '_aSortData';
8553	
8554		return this.iterator( 'cell', function ( settings, row, column ) {
8555			return settings.aoData[ row ][ type ][ column ];
8556		}, 1 );
8557	} );
8558	
8559	
8560	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8561		return this.iterator( 'cell', function ( settings, row, column ) {
8562			return _fnGetCellData( settings, row, column, type );
8563		}, 1 );
8564	} );
8565	
8566	
8567	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8568		return this.iterator( 'cell', function ( settings, row, column ) {
8569			return {
8570				row: row,
8571				column: column,
8572				columnVisible: _fnColumnIndexToVisible( settings, column )
8573			};
8574		}, 1 );
8575	} );
8576	
8577	
8578	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8579		return this.iterator( 'cell', function ( settings, row, column ) {
8580			_fnInvalidate( settings, row, src, column );
8581		} );
8582	} );
8583	
8584	
8585	
8586	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8587		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8588	} );
8589	
8590	
8591	_api_register( 'cell().data()', function ( data ) {
8592		var ctx = this.context;
8593		var cell = this[0];
8594	
8595		if ( data === undefined ) {
8596			// Get
8597			return ctx.length && cell.length ?
8598				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8599				undefined;
8600		}
8601	
8602		// Set
8603		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8604		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8605	
8606		return this;
8607	} );
8608	
8609	
8610	
8611	/**
8612	 * Get current ordering (sorting) that has been applied to the table.
8613	 *
8614	 * @returns {array} 2D array containing the sorting information for the first
8615	 *   table in the current context. Each element in the parent array represents
8616	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8617	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8618	 *   the column index that the sorting condition applies to, the second is the
8619	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8620	 *   index of the sorting order from the `column.sorting` initialisation array.
8621	 *//**
8622	 * Set the ordering for the table.
8623	 *
8624	 * @param {integer} order Column index to sort upon.
8625	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8626	 * @returns {DataTables.Api} this
8627	 *//**
8628	 * Set the ordering for the table.
8629	 *
8630	 * @param {array} order 1D array of sorting information to be applied.
8631	 * @param {array} [...] Optional additional sorting conditions
8632	 * @returns {DataTables.Api} this
8633	 *//**
8634	 * Set the ordering for the table.
8635	 *
8636	 * @param {array} order 2D array of sorting information to be applied.
8637	 * @returns {DataTables.Api} this
8638	 */
8639	_api_register( 'order()', function ( order, dir ) {
8640		var ctx = this.context;
8641	
8642		if ( order === undefined ) {
8643			// get
8644			return ctx.length !== 0 ?
8645				ctx[0].aaSorting :
8646				undefined;
8647		}
8648	
8649		// set
8650		if ( typeof order === 'number' ) {
8651			// Simple column / direction passed in
8652			order = [ [ order, dir ] ];
8653		}
8654		else if ( ! $.isArray( order[0] ) ) {
8655			// Arguments passed in (list of 1D arrays)
8656			order = Array.prototype.slice.call( arguments );
8657		}
8658		// otherwise a 2D array was passed in
8659	
8660		return this.iterator( 'table', function ( settings ) {
8661			settings.aaSorting = order.slice();
8662		} );
8663	} );
8664	
8665	
8666	/**
8667	 * Attach a sort listener to an element for a given column
8668	 *
8669	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8670	 *   listener to. This can take the form of a single DOM node, a jQuery
8671	 *   collection of nodes or a jQuery selector which will identify the node(s).
8672	 * @param {integer} column the column that a click on this node will sort on
8673	 * @param {function} [callback] callback function when sort is run
8674	 * @returns {DataTables.Api} this
8675	 */
8676	_api_register( 'order.listener()', function ( node, column, callback ) {
8677		return this.iterator( 'table', function ( settings ) {
8678			_fnSortAttachListener( settings, node, column, callback );
8679		} );
8680	} );
8681	
8682	
8683	// Order by the selected column(s)
8684	_api_register( [
8685		'columns().order()',
8686		'column().order()'
8687	], function ( dir ) {
8688		var that = this;
8689	
8690		return this.iterator( 'table', function ( settings, i ) {
8691			var sort = [];
8692	
8693			$.each( that[i], function (j, col) {
8694				sort.push( [ col, dir ] );
8695			} );
8696	
8697			settings.aaSorting = sort;
8698		} );
8699	} );
8700	
8701	
8702	
8703	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8704		var ctx = this.context;
8705	
8706		if ( input === undefined ) {
8707			// get
8708			return ctx.length !== 0 ?
8709				ctx[0].oPreviousSearch.sSearch :
8710				undefined;
8711		}
8712	
8713		// set
8714		return this.iterator( 'table', function ( settings ) {
8715			if ( ! settings.oFeatures.bFilter ) {
8716				return;
8717			}
8718	
8719			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8720				"sSearch": input+"",
8721				"bRegex":  regex === null ? false : regex,
8722				"bSmart":  smart === null ? true  : smart,
8723				"bCaseInsensitive": caseInsen === null ? true : caseInsen
8724			} ), 1 );
8725		} );
8726	} );
8727	
8728	
8729	_api_registerPlural(
8730		'columns().search()',
8731		'column().search()',
8732		function ( input, regex, smart, caseInsen ) {
8733			return this.iterator( 'column', function ( settings, column ) {
8734				var preSearch = settings.aoPreSearchCols;
8735	
8736				if ( input === undefined ) {
8737					// get
8738					return preSearch[ column ].sSearch;
8739				}
8740	
8741				// set
8742				if ( ! settings.oFeatures.bFilter ) {
8743					return;
8744				}
8745	
8746				$.extend( preSearch[ column ], {
8747					"sSearch": input+"",
8748					"bRegex":  regex === null ? false : regex,
8749					"bSmart":  smart === null ? true  : smart,
8750					"bCaseInsensitive": caseInsen === null ? true : caseInsen
8751				} );
8752	
8753				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8754			} );
8755		}
8756	);
8757	
8758	/*
8759	 * State API methods
8760	 */
8761	
8762	_api_register( 'state()', function () {
8763		return this.context.length ?
8764			this.context[0].oSavedState :
8765			null;
8766	} );
8767	
8768	
8769	_api_register( 'state.clear()', function () {
8770		return this.iterator( 'table', function ( settings ) {
8771			// Save an empty object
8772			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
8773		} );
8774	} );
8775	
8776	
8777	_api_register( 'state.loaded()', function () {
8778		return this.context.length ?
8779			this.context[0].oLoadedState :
8780			null;
8781	} );
8782	
8783	
8784	_api_register( 'state.save()', function () {
8785		return this.iterator( 'table', function ( settings ) {
8786			_fnSaveState( settings );
8787		} );
8788	} );
8789	
8790	
8791	
8792	/**
8793	 * Provide a common method for plug-ins to check the version of DataTables being
8794	 * used, in order to ensure compatibility.
8795	 *
8796	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
8797	 *    Note that the formats "X" and "X.Y" are also acceptable.
8798	 *  @returns {boolean} true if this version of DataTables is greater or equal to
8799	 *    the required version, or false if this version of DataTales is not
8800	 *    suitable
8801	 *  @static
8802	 *  @dtopt API-Static
8803	 *
8804	 *  @example
8805	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8806	 */
8807	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
8808	{
8809		var aThis = DataTable.version.split('.');
8810		var aThat = version.split('.');
8811		var iThis, iThat;
8812	
8813		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
8814			iThis = parseInt( aThis[i], 10 ) || 0;
8815			iThat = parseInt( aThat[i], 10 ) || 0;
8816	
8817			// Parts are the same, keep comparing
8818			if (iThis === iThat) {
8819				continue;
8820			}
8821	
8822			// Parts are different, return immediately
8823			return iThis > iThat;
8824		}
8825	
8826		return true;
8827	};
8828	
8829	
8830	/**
8831	 * Check if a `<table>` node is a DataTable table already or not.
8832	 *
8833	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
8834	 *      selector for the table to test. Note that if more than more than one
8835	 *      table is passed on, only the first will be checked
8836	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
8837	 *  @static
8838	 *  @dtopt API-Static
8839	 *
8840	 *  @example
8841	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8842	 *      $('#example').dataTable();
8843	 *    }
8844	 */
8845	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
8846	{
8847		var t = $(table).get(0);
8848		var is = false;
8849	
8850		$.each( DataTable.settings, function (i, o) {
8851			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
8852			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
8853	
8854			if ( o.nTable === t || head === t || foot === t ) {
8855				is = true;
8856			}
8857		} );
8858	
8859		return is;
8860	};
8861	
8862	
8863	/**
8864	 * Get all DataTable tables that have been initialised - optionally you can
8865	 * select to get only currently visible tables.
8866	 *
8867	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
8868	 *    or visible tables only.
8869	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
8870	 *    DataTables
8871	 *  @static
8872	 *  @dtopt API-Static
8873	 *
8874	 *  @example
8875	 *    $.each( $.fn.dataTable.tables(true), function () {
8876	 *      $(table).DataTable().columns.adjust();
8877	 *    } );
8878	 */
8879	DataTable.tables = DataTable.fnTables = function ( visible )
8880	{
8881		return $.map( DataTable.settings, function (o) {
8882			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8883				return o.nTable;
8884			}
8885		} );
8886	};
8887	
8888	
8889	/**
8890	 * DataTables utility methods
8891	 * 
8892	 * This namespace provides helper methods that DataTables uses internally to
8893	 * create a DataTable, but which are not exclusively used only for DataTables.
8894	 * These methods can be used by extension authors to save the duplication of
8895	 * code.
8896	 *
8897	 *  @namespace
8898	 */
8899	DataTable.util = {
8900		/**
8901		 * Throttle the calls to a function. Arguments and context are maintained
8902		 * for the throttled function.
8903		 *
8904		 * @param {function} fn Function to be called
8905		 * @param {integer} freq Call frequency in mS
8906		 * @return {function} Wrapped function
8907		 */
8908		throttle: _fnThrottle,
8909	
8910	
8911		/**
8912		 * Escape a string such that it can be used in a regular expression
8913		 *
8914		 *  @param {string} sVal string to escape
8915		 *  @returns {string} escaped string
8916		 */
8917		escapeRegex: _fnEscapeRegex
8918	};
8919	
8920	
8921	/**
8922	 * Convert from camel case parameters to Hungarian notation. This is made public
8923	 * for the extensions to provide the same ability as DataTables core to accept
8924	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
8925	 * parameters.
8926	 *
8927	 *  @param {object} src The model object which holds all parameters that can be
8928	 *    mapped.
8929	 *  @param {object} user The object to convert from camel case to Hungarian.
8930	 *  @param {boolean} force When set to `true`, properties which already have a
8931	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
8932	 *    won't be.
8933	 */
8934	DataTable.camelToHungarian = _fnCamelToHungarian;
8935	
8936	
8937	
8938	/**
8939	 *
8940	 */
8941	_api_register( '$()', function ( selector, opts ) {
8942		var
8943			rows   = this.rows( opts ).nodes(), // Get all rows
8944			jqRows = $(rows);
8945	
8946		return $( [].concat(
8947			jqRows.filter( selector ).toArray(),
8948			jqRows.find( selector ).toArray()
8949		) );
8950	} );
8951	
8952	
8953	// jQuery functions to operate on the tables
8954	$.each( [ 'on', 'one', 'off' ], function (i, key) {
8955		_api_register( key+'()', function ( /* event, handler */ ) {
8956			var args = Array.prototype.slice.call(arguments);
8957	
8958			// Add the `dt` namespace automatically if it isn't already present
8959			if ( ! args[0].match(/\.dt\b/) ) {
8960				args[0] += '.dt';
8961			}
8962	
8963			var inst = $( this.tables().nodes() );
8964			inst[key].apply( inst, args );
8965			return this;
8966		} );
8967	} );
8968	
8969	
8970	_api_register( 'clear()', function () {
8971		return this.iterator( 'table', function ( settings ) {
8972			_fnClearTable( settings );
8973		} );
8974	} );
8975	
8976	
8977	_api_register( 'settings()', function () {
8978		return new _Api( this.context, this.context );
8979	} );
8980	
8981	
8982	_api_register( 'init()', function () {
8983		var ctx = this.context;
8984		return ctx.length ? ctx[0].oInit : null;
8985	} );
8986	
8987	
8988	_api_register( 'data()', function () {
8989		return this.iterator( 'table', function ( settings ) {
8990			return _pluck( settings.aoData, '_aData' );
8991		} ).flatten();
8992	} );
8993	
8994	
8995	_api_register( 'destroy()', function ( remove ) {
8996		remove = remove || false;
8997	
8998		return this.iterator( 'table', function ( settings ) {
8999			var orig      = settings.nTableWrapper.parentNode;
9000			var classes   = settings.oClasses;
9001			var table     = settings.nTable;
9002			var tbody     = settings.nTBody;
9003			var thead     = settings.nTHead;
9004			var tfoot     = settings.nTFoot;
9005			var jqTable   = $(table);
9006			var jqTbody   = $(tbody);
9007			var jqWrapper = $(settings.nTableWrapper);
9008			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9009			var i, ien;
9010	
9011			// Flag to note that the table is currently being destroyed - no action
9012			// should be taken
9013			settings.bDestroying = true;
9014	
9015			// Fire off the destroy callbacks for plug-ins etc
9016			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9017	
9018			// If not being removed from the document, make all columns visible
9019			if ( ! remove ) {
9020				new _Api( settings ).columns().visible( true );
9021			}
9022	
9023			// Blitz all `DT` namespaced events (these are internal events, the
9024			// lowercase, `dt` events are user subscribed and they are responsible
9025			// for removing them
9026			jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
9027			$(window).unbind('.DT-'+settings.sInstance);
9028	
9029			// When scrolling we had to break the table up - restore it
9030			if ( table != thead.parentNode ) {
9031				jqTable.children('thead').detach();
9032				jqTable.append( thead );
9033			}
9034	
9035			if ( tfoot && table != tfoot.parentNode ) {
9036				jqTable.children('tfoot').detach();
9037				jqTable.append( tfoot );
9038			}
9039	
9040			// Remove the DataTables generated nodes, events and classes
9041			jqTable.detach();
9042			jqWrapper.detach();
9043	
9044			settings.aaSorting = [];
9045			settings.aaSortingFixed = [];
9046			_fnSortingClasses( settings );
9047	
9048			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9049	
9050			$('th, td', thead).removeClass( classes.sSortable+' '+
9051				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9052			);
9053	
9054			if ( settings.bJUI ) {
9055				$('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
9056				$('th, td', thead).each( function () {
9057					var wrapper = $('div.'+classes.sSortJUIWrapper, this);
9058					$(this).append( wrapper.contents() );
9059					wrapper.detach();
9060				} );
9061			}
9062	
9063			if ( ! remove && orig ) {
9064				// insertBefore acts like appendChild if !arg[1]
9065				orig.insertBefore( table, settings.nTableReinsertBefore );
9066			}
9067	
9068			// Add the TR elements back into the table in their original order
9069			jqTbody.children().detach();
9070			jqTbody.append( rows );
9071	
9072			// Restore the width of the original table - was read from the style property,
9073			// so we can restore directly to that
9074			jqTable
9075				.css( 'width', settings.sDestroyWidth )
9076				.removeClass( classes.sTable );
9077	
9078			// If the were originally stripe classes - then we add them back here.
9079			// Note this is not fool proof (for example if not all rows had stripe
9080			// classes - but it's a good effort without getting carried away
9081			ien = settings.asDestroyStripes.length;
9082	
9083			if ( ien ) {
9084				jqTbody.children().each( function (i) {
9085					$(this).addClass( settings.asDestroyStripes[i % ien] );
9086				} );
9087			}
9088	
9089			/* Remove the settings object from the settings array */
9090			var idx = $.inArray( settings, DataTable.settings );
9091			if ( idx !== -1 ) {
9092				DataTable.settings.splice( idx, 1 );
9093			}
9094		} );
9095	} );
9096	
9097	
9098	// Add the `every()` method for rows, columns and cells in a compact form
9099	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9100		_api_register( type+'s().every()', function ( fn ) {
9101			return this.iterator( type, function ( settings, idx, idx2 ) {
9102				// idx2 is undefined for rows and columns.
9103				fn.call( new _Api( settings )[ type ]( idx, idx2 ) );
9104			} );
9105		} );
9106	} );
9107	
9108	
9109	// i18n method for extensions to be able to use the language object from the
9110	// DataTable
9111	_api_register( 'i18n()', function ( token, def, plural ) {
9112		var ctx = this.context[0];
9113		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9114	
9115		if ( resolved === undefined ) {
9116			resolved = def;
9117		}
9118	
9119		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9120			resolved = resolved[ plural ] !== undefined ?
9121				resolved[ plural ] :
9122				resolved._;
9123		}
9124	
9125		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9126	} );
9127
9128	/**
9129	 * Version string for plug-ins to check compatibility. Allowed format is
9130	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9131	 * only for non-release builds. See http://semver.org/ for more information.
9132	 *  @member
9133	 *  @type string
9134	 *  @default Version number
9135	 */
9136	DataTable.version = "1.10.7";
9137
9138	/**
9139	 * Private data store, containing all of the settings objects that are
9140	 * created for the tables on a given page.
9141	 *
9142	 * Note that the `DataTable.settings` object is aliased to
9143	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9144	 * manipulated, or `jQuery.fn.dataTable.settings`.
9145	 *  @member
9146	 *  @type array
9147	 *  @default []
9148	 *  @private
9149	 */
9150	DataTable.settings = [];
9151
9152	/**
9153	 * Object models container, for the various models that DataTables has
9154	 * available to it. These models define the objects that are used to hold
9155	 * the active state and configuration of the table.
9156	 *  @namespace
9157	 */
9158	DataTable.models = {};
9159	
9160	
9161	
9162	/**
9163	 * Template object for the way in which DataTables holds information about
9164	 * search information for the global filter and individual column filters.
9165	 *  @namespace
9166	 */
9167	DataTable.models.oSearch = {
9168		/**
9169		 * Flag to indicate if the filtering should be case insensitive or not
9170		 *  @type boolean
9171		 *  @default true
9172		 */
9173		"bCaseInsensitive": true,
9174	
9175		/**
9176		 * Applied search term
9177		 *  @type string
9178		 *  @default <i>Empty string</i>
9179		 */
9180		"sSearch": "",
9181	
9182		/**
9183		 * Flag to indicate if the search term should be interpreted as a
9184		 * regular expression (true) or not (false) and therefore and special
9185		 * regex characters escaped.
9186		 *  @type boolean
9187		 *  @default false
9188		 */
9189		"bRegex": false,
9190	
9191		/**
9192		 * Flag to indicate if DataTables is to use its smart filtering or not.
9193		 *  @type boolean
9194		 *  @default true
9195		 */
9196		"bSmart": true
9197	};
9198	
9199	
9200	
9201	
9202	/**
9203	 * Template object for the way in which DataTables holds information about
9204	 * each individual row. This is the object format used for the settings
9205	 * aoData array.
9206	 *  @namespace
9207	 */
9208	DataTable.models.oRow = {
9209		/**
9210		 * TR element for the row
9211		 *  @type node
9212		 *  @default null
9213		 */
9214		"nTr": null,
9215	
9216		/**
9217		 * Array of TD elements for each row. This is null until the row has been
9218		 * created.
9219		 *  @type array nodes
9220		 *  @default []
9221		 */
9222		"anCells": null,
9223	
9224		/**
9225		 * Data object from the original data source for the row. This is either
9226		 * an array if using the traditional form of DataTables, or an object if
9227		 * using mData options. The exact type will depend on the passed in
9228		 * data from the data source, or will be an array if using DOM a data
9229		 * source.
9230		 *  @type array|object
9231		 *  @default []
9232		 */
9233		"_aData": [],
9234	
9235		/**
9236		 * Sorting data cache - this array is ostensibly the same length as the
9237		 * number of columns (although each index is generated only as it is
9238		 * needed), and holds the data that is used for sorting each column in the
9239		 * row. We do this cache generation at the start of the sort in order that
9240		 * the formatting of the sort data need be done only once for each cell
9241		 * per sort. This array should not be read from or written to by anything
9242		 * other than the master sorting methods.
9243		 *  @type array
9244		 *  @default null
9245		 *  @private
9246		 */
9247		"_aSortData": null,
9248	
9249		/**
9250		 * Per cell filtering data cache. As per the sort data cache, used to
9251		 * increase the performance of the filtering in DataTables
9252		 *  @type array
9253		 *  @default null
9254		 *  @private
9255		 */
9256		"_aFilterData": null,
9257	
9258		/**
9259		 * Filtering data cache. This is the same as the cell filtering cache, but
9260		 * in this case a string rather than an array. This is easily computed with
9261		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9262		 * needed on every search (memory traded for performance)
9263		 *  @type array
9264		 *  @default null
9265		 *  @private
9266		 */
9267		"_sFilterRow": null,
9268	
9269		/**
9270		 * Cache of the class name that DataTables has applied to the row, so we
9271		 * can quickly look at this variable rather than needing to do a DOM check
9272		 * on className for the nTr property.
9273		 *  @type string
9274		 *  @default <i>Empty string</i>
9275		 *  @private
9276		 */
9277		"_sRowStripe": "",
9278	
9279		/**
9280		 * Denote if the original data source was from the DOM, or the data source
9281		 * object. This is used for invalidating data, so DataTables can
9282		 * automatically read data from the original source, unless uninstructed
9283		 * otherwise.
9284		 *  @type string
9285		 *  @default null
9286		 *  @private
9287		 */
9288		"src": null
9289	};
9290	
9291	
9292	/**
9293	 * Template object for the column information object in DataTables. This object
9294	 * is held in the settings aoColumns array and contains all the information that
9295	 * DataTables needs about each individual column.
9296	 *
9297	 * Note that this object is related to {@link DataTable.defaults.column}
9298	 * but this one is the internal data store for DataTables's cache of columns.
9299	 * It should NOT be manipulated outside of DataTables. Any configuration should
9300	 * be done through the initialisation options.
9301	 *  @namespace
9302	 */
9303	DataTable.models.oColumn = {
9304		/**
9305		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9306		 * is faster to just hold it as a variable
9307		 *  @type integer
9308		 *  @default null
9309		 */
9310		"idx": null,
9311	
9312		/**
9313		 * A list of the columns that sorting should occur on when this column
9314		 * is sorted. That this property is an array allows multi-column sorting
9315		 * to be defined for a column (for example first name / last name columns
9316		 * would benefit from this). The values are integers pointing to the
9317		 * columns to be sorted on (typically it will be a single integer pointing
9318		 * at itself, but that doesn't need to be the case).
9319		 *  @type array
9320		 */
9321		"aDataSort": null,
9322	
9323		/**
9324		 * Define the sorting directions that are applied to the column, in sequence
9325		 * as the column is repeatedly sorted upon - i.e. the first value is used
9326		 * as the sorting direction when the column if first sorted (clicked on).
9327		 * Sort it again (click again) and it will move on to the next index.
9328		 * Repeat until loop.
9329		 *  @type array
9330		 */
9331		"asSorting": null,
9332	
9333		/**
9334		 * Flag to indicate if the column is searchable, and thus should be included
9335		 * in the filtering or not.
9336		 *  @type boolean
9337		 */
9338		"bSearchable": null,
9339	
9340		/**
9341		 * Flag to indicate if the column is sortable or not.
9342		 *  @type boolean
9343		 */
9344		"bSortable": null,
9345	
9346		/**
9347		 * Flag to indicate if the column is currently visible in the table or not
9348		 *  @type boolean
9349		 */
9350		"bVisible": null,
9351	
9352		/**
9353		 * Store for manual type assignment using the `column.type` option. This
9354		 * is held in store so we can manipulate the column's `sType` property.
9355		 *  @type string
9356		 *  @default null
9357		 *  @private
9358		 */
9359		"_sManualType": null,
9360	
9361		/**
9362		 * Flag to indicate if HTML5 data attributes should be used as the data
9363		 * source for filtering or sorting. True is either are.
9364		 *  @type boolean
9365		 *  @default false
9366		 *  @private
9367		 */
9368		"_bAttrSrc": false,
9369	
9370		/**
9371		 * Developer definable function that is called whenever a cell is created (Ajax source,
9372		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9373		 * allowing you to modify the DOM element (add background colour for example) when the
9374		 * element is available.
9375		 *  @type function
9376		 *  @param {element} nTd The TD node that has been created
9377		 *  @param {*} sData The Data for the cell
9378		 *  @param {array|object} oData The data for the whole row
9379		 *  @param {int} iRow The row index for the aoData data store
9380		 *  @default null
9381		 */
9382		"fnCreatedCell": null,
9383	
9384		/**
9385		 * Function to get data from a cell in a column. You should <b>never</b>
9386		 * access data directly through _aData internally in DataTables - always use
9387		 * the method attached to this property. It allows mData to function as
9388		 * required. This function is automatically assigned by the column
9389		 * initialisation method
9390		 *  @type function
9391		 *  @param {array|object} oData The data array/object for the array
9392		 *    (i.e. aoData[]._aData)
9393		 *  @param {string} sSpecific The specific data type you want to get -
9394		 *    'display', 'type' 'filter' 'sort'
9395		 *  @returns {*} The data for the cell from the given row's data
9396		 *  @default null
9397		 */
9398		"fnGetData": null,
9399	
9400		/**
9401		 * Function to set data for a cell in the column. You should <b>never</b>
9402		 * set the data directly to _aData internally in DataTables - always use
9403		 * this method. It allows mData to function as required. This function
9404		 * is automatically assigned by the column initialisation method
9405		 *  @type function
9406		 *  @param {array|object} oData The data array/object for the array
9407		 *    (i.e. aoData[]._aData)
9408		 *  @param {*} sValue Value to set
9409		 *  @default null
9410		 */
9411		"fnSetData": null,
9412	
9413		/**
9414		 * Property to read the value for the cells in the column from the data
9415		 * source array / object. If null, then the default content is used, if a
9416		 * function is given then the return from the function is used.
9417		 *  @type function|int|string|null
9418		 *  @default null
9419		 */
9420		"mData": null,
9421	
9422		/**
9423		 * Partner property to mData which is used (only when defined) to get
9424		 * the data - i.e. it is basically the same as mData, but without the
9425		 * 'set' option, and also the data fed to it is the result from mData.
9426		 * This is the rendering method to match the data method of mData.
9427		 *  @type function|int|string|null
9428		 *  @default null
9429		 */
9430		"mRender": null,
9431	
9432		/**
9433		 * Unique header TH/TD element for this column - this is what the sorting
9434		 * listener is attached to (if sorting is enabled.)
9435		 *  @type node
9436		 *  @default null
9437		 */
9438		"nTh": null,
9439	
9440		/**
9441		 * Unique footer TH/TD element for this column (if there is one). Not used
9442		 * in DataTables as such, but can be used for plug-ins to reference the
9443		 * footer for each column.
9444		 *  @type node
9445		 *  @default null
9446		 */
9447		"nTf": null,
9448	
9449		/**
9450		 * The class to apply to all TD elements in the table's TBODY for the column
9451		 *  @type string
9452		 *  @default null
9453		 */
9454		"sClass": null,
9455	
9456		/**
9457		 * When DataTables calculates the column widths to assign to each column,
9458		 * it finds the longest string in each column and then constructs a
9459		 * temporary table and reads the widths from that. The problem with this
9460		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9461		 * string - thus the calculation can go wrong (doing it properly and putting
9462		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9463		 * a "work around" we provide this option. It will append its value to the
9464		 * text that is found to be the longest string for the column - i.e. padding.
9465		 *  @type string
9466		 */
9467		"sContentPadding": null,
9468	
9469		/**
9470		 * Allows a default value to be given for a column's data, and will be used
9471		 * whenever a null data source is encountered (this can be because mData
9472		 * is set to null, or because the data source itself is null).
9473		 *  @type string
9474		 *  @default null
9475		 */
9476		"sDefaultContent": null,
9477	
9478		/**
9479		 * Name for the column, allowing reference to the column by name as well as
9480		 * by index (needs a lookup to work by name).
9481		 *  @type string
9482		 */
9483		"sName": null,
9484	
9485		/**
9486		 * Custom sorting data type - defines which of the available plug-ins in
9487		 * afnSortData the custom sorting will use - if any is defined.
9488		 *  @type string
9489		 *  @default std
9490		 */
9491		"sSortDataType": 'std',
9492	
9493		/**
9494		 * Class to be applied to the header element when sorting on this column
9495		 *  @type string
9496		 *  @default null
9497		 */
9498		"sSortingClass": null,
9499	
9500		/**
9501		 * Class to be applied to the header element when sorting on this column -
9502		 * when jQuery UI theming is used.
9503		 *  @type string
9504		 *  @default null
9505		 */
9506		"sSortingClassJUI": null,
9507	
9508		/**
9509		 * Title of the column - what is seen in the TH element (nTh).
9510		 *  @type string
9511		 */
9512		"sTitle": null,
9513	
9514		/**
9515		 * Column sorting and filtering type
9516		 *  @type string
9517		 *  @default null
9518		 */
9519		"sType": null,
9520	
9521		/**
9522		 * Width of the column
9523		 *  @type string
9524		 *  @default null
9525		 */
9526		"sWidth": null,
9527	
9528		/**
9529		 * Width of the column when it was first "encountered"
9530		 *  @type string
9531		 *  @default null
9532		 */
9533		"sWidthOrig": null
9534	};
9535	
9536	
9537	/*
9538	 * Developer note: The properties of the object below are given in Hungarian
9539	 * notation, that was used as the interface for DataTables prior to v1.10, however
9540	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9541	 * breaking backwards compatibility utterly with this change, the Hungarian
9542	 * version is still, internally the primary interface, but is is not documented
9543	 * - hence the @name tags in each doc comment. This allows a Javascript function
9544	 * to create a map from Hungarian notation to camel case (going the other direction
9545	 * would require each property to be listed, which would at around 3K to the size
9546	 * of DataTables, while this method is about a 0.5K hit
vendor: 16,919 bytes, lines 9546-10057
9546.
9547	 *
9548	 * Ultimately this does pave the way for Hungarian notation to be dropped
9549	 * completely, but that is a massive amount of work and will break current
9550	 * installs (therefore is on-hold until v2).
9551	 */
9552	
9553	/**
9554	 * Initialisation options that can be given to DataTables at initialisation
9555	 * time.
9556	 *  @namespace
9557	 */
9558	DataTable.defaults = {
9559		/**
9560		 * An array of data to use for the table, passed in at initialisation which
9561		 * will be used in preference to any data which is already in the DOM. This is
9562		 * particularly useful for constructing tables purely in Javascript, for
9563		 * example with a custom Ajax call.
9564		 *  @type array
9565		 *  @default null
9566		 *
9567		 *  @dtopt Option
9568		 *  @name DataTable.defaults.data
9569		 *
9570		 *  @example
9571		 *    // Using a 2D array data source
9572		 *    $(document).ready( function () {
9573		 *      $('#example').dataTable( {
9574		 *        "data": [
9575		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9576		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9577		 *        ],
9578		 *        "columns": [
9579		 *          { "title": "Engine" },
9580		 *          { "title": "Browser" },
9581		 *          { "title": "Platform" },
9582		 *          { "title": "Version" },
9583		 *          { "title": "Grade" }
9584		 *        ]
9585		 *      } );
9586		 *    } );
9587		 *
9588		 *  @example
9589		 *    // Using an array of objects as a data source (`data`)
9590		 *    $(document).ready( function () {
9591		 *      $('#example').dataTable( {
9592		 *        "data": [
9593		 *          {
9594		 *            "engine":   "Trident",
9595		 *            "browser":  "Internet Explorer 4.0",
9596		 *            "platform": "Win 95+",
9597		 *            "version":  4,
9598		 *            "grade":    "X"
9599		 *          },
9600		 *          {
9601		 *            "engine":   "Trident",
9602		 *            "browser":  "Internet Explorer 5.0",
9603		 *            "platform": "Win 95+",
9604		 *            "version":  5,
9605		 *            "grade":    "C"
9606		 *          }
9607		 *        ],
9608		 *        "columns": [
9609		 *          { "title": "Engine",   "data": "engine" },
9610		 *          { "title": "Browser",  "data": "browser" },
9611		 *          { "title": "Platform", "data": "platform" },
9612		 *          { "title": "Version",  "data": "version" },
9613		 *          { "title": "Grade",    "data": "grade" }
9614		 *        ]
9615		 *      } );
9616		 *    } );
9617		 */
9618		"aaData": null,
9619	
9620	
9621		/**
9622		 * If ordering is enabled, then DataTables will perform a first pass sort on
9623		 * initialisation. You can define which column(s) the sort is performed
9624		 * upon, and the sorting direction, with this variable. The `sorting` array
9625		 * should contain an array for each column to be sorted initially containing
9626		 * the column's index and a direction string ('asc' or 'desc').
9627		 *  @type array
9628		 *  @default [[0,'asc']]
9629		 *
9630		 *  @dtopt Option
9631		 *  @name DataTable.defaults.order
9632		 *
9633		 *  @example
9634		 *    // Sort by 3rd column first, and then 4th column
9635		 *    $(document).ready( function() {
9636		 *      $('#example').dataTable( {
9637		 *        "order": [[2,'asc'], [3,'desc']]
9638		 *      } );
9639		 *    } );
9640		 *
9641		 *    // No initial sorting
9642		 *    $(document).ready( function() {
9643		 *      $('#example').dataTable( {
9644		 *        "order": []
9645		 *      } );
9646		 *    } );
9647		 */
9648		"aaSorting": [[0,'asc']],
9649	
9650	
9651		/**
9652		 * This parameter is basically identical to the `sorting` parameter, but
9653		 * cannot be overridden by user interaction with the table. What this means
9654		 * is that you could have a column (visible or hidden) which the sorting
9655		 * will always be forced on first - any sorting after that (from the user)
9656		 * will then be performed as required. This can be useful for grouping rows
9657		 * together.
9658		 *  @type array
9659		 *  @default null
9660		 *
9661		 *  @dtopt Option
9662		 *  @name DataTable.defaults.orderFixed
9663		 *
9664		 *  @example
9665		 *    $(document).ready( function() {
9666		 *      $('#example').dataTable( {
9667		 *        "orderFixed": [[0,'asc']]
9668		 *      } );
9669		 *    } )
9670		 */
9671		"aaSortingFixed": [],
9672	
9673	
9674		/**
9675		 * DataTables can be instructed to load data to display in the table from a
9676		 * Ajax source. This option defines how that Ajax call is made and where to.
9677		 *
9678		 * The `ajax` property has three different modes of operation, depending on
9679		 * how it is defined. These are:
9680		 *
9681		 * * `string` - Set the URL from where the data should be loaded from.
9682		 * * `object` - Define properties for `jQuery.ajax`.
9683		 * * `function` - Custom data get function
9684		 *
9685		 * `string`
9686		 * --------
9687		 *
9688		 * As a string, the `ajax` property simply defines the URL from which
9689		 * DataTables will load data.
9690		 *
9691		 * `object`
9692		 * --------
9693		 *
9694		 * As an object, the parameters in the object are passed to
9695		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9696		 * of the Ajax request. DataTables has a number of default parameters which
9697		 * you can override using this option. Please refer to the jQuery
9698		 * documentation for a full description of the options available, although
9699		 * the following parameters provide additional options in DataTables or
9700		 * require special consideration:
9701		 *
9702		 * * `data` - As with jQuery, `data` can be provided as an object, but it
9703		 *   can also be used as a function to manipulate the data DataTables sends
9704		 *   to the server. The function takes a single parameter, an object of
9705		 *   parameters with the values that DataTables has readied for sending. An
9706		 *   object may be returned which will be merged into the DataTables
9707		 *   defaults, or you can add the items to the object that was passed in and
9708		 *   not return anything from the function. This supersedes `fnServerParams`
9709		 *   from DataTables 1.9-.
9710		 *
9711		 * * `dataSrc` - By default DataTables will look for the property `data` (or
9712		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9713		 *   from an Ajax source or for server-side processing - this parameter
9714		 *   allows that property to be changed. You can use Javascript dotted
9715		 *   object notation to get a data source for multiple levels of nesting, or
9716		 *   it my be used as a function. As a function it takes a single parameter,
9717		 *   the JSON returned from the server, which can be manipulated as
9718		 *   required, with the returned value being that used by DataTables as the
9719		 *   data source for the table. This supersedes `sAjaxDataProp` from
9720		 *   DataTables 1.9-.
9721		 *
9722		 * * `success` - Should not be overridden it is used internally in
9723		 *   DataTables. To manipulate / transform the data returned by the server
9724		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9725		 *
9726		 * `function`
9727		 * ----------
9728		 *
9729		 * As a function, making the Ajax call is left up to yourself allowing
9730		 * complete control of the Ajax request. Indeed, if desired, a method other
9731		 * than Ajax could be used to obtain the required data, such as Web storage
9732		 * or an AIR database.
9733		 *
9734		 * The function is given four parameters and no return is required. The
9735		 * parameters are:
9736		 *
9737		 * 1. _object_ - Data to send to the server
9738		 * 2. _function_ - Callback function that must be executed when the required
9739		 *    data has been obtained. That data should be passed into the callback
9740		 *    as the only parameter
9741		 * 3. _object_ - DataTables settings object for the table
9742		 *
9743		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
9744		 *
9745		 *  @type string|object|function
9746		 *  @default null
9747		 *
9748		 *  @dtopt Option
9749		 *  @name DataTable.defaults.ajax
9750		 *  @since 1.10.0
9751		 *
9752		 * @example
9753		 *   // Get JSON data from a file via Ajax.
9754		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9755		 *   $('#example').dataTable( {
9756		 *     "ajax": "data.json"
9757		 *   } );
9758		 *
9759		 * @example
9760		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
9761		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9762		 *   $('#example').dataTable( {
9763		 *     "ajax": {
9764		 *       "url": "data.json",
9765		 *       "dataSrc": "tableData"
9766		 *     }
9767		 *   } );
9768		 *
9769		 * @example
9770		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
9771		 *   // from a plain array rather than an array in an object
9772		 *   $('#example').dataTable( {
9773		 *     "ajax": {
9774		 *       "url": "data.json",
9775		 *       "dataSrc": ""
9776		 *     }
9777		 *   } );
9778		 *
9779		 * @example
9780		 *   // Manipulate the data returned from the server - add a link to data
9781		 *   // (note this can, should, be done using `render` for the column - this
9782		 *   // is just a simple example of how the data can be manipulated).
9783		 *   $('#example').dataTable( {
9784		 *     "ajax": {
9785		 *       "url": "data.json",
9786		 *       "dataSrc": function ( json ) {
9787		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9788		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9789		 *         }
9790		 *         return json;
9791		 *       }
9792		 *     }
9793		 *   } );
9794		 *
9795		 * @example
9796		 *   // Add data to the request
9797		 *   $('#example').dataTable( {
9798		 *     "ajax": {
9799		 *       "url": "data.json",
9800		 *       "data": function ( d ) {
9801		 *         return {
9802		 *           "extra_search": $('#extra').val()
9803		 *         };
9804		 *       }
9805		 *     }
9806		 *   } );
9807		 *
9808		 * @example
9809		 *   // Send request as POST
9810		 *   $('#example').dataTable( {
9811		 *     "ajax": {
9812		 *       "url": "data.json",
9813		 *       "type": "POST"
9814		 *     }
9815		 *   } );
9816		 *
9817		 * @example
9818		 *   // Get the data from localStorage (could interface with a form for
9819		 *   // adding, editing and removing rows).
9820		 *   $('#example').dataTable( {
9821		 *     "ajax": function (data, callback, settings) {
9822		 *       callback(
9823		 *         JSON.parse( localStorage.getItem('dataTablesData') )
9824		 *       );
9825		 *     }
9826		 *   } );
9827		 */
9828		"ajax": null,
9829	
9830	
9831		/**
9832		 * This parameter allows you to readily specify the entries in the length drop
9833		 * down menu that DataTables shows when pagination is enabled. It can be
9834		 * either a 1D array of options which will be used for both the displayed
9835		 * option and the value, or a 2D array which will use the array in the first
9836		 * position as the value, and the array in the second position as the
9837		 * displayed options (useful for language strings such as 'All').
9838		 *
9839		 * Note that the `pageLength` property will be automatically set to the
9840		 * first value given in this array, unless `pageLength` is also provided.
9841		 *  @type array
9842		 *  @default [ 10, 25, 50, 100 ]
9843		 *
9844		 *  @dtopt Option
9845		 *  @name DataTable.defaults.lengthMenu
9846		 *
9847		 *  @example
9848		 *    $(document).ready( function() {
9849		 *      $('#example').dataTable( {
9850		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9851		 *      } );
9852		 *    } );
9853		 */
9854		"aLengthMenu": [ 10, 25, 50, 100 ],
9855	
9856	
9857		/**
9858		 * The `columns` option in the initialisation parameter allows you to define
9859		 * details about the way individual columns behave. For a full list of
9860		 * column options that can be set, please see
9861		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
9862		 * define your columns, you must have an entry in the array for every single
9863		 * column that you have in your table (these can be null if you don't which
9864		 * to specify any options).
9865		 *  @member
9866		 *
9867		 *  @name DataTable.defaults.column
9868		 */
9869		"aoColumns": null,
9870	
9871		/**
9872		 * Very similar to `columns`, `columnDefs` allows you to target a specific
9873		 * column, multiple columns, or all columns, using the `targets` property of
9874		 * each object in the array. This allows great flexibility when creating
9875		 * tables, as the `columnDefs` arrays can be of any length, targeting the
9876		 * columns you specifically want. `columnDefs` may use any of the column
9877		 * options available: {@link DataTable.defaults.column}, but it _must_
9878		 * have `targets` defined in each object in the array. Values in the `targets`
9879		 * array may be:
9880		 *   <ul>
9881		 *     <li>a string - class name will be matched on the TH for the column</li>
9882		 *     <li>0 or a positive integer - column index counting from the left</li>
9883		 *     <li>a negative integer - column index counting from the right</li>
9884		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
9885		 *   </ul>
9886		 *  @member
9887		 *
9888		 *  @name DataTable.defaults.columnDefs
9889		 */
9890		"aoColumnDefs": null,
9891	
9892	
9893		/**
9894		 * Basically the same as `search`, this parameter defines the individual column
9895		 * filtering state at initialisation time. The array must be of the same size
9896		 * as the number of columns, and each element be an object with the parameters
9897		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
9898		 * accepted and the default will be used.
9899		 *  @type array
9900		 *  @default []
9901		 *
9902		 *  @dtopt Option
9903		 *  @name DataTable.defaults.searchCols
9904		 *
9905		 *  @example
9906		 *    $(document).ready( function() {
9907		 *      $('#example').dataTable( {
9908		 *        "searchCols": [
9909		 *          null,
9910		 *          { "search": "My filter" },
9911		 *          null,
9912		 *          { "search": "^[0-9]", "escapeRegex": false }
9913		 *        ]
9914		 *      } );
9915		 *    } )
9916		 */
9917		"aoSearchCols": [],
9918	
9919	
9920		/**
9921		 * An array of CSS classes that should be applied to displayed rows. This
9922		 * array may be of any length, and DataTables will apply each class
9923		 * sequentially, looping when required.
9924		 *  @type array
9925		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
9926		 *    options</i>
9927		 *
9928		 *  @dtopt Option
9929		 *  @name DataTable.defaults.stripeClasses
9930		 *
9931		 *  @example
9932		 *    $(document).ready( function() {
9933		 *      $('#example').dataTable( {
9934		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
9935		 *      } );
9936		 *    } )
9937		 */
9938		"asStripeClasses": null,
9939	
9940	
9941		/**
9942		 * Enable or disable automatic column width calculation. This can be disabled
9943		 * as an optimisation (it takes some time to calculate the widths) if the
9944		 * tables widths are passed in using `columns`.
9945		 *  @type boolean
9946		 *  @default true
9947		 *
9948		 *  @dtopt Features
9949		 *  @name DataTable.defaults.autoWidth
9950		 *
9951		 *  @example
9952		 *    $(document).ready( function () {
9953		 *      $('#example').dataTable( {
9954		 *        "autoWidth": false
9955		 *      } );
9956		 *    } );
9957		 */
9958		"bAutoWidth": true,
9959	
9960	
9961		/**
9962		 * Deferred rendering can provide DataTables with a huge speed boost when you
9963		 * are using an Ajax or JS data source for the table. This option, when set to
9964		 * true, will cause DataTables to defer the creation of the table elements for
9965		 * each row until they are needed for a draw - saving a significant amount of
9966		 * time.
9967		 *  @type boolean
9968		 *  @default false
9969		 *
9970		 *  @dtopt Features
9971		 *  @name DataTable.defaults.deferRender
9972		 *
9973		 *  @example
9974		 *    $(document).ready( function() {
9975		 *      $('#example').dataTable( {
9976		 *        "ajax": "sources/arrays.txt",
9977		 *        "deferRender": true
9978		 *      } );
9979		 *    } );
9980		 */
9981		"bDeferRender": false,
9982	
9983	
9984		/**
9985		 * Replace a DataTable which matches the given selector and replace it with
9986		 * one which has the properties of the new initialisation object passed. If no
9987		 * table matches the selector, then the new DataTable will be constructed as
9988		 * per normal.
9989		 *  @type boolean
9990		 *  @default false
9991		 *
9992		 *  @dtopt Options
9993		 *  @name DataTable.defaults.destroy
9994		 *
9995		 *  @example
9996		 *    $(document).ready( function() {
9997		 *      $('#example').dataTable( {
9998		 *        "srollY": "200px",
9999		 *        "paginate": false
10000		 *      } );
10001		 *
10002		 *      // Some time later....
10003		 *      $('#example').dataTable( {
10004		 *        "filter": false,
10005		 *        "destroy": true
10006		 *      } );
10007		 *    } );
10008		 */
10009		"bDestroy": false,
10010	
10011	
10012		/**
10013		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10014		 * that it allows the end user to input multiple words (space separated) and
10015		 * will match a row containing those words, even if not in the order that was
10016		 * specified (this allow matching across multiple columns). Note that if you
10017		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10018		 * default filtering input box and retain filtering abilities, please use
10019		 * {@link DataTable.defaults.dom}.
10020		 *  @type boolean
10021		 *  @default true
10022		 *
10023		 *  @dtopt Features
10024		 *  @name DataTable.defaults.searching
10025		 *
10026		 *  @example
10027		 *    $(document).ready( function () {
10028		 *      $('#example').dataTable( {
10029		 *        "searching": false
10030		 *      } );
10031		 *    } );
10032		 */
10033		"bFilter": true,
10034	
10035	
10036		/**
10037		 * Enable or disable the table information display. This shows information
10038		 * about the data that is currently visible on the page, including information
10039		 * about filtered data if that action is being performed.
10040		 *  @type boolean
10041		 *  @default true
10042		 *
10043		 *  @dtopt Features
10044		 *  @name DataTable.defaults.info
10045		 *
10046		 *  @example
10047		 *    $(document).ready( function () {
10048		 *      $('#example').dataTable( {
10049		 *        "info": false
10050		 *      } );
10051		 *    } );
10052		 */
10053		"bInfo": true,
10054	
10055	
10056		/**
10057		 * 
10057Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
10058		 * slightly different and additional mark-up from what DataTables has
10059		 * traditionally used).
10060		 *  @type boolean
10061		 *  @default false
10062		 *
10063		 *  @dtopt Features
10064		 *  @name DataTable.defaults.jQueryUI
10065		 *
10066		 *  @example
10067		 *    $(document).ready( function() {
10068		 *      $('#example').dataTable( {
10069		 *        "jQueryUI": true
10070		 *      } );
10071		 *    } );
10072		 */
10073		"bJQueryUI": fals
vendor: 18,080 bytes, lines 10073-10635
10073e,
10074	
10075	
10076		/**
10077		 * Allows the end user to select the size of a formatted page from a select
10078		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10079		 *  @type boolean
10080		 *  @default true
10081		 *
10082		 *  @dtopt Features
10083		 *  @name DataTable.defaults.lengthChange
10084		 *
10085		 *  @example
10086		 *    $(document).ready( function () {
10087		 *      $('#example').dataTable( {
10088		 *        "lengthChange": false
10089		 *      } );
10090		 *    } );
10091		 */
10092		"bLengthChange": true,
10093	
10094	
10095		/**
10096		 * Enable or disable pagination.
10097		 *  @type boolean
10098		 *  @default true
10099		 *
10100		 *  @dtopt Features
10101		 *  @name DataTable.defaults.paging
10102		 *
10103		 *  @example
10104		 *    $(document).ready( function () {
10105		 *      $('#example').dataTable( {
10106		 *        "paging": false
10107		 *      } );
10108		 *    } );
10109		 */
10110		"bPaginate": true,
10111	
10112	
10113		/**
10114		 * Enable or disable the display of a 'processing' indicator when the table is
10115		 * being processed (e.g. a sort). This is particularly useful for tables with
10116		 * large amounts of data where it can take a noticeable amount of time to sort
10117		 * the entries.
10118		 *  @type boolean
10119		 *  @default false
10120		 *
10121		 *  @dtopt Features
10122		 *  @name DataTable.defaults.processing
10123		 *
10124		 *  @example
10125		 *    $(document).ready( function () {
10126		 *      $('#example').dataTable( {
10127		 *        "processing": true
10128		 *      } );
10129		 *    } );
10130		 */
10131		"bProcessing": false,
10132	
10133	
10134		/**
10135		 * Retrieve the DataTables object for the given selector. Note that if the
10136		 * table has already been initialised, this parameter will cause DataTables
10137		 * to simply return the object that has already been set up - it will not take
10138		 * account of any changes you might have made to the initialisation object
10139		 * passed to DataTables (setting this parameter to true is an acknowledgement
10140		 * that you understand this). `destroy` can be used to reinitialise a table if
10141		 * you need.
10142		 *  @type boolean
10143		 *  @default false
10144		 *
10145		 *  @dtopt Options
10146		 *  @name DataTable.defaults.retrieve
10147		 *
10148		 *  @example
10149		 *    $(document).ready( function() {
10150		 *      initTable();
10151		 *      tableActions();
10152		 *    } );
10153		 *
10154		 *    function initTable ()
10155		 *    {
10156		 *      return $('#example').dataTable( {
10157		 *        "scrollY": "200px",
10158		 *        "paginate": false,
10159		 *        "retrieve": true
10160		 *      } );
10161		 *    }
10162		 *
10163		 *    function tableActions ()
10164		 *    {
10165		 *      var table = initTable();
10166		 *      // perform API operations with oTable
10167		 *    }
10168		 */
10169		"bRetrieve": false,
10170	
10171	
10172		/**
10173		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10174		 * the table's viewport to the given height at all times (useful for layout).
10175		 * However, this can look odd when filtering data down to a small data set,
10176		 * and the footer is left "floating" further down. This parameter (when
10177		 * enabled) will cause DataTables to collapse the table's viewport down when
10178		 * the result set will fit within the given Y height.
10179		 *  @type boolean
10180		 *  @default false
10181		 *
10182		 *  @dtopt Options
10183		 *  @name DataTable.defaults.scrollCollapse
10184		 *
10185		 *  @example
10186		 *    $(document).ready( function() {
10187		 *      $('#example').dataTable( {
10188		 *        "scrollY": "200",
10189		 *        "scrollCollapse": true
10190		 *      } );
10191		 *    } );
10192		 */
10193		"bScrollCollapse": false,
10194	
10195	
10196		/**
10197		 * Configure DataTables to use server-side processing. Note that the
10198		 * `ajax` parameter must also be given in order to give DataTables a
10199		 * source to obtain the required data for each draw.
10200		 *  @type boolean
10201		 *  @default false
10202		 *
10203		 *  @dtopt Features
10204		 *  @dtopt Server-side
10205		 *  @name DataTable.defaults.serverSide
10206		 *
10207		 *  @example
10208		 *    $(document).ready( function () {
10209		 *      $('#example').dataTable( {
10210		 *        "serverSide": true,
10211		 *        "ajax": "xhr.php"
10212		 *      } );
10213		 *    } );
10214		 */
10215		"bServerSide": false,
10216	
10217	
10218		/**
10219		 * Enable or disable sorting of columns. Sorting of individual columns can be
10220		 * disabled by the `sortable` option for each column.
10221		 *  @type boolean
10222		 *  @default true
10223		 *
10224		 *  @dtopt Features
10225		 *  @name DataTable.defaults.ordering
10226		 *
10227		 *  @example
10228		 *    $(document).ready( function () {
10229		 *      $('#example').dataTable( {
10230		 *        "ordering": false
10231		 *      } );
10232		 *    } );
10233		 */
10234		"bSort": true,
10235	
10236	
10237		/**
10238		 * Enable or display DataTables' ability to sort multiple columns at the
10239		 * same time (activated by shift-click by the user).
10240		 *  @type boolean
10241		 *  @default true
10242		 *
10243		 *  @dtopt Options
10244		 *  @name DataTable.defaults.orderMulti
10245		 *
10246		 *  @example
10247		 *    // Disable multiple column sorting ability
10248		 *    $(document).ready( function () {
10249		 *      $('#example').dataTable( {
10250		 *        "orderMulti": false
10251		 *      } );
10252		 *    } );
10253		 */
10254		"bSortMulti": true,
10255	
10256	
10257		/**
10258		 * Allows control over whether DataTables should use the top (true) unique
10259		 * cell that is found for a single column, or the bottom (false - default).
10260		 * This is useful when using complex headers.
10261		 *  @type boolean
10262		 *  @default false
10263		 *
10264		 *  @dtopt Options
10265		 *  @name DataTable.defaults.orderCellsTop
10266		 *
10267		 *  @example
10268		 *    $(document).ready( function() {
10269		 *      $('#example').dataTable( {
10270		 *        "orderCellsTop": true
10271		 *      } );
10272		 *    } );
10273		 */
10274		"bSortCellsTop": false,
10275	
10276	
10277		/**
10278		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10279		 * `sorting\_3` to the columns which are currently being sorted on. This is
10280		 * presented as a feature switch as it can increase processing time (while
10281		 * classes are removed and added) so for large data sets you might want to
10282		 * turn this off.
10283		 *  @type boolean
10284		 *  @default true
10285		 *
10286		 *  @dtopt Features
10287		 *  @name DataTable.defaults.orderClasses
10288		 *
10289		 *  @example
10290		 *    $(document).ready( function () {
10291		 *      $('#example').dataTable( {
10292		 *        "orderClasses": false
10293		 *      } );
10294		 *    } );
10295		 */
10296		"bSortClasses": true,
10297	
10298	
10299		/**
10300		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10301		 * used to save table display information such as pagination information,
10302		 * display length, filtering and sorting. As such when the end user reloads
10303		 * the page the display display will match what thy had previously set up.
10304		 *
10305		 * Due to the use of `localStorage` the default state saving is not supported
10306		 * in IE6 or 7. If state saving is required in those browsers, use
10307		 * `stateSaveCallback` to provide a storage solution such as cookies.
10308		 *  @type boolean
10309		 *  @default false
10310		 *
10311		 *  @dtopt Features
10312		 *  @name DataTable.defaults.stateSave
10313		 *
10314		 *  @example
10315		 *    $(document).ready( function () {
10316		 *      $('#example').dataTable( {
10317		 *        "stateSave": true
10318		 *      } );
10319		 *    } );
10320		 */
10321		"bStateSave": false,
10322	
10323	
10324		/**
10325		 * This function is called when a TR element is created (and all TD child
10326		 * elements have been inserted), or registered if using a DOM source, allowing
10327		 * manipulation of the TR element (adding classes etc).
10328		 *  @type function
10329		 *  @param {node} row "TR" element for the current row
10330		 *  @param {array} data Raw data array for this row
10331		 *  @param {int} dataIndex The index of this row in the internal aoData array
10332		 *
10333		 *  @dtopt Callbacks
10334		 *  @name DataTable.defaults.createdRow
10335		 *
10336		 *  @example
10337		 *    $(document).ready( function() {
10338		 *      $('#example').dataTable( {
10339		 *        "createdRow": function( row, data, dataIndex ) {
10340		 *          // Bold the grade for all 'A' grade browsers
10341		 *          if ( data[4] == "A" )
10342		 *          {
10343		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10344		 *          }
10345		 *        }
10346		 *      } );
10347		 *    } );
10348		 */
10349		"fnCreatedRow": null,
10350	
10351	
10352		/**
10353		 * This function is called on every 'draw' event, and allows you to
10354		 * dynamically modify any aspect you want about the created DOM.
10355		 *  @type function
10356		 *  @param {object} settings DataTables settings object
10357		 *
10358		 *  @dtopt Callbacks
10359		 *  @name DataTable.defaults.drawCallback
10360		 *
10361		 *  @example
10362		 *    $(document).ready( function() {
10363		 *      $('#example').dataTable( {
10364		 *        "drawCallback": function( settings ) {
10365		 *          alert( 'DataTables has redrawn the table' );
10366		 *        }
10367		 *      } );
10368		 *    } );
10369		 */
10370		"fnDrawCallback": null,
10371	
10372	
10373		/**
10374		 * Identical to fnHeaderCallback() but for the table footer this function
10375		 * allows you to modify the table footer on every 'draw' event.
10376		 *  @type function
10377		 *  @param {node} foot "TR" element for the footer
10378		 *  @param {array} data Full table data (as derived from the original HTML)
10379		 *  @param {int} start Index for the current display starting point in the
10380		 *    display array
10381		 *  @param {int} end Index for the current display ending point in the
10382		 *    display array
10383		 *  @param {array int} display Index array to translate the visual position
10384		 *    to the full data array
10385		 *
10386		 *  @dtopt Callbacks
10387		 *  @name DataTable.defaults.footerCallback
10388		 *
10389		 *  @example
10390		 *    $(document).ready( function() {
10391		 *      $('#example').dataTable( {
10392		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10393		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10394		 *        }
10395		 *      } );
10396		 *    } )
10397		 */
10398		"fnFooterCallback": null,
10399	
10400	
10401		/**
10402		 * When rendering large numbers in the information element for the table
10403		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10404		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10405		 * rendered as "1,000,000") to help readability for the end user. This
10406		 * function will override the default method DataTables uses.
10407		 *  @type function
10408		 *  @member
10409		 *  @param {int} toFormat number to be formatted
10410		 *  @returns {string} formatted string for DataTables to show the number
10411		 *
10412		 *  @dtopt Callbacks
10413		 *  @name DataTable.defaults.formatNumber
10414		 *
10415		 *  @example
10416		 *    // Format a number using a single quote for the separator (note that
10417		 *    // this can also be done with the language.thousands option)
10418		 *    $(document).ready( function() {
10419		 *      $('#example').dataTable( {
10420		 *        "formatNumber": function ( toFormat ) {
10421		 *          return toFormat.toString().replace(
10422		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10423		 *          );
10424		 *        };
10425		 *      } );
10426		 *    } );
10427		 */
10428		"fnFormatNumber": function ( toFormat ) {
10429			return toFormat.toString().replace(
10430				/\B(?=(\d{3})+(?!\d))/g,
10431				this.oLanguage.sThousands
10432			);
10433		},
10434	
10435	
10436		/**
10437		 * This function is called on every 'draw' event, and allows you to
10438		 * dynamically modify the header row. This can be used to calculate and
10439		 * display useful information about the table.
10440		 *  @type function
10441		 *  @param {node} head "TR" element for the header
10442		 *  @param {array} data Full table data (as derived from the original HTML)
10443		 *  @param {int} start Index for the current display starting point in the
10444		 *    display array
10445		 *  @param {int} end Index for the current display ending point in the
10446		 *    display array
10447		 *  @param {array int} display Index array to translate the visual position
10448		 *    to the full data array
10449		 *
10450		 *  @dtopt Callbacks
10451		 *  @name DataTable.defaults.headerCallback
10452		 *
10453		 *  @example
10454		 *    $(document).ready( function() {
10455		 *      $('#example').dataTable( {
10456		 *        "fheaderCallback": function( head, data, start, end, display ) {
10457		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10458		 *        }
10459		 *      } );
10460		 *    } )
10461		 */
10462		"fnHeaderCallback": null,
10463	
10464	
10465		/**
10466		 * The information element can be used to convey information about the current
10467		 * state of the table. Although the internationalisation options presented by
10468		 * DataTables are quite capable of dealing with most customisations, there may
10469		 * be times where you wish to customise the string further. This callback
10470		 * allows you to do exactly that.
10471		 *  @type function
10472		 *  @param {object} oSettings DataTables settings object
10473		 *  @param {int} start Starting position in data for the draw
10474		 *  @param {int} end End position in data for the draw
10475		 *  @param {int} max Total number of rows in the table (regardless of
10476		 *    filtering)
10477		 *  @param {int} total Total number of rows in the data set, after filtering
10478		 *  @param {string} pre The string that DataTables has formatted using it's
10479		 *    own rules
10480		 *  @returns {string} The string to be displayed in the information element.
10481		 *
10482		 *  @dtopt Callbacks
10483		 *  @name DataTable.defaults.infoCallback
10484		 *
10485		 *  @example
10486		 *    $('#example').dataTable( {
10487		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10488		 *        return start +" to "+ end;
10489		 *      }
10490		 *    } );
10491		 */
10492		"fnInfoCallback": null,
10493	
10494	
10495		/**
10496		 * Called when the table has been initialised. Normally DataTables will
10497		 * initialise sequentially and there will be no need for this function,
10498		 * however, this does not hold true when using external language information
10499		 * since that is obtained using an async XHR call.
10500		 *  @type function
10501		 *  @param {object} settings DataTables settings object
10502		 *  @param {object} json The JSON object request from the server - only
10503		 *    present if client-side Ajax sourced data is used
10504		 *
10505		 *  @dtopt Callbacks
10506		 *  @name DataTable.defaults.initComplete
10507		 *
10508		 *  @example
10509		 *    $(document).ready( function() {
10510		 *      $('#example').dataTable( {
10511		 *        "initComplete": function(settings, json) {
10512		 *          alert( 'DataTables has finished its initialisation.' );
10513		 *        }
10514		 *      } );
10515		 *    } )
10516		 */
10517		"fnInitComplete": null,
10518	
10519	
10520		/**
10521		 * Called at the very start of each table draw and can be used to cancel the
10522		 * draw by returning false, any other return (including undefined) results in
10523		 * the full draw occurring).
10524		 *  @type function
10525		 *  @param {object} settings DataTables settings object
10526		 *  @returns {boolean} False will cancel the draw, anything else (including no
10527		 *    return) will allow it to complete.
10528		 *
10529		 *  @dtopt Callbacks
10530		 *  @name DataTable.defaults.preDrawCallback
10531		 *
10532		 *  @example
10533		 *    $(document).ready( function() {
10534		 *      $('#example').dataTable( {
10535		 *        "preDrawCallback": function( settings ) {
10536		 *          if ( $('#test').val() == 1 ) {
10537		 *            return false;
10538		 *          }
10539		 *        }
10540		 *      } );
10541		 *    } );
10542		 */
10543		"fnPreDrawCallback": null,
10544	
10545	
10546		/**
10547		 * This function allows you to 'post process' each row after it have been
10548		 * generated for each table draw, but before it is rendered on screen. This
10549		 * function might be used for setting the row class name etc.
10550		 *  @type function
10551		 *  @param {node} row "TR" element for the current row
10552		 *  @param {array} data Raw data array for this row
10553		 *  @param {int} displayIndex The display index for the current table draw
10554		 *  @param {int} displayIndexFull The index of the data in the full list of
10555		 *    rows (after filtering)
10556		 *
10557		 *  @dtopt Callbacks
10558		 *  @name DataTable.defaults.rowCallback
10559		 *
10560		 *  @example
10561		 *    $(document).ready( function() {
10562		 *      $('#example').dataTable( {
10563		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10564		 *          // Bold the grade for all 'A' grade browsers
10565		 *          if ( data[4] == "A" ) {
10566		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10567		 *          }
10568		 *        }
10569		 *      } );
10570		 *    } );
10571		 */
10572		"fnRowCallback": null,
10573	
10574	
10575		/**
10576		 * __Deprecated__ The functionality provided by this parameter has now been
10577		 * superseded by that provided through `ajax`, which should be used instead.
10578		 *
10579		 * This parameter allows you to override the default function which obtains
10580		 * the data from the server so something more suitable for your application.
10581		 * For example you could use POST data, or pull information from a Gears or
10582		 * AIR database.
10583		 *  @type function
10584		 *  @member
10585		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10586		 *  @param {array} data A key/value pair object containing the data to send
10587		 *    to the server
10588		 *  @param {function} callback to be called on completion of the data get
10589		 *    process that will draw the data on the page.
10590		 *  @param {object} settings DataTables settings object
10591		 *
10592		 *  @dtopt Callbacks
10593		 *  @dtopt Server-side
10594		 *  @name DataTable.defaults.serverData
10595		 *
10596		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10597		 */
10598		"fnServerData": null,
10599	
10600	
10601		/**
10602		 * __Deprecated__ The functionality provided by this parameter has now been
10603		 * superseded by that provided through `ajax`, which should be used instead.
10604		 *
10605		 *  It is often useful to send extra data to the server when making an Ajax
10606		 * request - for example custom filtering information, and this callback
10607		 * function makes it trivial to send extra information to the server. The
10608		 * passed in parameter is the data set that has been constructed by
10609		 * DataTables, and you can add to this or modify it as you require.
10610		 *  @type function
10611		 *  @param {array} data Data array (array of objects which are name/value
10612		 *    pairs) that has been constructed by DataTables and will be sent to the
10613		 *    server. In the case of Ajax sourced data with server-side processing
10614		 *    this will be an empty array, for server-side processing there will be a
10615		 *    significant number of parameters!
10616		 *  @returns {undefined} Ensure that you modify the data array passed in,
10617		 *    as this is passed by reference.
10618		 *
10619		 *  @dtopt Callbacks
10620		 *  @dtopt Server-side
10621		 *  @name DataTable.defaults.serverParams
10622		 *
10623		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10624		 */
10625		"fnServerParams": null,
10626	
10627	
10628		/**
10629		 * Load the table state. With this function you can define from where, and how, the
10630		 * state of a table is loaded. By default DataTables will load from `localStorage`
10631		 * but you might wish to use a server-side database or cookies.
10632		 *  @type function
10633		 *  @member
10634		 *  @param {object} settings DataTables settings object
10635		 *  @
10635return {object} The DataTables state object to be loaded
10636		 *
10637		 *  @dtopt Callbacks
10638		 *  @name DataTable.defaults.stateLoadCallback
10639		 *
10640		 *  @example
10641		 *    $(document).ready( function() {
10642		 *      $('#example').dataTable( {
10643		 *        "stateSave": true,
10644		 *        "stateLoadCallback": function (settings) {
10645		 *          var o;
10646		 *
10647		 *          // Send an Ajax request to the server to get the data. Note that
10648		 *          // this is a synchronous request.
10649		 *          $.ajax( {
10650		 *            "url": "/state_load",
10651		 *            "async": false,
10652		 *            "dataType": "json",
10653		 *            "success": function (json) {
10654		 *              o = json;
10655		 *            }
10656		 *          } );
10657		 *
10658		 *          return o;
10659		 *        }
10660		 *      } );
10661		 *    } );
10662		 */
10663		"fnStateLoadCallback": function ( settings ) {
10664			try {
10665				return JSON.parse(
10666					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10667						'DataTables_'+settings.sInstance+'_'+location.pathname
10668					)
10669				);
10670			} catch (e) {
vendor: 21,139 bytes, lines 10670-11347
10670}
10671		},
10672	
10673	
10674		/**
10675		 * Callback which allows modification of the saved state prior to loading that state.
10676		 * This callback is called when the table is loading state from the stored data, but
10677		 * prior to the settings object being modified by the saved state. Note that for
10678		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10679		 * a plug-in.
10680		 *  @type function
10681		 *  @param {object} settings DataTables settings object
10682		 *  @param {object} data The state object that is to be loaded
10683		 *
10684		 *  @dtopt Callbacks
10685		 *  @name DataTable.defaults.stateLoadParams
10686		 *
10687		 *  @example
10688		 *    // Remove a saved filter, so filtering is never loaded
10689		 *    $(document).ready( function() {
10690		 *      $('#example').dataTable( {
10691		 *        "stateSave": true,
10692		 *        "stateLoadParams": function (settings, data) {
10693		 *          data.oSearch.sSearch = "";
10694		 *        }
10695		 *      } );
10696		 *    } );
10697		 *
10698		 *  @example
10699		 *    // Disallow state loading by returning false
10700		 *    $(document).ready( function() {
10701		 *      $('#example').dataTable( {
10702		 *        "stateSave": true,
10703		 *        "stateLoadParams": function (settings, data) {
10704		 *          return false;
10705		 *        }
10706		 *      } );
10707		 *    } );
10708		 */
10709		"fnStateLoadParams": null,
10710	
10711	
10712		/**
10713		 * Callback that is called when the state has been loaded from the state saving method
10714		 * and the DataTables settings object has been modified as a result of the loaded state.
10715		 *  @type function
10716		 *  @param {object} settings DataTables settings object
10717		 *  @param {object} data The state object that was loaded
10718		 *
10719		 *  @dtopt Callbacks
10720		 *  @name DataTable.defaults.stateLoaded
10721		 *
10722		 *  @example
10723		 *    // Show an alert with the filtering value that was saved
10724		 *    $(document).ready( function() {
10725		 *      $('#example').dataTable( {
10726		 *        "stateSave": true,
10727		 *        "stateLoaded": function (settings, data) {
10728		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10729		 *        }
10730		 *      } );
10731		 *    } );
10732		 */
10733		"fnStateLoaded": null,
10734	
10735	
10736		/**
10737		 * Save the table state. This function allows you to define where and how the state
10738		 * information for the table is stored By default DataTables will use `localStorage`
10739		 * but you might wish to use a server-side database or cookies.
10740		 *  @type function
10741		 *  @member
10742		 *  @param {object} settings DataTables settings object
10743		 *  @param {object} data The state object to be saved
10744		 *
10745		 *  @dtopt Callbacks
10746		 *  @name DataTable.defaults.stateSaveCallback
10747		 *
10748		 *  @example
10749		 *    $(document).ready( function() {
10750		 *      $('#example').dataTable( {
10751		 *        "stateSave": true,
10752		 *        "stateSaveCallback": function (settings, data) {
10753		 *          // Send an Ajax request to the server with the state object
10754		 *          $.ajax( {
10755		 *            "url": "/state_save",
10756		 *            "data": data,
10757		 *            "dataType": "json",
10758		 *            "method": "POST"
10759		 *            "success": function () {}
10760		 *          } );
10761		 *        }
10762		 *      } );
10763		 *    } );
10764		 */
10765		"fnStateSaveCallback": function ( settings, data ) {
10766			try {
10767				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
10768					'DataTables_'+settings.sInstance+'_'+location.pathname,
10769					JSON.stringify( data )
10770				);
10771			} catch (e) {}
10772		},
10773	
10774	
10775		/**
10776		 * Callback which allows modification of the state to be saved. Called when the table
10777		 * has changed state a new state save is required. This method allows modification of
10778		 * the state saving object prior to actually doing the save, including addition or
10779		 * other state properties or modification. Note that for plug-in authors, you should
10780		 * use the `stateSaveParams` event to save parameters for a plug-in.
10781		 *  @type function
10782		 *  @param {object} settings DataTables settings object
10783		 *  @param {object} data The state object to be saved
10784		 *
10785		 *  @dtopt Callbacks
10786		 *  @name DataTable.defaults.stateSaveParams
10787		 *
10788		 *  @example
10789		 *    // Remove a saved filter, so filtering is never saved
10790		 *    $(document).ready( function() {
10791		 *      $('#example').dataTable( {
10792		 *        "stateSave": true,
10793		 *        "stateSaveParams": function (settings, data) {
10794		 *          data.oSearch.sSearch = "";
10795		 *        }
10796		 *      } );
10797		 *    } );
10798		 */
10799		"fnStateSaveParams": null,
10800	
10801	
10802		/**
10803		 * Duration for which the saved state information is considered valid. After this period
10804		 * has elapsed the state will be returned to the default.
10805		 * Value is given in seconds.
10806		 *  @type int
10807		 *  @default 7200 <i>(2 hours)</i>
10808		 *
10809		 *  @dtopt Options
10810		 *  @name DataTable.defaults.stateDuration
10811		 *
10812		 *  @example
10813		 *    $(document).ready( function() {
10814		 *      $('#example').dataTable( {
10815		 *        "stateDuration": 60*60*24; // 1 day
10816		 *      } );
10817		 *    } )
10818		 */
10819		"iStateDuration": 7200,
10820	
10821	
10822		/**
10823		 * When enabled DataTables will not make a request to the server for the first
10824		 * page draw - rather it will use the data already on the page (no sorting etc
10825		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10826		 * is used to indicate that deferred loading is required, but it is also used
10827		 * to tell DataTables how many records there are in the full table (allowing
10828		 * the information element and pagination to be displayed correctly). In the case
10829		 * where a filtering is applied to the table on initial load, this can be
10830		 * indicated by giving the parameter as an array, where the first element is
10831		 * the number of records available after filtering and the second element is the
10832		 * number of records without filtering (allowing the table information element
10833		 * to be shown correctly).
10834		 *  @type int | array
10835		 *  @default null
10836		 *
10837		 *  @dtopt Options
10838		 *  @name DataTable.defaults.deferLoading
10839		 *
10840		 *  @example
10841		 *    // 57 records available in the table, no filtering applied
10842		 *    $(document).ready( function() {
10843		 *      $('#example').dataTable( {
10844		 *        "serverSide": true,
10845		 *        "ajax": "scripts/server_processing.php",
10846		 *        "deferLoading": 57
10847		 *      } );
10848		 *    } );
10849		 *
10850		 *  @example
10851		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
10852		 *    $(document).ready( function() {
10853		 *      $('#example').dataTable( {
10854		 *        "serverSide": true,
10855		 *        "ajax": "scripts/server_processing.php",
10856		 *        "deferLoading": [ 57, 100 ],
10857		 *        "search": {
10858		 *          "search": "my_filter"
10859		 *        }
10860		 *      } );
10861		 *    } );
10862		 */
10863		"iDeferLoading": null,
10864	
10865	
10866		/**
10867		 * Number of rows to display on a single page when using pagination. If
10868		 * feature enabled (`lengthChange`) then the end user will be able to override
10869		 * this to a custom setting using a pop-up menu.
10870		 *  @type int
10871		 *  @default 10
10872		 *
10873		 *  @dtopt Options
10874		 *  @name DataTable.defaults.pageLength
10875		 *
10876		 *  @example
10877		 *    $(document).ready( function() {
10878		 *      $('#example').dataTable( {
10879		 *        "pageLength": 50
10880		 *      } );
10881		 *    } )
10882		 */
10883		"iDisplayLength": 10,
10884	
10885	
10886		/**
10887		 * Define the starting point for data display when using DataTables with
10888		 * pagination. Note that this parameter is the number of records, rather than
10889		 * the page number, so if you have 10 records per page and want to start on
10890		 * the third page, it should be "20".
10891		 *  @type int
10892		 *  @default 0
10893		 *
10894		 *  @dtopt Options
10895		 *  @name DataTable.defaults.displayStart
10896		 *
10897		 *  @example
10898		 *    $(document).ready( function() {
10899		 *      $('#example').dataTable( {
10900		 *        "displayStart": 20
10901		 *      } );
10902		 *    } )
10903		 */
10904		"iDisplayStart": 0,
10905	
10906	
10907		/**
10908		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
10909		 * and filtering) by adding a `tabindex` attribute to the required elements. This
10910		 * allows you to tab through the controls and press the enter key to activate them.
10911		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
10912		 * You can overrule this using this parameter if you wish. Use a value of -1 to
10913		 * disable built-in keyboard navigation.
10914		 *  @type int
10915		 *  @default 0
10916		 *
10917		 *  @dtopt Options
10918		 *  @name DataTable.defaults.tabIndex
10919		 *
10920		 *  @example
10921		 *    $(document).ready( function() {
10922		 *      $('#example').dataTable( {
10923		 *        "tabIndex": 1
10924		 *      } );
10925		 *    } );
10926		 */
10927		"iTabIndex": 0,
10928	
10929	
10930		/**
10931		 * Classes that DataTables assigns to the various components and features
10932		 * that it adds to the HTML table. This allows classes to be configured
10933		 * during initialisation in addition to through the static
10934		 * {@link DataTable.ext.oStdClasses} object).
10935		 *  @namespace
10936		 *  @name DataTable.defaults.classes
10937		 */
10938		"oClasses": {},
10939	
10940	
10941		/**
10942		 * All strings that DataTables uses in the user interface that it creates
10943		 * are defined in this object, allowing you to modified them individually or
10944		 * completely replace them all as required.
10945		 *  @namespace
10946		 *  @name DataTable.defaults.language
10947		 */
10948		"oLanguage": {
10949			/**
10950			 * Strings that are used for WAI-ARIA labels and controls only (these are not
10951			 * actually visible on the page, but will be read by screenreaders, and thus
10952			 * must be internationalised as well).
10953			 *  @namespace
10954			 *  @name DataTable.defaults.language.aria
10955			 */
10956			"oAria": {
10957				/**
10958				 * ARIA label that is added to the table headers when the column may be
10959				 * sorted ascending by activing the column (click or return when focused).
10960				 * Note that the column header is prefixed to this string.
10961				 *  @type string
10962				 *  @default : activate to sort column ascending
10963				 *
10964				 *  @dtopt Language
10965				 *  @name DataTable.defaults.language.aria.sortAscending
10966				 *
10967				 *  @example
10968				 *    $(document).ready( function() {
10969				 *      $('#example').dataTable( {
10970				 *        "language": {
10971				 *          "aria": {
10972				 *            "sortAscending": " - click/return to sort ascending"
10973				 *          }
10974				 *        }
10975				 *      } );
10976				 *    } );
10977				 */
10978				"sSortAscending": ": activate to sort column ascending",
10979	
10980				/**
10981				 * ARIA label that is added to the table headers when the column may be
10982				 * sorted descending by activing the column (click or return when focused).
10983				 * Note that the column header is prefixed to this string.
10984				 *  @type string
10985				 *  @default : activate to sort column ascending
10986				 *
10987				 *  @dtopt Language
10988				 *  @name DataTable.defaults.language.aria.sortDescending
10989				 *
10990				 *  @example
10991				 *    $(document).ready( function() {
10992				 *      $('#example').dataTable( {
10993				 *        "language": {
10994				 *          "aria": {
10995				 *            "sortDescending": " - click/return to sort descending"
10996				 *          }
10997				 *        }
10998				 *      } );
10999				 *    } );
11000				 */
11001				"sSortDescending": ": activate to sort column descending"
11002			},
11003	
11004			/**
11005			 * Pagination string used by DataTables for the built-in pagination
11006			 * control types.
11007			 *  @namespace
11008			 *  @name DataTable.defaults.language.paginate
11009			 */
11010			"oPaginate": {
11011				/**
11012				 * Text to use when using the 'full_numbers' type of pagination for the
11013				 * button to take the user to the first page.
11014				 *  @type string
11015				 *  @default First
11016				 *
11017				 *  @dtopt Language
11018				 *  @name DataTable.defaults.language.paginate.first
11019				 *
11020				 *  @example
11021				 *    $(document).ready( function() {
11022				 *      $('#example').dataTable( {
11023				 *        "language": {
11024				 *          "paginate": {
11025				 *            "first": "First page"
11026				 *          }
11027				 *        }
11028				 *      } );
11029				 *    } );
11030				 */
11031				"sFirst": "First",
11032	
11033	
11034				/**
11035				 * Text to use when using the 'full_numbers' type of pagination for the
11036				 * button to take the user to the last page.
11037				 *  @type string
11038				 *  @default Last
11039				 *
11040				 *  @dtopt Language
11041				 *  @name DataTable.defaults.language.paginate.last
11042				 *
11043				 *  @example
11044				 *    $(document).ready( function() {
11045				 *      $('#example').dataTable( {
11046				 *        "language": {
11047				 *          "paginate": {
11048				 *            "last": "Last page"
11049				 *          }
11050				 *        }
11051				 *      } );
11052				 *    } );
11053				 */
11054				"sLast": "Last",
11055	
11056	
11057				/**
11058				 * Text to use for the 'next' pagination button (to take the user to the
11059				 * next page).
11060				 *  @type string
11061				 *  @default Next
11062				 *
11063				 *  @dtopt Language
11064				 *  @name DataTable.defaults.language.paginate.next
11065				 *
11066				 *  @example
11067				 *    $(document).ready( function() {
11068				 *      $('#example').dataTable( {
11069				 *        "language": {
11070				 *          "paginate": {
11071				 *            "next": "Next page"
11072				 *          }
11073				 *        }
11074				 *      } );
11075				 *    } );
11076				 */
11077				"sNext": "Next",
11078	
11079	
11080				/**
11081				 * Text to use for the 'previous' pagination button (to take the user to
11082				 * the previous page).
11083				 *  @type string
11084				 *  @default Previous
11085				 *
11086				 *  @dtopt Language
11087				 *  @name DataTable.defaults.language.paginate.previous
11088				 *
11089				 *  @example
11090				 *    $(document).ready( function() {
11091				 *      $('#example').dataTable( {
11092				 *        "language": {
11093				 *          "paginate": {
11094				 *            "previous": "Previous page"
11095				 *          }
11096				 *        }
11097				 *      } );
11098				 *    } );
11099				 */
11100				"sPrevious": "Previous"
11101			},
11102	
11103			/**
11104			 * This string is shown in preference to `zeroRecords` when the table is
11105			 * empty of data (regardless of filtering). Note that this is an optional
11106			 * parameter - if it is not given, the value of `zeroRecords` will be used
11107			 * instead (either the default or given value).
11108			 *  @type string
11109			 *  @default No data available in table
11110			 *
11111			 *  @dtopt Language
11112			 *  @name DataTable.defaults.language.emptyTable
11113			 *
11114			 *  @example
11115			 *    $(document).ready( function() {
11116			 *      $('#example').dataTable( {
11117			 *        "language": {
11118			 *          "emptyTable": "No data available in table"
11119			 *        }
11120			 *      } );
11121			 *    } );
11122			 */
11123			"sEmptyTable": "No data available in table",
11124	
11125	
11126			/**
11127			 * This string gives information to the end user about the information
11128			 * that is current on display on the page. The following tokens can be
11129			 * used in the string and will be dynamically replaced as the table
11130			 * display updates. This tokens can be placed anywhere in the string, or
11131			 * removed as needed by the language requires:
11132			 *
11133			 * * `\_START\_` - Display index of the first record on the current page
11134			 * * `\_END\_` - Display index of the last record on the current page
11135			 * * `\_TOTAL\_` - Number of records in the table after filtering
11136			 * * `\_MAX\_` - Number of records in the table without filtering
11137			 * * `\_PAGE\_` - Current page number
11138			 * * `\_PAGES\_` - Total number of pages of data in the table
11139			 *
11140			 *  @type string
11141			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11142			 *
11143			 *  @dtopt Language
11144			 *  @name DataTable.defaults.language.info
11145			 *
11146			 *  @example
11147			 *    $(document).ready( function() {
11148			 *      $('#example').dataTable( {
11149			 *        "language": {
11150			 *          "info": "Showing page _PAGE_ of _PAGES_"
11151			 *        }
11152			 *      } );
11153			 *    } );
11154			 */
11155			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11156	
11157	
11158			/**
11159			 * Display information string for when the table is empty. Typically the
11160			 * format of this string should match `info`.
11161			 *  @type string
11162			 *  @default Showing 0 to 0 of 0 entries
11163			 *
11164			 *  @dtopt Language
11165			 *  @name DataTable.defaults.language.infoEmpty
11166			 *
11167			 *  @example
11168			 *    $(document).ready( function() {
11169			 *      $('#example').dataTable( {
11170			 *        "language": {
11171			 *          "infoEmpty": "No entries to show"
11172			 *        }
11173			 *      } );
11174			 *    } );
11175			 */
11176			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11177	
11178	
11179			/**
11180			 * When a user filters the information in a table, this string is appended
11181			 * to the information (`info`) to give an idea of how strong the filtering
11182			 * is. The variable _MAX_ is dynamically updated.
11183			 *  @type string
11184			 *  @default (filtered from _MAX_ total entries)
11185			 *
11186			 *  @dtopt Language
11187			 *  @name DataTable.defaults.language.infoFiltered
11188			 *
11189			 *  @example
11190			 *    $(document).ready( function() {
11191			 *      $('#example').dataTable( {
11192			 *        "language": {
11193			 *          "infoFiltered": " - filtering from _MAX_ records"
11194			 *        }
11195			 *      } );
11196			 *    } );
11197			 */
11198			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11199	
11200	
11201			/**
11202			 * If can be useful to append extra information to the info string at times,
11203			 * and this variable does exactly that. This information will be appended to
11204			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11205			 * being used) at all times.
11206			 *  @type string
11207			 *  @default <i>Empty string</i>
11208			 *
11209			 *  @dtopt Language
11210			 *  @name DataTable.defaults.language.infoPostFix
11211			 *
11212			 *  @example
11213			 *    $(document).ready( function() {
11214			 *      $('#example').dataTable( {
11215			 *        "language": {
11216			 *          "infoPostFix": "All records shown are derived from real information."
11217			 *        }
11218			 *      } );
11219			 *    } );
11220			 */
11221			"sInfoPostFix": "",
11222	
11223	
11224			/**
11225			 * This decimal place operator is a little different from the other
11226			 * language options since DataTables doesn't output floating point
11227			 * numbers, so it won't ever use this for display of a number. Rather,
11228			 * what this parameter does is modify the sort methods of the table so
11229			 * that numbers which are in a format which has a character other than
11230			 * a period (`.`) as a decimal place will be sorted numerically.
11231			 *
11232			 * Note that numbers with different decimal places cannot be shown in
11233			 * the same table and still be sortable, the table must be consistent.
11234			 * However, multiple different tables on the page can use different
11235			 * decimal place characters.
11236			 *  @type string
11237			 *  @default 
11238			 *
11239			 *  @dtopt Language
11240			 *  @name DataTable.defaults.language.decimal
11241			 *
11242			 *  @example
11243			 *    $(document).ready( function() {
11244			 *      $('#example').dataTable( {
11245			 *        "language": {
11246			 *          "decimal": ","
11247			 *          "thousands": "."
11248			 *        }
11249			 *      } );
11250			 *    } );
11251			 */
11252			"sDecimal": "",
11253	
11254	
11255			/**
11256			 * DataTables has a build in number formatter (`formatNumber`) which is
11257			 * used to format large numbers that are used in the table information.
11258			 * By default a comma is used, but this can be trivially changed to any
11259			 * character you wish with this parameter.
11260			 *  @type string
11261			 *  @default ,
11262			 *
11263			 *  @dtopt Language
11264			 *  @name DataTable.defaults.language.thousands
11265			 *
11266			 *  @example
11267			 *    $(document).ready( function() {
11268			 *      $('#example').dataTable( {
11269			 *        "language": {
11270			 *          "thousands": "'"
11271			 *        }
11272			 *      } );
11273			 *    } );
11274			 */
11275			"sThousands": ",",
11276	
11277	
11278			/**
11279			 * Detail the action that will be taken when the drop down menu for the
11280			 * pagination length option is changed. The '_MENU_' variable is replaced
11281			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11282			 * with a custom select box if required.
11283			 *  @type string
11284			 *  @default Show _MENU_ entries
11285			 *
11286			 *  @dtopt Language
11287			 *  @name DataTable.defaults.language.lengthMenu
11288			 *
11289			 *  @example
11290			 *    // Language change only
11291			 *    $(document).ready( function() {
11292			 *      $('#example').dataTable( {
11293			 *        "language": {
11294			 *          "lengthMenu": "Display _MENU_ records"
11295			 *        }
11296			 *      } );
11297			 *    } );
11298			 *
11299			 *  @example
11300			 *    // Language and options change
11301			 *    $(document).ready( function() {
11302			 *      $('#example').dataTable( {
11303			 *        "language": {
11304			 *          "lengthMenu": 'Display <select>'+
11305			 *            '<option value="10">10</option>'+
11306			 *            '<option value="20">20</option>'+
11307			 *            '<option value="30">30</option>'+
11308			 *            '<option value="40">40</option>'+
11309			 *            '<option value="50">50</option>'+
11310			 *            '<option value="-1">All</option>'+
11311			 *            '</select> records'
11312			 *        }
11313			 *      } );
11314			 *    } );
11315			 */
11316			"sLengthMenu": "Show _MENU_ entries",
11317	
11318	
11319			/**
11320			 * When using Ajax sourced data and during the first draw when DataTables is
11321			 * gathering the data, this message is shown in an empty row in the table to
11322			 * indicate to the end user the the data is being loaded. Note that this
11323			 * parameter is not used when loading data by server-side processing, just
11324			 * Ajax sourced data with client-side processing.
11325			 *  @type string
11326			 *  @default Loading...
11327			 *
11328			 *  @dtopt Language
11329			 *  @name DataTable.defaults.language.loadingRecords
11330			 *
11331			 *  @example
11332			 *    $(document).ready( function() {
11333			 *      $('#example').dataTable( {
11334			 *        "language": {
11335			 *          "loadingRecords": "Please wait - loading..."
11336			 *        }
11337			 *      } );
11338			 *    } );
11339			 */
11340			"sLoadingRecords": "Loading...",
11341	
11342	
11343			/**
11344			 * Text which is displayed when the table is processing a user action
11345			 * (usually a sort command or similar).
11346			 *  @type string
11347			 *
11347  @default Processing...
11348			 *
11349			 *  @dtopt Language
11350			 *  @name DataTable.defaults.language.processing
11351			 *
11352			 *  @example
11353			 *    $(document).ready( function() {
11354			 *      $('#example').dataTable( {
11355			 *        "language": {
11356			 *          "processing": "DataTables is currently busy"
11357			 *        }
11358			 *      } );
11359			 *    } );
11360			 */
11361			"sProcessing": "Processing...",
11362	
11363	
11364			/**
11365			 * Details the actions that will be taken when the user types into the
11366			 * filtering input text box. The variable "_INPUT_", if used in the string,
11367			 * is replaced with the HTML text box for the filtering input allowing
11368			 * control over where it appears in the string. If "_INPUT_" is not given
11369			 * then the input box is appended to the string automatically.
11370			 *  @type string
11371			 *  @default Search:
11372			 *
11373			 *  @dtopt Language
11374			 *  @name DataTable.defaults.language.search
11375			 *
11376			 *  @example
11377			 *    // Input text box will be appended at the end automatically
11378			 *    $(document).ready( function() {
11379			 *      $('#example').dataTable( {
11380			 *        "language": {
11381			 *          "search": "Filter records:"
11382			 *        }
11383			 *      } );
11384			 *    } );
11385			 *
11386			 *  @example
11387			 *    // Specify where the filter should appear
11388			 *    $(document).ready( function() {
11389			 *      $('#example').dataTable( {
11390			 *        "language": {
11391			 *          "search": "Apply filter _INPUT_ to table"
11392			 *        }
11393			 *      } );
11394			 *    } );
11395			 */
11396			"sSearch": "Search:",
11397	
11398	
11399			/**
11400			 * Assign a `placeholder` attribute to the search `input` element
11401			 *  @type string
11402			 *  @default 
11403			 *
11404			 *  @dtopt Language
11405			 *  @name DataTable.defaults.language.searchPlaceholder
11406			 */
11407			"sSearchPlaceholder": "",
11408	
11409	
11410			/**
11411			 * All of the language information can be stored in a file on the
11412			 * server-side, which DataTables will look up if this parameter is passed.
11413			 * It must store the URL of the language file, which is in a JSON format,
11414			 * and the object has the same properties as the oLanguage object in the
11415			 * initialiser object (i.e. the above parameters). Please refer to one of
11416			 * the example language files to see how this works in action.
11417			 *  @type string
11418			 *  @default <i>Empty string - i.e. disabled</i>
11419			 *
11420			 *  @dtopt Language
11421			 *  @name DataTable.defaults.language.url
11422			 *
11423			 *  @example
11424			 *    $(document).ready( function() {
11425			 *      $('#example').dataTable( {
11426			 *        "language": {
11427			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11428			 *        }
11429			 *      } );
11430			 *    } );
11431			 */
11432			"sUrl": "",
11433	
11434	
11435			/**
11436			 * Text shown inside the table records when the is no information to be
11437			 * displayed after filtering. `emptyTable` is shown when there is simply no
11438			 * information in the table at all (regardless of filtering).
11439			 *  @type string
11440			 *  @default No matching records found
11441			 *
11442			 *  @dtopt Language
11443			 *  @name DataTable.defaults.language.zeroRecords
11444			 *
11445			 *  @example
11446			 *    $(document).ready( function() {
11447			 *      $('#example').dataTable( {
11448			 *        "language": {
11449			 *          "zeroRecords": "No records to display"
11450			 *        }
11451			 *      } );
11452			 *    } );
11453			 */
11454			"sZeroRecords": "No matching records found"
11455		},
11456	
11457	
11458		/**
11459		 * This parameter allows you to have define the global filtering state at
11460		 * initialisation time. As an object the `search` parameter must be
11461		 * defined, but all other parameters are optional. When `regex` is true,
11462		 * the search string will be treated as a regular expression, when false
11463		 * (default) it will be treated as a straight string. When `smart`
11464		 * DataTables will use it's smart filtering methods (to word match at
11465		 * any point in the data), when false this will not be done.
11466		 *  @namespace
11467		 *  @extends DataTable.models.oSearch
11468		 *
11469		 *  @dtopt Options
11470		 *  @name DataTable.defaults.search
11471		 *
11472		 *  @example
11473		 *    $(document).ready( function() {
11474		 *      $('#example').dataTable( {
11475		 *        "search": {"search": "Initial search"}
11476		 *      } );
11477		 *    } )
11478		 */
11479		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11480	
11481	
11482		/**
11483		 * __Deprecated__ The functionality provided by this parameter has now been
11484		 * superseded by that provided through `ajax`, which should be used instead.
11485		 *
11486		 * By default DataTables will look for the property `data` (or `aaData` for
11487		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11488		 * source or for server-side processing - this parameter allows that
11489		 * property to be changed. You can use Javascript dotted object notation to
11490		 * get a data source for multiple levels of nesting.
11491		 *  @type string
11492		 *  @default data
11493		 *
11494		 *  @dtopt Options
11495		 *  @dtopt Server-side
11496		 *  @name DataTable.defaults.ajaxDataProp
11497		 *
11498		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11499		 */
11500		"sAjaxDataProp": "data",
11501	
11502	
11503		/**
11504		 * __Deprecated__ The functionality provided by this parameter has now been
11505		 * superseded by that provided through `ajax`, which should be used instead.
11506		 *
11507		 * You can instruct DataTables to load data from an external
11508		 * source using this parameter (use aData if you want to pass data in you
11509		 * already have). Simply provide a url a JSON object can be obtained from.
11510		 *  @type string
11511		 *  @default null
11512		 *
11513		 *  @dtopt Options
11514		 *  @dtopt Server-side
11515		 *  @name DataTable.defaults.ajaxSource
11516		 *
11517		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11518		 */
11519		"sAjaxSource": null,
11520	
11521	
11522		/**
11523		 * This initialisation variable allows you to specify exactly where in the
11524		 * DOM you want DataTables to inject the various controls it adds to the page
11525		 * (for example you might want the pagination controls at the top of the
11526		 * table). DIV elements (with or without a custom class) can also be added to
11527		 * aid styling. The follow syntax is used:
11528		 *   <ul>
11529		 *     <li>The following options are allowed:
11530		 *       <ul>
11531		 *         <li>'l' - Length changing</li>
11532		 *         <li>'f' - Filtering input</li>
11533		 *         <li>'t' - The table!</li>
11534		 *         <li>'i' - Information</li>
11535		 *         <li>'p' - Pagination</li>
11536		 *         <li>'r' - pRocessing</li>
11537		 *       </ul>
11538		 *     </li>
11539		 *     <li>The following constants are allowed:
11540		 *       <ul>
11541		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11542		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11543		 *       </ul>
11544		 *     </li>
11545		 *     <li>The following syntax is expected:
11546		 *       <ul>
11547		 *         <li>'&lt;' and '&gt;' - div elements</li>
11548		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11549		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11550		 *       </ul>
11551		 *     </li>
11552		 *     <li>Examples:
11553		 *       <ul>
11554		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11555		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11556		 *       </ul>
11557		 *     </li>
11558		 *   </ul>
11559		 *  @type string
11560		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11561		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11562		 *
11563		 *  @dtopt Options
11564		 *  @name DataTable.defaults.dom
11565		 *
11566		 *  @example
11567		 *    $(document).ready( function() {
11568		 *      $('#example').dataTable( {
11569		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11570		 *      } );
11571		 *    } );
11572		 */
11573		"sDom": "lfrtip",
11574	
11575	
11576		/**
11577		 * Search delay option. This will throttle full table searches that use the
11578		 * DataTables provided search input element (it does not effect calls to
11579		 * `dt-api search()`, providing a delay before the search is made.
11580		 *  @type integer
11581		 *  @default 0
11582		 *
11583		 *  @dtopt Options
11584		 *  @name DataTable.defaults.searchDelay
11585		 *
11586		 *  @example
11587		 *    $(document).ready( function() {
11588		 *      $('#example').dataTable( {
11589		 *        "searchDelay": 200
11590		 *      } );
11591		 *    } )
11592		 */
11593		"searchDelay": null,
11594	
11595	
11596		/**
11597		 * DataTables features four different built-in options for the buttons to
11598		 * display for pagination control:
11599		 *
11600		 * * `simple` - 'Previous' and 'Next' buttons only
11601		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11602		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11603		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11604		 *   page numbers
11605		 *  
11606		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11607		 *  @type string
11608		 *  @default simple_numbers
11609		 *
11610		 *  @dtopt Options
11611		 *  @name DataTable.defaults.pagingType
11612		 *
11613		 *  @example
11614		 *    $(document).ready( function() {
11615		 *      $('#example').dataTable( {
11616		 *        "pagingType": "full_numbers"
11617		 *      } );
11618		 *    } )
11619		 */
11620		"sPaginationType": "simple_numbers",
11621	
11622	
11623		/**
11624		 * Enable horizontal scrolling. When a table is too wide to fit into a
11625		 * certain layout, or you have a large number of columns in the table, you
11626		 * can enable x-scrolling to show the table in a viewport, which can be
11627		 * scrolled. This property can be `true` which will allow the table to
11628		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11629		 * case it will be treated as a pixel measurement). Setting as simply `true`
11630		 * is recommended.
11631		 *  @type boolean|string
11632		 *  @default <i>blank string - i.e. disabled</i>
11633		 *
11634		 *  @dtopt Features
11635		 *  @name DataTable.defaults.scrollX
11636		 *
11637		 *  @example
11638		 *    $(document).ready( function() {
11639		 *      $('#example').dataTable( {
11640		 *        "scrollX": true,
11641		 *        "scrollCollapse": true
11642		 *      } );
11643		 *    } );
11644		 */
11645		"sScrollX": "",
11646	
11647	
11648		/**
11649		 * This property can be used to force a DataTable to use more width than it
11650		 * might otherwise do when x-scrolling is enabled. For example if you have a
11651		 * table which requires to be well spaced, this parameter is useful for
11652		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11653		 * any CSS unit, or a number (in which case it will be treated as a pixel
11654		 * measurement).
11655		 *  @type string
11656		 *  @default <i>blank string - i.e. disabled</i>
11657		 *
11658		 *  @dtopt Options
11659		 *  @name DataTable.defaults.scrollXInner
11660		 *
11661		 *  @example
11662		 *    $(document).ready( function() {
11663		 *      $('#example').dataTable( {
11664		 *        "scrollX": "100%",
11665		 *        "scrollXInner": "110%"
11666		 *      } );
11667		 *    } );
11668		 */
11669		"sScrollXInner": "",
11670	
11671	
11672		/**
11673		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11674		 * to the given height, and enable scrolling for any data which overflows the
11675		 * current viewport. This can be used as an alternative to paging to display
11676		 * a lot of data in a small area (although paging and scrolling can both be
11677		 * enabled at the same time). This property can be any CSS unit, or a number
11678		 * (in which case it will be treated as a pixel measurement).
11679		 *  @type string
11680		 *  @default <i>blank string - i.e. disabled</i>
11681		 *
11682		 *  @dtopt Features
11683		 *  @name DataTable.defaults.scrollY
11684		 *
11685		 *  @example
11686		 *    $(document).ready( function() {
11687		 *      $('#example').dataTable( {
11688		 *        "scrollY": "200px",
11689		 *        "paginate": false
11690		 *      } );
11691		 *    } );
11692		 */
11693		"sScrollY": "",
11694	
11695	
11696		/**
11697		 * __Deprecated__ The functionality provided by this parameter has now been
11698		 * superseded by that provided through `ajax`, which should be used instead.
11699		 *
11700		 * Set the HTTP method that is used to make the Ajax call for server-side
11701		 * processing or Ajax sourced data.
11702		 *  @type string
11703		 *  @default GET
11704		 *
11705		 *  @dtopt Options
11706		 *  @dtopt Server-side
11707		 *  @name DataTable.defaults.serverMethod
11708		 *
11709		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11710		 */
11711		"sServerMethod": "GET",
11712	
11713	
11714		/**
11715		 * DataTables makes use of renderers when displaying HTML elements for
11716		 * a table. These renderers can be added or modified by plug-ins to
11717		 * generate suitable mark-up for a site. For example the Bootstrap
11718		 * integration plug-in for DataTables uses a paging button renderer to
11719		 * display pagination buttons in the mark-up required by Bootstrap.
11720		 *
11721		 * For further information about the renderers available see
11722		 * DataTable.ext.renderer
11723		 *  @type string|object
11724		 *  @default null
11725		 *
11726		 *  @name DataTable.defaults.renderer
11727		 *
11728		 */
11729		"renderer": null
11730	};
11731	
11732	_fnHungarianMap( DataTable.defaults );
11733	
11734	
11735	
11736	/*
11737	 * Developer note - See note in model.defaults.js about the use of Hungarian
11738	 * notation and camel case.
11739	 */
11740	
11741	/**
11742	 * Column options that can be given to DataTables at initialisation time.
11743	 *  @namespace
11744	 */
11745	DataTable.defaults.column = {
11746		/**
11747		 * Define which column(s) an order will occur on for this column. This
11748		 * allows a column's ordering to take multiple columns into account when
11749		 * doing a sort or use the data from a different column. For example first
11750		 * name / last name columns make sense to do a multi-column sort over the
11751		 * two columns.
11752		 *  @type array|int
11753		 *  @default null <i>Takes the value of the column index automatically</i>
11754		 *
11755		 *  @name DataTable.defaults.column.orderData
11756		 *  @dtopt Columns
11757		 *
11758		 *  @example
11759		 *    // Using `columnDefs`
11760		 *    $(document).ready( function() {
11761		 *      $('#example').dataTable( {
11762		 *        "columnDefs": [
11763		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11764		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11765		 *          { "orderData": 2, "targets": [ 2 ] }
11766		 *        ]
11767		 *      } );
11768		 *    } );
11769		 *
11770		 *  @example
11771		 *    // Using `columns`
11772		 *    $(document).ready( function() {
11773		 *      $('#example').dataTable( {
11774		 *        "columns": [
11775		 *          { "orderData": [ 0, 1 ] },
11776		 *          { "orderData": [ 1, 0 ] },
11777		 *          { "orderData": 2 },
11778		 *          null,
11779		 *          null
11780		 *        ]
11781		 *      } );
11782		 *    } );
11783		 */
11784		"aDataSort": null,
11785		"iDataSort": -1,
11786	
11787	
11788		/**
11789		 * You can control the default ordering direction, and even alter the
11790		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11791		 * using this parameter.
11792		 *  @type array
11793		 *  @default [ 'asc', 'desc' ]
11794		 *
11795		 *  @name DataTable.defaults.column.orderSequence
11796		 *  @dtopt Columns
11797		 *
11798		 *  @example
11799		 *    // Using `columnDefs`
11800		 *    $(document).ready( function() {
11801		 *      $('#example').dataTable( {
11802		 *        "columnDefs": [
11803		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11804		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11805		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11806		 *        ]
11807		 *      } );
11808		 *    } );
11809		 *
11810		 *  @example
11811		 *    // Using `columns`
11812		 *    $(document).ready( function() {
11813		 *      $('#example').dataTable( {
11814		 *        "columns": [
11815		 *          null,
11816		 *          { "orderSequence": [ "asc" ] },
11817		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
11818		 *          { "orderSequence": [ "desc" ] },
11819		 *          null
11820		 *        ]
11821		 *      } );
11822		 *    } );
11823		 */
11824		"asSorting": [ 'asc', 'desc' ],
11825	
11826	
11827		/**
11828		 * Enable or disable filtering on the data in this column.
11829		 *  @type boolean
11830		 *  @default true
11831		 *
11832		 *  @name DataTable.defaults.column.searchable
11833		 *  @dtopt Columns
11834		 *
11835		 *  @example
11836		 *    // Using `columnDefs`
11837		 *    $(document).ready( function() {
11838		 *      $('#example').dataTable( {
11839		 *        "columnDefs": [
11840		 *          { "searchable": false, "targets": [ 0 ] }
11841		 *        ] } );
11842		 *    } );
11843		 *
11844		 *  @example
11845		 *    // Using `columns`
11846		 *    $(document).ready( function() {
11847		 *      $('#example').dataTable( {
11848		 *        "columns": [
11849		 *          { "searchable": false },
11850		 *          null,
11851		 *          null,
11852		 *          null,
11853		 *          null
11854		 *        ] } );
11855		 *    } );
11856		 */
11857		"bSearchable": true,
11858	
11859	
11860		/**
11861		 * Enable or disable ordering on this column.
11862		 *  @type boolean
11863		 *  @default true
11864		 *
11865		 *  @name DataTable.defaults.column.orderable
11866		 *  @dtopt Columns
11867		 *
11868		 *  @example
11869		 *    // Using `columnDefs`
11870		 *    $(document).ready( function() {
11871		 *      $('#example').dataTable( {
11872		 *        "columnDefs": [
11873		 *          { "orderable": false, "targets": [ 0 ] }
11874		 *        ] } );
11875		 *    } );
11876		 *
11877		 *  @example
11878		 *    // Using `columns`
11879		 *    $(document).ready( function() {
11880		 *      $('#example').dataTable( {
11881		 *        "columns": [
11882		 *          { "orderable": false },
11883		 *          null,
11884		 *          null,
11885		 *          null,
11886		 *          null
11887		 *        ] } );
11888		 *    } );
11889		 */
11890		"bSortable": true,
11891	
11892	
11893		/**
11894		 * Enable or disable the display of this column.
11895		 *  @type boolean
11896		 *  @default true
11897		 *
11898		 *  @name DataTable.defaults.column.visible
11899		 *  @dtopt Columns
11900		 *
11901		 *  @example
11902		 *    // Using `columnDefs`
11903		 *    $(document).ready( function() {
11904		 *      $('#example').dataTable( {
11905		 *        "columnDefs": [
11906		 *          { "visible": false, "targets": [ 0 ] }
11907		 *        ] } );
11908		 *    } );
11909		 *
11910		 *  @example
11911		 *    // Using `columns`
11912		 *    $(document).ready( function() {
11913		 *      $('#example').dataTable( {
11914		 *        "columns": [
11915		 *          { "visible": false },
11916		 *          null,
11917		 *          null,
11918		 *          null,
11919		 *          null
11920		 *        ] } );
11921		 *    } );
11922		 */
11923		"bVisible": true,
11924	
11925	
11926		/**
11927		 * Developer definable function that is called whenever a cell is created (Ajax source,
11928		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11929		 * allowing you to modify the DOM element (add background colour for example) when the
11930		 * element is available.
11931		 *  @type function
11932		 *  @param {element} td The TD node that has been created
11933		 *  @param {*} cellData The Data for the cell
11934		 *  @param {array|object} rowData The data for the whole row
11935		 *  @param {int} row The row index for the aoData data store
11936		 *  @param {int} col The column index for aoColumns
11937		 *
11938		 *  @name DataTable.defaults.column.createdCell
11939		 *  @dtopt Columns
11940		 *
11941		 *  @example
11942		 *    $(document).ready( function() {
11943		 *      $('#example').dataTable( {
11944		 *        "columnDefs": [ {
11945		 *          "targets": [3],
11946		 *          "createdCell": function (td, cellData, rowData, row, c
11946ol) {
11947		 *            if ( cellData == "1.7" ) {
11948		 *              $(td).css('color', 'blue')
11949		 *            }
11950		 *          }
11951		 *        } ]
11952		 *      });
11953		 *    } );
11954		 */
11955		"fnCreatedCell": null,
11956	
11957	
11958		/**
11959		 * This parameter has been replaced by `data` in DataTables to ensure naming
11960		 * consistency. `dataProp` can still be used, as there is backwards
11961		 * compatibility in DataTables for this option, but it is strongly
11962		 * recommended that you use `data` in preference to `dataProp`.
11963		 *  @name DataTable.defaults.column.dataProp
11964		 */
11965	
11966	
11967		/**
11968		 * This property can be used to read data from any data source property,
11969		 * including deeply nested objects / properties. `data` can be given in a
11970		 * number of different ways which effect its behaviour:
11971		 *
11972		 * * `integer` - treated as an array index for the data source. This is the
11973		 *   default that DataTables uses (incrementally increased for each column).
11974		 * * `string` - read an object property from the data source. There are
11975		 *   three 'special' options that can be used in the string to alter how
11976		 *   DataTables reads the data from the source object:
11977		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11978		 *      Javascript to read from nested objects, so to can the options
11979		 *      specified in `data`. For example: `browser.version` or
11980		 *      `browser.name`. If your object parameter name contains a period, use
11981		 *      `\\` to escape it - i.e. `first\\.name`.
11982		 *    * `[]` - Array notation. DataTables can automatically combine data
11983		 *      from and array source, joining the data with the characters provided
11984		 *      between the two brackets. For example: `name[, ]` would provide a
11985		 *      comma-space separated list from the source array. If no characters
11986		 *      are provided between the brackets, the original array source is
11987		 *      returned.
11988		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
11989		 *      execute a function of the name given. For example: `browser()` for a
11990		 *      simple function on the data source, `browser.version()` for a
11991		 *      function in a nested property or even `browser().version` to get an
11992		 *      object property if the function called returns an object. Note that
11993		 *      function notation is recommended for use in `render` rather than
11994		 *      `data` as it is much simpler to use as a renderer.
11995		 * * `null` - use the original data source for the row rather than plucking
11996		 *   data directly from it. This action has effects on two other
11997		 *   initialisation options:
11998		 *    * `defaultContent` - When null is given as the `data` option and
11999		 *      `defaultContent` is specified for the column, the value defined by
12000		 *      `defaultContent` will be used for the cell.
12001		 *    * `render` - When null is used for the `data` option and the `render`
12002		 *      option is specified for the column, the whole data source for the
12003		 *      row is used for the renderer.
12004		 * * `function` - the function given will be executed whenever DataTables
12005		 *   needs to set or get the data for a cell in the column. The function
12006		 *   takes three parameters:
12007		 *    * Parameters:
12008		 *      * `{array|object}` The data source for the row
12009		 *      * `{string}` The type call data requested - this will be 'set' when
12010		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12011		 *        when gathering data. Note that when `undefined` is given for the
12012		 *        type DataTables expects to get the raw data for the object back<
12013		 *      * `{*}` Data to set when the second parameter is 'set'.
12014		 *    * Return:
12015		 *      * The return value from the function is not required when 'set' is
12016		 *        the type of call, but otherwise the return is what will be used
12017		 *        for the data requested.
12018		 *
12019		 * Note that `data` is a getter and setter option. If you just require
12020		 * formatting of data for output, you will likely want to use `render` which
12021		 * is simply a getter and thus simpler to use.
12022		 *
12023		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12024		 * name change reflects the flexibility of this property and is consistent
12025		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12026		 * be used by DataTables, as it automatically maps the old name to the new
12027		 * if required.
12028		 *
12029		 *  @type string|int|function|null
12030		 *  @default null <i>Use automatically calculated column index</i>
12031		 *
12032		 *  @name DataTable.defaults.column.data
12033		 *  @dtopt Columns
12034		 *
12035		 *  @example
12036		 *    // Read table data from objects
12037		 *    // JSON structure for each row:
12038		 *    //   {
12039		 *    //      "engine": {value},
12040		 *    //      "browser": {value},
12041		 *    //      "platform": {value},
12042		 *    //      "version": {value},
12043		 *    //      "grade": {value}
12044		 *    //   }
12045		 *    $(document).ready( function() {
12046		 *      $('#example').dataTable( {
12047		 *        "ajaxSource": "sources/objects.txt",
12048		 *        "columns": [
12049		 *          { "data": "engine" },
12050		 *          { "data": "browser" },
12051		 *          { "data": "platform" },
12052		 *          { "data": "version" },
12053		 *          { "data": "grade" }
12054		 *        ]
12055		 *      } );
12056		 *    } );
12057		 *
12058		 *  @example
12059		 *    // Read information from deeply nested objects
12060		 *    // JSON structure for each row:
12061		 *    //   {
12062		 *    //      "engine": {value},
12063		 *    //      "browser": {value},
12064		 *    //      "platform": {
12065		 *    //         "inner": {value}
12066		 *    //      },
12067		 *    //      "details": [
12068		 *    //         {value}, {value}
12069		 *    //      ]
12070		 *    //   }
12071		 *    $(document).ready( function() {
12072		 *      $('#example').dataTable( {
12073		 *        "ajaxSource": "sources/deep.txt",
12074		 *        "columns": [
12075		 *          { "data": "engine" },
12076		 *          { "data": "browser" },
12077		 *          { "data": "platform.inner" },
12078		 *          { "data": "platform.details.0" },
12079		 *          { "data": "platform.details.1" }
12080		 *        ]
12081		 *      } );
12082		 *    } );
12083		 *
12084		 *  @example
12085		 *    // Using `data` as a function to provide different information for
12086		 *    // sorting, filtering and display. In this case, currency (price)
12087		 *    $(document).ready( function() {
12088		 *      $('#example').dataTable( {
12089		 *        "columnDefs": [ {
12090		 *          "targets": [ 0 ],
12091		 *          "data": function ( source, type, val ) {
12092		 *            if (type === 'set') {
12093		 *              source.price = val;
12094		 *              // Store the computed dis
vendor: 18,284 bytes, lines 12094-12643
12094lay and filter values for efficiency
12095		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12096		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12097		 *              return;
12098		 *            }
12099		 *            else if (type === 'display') {
12100		 *              return source.price_display;
12101		 *            }
12102		 *            else if (type === 'filter') {
12103		 *              return source.price_filter;
12104		 *            }
12105		 *            // 'sort', 'type' and undefined all just use the integer
12106		 *            return source.price;
12107		 *          }
12108		 *        } ]
12109		 *      } );
12110		 *    } );
12111		 *
12112		 *  @example
12113		 *    // Using default content
12114		 *    $(document).ready( function() {
12115		 *      $('#example').dataTable( {
12116		 *        "columnDefs": [ {
12117		 *          "targets": [ 0 ],
12118		 *          "data": null,
12119		 *          "defaultContent": "Click to edit"
12120		 *        } ]
12121		 *      } );
12122		 *    } );
12123		 *
12124		 *  @example
12125		 *    // Using array notation - outputting a list from an array
12126		 *    $(document).ready( function() {
12127		 *      $('#example').dataTable( {
12128		 *        "columnDefs": [ {
12129		 *          "targets": [ 0 ],
12130		 *          "data": "name[, ]"
12131		 *        } ]
12132		 *      } );
12133		 *    } );
12134		 *
12135		 */
12136		"mData": null,
12137	
12138	
12139		/**
12140		 * This property is the rendering partner to `data` and it is suggested that
12141		 * when you want to manipulate data for display (including filtering,
12142		 * sorting etc) without altering the underlying data for the table, use this
12143		 * property. `render` can be considered to be the the read only companion to
12144		 * `data` which is read / write (then as such more complex). Like `data`
12145		 * this option can be given in a number of different ways to effect its
12146		 * behaviour:
12147		 *
12148		 * * `integer` - treated as an array index for the data source. This is the
12149		 *   default that DataTables uses (incrementally increased for each column).
12150		 * * `string` - read an object property from the data source. There are
12151		 *   three 'special' options that can be used in the string to alter how
12152		 *   DataTables reads the data from the source object:
12153		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12154		 *      Javascript to read from nested objects, so to can the options
12155		 *      specified in `data`. For example: `browser.version` or
12156		 *      `browser.name`. If your object parameter name contains a period, use
12157		 *      `\\` to escape it - i.e. `first\\.name`.
12158		 *    * `[]` - Array notation. DataTables can automatically combine data
12159		 *      from and array source, joining the data with the characters provided
12160		 *      between the two brackets. For example: `name[, ]` would provide a
12161		 *      comma-space separated list from the source array. If no characters
12162		 *      are provided between the brackets, the original array source is
12163		 *      returned.
12164		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12165		 *      execute a function of the name given. For example: `browser()` for a
12166		 *      simple function on the data source, `browser.version()` for a
12167		 *      function in a nested property or even `browser().version` to get an
12168		 *      object property if the function called returns an object.
12169		 * * `object` - use different data for the different data types requested by
12170		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12171		 *   of the object is the data type the property refers to and the value can
12172		 *   defined using an integer, string or function using the same rules as
12173		 *   `render` normally does. Note that an `_` option _must_ be specified.
12174		 *   This is the default value to use if you haven't specified a value for
12175		 *   the data type requested by DataTables.
12176		 * * `function` - the function given will be executed whenever DataTables
12177		 *   needs to set or get the data for a cell in the column. The function
12178		 *   takes three parameters:
12179		 *    * Parameters:
12180		 *      * {array|object} The data source for the row (based on `data`)
12181		 *      * {string} The type call data requested - this will be 'filter',
12182		 *        'display', 'type' or 'sort'.
12183		 *      * {array|object} The full data source for the row (not based on
12184		 *        `data`)
12185		 *    * Return:
12186		 *      * The return value from the function is what will be used for the
12187		 *        data requested.
12188		 *
12189		 *  @type string|int|function|object|null
12190		 *  @default null Use the data source value.
12191		 *
12192		 *  @name DataTable.defaults.column.render
12193		 *  @dtopt Columns
12194		 *
12195		 *  @example
12196		 *    // Create a comma separated list from an array of objects
12197		 *    $(document).ready( function() {
12198		 *      $('#example').dataTable( {
12199		 *        "ajaxSource": "sources/deep.txt",
12200		 *        "columns": [
12201		 *          { "data": "engine" },
12202		 *          { "data": "browser" },
12203		 *          {
12204		 *            "data": "platform",
12205		 *            "render": "[, ].name"
12206		 *          }
12207		 *        ]
12208		 *      } );
12209		 *    } );
12210		 *
12211		 *  @example
12212		 *    // Execute a function to obtain data
12213		 *    $(document).ready( function() {
12214		 *      $('#example').dataTable( {
12215		 *        "columnDefs": [ {
12216		 *          "targets": [ 0 ],
12217		 *          "data": null, // Use the full data source object for the renderer's source
12218		 *          "render": "browserName()"
12219		 *        } ]
12220		 *      } );
12221		 *    } );
12222		 *
12223		 *  @example
12224		 *    // As an object, extracting different data for the different types
12225		 *    // This would be used with a data source such as:
12226		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12227		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12228		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12229		 *    // the formatted phone number is the one that is shown in the table.
12230		 *    $(document).ready( function() {
12231		 *      $('#example').dataTable( {
12232		 *        "columnDefs": [ {
12233		 *          "targets": [ 0 ],
12234		 *          "data": null, // Use the full data source object for the renderer's source
12235		 *          "render": {
12236		 *            "_": "phone",
12237		 *            "filter": "phone_filter",
12238		 *            "display": "phone_display"
12239		 *          }
12240		 *        } ]
12241		 *      } );
12242		 *    } );
12243		 *
12244		 *  @example
12245		 *    // Use as a function to create a link from the data source
12246		 *    $(document).ready( function() {
12247		 *      $('#example').dataTable( {
12248		 *        "columnDefs": [ {
12249		 *          "targets": [ 0 ],
12250		 *          "data": "download_link",
12251		 *          "render": function ( data, type, full ) {
12252		 *            return '<a href="'+data+'">Download</a>';
12253		 *          }
12254		 *        } ]
12255		 *      } );
12256		 *    } );
12257		 */
12258		"mRender": null,
12259	
12260	
12261		/**
12262		 * Change the cell type created for the column - either TD cells or TH cells. This
12263		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12264		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12265		 *  @type string
12266		 *  @default td
12267		 *
12268		 *  @name DataTable.defaults.column.cellType
12269		 *  @dtopt Columns
12270		 *
12271		 *  @example
12272		 *    // Make the first column use TH cells
12273		 *    $(document).ready( function() {
12274		 *      $('#example').dataTable( {
12275		 *        "columnDefs": [ {
12276		 *          "targets": [ 0 ],
12277		 *          "cellType": "th"
12278		 *        } ]
12279		 *      } );
12280		 *    } );
12281		 */
12282		"sCellType": "td",
12283	
12284	
12285		/**
12286		 * Class to give to each cell in this column.
12287		 *  @type string
12288		 *  @default <i>Empty string</i>
12289		 *
12290		 *  @name DataTable.defaults.column.class
12291		 *  @dtopt Columns
12292		 *
12293		 *  @example
12294		 *    // Using `columnDefs`
12295		 *    $(document).ready( function() {
12296		 *      $('#example').dataTable( {
12297		 *        "columnDefs": [
12298		 *          { "class": "my_class", "targets": [ 0 ] }
12299		 *        ]
12300		 *      } );
12301		 *    } );
12302		 *
12303		 *  @example
12304		 *    // Using `columns`
12305		 *    $(document).ready( function() {
12306		 *      $('#example').dataTable( {
12307		 *        "columns": [
12308		 *          { "class": "my_class" },
12309		 *          null,
12310		 *          null,
12311		 *          null,
12312		 *          null
12313		 *        ]
12314		 *      } );
12315		 *    } );
12316		 */
12317		"sClass": "",
12318	
12319		/**
12320		 * When DataTables calculates the column widths to assign to each column,
12321		 * it finds the longest string in each column and then constructs a
12322		 * temporary table and reads the widths from that. The problem with this
12323		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12324		 * string - thus the calculation can go wrong (doing it properly and putting
12325		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12326		 * a "work around" we provide this option. It will append its value to the
12327		 * text that is found to be the longest string for the column - i.e. padding.
12328		 * Generally you shouldn't need this!
12329		 *  @type string
12330		 *  @default <i>Empty string<i>
12331		 *
12332		 *  @name DataTable.defaults.column.contentPadding
12333		 *  @dtopt Columns
12334		 *
12335		 *  @example
12336		 *    // Using `columns`
12337		 *    $(document).ready( function() {
12338		 *      $('#example').dataTable( {
12339		 *        "columns": [
12340		 *          null,
12341		 *          null,
12342		 *          null,
12343		 *          {
12344		 *            "contentPadding": "mmm"
12345		 *          }
12346		 *        ]
12347		 *      } );
12348		 *    } );
12349		 */
12350		"sContentPadding": "",
12351	
12352	
12353		/**
12354		 * Allows a default value to be given for a column's data, and will be used
12355		 * whenever a null data source is encountered (this can be because `data`
12356		 * is set to null, or because the data source itself is null).
12357		 *  @type string
12358		 *  @default null
12359		 *
12360		 *  @name DataTable.defaults.column.defaultContent
12361		 *  @dtopt Columns
12362		 *
12363		 *  @example
12364		 *    // Using `columnDefs`
12365		 *    $(document).ready( function() {
12366		 *      $('#example').dataTable( {
12367		 *        "columnDefs": [
12368		 *          {
12369		 *            "data": null,
12370		 *            "defaultContent": "Edit",
12371		 *            "targets": [ -1 ]
12372		 *          }
12373		 *        ]
12374		 *      } );
12375		 *    } );
12376		 *
12377		 *  @example
12378		 *    // Using `columns`
12379		 *    $(document).ready( function() {
12380		 *      $('#example').dataTable( {
12381		 *        "columns": [
12382		 *          null,
12383		 *          null,
12384		 *          null,
12385		 *          {
12386		 *            "data": null,
12387		 *            "defaultContent": "Edit"
12388		 *          }
12389		 *        ]
12390		 *      } );
12391		 *    } );
12392		 */
12393		"sDefaultContent": null,
12394	
12395	
12396		/**
12397		 * This parameter is only used in DataTables' server-side processing. It can
12398		 * be exceptionally useful to know what columns are being displayed on the
12399		 * client side, and to map these to database fields. When defined, the names
12400		 * also allow DataTables to reorder information from the server if it comes
12401		 * back in an unexpected order (i.e. if you switch your columns around on the
12402		 * client-side, your server-side code does not also need updating).
12403		 *  @type string
12404		 *  @default <i>Empty string</i>
12405		 *
12406		 *  @name DataTable.defaults.column.name
12407		 *  @dtopt Columns
12408		 *
12409		 *  @example
12410		 *    // Using `columnDefs`
12411		 *    $(document).ready( function() {
12412		 *      $('#example').dataTable( {
12413		 *        "columnDefs": [
12414		 *          { "name": "engine", "targets": [ 0 ] },
12415		 *          { "name": "browser", "targets": [ 1 ] },
12416		 *          { "name": "platform", "targets": [ 2 ] },
12417		 *          { "name": "version", "targets": [ 3 ] },
12418		 *          { "name": "grade", "targets": [ 4 ] }
12419		 *        ]
12420		 *      } );
12421		 *    } );
12422		 *
12423		 *  @example
12424		 *    // Using `columns`
12425		 *    $(document).ready( function() {
12426		 *      $('#example').dataTable( {
12427		 *        "columns": [
12428		 *          { "name": "engine" },
12429		 *          { "name": "browser" },
12430		 *          { "name": "platform" },
12431		 *          { "name": "version" },
12432		 *          { "name": "grade" }
12433		 *        ]
12434		 *      } );
12435		 *    } );
12436		 */
12437		"sName": "",
12438	
12439	
12440		/**
12441		 * Defines a data source type for the ordering which can be used to read
12442		 * real-time information from the table (updating the internally cached
12443		 * version) prior to ordering. This allows ordering to occur on user
12444		 * editable elements such as form inputs.
12445		 *  @type string
12446		 *  @default std
12447		 *
12448		 *  @name DataTable.defaults.column.orderDataType
12449		 *  @dtopt Columns
12450		 *
12451		 *  @example
12452		 *    // Using `columnDefs`
12453		 *    $(document).ready( function() {
12454		 *      $('#example').dataTable( {
12455		 *        "columnDefs": [
12456		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12457		 *          { "type": "numeric", "targets": [ 3 ] },
12458		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12459		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12460		 *        ]
12461		 *      } );
12462		 *    } );
12463		 *
12464		 *  @example
12465		 *    // Using `columns`
12466		 *    $(document).ready( function() {
12467		 *      $('#example').dataTable( {
12468		 *        "columns": [
12469		 *          null,
12470		 *          null,
12471		 *          { "orderDataType": "dom-text" },
12472		 *          { "orderDataType": "dom-text", "type": "numeric" },
12473		 *          { "orderDataType": "dom-select" },
12474		 *          { "orderDataType": "dom-checkbox" }
12475		 *        ]
12476		 *      } );
12477		 *    } );
12478		 */
12479		"sSortDataType": "std",
12480	
12481	
12482		/**
12483		 * The title of this column.
12484		 *  @type string
12485		 *  @default null <i>Derived from the 'TH' value for this column in the
12486		 *    original HTML table.</i>
12487		 *
12488		 *  @name DataTable.defaults.column.title
12489		 *  @dtopt Columns
12490		 *
12491		 *  @example
12492		 *    // Using `columnDefs`
12493		 *    $(document).ready( function() {
12494		 *      $('#example').dataTable( {
12495		 *        "columnDefs": [
12496		 *          { "title": "My column title", "targets": [ 0 ] }
12497		 *        ]
12498		 *      } );
12499		 *    } );
12500		 *
12501		 *  @example
12502		 *    // Using `columns`
12503		 *    $(document).ready( function() {
12504		 *      $('#example').dataTable( {
12505		 *        "columns": [
12506		 *          { "title": "My column title" },
12507		 *          null,
12508		 *          null,
12509		 *          null,
12510		 *          null
12511		 *        ]
12512		 *      } );
12513		 *    } );
12514		 */
12515		"sTitle": null,
12516	
12517	
12518		/**
12519		 * The type allows you to specify how the data for this column will be
12520		 * ordered. Four types (string, numeric, date and html (which will strip
12521		 * HTML tags before ordering)) are currently available. Note that only date
12522		 * formats understood by Javascript's Date() object will be accepted as type
12523		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12524		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12525		 * through plug-ins.
12526		 *  @type string
12527		 *  @default null <i>Auto-detected from raw data</i>
12528		 *
12529		 *  @name DataTable.defaults.column.type
12530		 *  @dtopt Columns
12531		 *
12532		 *  @example
12533		 *    // Using `columnDefs`
12534		 *    $(document).ready( function() {
12535		 *      $('#example').dataTable( {
12536		 *        "columnDefs": [
12537		 *          { "type": "html", "targets": [ 0 ] }
12538		 *        ]
12539		 *      } );
12540		 *    } );
12541		 *
12542		 *  @example
12543		 *    // Using `columns`
12544		 *    $(document).ready( function() {
12545		 *      $('#example').dataTable( {
12546		 *        "columns": [
12547		 *          { "type": "html" },
12548		 *          null,
12549		 *          null,
12550		 *          null,
12551		 *          null
12552		 *        ]
12553		 *      } );
12554		 *    } );
12555		 */
12556		"sType": null,
12557	
12558	
12559		/**
12560		 * Defining the width of the column, this parameter may take any CSS value
12561		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12562		 * been given a specific width through this interface ensuring that the table
12563		 * remains readable.
12564		 *  @type string
12565		 *  @default null <i>Automatic</i>
12566		 *
12567		 *  @name DataTable.defaults.column.width
12568		 *  @dtopt Columns
12569		 *
12570		 *  @example
12571		 *    // Using `columnDefs`
12572		 *    $(document).ready( function() {
12573		 *      $('#example').dataTable( {
12574		 *        "columnDefs": [
12575		 *          { "width": "20%", "targets": [ 0 ] }
12576		 *        ]
12577		 *      } );
12578		 *    } );
12579		 *
12580		 *  @example
12581		 *    // Using `columns`
12582		 *    $(document).ready( function() {
12583		 *      $('#example').dataTable( {
12584		 *        "columns": [
12585		 *          { "width": "20%" },
12586		 *          null,
12587		 *          null,
12588		 *          null,
12589		 *          null
12590		 *        ]
12591		 *      } );
12592		 *    } );
12593		 */
12594		"sWidth": null
12595	};
12596	
12597	_fnHungarianMap( DataTable.defaults.column );
12598	
12599	
12600	
12601	/**
12602	 * DataTables settings object - this holds all the information needed for a
12603	 * given table, including configuration, data and current application of the
12604	 * table options. DataTables does not have a single instance for each DataTable
12605	 * with the settings attached to that instance, but rather instances of the
12606	 * DataTable "class" are created on-the-fly as needed (typically by a
12607	 * $().dataTable() call) and the settings object is then applied to that
12608	 * instance.
12609	 *
12610	 * Note that this object is related to {@link DataTable.defaults} but this
12611	 * one is the internal data store for DataTables's cache of columns. It should
12612	 * NOT be manipulated outside of DataTables. Any configuration should be done
12613	 * through the initialisation options.
12614	 *  @namespace
12615	 *  @todo Really should attach the settings object to individual instances so we
12616	 *    don't need to create new instances on each $().dataTable() call (if the
12617	 *    table already exists). It would also save passing oSettings around and
12618	 *    into every single function. However, this is a very significant
12619	 *    architecture change for DataTables and will almost certainly break
12620	 *    backwards compatibility with older installations. This is something that
12621	 *    will be done in 2.0.
12622	 */
12623	DataTable.models.oSettings = {
12624		/**
12625		 * Primary features of DataTables and their enablement state.
12626		 *  @namespace
12627		 */
12628		"oFeatures": {
12629	
12630			/**
12631			 * Flag to say if DataTables should automatically try to calculate the
12632			 * optimum table and columns widths (true) or not (false).
12633			 * Note that this parameter will be set by the initialisation routine. To
12634			 * set a default use {@link DataTable.defaults}.
12635			 *  @type boolean
12636			 */
12637			"bAutoWidth": null,
12638	
12639			/**
12640			 * Delay the creation of TR and TD elements until they are actually
12641			 * needed by a driven page draw. This can give a significant speed
12642			 * increase for Ajax source and Javascript source data, but makes no
12643			 * difference at all f
12643ro DOM and server-side processing tables.
12644			 * Note that this parameter will be set by the initialisation routine. To
12645			 * set a default use {@link DataTable.defaults}.
12646			 *  @type boolean
12647			 */
12648			"bDeferRender": null,
12649	
12650			/**
12651			 * Enable filtering on the table or not. Note that if this is disabled
12652			 * then there is no filtering at all on the table, including fnFilter.
12653			 * To just remove the filtering input use sDom and remove the 'f' option.
12654			 * Note that this parameter will be set by the initialisation routine. To
12655			 * set a default use {@link DataTable.defaults}.
12656			 *  @type boolean
12657			 */
12658			"bFilter": null,
12659	
12660			/**
12661			 * Table information element (the 'Showing x of y records' div) enable
12662			 * flag.
12663			 * Note that this parameter will be set by the initialisation routine. To
12664			 * set a default use {@link DataTable.defaults}.
12665			 *  @type boolean
12666			 */
12667			"bInfo": null,
12668	
12669			/**
12670			 * Present a user control allowing the end user to change the page size
12671			 * when pagination is enabled.
12672			 * Note that this parameter will be set by the initialisation routine. To
12673			 * set a default use {@link DataTable.defaults}.
12674			 *  @type boolean
12675			 */
12676			"bLengthChange": null,
12677	
12678			/**
12679			 * Pagination enabled or not. Note that if this is disabled then length
12680			 * changing must also be disabled.
12681			 * Note that this parameter will be set by the initialisation routine. To
12682			 * set a default use {@link DataTable.defaults}.
12683			 *  @type boolean
12684			 */
12685			"bPaginate": null,
12686	
12687			/**
12688			 * Processing indicator enable flag whenever DataTables is enacting a
12689			 * user request - typically an Ajax request for server-side processing.
12690			 * Note that this parameter will be set by the initialisation routine. To
12691			 * set a default use {@link DataTable.defaults}.
12692			 *  @type boolean
12693			 */
12694			"bProcessing": null,
12695	
12696			/**
12697			 * Server-side processing enabled flag - when enabled DataTables will
12698			 * get all data from the server for every draw - there is no filtering,
12699			 * sorting or paging done on the client-side.
12700			 * Note that this parameter will be set by the initialisation routine. To
12701			 * set a default use {@link DataTable.defaults}.
12702			 *  @type boolean
12703			 */
12704			"bServerSide": null,
12705	
12706			/**
12707			 * Sorting enablement flag.
12708			 * Note that this parameter will be set by the initialisation routine. To
12709			 * set a default use {@link DataTable.defaults}.
12710			 *  @type boolean
12711			 */
12712			"bSort": null,
12713	
12714			/**
vendor: 9,250 bytes, lines 12715-13102
12715			 * Multi-column sorting
12716			 * Note that this parameter will be set by the initialisation routine. To
12717			 * set a default use {@link DataTable.defaults}.
12718			 *  @type boolean
12719			 */
12720			"bSortMulti": null,
12721	
12722			/**
12723			 * Apply a class to the columns which are being sorted to provide a
12724			 * visual highlight or not. This can slow things down when enabled since
12725			 * there is a lot of DOM interaction.
12726			 * Note that this parameter will be set by the initialisation routine. To
12727			 * set a default use {@link DataTable.defaults}.
12728			 *  @type boolean
12729			 */
12730			"bSortClasses": null,
12731	
12732			/**
12733			 * State saving enablement flag.
12734			 * Note that this parameter will be set by the initialisation routine. To
12735			 * set a default use {@link DataTable.defaults}.
12736			 *  @type boolean
12737			 */
12738			"bStateSave": null
12739		},
12740	
12741	
12742		/**
12743		 * Scrolling settings for a table.
12744		 *  @namespace
12745		 */
12746		"oScroll": {
12747			/**
12748			 * When the table is shorter in height than sScrollY, collapse the
12749			 * table container down to the height of the table (when true).
12750			 * Note that this parameter will be set by the initialisation routine. To
12751			 * set a default use {@link DataTable.defaults}.
12752			 *  @type boolean
12753			 */
12754			"bCollapse": null,
12755	
12756			/**
12757			 * Width of the scrollbar for the web-browser's platform. Calculated
12758			 * during table initialisation.
12759			 *  @type int
12760			 *  @default 0
12761			 */
12762			"iBarWidth": 0,
12763	
12764			/**
12765			 * Viewport width for horizontal scrolling. Horizontal scrolling is
12766			 * disabled if an empty string.
12767			 * Note that this parameter will be set by the initialisation routine. To
12768			 * set a default use {@link DataTable.defaults}.
12769			 *  @type string
12770			 */
12771			"sX": null,
12772	
12773			/**
12774			 * Width to expand the table to when using x-scrolling. Typically you
12775			 * should not need to use this.
12776			 * Note that this parameter will be set by the initialisation routine. To
12777			 * set a default use {@link DataTable.defaults}.
12778			 *  @type string
12779			 *  @deprecated
12780			 */
12781			"sXInner": null,
12782	
12783			/**
12784			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
12785			 * if an empty string.
12786			 * Note that this parameter will be set by the initialisation routine. To
12787			 * set a default use {@link DataTable.defaults}.
12788			 *  @type string
12789			 */
12790			"sY": null
12791		},
12792	
12793		/**
12794		 * Language information for the table.
12795		 *  @namespace
12796		 *  @extends DataTable.defaults.oLanguage
12797		 */
12798		"oLanguage": {
12799			/**
12800			 * Information callback function. See
12801			 * {@link DataTable.defaults.fnInfoCallback}
12802			 *  @type function
12803			 *  @default null
12804			 */
12805			"fnInfoCallback": null
12806		},
12807	
12808		/**
12809		 * Browser support parameters
12810		 *  @namespace
12811		 */
12812		"oBrowser": {
12813			/**
12814			 * Indicate if the browser incorrectly calculates width:100% inside a
12815			 * scrolling element (IE6/7)
12816			 *  @type boolean
12817			 *  @default false
12818			 */
12819			"bScrollOversize": false,
12820	
12821			/**
12822			 * Determine if the vertical scrollbar is on the right or left of the
12823			 * scrolling container - needed for rtl language layout, although not
12824			 * all browsers move the scrollbar (Safari).
12825			 *  @type boolean
12826			 *  @default false
12827			 */
12828			"bScrollbarLeft": false
12829		},
12830	
12831	
12832		"ajax": null,
12833	
12834	
12835		/**
12836		 * Array referencing the nodes which are used for the features. The
12837		 * parameters of this object match what is allowed by sDom - i.e.
12838		 *   <ul>
12839		 *     <li>'l' - Length changing</li>
12840		 *     <li>'f' - Filtering input</li>
12841		 *     <li>'t' - The table!</li>
12842		 *     <li>'i' - Information</li>
12843		 *     <li>'p' - Pagination</li>
12844		 *     <li>'r' - pRocessing</li>
12845		 *   </ul>
12846		 *  @type array
12847		 *  @default []
12848		 */
12849		"aanFeatures": [],
12850	
12851		/**
12852		 * Store data information - see {@link DataTable.models.oRow} for detailed
12853		 * information.
12854		 *  @type array
12855		 *  @default []
12856		 */
12857		"aoData": [],
12858	
12859		/**
12860		 * Array of indexes which are in the current display (after filtering etc)
12861		 *  @type array
12862		 *  @default []
12863		 */
12864		"aiDisplay": [],
12865	
12866		/**
12867		 * Array of indexes for display - no filtering
12868		 *  @type array
12869		 *  @default []
12870		 */
12871		"aiDisplayMaster": [],
12872	
12873		/**
12874		 * Store information about each column that is in use
12875		 *  @type array
12876		 *  @default []
12877		 */
12878		"aoColumns": [],
12879	
12880		/**
12881		 * Store information about the table's header
12882		 *  @type array
12883		 *  @default []
12884		 */
12885		"aoHeader": [],
12886	
12887		/**
12888		 * Store information about the table's footer
12889		 *  @type array
12890		 *  @default []
12891		 */
12892		"aoFooter": [],
12893	
12894		/**
12895		 * Store the applied global search information in case we want to force a
12896		 * research or compare the old search to a new one.
12897		 * Note that this parameter will be set by the initialisation routine. To
12898		 * set a default use {@link DataTable.defaults}.
12899		 *  @namespace
12900		 *  @extends DataTable.models.oSearch
12901		 */
12902		"oPreviousSearch": {},
12903	
12904		/**
12905		 * Store the applied search for each column - see
12906		 * {@link DataTable.models.oSearch} for the format that is used for the
12907		 * filtering information for each column.
12908		 *  @type array
12909		 *  @default []
12910		 */
12911		"aoPreSearchCols": [],
12912	
12913		/**
12914		 * Sorting that is applied to the table. Note that the inner arrays are
12915		 * used in the following manner:
12916		 * <ul>
12917		 *   <li>Index 0 - column number</li>
12918		 *   <li>Index 1 - current sorting direction</li>
12919		 * </ul>
12920		 * Note that this parameter will be set by the initialisation routine. To
12921		 * set a default use {@link DataTable.defaults}.
12922		 *  @type array
12923		 *  @todo These inner arrays should really be objects
12924		 */
12925		"aaSorting": null,
12926	
12927		/**
12928		 * Sorting that is always applied to the table (i.e. prefixed in front of
12929		 * aaSorting).
12930		 * Note that this parameter will be set by the initialisation routine. To
12931		 * set a default use {@link DataTable.defaults}.
12932		 *  @type array
12933		 *  @default []
12934		 */
12935		"aaSortingFixed": [],
12936	
12937		/**
12938		 * Classes to use for the striping of a table.
12939		 * Note that this parameter will be set by the initialisation routine. To
12940		 * set a default use {@link DataTable.defaults}.
12941		 *  @type array
12942		 *  @default []
12943		 */
12944		"asStripeClasses": null,
12945	
12946		/**
12947		 * If restoring a table - we should restore its striping classes as well
12948		 *  @type array
12949		 *  @default []
12950		 */
12951		"asDestroyStripes": [],
12952	
12953		/**
12954		 * If restoring a table - we should restore its width
12955		 *  @type int
12956		 *  @default 0
12957		 */
12958		"sDestroyWidth": 0,
12959	
12960		/**
12961		 * Callback functions array for every time a row is inserted (i.e. on a draw).
12962		 *  @type array
12963		 *  @default []
12964		 */
12965		"aoRowCallback": [],
12966	
12967		/**
12968		 * Callback functions for the header on each draw.
12969		 *  @type array
12970		 *  @default []
12971		 */
12972		"aoHeaderCallback": [],
12973	
12974		/**
12975		 * Callback function for the footer on each draw.
12976		 *  @type array
12977		 *  @default []
12978		 */
12979		"aoFooterCallback": [],
12980	
12981		/**
12982		 * Array of callback functions for draw callback functions
12983		 *  @type array
12984		 *  @default []
12985		 */
12986		"aoDrawCallback": [],
12987	
12988		/**
12989		 * Array of callback functions for row created function
12990		 *  @type array
12991		 *  @default []
12992		 */
12993		"aoRowCreatedCallback": [],
12994	
12995		/**
12996		 * Callback functions for just before the table is redrawn. A return of
12997		 * false will be used to cancel the draw.
12998		 *  @type array
12999		 *  @default []
13000		 */
13001		"aoPreDrawCallback": [],
13002	
13003		/**
13004		 * Callback functions for when the table has been initialised.
13005		 *  @type array
13006		 *  @default []
13007		 */
13008		"aoInitComplete": [],
13009	
13010	
13011		/**
13012		 * Callbacks for modifying the settings to be stored for state saving, prior to
13013		 * saving state.
13014		 *  @type array
13015		 *  @default []
13016		 */
13017		"aoStateSaveParams": [],
13018	
13019		/**
13020		 * Callbacks for modifying the settings that have been stored for state saving
13021		 * prior to using the stored values to restore the state.
13022		 *  @type array
13023		 *  @default []
13024		 */
13025		"aoStateLoadParams": [],
13026	
13027		/**
13028		 * Callbacks for operating on the settings object once the saved state has been
13029		 * loaded
13030		 *  @type array
13031		 *  @default []
13032		 */
13033		"aoStateLoaded": [],
13034	
13035		/**
13036		 * Cache the table ID for quick access
13037		 *  @type string
13038		 *  @default <i>Empty string</i>
13039		 */
13040		"sTableId": "",
13041	
13042		/**
13043		 * The TABLE node for the main table
13044		 *  @type node
13045		 *  @default null
13046		 */
13047		"nTable": null,
13048	
13049		/**
13050		 * Permanent ref to the thead element
13051		 *  @type node
13052		 *  @default null
13053		 */
13054		"nTHead": null,
13055	
13056		/**
13057		 * Permanent ref to the tfoot element - if it exists
13058		 *  @type node
13059		 *  @default null
13060		 */
13061		"nTFoot": null,
13062	
13063		/**
13064		 * Permanent ref to the tbody element
13065		 *  @type node
13066		 *  @default null
13067		 */
13068		"nTBody": null,
13069	
13070		/**
13071		 * Cache the wrapper node (contains all DataTables controlled elements)
13072		 *  @type node
13073		 *  @default null
13074		 */
13075		"nTableWrapper": null,
13076	
13077		/**
13078		 * Indicate if when using server-side processing the loading of data
13079		 * should be deferred until the second draw.
13080		 * Note that this parameter will be set by the initialisation routine. To
13081		 * set a default use {@link DataTable.defaults}.
13082		 *  @type boolean
13083		 *  @default false
13084		 */
13085		"bDeferLoading": false,
13086	
13087		/**
13088		 * Indicate if all required information has been read in
13089		 *  @type boolean
13090		 *  @default false
13091		 */
13092		"bInitialised": false,
13093	
13094		/**
13095		 * Information about open rows. Each object in the array has the parameters
13096		 * 'nTr' and 'nParent'
13097		 *  @type array
13098		 *  @default []
13099		 */
13100		"aoOpenRows": [],
13101	
13102		/**
13103		 * Dictate the positioning of DataTables' control elements - see
13104		 * {@link DataTable.model.oInit.sDom}.
13105		 * Note that this parameter will be set by the initialisation routine. To
13106		 * set a default use {@link DataTable.defaults}.
13107		 *  @type string
13108		 *  @default null
13109		 */
13110		"sDom": null,
13111	
13112		/**
13113		 * Search delay (in mS)
13114		 *  @type integer
13115		 *  @default null
13116		 */
13117		"searchDelay": null,
13118	
13119		/**
13120		 * Which type of pagination should be used.
13121		 * Note that this parameter will be set by the initialisation routine. To
13122		 * set a default use {@link DataTable.defaults}.
13123		 *  @type string
13124		 *  @default two_button
13125		 */
13126		"sPaginationType": "two_button",
13127	
13128		/**
13129		 * The state duration (for `stateSave`) in seconds.
13130		 * Note that this parameter will be set by the initialisation routine. To
13131		 * set a default use {@link DataTable.defaults}.
13132		 *  @type int
13133		 *  @default 0
13134		 */
13135		"iStateDuration": 0,
13136	
13137		/**
13138		 * Array of callback functions for state saving. Each array element is an
13139		 * object with the following parameters:
13140		 *   <ul>
13141		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13142		 *       and the JSON string to save that has been thus far created. Returns
13143		 *       a JSON string to be inserted into a json object
13144		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13145		 *     <li>string:sName - name of callback</li>
13146		 *   </ul>
13147		 *  @type array
13148		 *  @default []
13149		 */
13150		"aoStateSave": [],
13151	
13152		/**
13153		 * Array of callback functions for state loading. Each array element is an
13154		 * object with the following parameters:
13155		 *   <ul>
13156		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13157		 *       and the object stored. May return false to cancel state loading</li>
13158		 *     <li>string:sName - name of callback</li>
13159		 *   </ul>
13160		 *  @type array
13161		 *  @default []
13162		 */
13163		"aoStateLoad": [],
13164	
13165		/**
13166		 * State that was saved. Useful for back reference
13167		 *  @type object
13168		 *  @default null
13169		 */
13170		"oSavedState": null,
13171	
13172		/**
13173		 * State that was loaded. Useful for back reference
13174		 *  @type object
13175		 *  @default null
13176		 */
13177		"oLoadedState": null,
13178	
13179		/**
13180		 * Source url for AJAX data for the table.
13181		 * Note that this parameter will be set by the initialisation routine. To
13182		 * set a default use {@link DataTable.defaults}.
13183		 *  @type string
13184		 *  @default null
13185		 */
13186		"sAjaxSource": null,
13187	
13188		/**
13189		 * Property from a given object from which to read the table data from. This
13190		 * can be an empty string (when not server-side processing), in which case
13191		 * it is  assumed an an array is given directly.
13192		 * Note that this parameter will be set by the initialisation routine. To
13193		 * set a default use {@link DataTable.defaults}.
13194		 *  @type string
13195		 */
13196		"sAjaxDataProp": null,
13197	
13198		/**
13199		 * Note if draw should be blocked while getting data
13200		 *  @type boolean
13201		 *  @default true
13202		 */
13203		"bAjaxDataGet": true,
13204	
13205		/**
13206		 * The last jQuery XHR object that was used for server-side data gathering.
13207		 * This can be used for working with the XHR information in one of the
13208		 * callbacks
13209		 *  @type object
13210		 *  @default null
13211		 */
13212		"jqXHR": null,
13213	
13214		/**
13215		 * JSON returned from the server in the last Ajax request
13216		 *  @type object
13217		 *  @default undefined
13218		 */
13219		"json": undefined,
13220	
13221		/**
13222		 * Data submitted as part of the last Ajax request
13223		 *  @type object
13224		 *  @default undefined
13225		 */
13226		"oAjaxData": undefined,
13227	
13228		/**
13229		 * Function to get the server-side data.
13230		 * Note that this parameter will be set by the initialisation routine. To
13231		 * set a default use {@link DataTable.defaults}.
13232		 *  @type function
13233		 */
13234		"fnServerData": null,
13235	
13236		/**
13237		 * Functions which are called prior to sending an Ajax request so extra
13238		 * parameters can easily be sent to the server
13239		 *  @type array
13240		 *  @default []
13241		 */
13242		"aoServerParams": [],
13243	
13244		/**
13245		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13246		 * required).
13247		 * Note that this parameter will be set by the initialisation routine. To
13248		 * set a default use {@link DataTable.defaults}.
13249		 *  @type string
13250		 */
13251		"sServerMethod": null,
13252	
13253		/**
13254		 * Format numbers for display.
13255		 * Note that this parameter will be set by the initialisation routine. To
13256		 * set a default use {@link DataTable.defaults}.
13257		 *  @type function
13258		 */
13259		"fnFormatNumber": null,
13260	
13261		/**
13262		 * List of options that can be used for the user selectable length menu.
13263		 * Note that this parameter will be set by the initialisation routine. To
13264		 * set a default use {@link DataTable.defaults}.
13265		 *  @type array
13266		 *  @default []
13267		 */
13268		"aLengthMenu": null,
13269	
13270		/**
13271		 * Counter for the draws that the table does. Also used as a tracker for
13272		 * server-side processing
13273		 *  @type int
13274		 *  @default 0
13275		 */
13276		"iDraw": 0,
13277	
13278		/**
13279		 * Indicate if a redraw is being done - useful for Ajax
13280		 *  @type boolean
13281		 *  @default false
13282		 */
13283		"bDrawing": false,
13284	
13285		/**
13286		 * Draw index (iDraw) of the last error when parsing the returned data
13287		 *  @type int
13288		 *  @default -1
13289		 */
13290		"iDrawError": -1,
13291	
13292		/**
13293		 * Paging display length
13294		 *  @type int
13295		 *  @default 10
13296		 */
13297		"_iDisplayLength": 10,
13298	
13299		/**
13300		 * Paging start point - aiDisplay index
13301		 *  @type int
13302		 *  @default 0
13303		 */
13304		"_iDisplayStart": 0,
13305	
13306		/**
13307		 * Server-side processing - number of records in the result set
13308		 * (i.e. before filtering), Use fnRecordsTotal rather than
13309		 * this property to get the value of the number of records, regardless of
13310		 * the server-side processing setting.
13311		 *  @type int
13312		 *  @default 0
13313		 *  @private
13314		 */
13315		"_iRecordsTotal": 0,
13316	
13317		/**
13318		 * Server-side processing - number of records in the current display set
13319		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13320		 * this property to get the value of the number of records, regardless of
13321		 * the server-side processing setting.
13322		 *  @type boolean
13323		 *  @default 0
13324		 *  @private
13325		 */
13326		"_iRecordsDisplay": 0,
13327	
13328		/**
13329		 * Flag to indicate if jQuery UI marking and classes should be used.
13330		 * Note that this parameter will be set by the initialisation routine. To
13331		 * set a default use {@link DataTable.defaults}.
13332		 *  @type boolean
13333		 */
13334		"bJUI": null,
13335	
13336		/**
13337		 * The classes to use for the table
13338		 *  @type object
13339		 *  @default {}
13340		 */
vendor: 4,450 bytes, lines 13341-13527
13341		"oClasses": {},
13342	
13343		/**
13344		 * Flag attached to the settings object so you can check in the draw
13345		 * callback if filtering has been done in the draw. Deprecated in favour of
13346		 * events.
13347		 *  @type boolean
13348		 *  @default false
13349		 *  @deprecated
13350		 */
13351		"bFiltered": false,
13352	
13353		/**
13354		 * Flag attached to the settings object so you can check in the draw
13355		 * callback if sorting has been done in the draw. Deprecated in favour of
13356		 * events.
13357		 *  @type boolean
13358		 *  @default false
13359		 *  @deprecated
13360		 */
13361		"bSorted": false,
13362	
13363		/**
13364		 * Indicate that if multiple rows are in the header and there is more than
13365		 * one unique cell per column, if the top one (true) or bottom one (false)
13366		 * should be used for sorting / title by DataTables.
13367		 * Note that this parameter will be set by the initialisation routine. To
13368		 * set a default use {@link DataTable.defaults}.
13369		 *  @type boolean
13370		 */
13371		"bSortCellsTop": null,
13372	
13373		/**
13374		 * Initialisation object that is used for the table
13375		 *  @type object
13376		 *  @default null
13377		 */
13378		"oInit": null,
13379	
13380		/**
13381		 * Destroy callback functions - for plug-ins to attach themselves to the
13382		 * destroy so they can clean up markup and events.
13383		 *  @type array
13384		 *  @default []
13385		 */
13386		"aoDestroyCallback": [],
13387	
13388	
13389		/**
13390		 * Get the number of records in the current record set, before filtering
13391		 *  @type function
13392		 */
13393		"fnRecordsTotal": function ()
13394		{
13395			return _fnDataSource( this ) == 'ssp' ?
13396				this._iRecordsTotal * 1 :
13397				this.aiDisplayMaster.length;
13398		},
13399	
13400		/**
13401		 * Get the number of records in the current record set, after filtering
13402		 *  @type function
13403		 */
13404		"fnRecordsDisplay": function ()
13405		{
13406			return _fnDataSource( this ) == 'ssp' ?
13407				this._iRecordsDisplay * 1 :
13408				this.aiDisplay.length;
13409		},
13410	
13411		/**
13412		 * Get the display end point - aiDisplay index
13413		 *  @type function
13414		 */
13415		"fnDisplayEnd": function ()
13416		{
13417			var
13418				len      = this._iDisplayLength,
13419				start    = this._iDisplayStart,
13420				calc     = start + len,
13421				records  = this.aiDisplay.length,
13422				features = this.oFeatures,
13423				paginate = features.bPaginate;
13424	
13425			if ( features.bServerSide ) {
13426				return paginate === false || len === -1 ?
13427					start + records :
13428					Math.min( start+len, this._iRecordsDisplay );
13429			}
13430			else {
13431				return ! paginate || calc>records || len===-1 ?
13432					records :
13433					calc;
13434			}
13435		},
13436	
13437		/**
13438		 * The DataTables object for this table
13439		 *  @type object
13440		 *  @default null
13441		 */
13442		"oInstance": null,
13443	
13444		/**
13445		 * Unique identifier for each instance of the DataTables object. If there
13446		 * is an ID on the table node, then it takes that value, otherwise an
13447		 * incrementing internal counter is used.
13448		 *  @type string
13449		 *  @default null
13450		 */
13451		"sInstance": null,
13452	
13453		/**
13454		 * tabindex attribute value that is added to DataTables control elements, allowing
13455		 * keyboard navigation of the table and its controls.
13456		 */
13457		"iTabIndex": 0,
13458	
13459		/**
13460		 * DIV container for the footer scrolling table if scrolling
13461		 */
13462		"nScrollHead": null,
13463	
13464		/**
13465		 * DIV container for the footer scrolling table if scrolling
13466		 */
13467		"nScrollFoot": null,
13468	
13469		/**
13470		 * Last applied sort
13471		 *  @type array
13472		 *  @default []
13473		 */
13474		"aLastSort": [],
13475	
13476		/**
13477		 * Stored plug-in instances
13478		 *  @type object
13479		 *  @default {}
13480		 */
13481		"oPlugins": {}
13482	};
13483
13484	/**
13485	 * Extension object for DataTables that is used to provide all extension
13486	 * options.
13487	 *
13488	 * Note that the `DataTable.ext` object is available through
13489	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13490	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13491	 *  @namespace
13492	 *  @extends DataTable.models.ext
13493	 */
13494	
13495	
13496	/**
13497	 * DataTables extensions
13498	 * 
13499	 * This namespace acts as a collection area for plug-ins that can be used to
13500	 * extend DataTables capabilities. Indeed many of the build in methods
13501	 * use this method to provide their own capabilities (sorting methods for
13502	 * example).
13503	 *
13504	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13505	 * reasons
13506	 *
13507	 *  @namespace
13508	 */
13509	DataTable.ext = _ext = {
13510		/**
13511		 * Buttons. For use with the Buttons extension for DataTables. This is
13512		 * defined here so other extensions can define buttons regardless of load
13513		 * order. It is _not_ used by DataTables core.
13514		 *
13515		 *  @type object
13516		 *  @default {}
13517		 */
13518		buttons: {},
13519	
13520	
13521		/**
13522		 * Element class names
13523		 *
13524		 *  @type object
13525		 *  @default {}
13526		 */
13527		classes: {}
vendor: 10,711 bytes, lines 13527-13841
13527,
13528	
13529	
13530		/**
13531		 * Error reporting.
13532		 * 
13533		 * How should DataTables report an error. Can take the value 'alert',
13534		 * 'throw', 'none' or a function.
13535		 *
13536		 *  @type string|function
13537		 *  @default alert
13538		 */
13539		errMode: "alert",
13540	
13541	
13542		/**
13543		 * Feature plug-ins.
13544		 * 
13545		 * This is an array of objects which describe the feature plug-ins that are
13546		 * available to DataTables. These feature plug-ins are then available for
13547		 * use through the `dom` initialisation option.
13548		 * 
13549		 * Each feature plug-in is described by an object which must have the
13550		 * following properties:
13551		 * 
13552		 * * `fnInit` - function that is used to initialise the plug-in,
13553		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13554		 *   instillation option. This is case sensitive.
13555		 *
13556		 * The `fnInit` function has the following input parameters:
13557		 *
13558		 * 1. `{object}` DataTables settings object: see
13559		 *    {@link DataTable.models.oSettings}
13560		 *
13561		 * And the following return is expected:
13562		 * 
13563		 * * {node|null} The element which contains your feature. Note that the
13564		 *   return may also be void if your plug-in does not require to inject any
13565		 *   DOM elements into DataTables control (`dom`) - for example this might
13566		 *   be useful when developing a plug-in which allows table control via
13567		 *   keyboard entry
13568		 *
13569		 *  @type array
13570		 *
13571		 *  @example
13572		 *    $.fn.dataTable.ext.features.push( {
13573		 *      "fnInit": function( oSettings ) {
13574		 *        return new TableTools( { "oDTSettings": oSettings } );
13575		 *      },
13576		 *      "cFeature": "T"
13577		 *    } );
13578		 */
13579		feature: [],
13580	
13581	
13582		/**
13583		 * Row searching.
13584		 * 
13585		 * This method of searching is complimentary to the default type based
13586		 * searching, and a lot more comprehensive as it allows you complete control
13587		 * over the searching logic. Each element in this array is a function
13588		 * (parameters described below) that is called for every row in the table,
13589		 * and your logic decides if it should be included in the searching data set
13590		 * or not.
13591		 *
13592		 * Searching functions have the following input parameters:
13593		 *
13594		 * 1. `{object}` DataTables settings object: see
13595		 *    {@link DataTable.models.oSettings}
13596		 * 2. `{array|object}` Data for the row to be processed (same as the
13597		 *    original format that was passed in as the data source, or an array
13598		 *    from a DOM data source
13599		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13600		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13601		 *
13602		 * And the following return is expected:
13603		 *
13604		 * * {boolean} Include the row in the searched result set (true) or not
13605		 *   (false)
13606		 *
13607		 * Note that as with the main search ability in DataTables, technically this
13608		 * is "filtering", since it is subtractive. However, for consistency in
13609		 * naming we call it searching here.
13610		 *
13611		 *  @type array
13612		 *  @default []
13613		 *
13614		 *  @example
13615		 *    // The following example shows custom search being applied to the
13616		 *    // fourth column (i.e. the data[3] index) based on two input values
13617		 *    // from the end-user, matching the data in a certain range.
13618		 *    $.fn.dataTable.ext.search.push(
13619		 *      function( settings, data, dataIndex ) {
13620		 *        var min = document.getElementById('min').value * 1;
13621		 *        var max = document.getElementById('max').value * 1;
13622		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13623		 *
13624		 *        if ( min == "" && max == "" ) {
13625		 *          return true;
13626		 *        }
13627		 *        else if ( min == "" && version < max ) {
13628		 *          return true;
13629		 *        }
13630		 *        else if ( min < version && "" == max ) {
13631		 *          return true;
13632		 *        }
13633		 *        else if ( min < version && version < max ) {
13634		 *          return true;
13635		 *        }
13636		 *        return false;
13637		 *      }
13638		 *    );
13639		 */
13640		search: [],
13641	
13642	
13643		/**
13644		 * Selector extensions
13645		 *
13646		 * The `selector` option can be used to extend the options available for the
13647		 * selector modifier options (`selector-modifier` object data type) that
13648		 * each of the three built in selector types offer (row, column and cell +
13649		 * their plural counterparts). For example the Select extension uses this
13650		 * mechanism to provide an option to select only rows, columns and cells
13651		 * that have been marked as selected by the end user (`{selected: true}`),
13652		 * which can be used in conjunction with the existing built in selector
13653		 * options.
13654		 *
13655		 * Each property is an array to which functions can be pushed. The functions
13656		 * take three attributes:
13657		 *
13658		 * * Settings object for the host table
13659		 * * Options object (`selector-modifier` object type)
13660		 * * Array of selected item indexes
13661		 *
13662		 * The return is an array of the resulting item indexes after the custom
13663		 * selector has been applied.
13664		 *
13665		 *  @type object
13666		 */
13667		selector: {
13668			cell: [],
13669			column: [],
13670			row: []
13671		},
13672	
13673	
13674		/**
13675		 * Internal functions, exposed for used in plug-ins.
13676		 * 
13677		 * Please note that you should not need to use the internal methods for
13678		 * anything other than a plug-in (and even then, try to avoid if possible).
13679		 * The internal function may change between releases.
13680		 *
13681		 *  @type object
13682		 *  @default {}
13683		 */
13684		internal: {},
13685	
13686	
13687		/**
13688		 * Legacy configuration options. Enable and disable legacy options that
13689		 * are available in DataTables.
13690		 *
13691		 *  @type object
13692		 */
13693		legacy: {
13694			/**
13695			 * Enable / disable DataTables 1.9 compatible server-side processing
13696			 * requests
13697			 *
13698			 *  @type boolean
13699			 *  @default null
13700			 */
13701			ajax: null
13702		},
13703	
13704	
13705		/**
13706		 * Pagination plug-in methods.
13707		 * 
13708		 * Each entry in this object is a function and defines which buttons should
13709		 * be shown by the pagination rendering method that is used for the table:
13710		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13711		 * buttons are displayed in the document, while the functions here tell it
13712		 * what buttons to display. This is done by returning an array of button
13713		 * descriptions (what each button will do).
13714		 *
13715		 * Pagination types (the four built in options and any additional plug-in
13716		 * options defined here) can be used through the `paginationType`
13717		 * initialisation parameter.
13718		 *
13719		 * The functions defined take two parameters:
13720		 *
13721		 * 1. `{int} page` The current page index
13722		 * 2. `{int} pages` The number of pages in the table
13723		 *
13724		 * Each function is expected to return an array where each element of the
13725		 * array can be one of:
13726		 *
13727		 * * `first` - Jump to first page when activated
13728		 * * `last` - Jump to last page when activated
13729		 * * `previous` - Show previous page when activated
13730		 * * `next` - Show next page when activated
13731		 * * `{int}` - Show page of the index given
13732		 * * `{array}` - A nested array containing the above elements to add a
13733		 *   containing 'DIV' element (might be useful for styling).
13734		 *
13735		 * Note that DataTables v1.9- used this object slightly differently whereby
13736		 * an object with two functions would be defined for each plug-in. That
13737		 * ability is still supported by DataTables 1.10+ to provide backwards
13738		 * compatibility, but this option of use is now decremented and no longer
13739		 * documented in DataTables 1.10+.
13740		 *
13741		 *  @type object
13742		 *  @default {}
13743		 *
13744		 *  @example
13745		 *    // Show previous, next and current page buttons only
13746		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13747		 *      return [ 'previous', page, 'next' ];
13748		 *    };
13749		 */
13750		pager: {},
13751	
13752	
13753		renderer: {
13754			pageButton: {},
13755			header: {}
13756		},
13757	
13758	
13759		/**
13760		 * Ordering plug-ins - custom data source
13761		 * 
13762		 * The extension options for ordering of data available here is complimentary
13763		 * to the default type based ordering that DataTables typically uses. It
13764		 * allows much greater control over the the data that is being used to
13765		 * order a column, but is necessarily therefore more complex.
13766		 * 
13767		 * This type of ordering is useful if you want to do ordering based on data
13768		 * live from the DOM (for example the contents of an 'input' element) rather
13769		 * than just the static string that DataTables knows of.
13770		 * 
13771		 * The way these plug-ins work is that you create an array of the values you
13772		 * wish to be ordering for the column in question and then return that
13773		 * array. The data in the array much be in the index order of the rows in
13774		 * the table (not the currently ordering order!). Which order data gathering
13775		 * function is run here depends on the `dt-init columns.orderDataType`
13776		 * parameter that is used for the column (if any).
13777		 *
13778		 * The functions defined take two parameters:
13779		 *
13780		 * 1. `{object}` DataTables settings object: see
13781		 *    {@link DataTable.models.oSettings}
13782		 * 2. `{int}` Target column index
13783		 *
13784		 * Each function is expected to return an array:
13785		 *
13786		 * * `{array}` Data for the column to be ordering upon
13787		 *
13788		 *  @type array
13789		 *
13790		 *  @example
13791		 *    // Ordering using `input` node values
13792		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
13793		 *    {
13794		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13795		 *        return $('input', td).val();
13796		 *      } );
13797		 *    }
13798		 */
13799		order: {},
13800	
13801	
13802		/**
13803		 * Type based plug-ins.
13804		 *
13805		 * Each column in DataTables has a type assigned to it, either by automatic
13806		 * detection or by direct assignment using the `type` option for the column.
13807		 * The type of a column will effect how it is ordering and search (plug-ins
13808		 * can also make use of the column type if required).
13809		 *
13810		 * @namespace
13811		 */
13812		type: {
13813			/**
13814			 * Type detection functions.
13815			 *
13816			 * The functions defined in this object are used to automatically detect
13817			 * a column's type, making initialisation of DataTables super easy, even
13818			 * when complex data is in the table.
13819			 *
13820			 * The functions defined take two parameters:
13821			 *
13822		     *  1. `{*}` Data from the column cell to be analysed
13823		     *  2. `{settings}` DataTables settings object. This can be used to
13824		     *     perform context specific type detection - for example detection
13825		     *     based on language settings such as using a comma for a decimal
13826		     *     place. Generally speaking the options from the settings will not
13827		     *     be required
13828			 *
13829			 * Each function is expected to return:
13830			 *
13831			 * * `{string|null}` Data type detected, or null if unknown (and thus
13832			 *   pass it on to the other type detection functions.
13833			 *
13834			 *  @type array
13835			 *
13836			 *  @example
13837			 *    // Currency type detection plug-in:
13838			 *    $.fn.dataTable.ext.type.detect.push(
13839			 *      function ( data, settings ) {
13840			 *        // Check the numeric part
13841			 *        if ( ! 
13841$.isNumeric( data.substring(1) ) ) {
13842			 *          return null;
13843			 *        }
13844			 *
13845			 *        // Check prefixed by currency
13846			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
13847			 *          return 'currency';
13848			 *        }
13849			 *        return null;
13850			 *      }
13851			 *    );
13852			 */
13853			detect: [],
13854	
13855	
13856			/**
13857			 * Type based search formatting.
13858			 *
13859			 * The type based searching functions can be used to pre-format the
13860			 * data to be search on. For example, it can be used to strip HTML
13861			 * tags or to de-format telephone numbers for numeric only searching.
13862			 *
13863			 * Note that is a search is not defined for a column of a given type,
13864			 * no search formatting will be performed.
13865			 * 
13866			 * Pre-processing of searching data plug-ins - When you assign the sType
13867			 * for a column (or have it automatically detected for you by DataTables
13868			 * or a type detection plug-in), you will typically be using this for
13869			 * custom sorting, but it can also be used to provide custom searching
13870			 * by allowing you to pre-processing the data and returning the data in
13871			 * the format that should be searched upon. This is done by adding
13872			 * functions this object with a parameter name which matches the sType
13873			 * for that target column. This is the corollary of <i>afnSortData</i>
13874			 * for searching data.
13875			 *
13876			 * The functions defined take a single parameter:
13877			 *
13878		     *  1. `{*}` Data from the column cell to be prepared for searching
13879			 *
13880			 * Each function is expected to return:
13881			 *
13882			 * * `{string|null}` Formatted string that will be used for the searching.
13883			 *
13884			 *  @type object
13885			 *  @default {}
13886			 *
13887			 *  @example
13888			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
13889			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
13890			 *    }
13891			 */
13892			search: {},
13893	
13894	
13895			/**
13896			 * Type based ordering.
13897			 *
13898			 * The column type tells DataTables what ordering to apply to the table
13899			 * when a column is sorted upon. The order for each type that is defined,
13900			 * is defined by the functions available in this object.
13901			 *
13902			 * Each ordering option can be described by three properties added to
13903			 * this object:
13904			 *
13905			 * * `{type}-pre` - Pre-formatting function
13906			 * * `{type}-asc` - Ascending order function
13907			 * * `{type}-desc` - Descending order function
13908			 *
13909			 * All three can be used together, only `{type}-pre` or only
13910			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
13911			 * that only `{type}-pre` is used, as this provides the optimal
13912			 * implementation in terms of speed, although the others are provided
13913			 * for compatibility with existing Javascript sort functions.
13914			 *
13915			 * `{type}-pre`: Functions defined take a single parameter:
13916			 *
13917		     *  1. `{*}` Data from the column cell to be prepared for ordering
13918			 *
13919			 * And return:
13920			 *
13921			 * * `{*}` Data to be sorted upon
13922			 *
13923			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
13924			 * functions, taking two parameters:
13925			 *
13926		     *  1. `{*}` Data to compare to the second parameter
13927		     *  2. `{*}` Data to compare to the first parameter
13928			 *
13929			 * And returning:
13930			 *
13931			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
13932			 *   than the second parameter, ===0 if the two parameters are equal and
13933			 *   >0 if the first parameter should be sorted height than the second
13934			 *   parameter.
13935			 * 
13936			 *  @type object
13937			 *  @default {}
13938			 *
13939			 *  @example
13940			 *    // Numeric ordering of formatted numbers with a pre-formatter
13941			 *    $.extend( $.fn.dataTable.ext.type.order, {
13942			 *      "string-pre": function(x) {
13943			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
13944			 *        return parseFloat( a );
13945			 *      }
13946			 *    } );
13947			 *
13948			 *  @example
13949			 *    // Case-sensitive string ordering, with no pre-formatting method
13950			 *    $.extend( $.fn.dataTable.ext.order, {
13951			 *      "string-case-asc": function(x,y) {
13952			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13953			 *      },
13954			 *      "string-case-desc": function(x,y) {
13955			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13956			 *      }
13957			 *    } );
13958			 */
13959			order: {}
13960		},
13961	
13962		/**
13963		 * Unique DataTables instance counter
13964		 *
13965		 * @type int
13966		 * @private
13967		 */
13968		_unique: 0,
13969	
13970	
13971		//
13972		// Depreciated
13973		// The following properties are retained for backwards compatiblity only.
13974		// The should not be used in new projects and will be removed in a future
13975		// version
13976		//
13977	
13978		/**
13979		 * Version check function.
13980		 *  @type function
13981		 *  @depreciated Since 1.10
13982		 */
13983		fnVersionCheck: DataTable.fnVersionCheck,
13984	
13985	
13986		/**
13987		 * Index for what 'this' index API functions should use
13988		 *  @type int
13989		 *  @deprecated Since v1.10
13990		 */
13991		iApiIndex: 0,
13992	
13993	
13994		/**
13995		 * jQuery UI class container
13996		 *  @type object
13997		 *  @deprecated Since v1.10
13998		 */
13999		oJUIClasses: {},
14000	
14001	
14002		/**
14003		 * Software version
14004		 *  @type string
14005		 *  @deprecated Since v1.10
14006		 */
14007		sVersion: DataTable.version
14008	};
14009	
14010	
14011	//
14012	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14013	//
14014	$.extend( _ext, {
14015		afnFiltering: _ext.search,
14016		aTypes:       _ext.type.detect,
14017		ofnSearch:    _ext.type.search,
14018		oSort:        _ext.type.order,
14019		afnSortData:  _ext.order,
14020		aoFeatures:   _ext.feature,
14021		oApi:         _ext.internal,
14022		oStdClasses:  _ext.classes,
14023		oPagination:  _ext.pager
14024	} );
14025	
14026	
14027	$.extend( DataTable.ext.classes, {
14028		"sTable": "dataTable",
14029		"sNoFooter": "no-footer",
14030	
14031		/* Paging buttons */
14032		"sPageButton": "paginate_button",
14033		"sPageButtonActive": "current",
14034		"sPageButtonDisabled": "disabled",
14035	
14036		/* Striping classes */
14037		"sStripeOdd": "odd",
14038		"sStripeEven": "even",
14039	
14040		/* Empty row */
14041		"sRowEmpty": "dataTables_empty",
14042	
14043		/* Features */
14044		"sWrapper": "dataTables_wrapper",
14045		"sFilter": "dataTables_filter",
14046		"sInfo": "dataTables_info",
14047		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14048		"sLength": "dataTables_length",
14049		"sProcessing": "dataTables_processing",
14050	
14051		/* Sorting */
14052		"sSortAsc": "sorting_asc",
14053		"sSortDesc": "sorting_desc",
14054		"sSortable": "sorting", /* Sortable in both directions */
14055		"sSortableAsc": "sorting_asc_disabled",
14056		"sSortableDesc": "sorting_desc_disabled",
14057		"sSortableNone": "sorting_disabled",
14058		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14059	
14060		/* Filtering */
14061		"sFilterInput": "",
14062	
14063		/* Page length */
14064		"sLengthSelect": "",
14065	
14066		/* Scrolling */
14067		"sScrollWrapper": "dataTables_scroll",
14068		"sScrollHead": "dataTables_scrollHead",
14069		"sScrollHeadInner": "dataTables_scrollHeadInner",
14070		"sScrollBody": "dataTables_scrollBody",
14071		"sScrollFoot": "dataTables_scrollFoot",
14072		"sScrollFootInner": "dataTables_scrollFootInner",
14073	
14074		/* Misc */
14075		"sHeaderTH": "",
14076		"sFooterTH": "",
14077	
14078		// Deprecated
14079		"sSortJUIAsc": "",
14080		"sSortJUIDesc": "",
14081		"sSortJUI": "",
14082		"sSortJUIAscAllowed": "",
14083		"sSortJUIDescAllowed": "",
14084		"sSortJUIWrapper": "",
14085		"sSortIcon": "",
14086		"sJUIHeader": "",
14087		"sJUIFooter": ""
14088	} );
14089	
14090	
14091	(function() {
14092	
14093	// Reused strings for better compression. Closure compiler appears to have a
vendor: 23,939 bytes, lines 14094-14883
14094	// weird edge case where it is trying to expand strings rather than use the
14095	// variable version. This results in about 200 bytes being added, for very
14096	// little preference benefit since it this run on script load only.
14097	var _empty = '';
14098	_empty = '';
14099	
14100	var _stateDefault = _empty + 'ui-state-default';
14101	var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
14102	var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
14103	
14104	$.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
14105		/* Full numbers paging buttons */
14106		"sPageButton":         "fg-button ui-button "+_stateDefault,
14107		"sPageButtonActive":   "ui-state-disabled",
14108		"sPageButtonDisabled": "ui-state-disabled",
14109	
14110		/* Features */
14111		"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
14112			"ui-buttonset-multi paging_", /* Note that the type is postfixed */
14113	
14114		/* Sorting */
14115		"sSortAsc":            _stateDefault+" sorting_asc",
14116		"sSortDesc":           _stateDefault+" sorting_desc",
14117		"sSortable":           _stateDefault+" sorting",
14118		"sSortableAsc":        _stateDefault+" sorting_asc_disabled",
14119		"sSortableDesc":       _stateDefault+" sorting_desc_disabled",
14120		"sSortableNone":       _stateDefault+" sorting_disabled",
14121		"sSortJUIAsc":         _sortIcon+"triangle-1-n",
14122		"sSortJUIDesc":        _sortIcon+"triangle-1-s",
14123		"sSortJUI":            _sortIcon+"carat-2-n-s",
14124		"sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
14125		"sSortJUIDescAllowed": _sortIcon+"carat-1-s",
14126		"sSortJUIWrapper":     "DataTables_sort_wrapper",
14127		"sSortIcon":           "DataTables_sort_icon",
14128	
14129		/* Scrolling */
14130		"sScrollHead": "dataTables_scrollHead "+_stateDefault,
14131		"sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
14132	
14133		/* Misc */
14134		"sHeaderTH":  _stateDefault,
14135		"sFooterTH":  _stateDefault,
14136		"sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
14137		"sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
14138	} );
14139	
14140	}());
14141	
14142	
14143	
14144	var extPagination = DataTable.ext.pager;
14145	
14146	function _numbers ( page, pages ) {
14147		var
14148			numbers = [],
14149			buttons = extPagination.numbers_length,
14150			half = Math.floor( buttons / 2 ),
14151			i = 1;
14152	
14153		if ( pages <= buttons ) {
14154			numbers = _range( 0, pages );
14155		}
14156		else if ( page <= half ) {
14157			numbers = _range( 0, buttons-2 );
14158			numbers.push( 'ellipsis' );
14159			numbers.push( pages-1 );
14160		}
14161		else if ( page >= pages - 1 - half ) {
14162			numbers = _range( pages-(buttons-2), pages );
14163			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14164			numbers.splice( 0, 0, 0 );
14165		}
14166		else {
14167			numbers = _range( page-half+2, page+half-1 );
14168			numbers.push( 'ellipsis' );
14169			numbers.push( pages-1 );
14170			numbers.splice( 0, 0, 'ellipsis' );
14171			numbers.splice( 0, 0, 0 );
14172		}
14173	
14174		numbers.DT_el = 'span';
14175		return numbers;
14176	}
14177	
14178	
14179	$.extend( extPagination, {
14180		simple: function ( page, pages ) {
14181			return [ 'previous', 'next' ];
14182		},
14183	
14184		full: function ( page, pages ) {
14185			return [  'first', 'previous', 'next', 'last' ];
14186		},
14187	
14188		simple_numbers: function ( page, pages ) {
14189			return [ 'previous', _numbers(page, pages), 'next' ];
14190		},
14191	
14192		full_numbers: function ( page, pages ) {
14193			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14194		},
14195	
14196		// For testing and plug-ins to use
14197		_numbers: _numbers,
14198	
14199		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14200		numbers_length: 7
14201	} );
14202	
14203	
14204	$.extend( true, DataTable.ext.renderer, {
14205		pageButton: {
14206			_: function ( settings, host, idx, buttons, page, pages ) {
14207				var classes = settings.oClasses;
14208				var lang = settings.oLanguage.oPaginate;
14209				var btnDisplay, btnClass, counter=0;
14210	
14211				var attach = function( container, buttons ) {
14212					var i, ien, node, button;
14213					var clickHandler = function ( e ) {
14214						_fnPageChange( settings, e.data.action, true );
14215					};
14216	
14217					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14218						button = buttons[i];
14219	
14220						if ( $.isArray( button ) ) {
14221							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14222								.appendTo( container );
14223							attach( inner, button );
14224						}
14225						else {
14226							btnDisplay = '';
14227							btnClass = '';
14228	
14229							switch ( button ) {
14230								case 'ellipsis':
14231									container.append('<span class="ellipsis">&#x2026;</span>');
14232									break;
14233	
14234								case 'first':
14235									btnDisplay = lang.sFirst;
14236									btnClass = button + (page > 0 ?
14237										'' : ' '+classes.sPageButtonDisabled);
14238									break;
14239	
14240								case 'previous':
14241									btnDisplay = lang.sPrevious;
14242									btnClass = button + (page > 0 ?
14243										'' : ' '+classes.sPageButtonDisabled);
14244									break;
14245	
14246								case 'next':
14247									btnDisplay = lang.sNext;
14248									btnClass = button + (page < pages-1 ?
14249										'' : ' '+classes.sPageButtonDisabled);
14250									break;
14251	
14252								case 'last':
14253									btnDisplay = lang.sLast;
14254									btnClass = button + (page < pages-1 ?
14255										'' : ' '+classes.sPageButtonDisabled);
14256									break;
14257	
14258								default:
14259									btnDisplay = button + 1;
14260									btnClass = page === button ?
14261										classes.sPageButtonActive : '';
14262									break;
14263							}
14264	
14265							if ( btnDisplay ) {
14266								node = $('<a>', {
14267										'class': classes.sPageButton+' '+btnClass,
14268										'aria-controls': settings.sTableId,
14269										'data-dt-idx': counter,
14270										'tabindex': settings.iTabIndex,
14271										'id': idx === 0 && typeof button === 'string' ?
14272											settings.sTableId +'_'+ button :
14273											null
14274									} )
14275									.html( btnDisplay )
14276									.appendTo( container );
14277	
14278								_fnBindAction(
14279									node, {action: button}, clickHandler
14280								);
14281	
14282								counter++;
14283							}
14284						}
14285					}
14286				};
14287	
14288				// IE9 throws an 'unknown error' if document.activeElement is used
14289				// inside an iframe or frame. Try / catch the error. Not good for
14290				// accessibility, but neither are frames.
14291				var activeEl;
14292	
14293				try {
14294					// Because this approach is destroying and recreating the paging
14295					// elements, focus is lost on the select button which is bad for
14296					// accessibility. So we want to restore focus once the draw has
14297					// completed
14298					activeEl = $(document.activeElement).data('dt-idx');
14299				}
14300				catch (e) {}
14301	
14302				attach( $(host).empty(), buttons );
14303	
14304				if ( activeEl ) {
14305					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14306				}
14307			}
14308		}
14309	} );
14310	
14311	
14312	
14313	// Built in type detection. See model.ext.aTypes for information about
14314	// what is required from this methods.
14315	$.extend( DataTable.ext.type.detect, [
14316		// Plain numbers - first since V8 detects some plain numbers as dates
14317		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14318		function ( d, settings )
14319		{
14320			var decimal = settings.oLanguage.sDecimal;
14321			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14322		},
14323	
14324		// Dates (only those recognised by the browser's Date.parse)
14325		function ( d, settings )
14326		{
14327			// V8 will remove any unknown characters at the start and end of the
14328			// expression, leading to false matches such as `$245.12` or `10%` being
14329			// a valid date. See forum thread 18941 for detail.
14330			if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14331				return null;
14332			}
14333			var parsed = Date.parse(d);
14334			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14335		},
14336	
14337		// Formatted numbers
14338		function ( d, settings )
14339		{
14340			var decimal = settings.oLanguage.sDecimal;
14341			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14342		},
14343	
14344		// HTML numeric
14345		function ( d, settings )
14346		{
14347			var decimal = settings.oLanguage.sDecimal;
14348			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14349		},
14350	
14351		// HTML numeric, formatted
14352		function ( d, settings )
14353		{
14354			var decimal = settings.oLanguage.sDecimal;
14355			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14356		},
14357	
14358		// HTML (this is strict checking - there must be html)
14359		function ( d, settings )
14360		{
14361			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14362				'html' : null;
14363		}
14364	] );
14365	
14366	
14367	
14368	// Filter formatting functions. See model.ext.ofnSearch for information about
14369	// what is required from these methods.
14370	// 
14371	// Note that additional search methods are added for the html numbers and
14372	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14373	// place is
14374	
14375	
14376	$.extend( DataTable.ext.type.search, {
14377		html: function ( data ) {
14378			return _empty(data) ?
14379				data :
14380				typeof data === 'string' ?
14381					data
14382						.replace( _re_new_lines, " " )
14383						.replace( _re_html, "" ) :
14384					'';
14385		},
14386	
14387		string: function ( data ) {
14388			return _empty(data) ?
14389				data :
14390				typeof data === 'string' ?
14391					data.replace( _re_new_lines, " " ) :
14392					data;
14393		}
14394	} );
14395	
14396	
14397	
14398	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14399		if ( d !== 0 && (!d || d === '-') ) {
14400			return -Infinity;
14401		}
14402	
14403		// If a decimal place other than `.` is used, it needs to be given to the
14404		// function so we can detect it and replace with a `.` which is the only
14405		// decimal place Javascript recognises - it is not locale aware.
14406		if ( decimalPlace ) {
14407			d = _numToDecimal( d, decimalPlace );
14408		}
14409	
14410		if ( d.replace ) {
14411			if ( re1 ) {
14412				d = d.replace( re1, '' );
14413			}
14414	
14415			if ( re2 ) {
14416				d = d.replace( re2, '' );
14417			}
14418		}
14419	
14420		return d * 1;
14421	};
14422	
14423	
14424	// Add the numeric 'deformatting' functions for sorting and search. This is done
14425	// in a function to provide an easy ability for the language options to add
14426	// additional methods if a non-period decimal place is used.
14427	function _addNumericSort ( decimalPlace ) {
14428		$.each(
14429			{
14430				// Plain numbers
14431				"num": function ( d ) {
14432					return __numericReplace( d, decimalPlace );
14433				},
14434	
14435				// Formatted numbers
14436				"num-fmt": function ( d ) {
14437					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14438				},
14439	
14440				// HTML numeric
14441				"html-num": function ( d ) {
14442					return __numericReplace( d, decimalPlace, _re_html );
14443				},
14444	
14445				// HTML numeric, formatted
14446				"html-num-fmt": function ( d ) {
14447					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14448				}
14449			},
14450			function ( key, fn ) {
14451				// Add the ordering method
14452				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14453	
14454				// For HTML types add a search formatter that will strip the HTML
14455				if ( key.match(/^html\-/) ) {
14456					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14457				}
14458			}
14459		);
14460	}
14461	
14462	
14463	// Default sort methods
14464	$.extend( _ext.type.order, {
14465		// Dates
14466		"date-pre": function ( d ) {
14467			return Date.parse( d ) || 0;
14468		},
14469	
14470		// html
14471		"html-pre": function ( a ) {
14472			return _empty(a) ?
14473				'' :
14474				a.replace ?
14475					a.replace( /<.*?>/g, "" ).toLowerCase() :
14476					a+'';
14477		},
14478	
14479		// string
14480		"string-pre": function ( a ) {
14481			// This is a little complex, but faster than always calling toString,
14482			// http://jsperf.com/tostring-v-check
14483			return _empty(a) ?
14484				'' :
14485				typeof a === 'string' ?
14486					a.toLowerCase() :
14487					! a.toString ?
14488						'' :
14489						a.toString();
14490		},
14491	
14492		// string-asc and -desc are retained only for compatibility with the old
14493		// sort methods
14494		"string-asc": function ( x, y ) {
14495			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14496		},
14497	
14498		"string-desc": function ( x, y ) {
14499			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14500		}
14501	} );
14502	
14503	
14504	// Numeric sorting types - order doesn't matter here
14505	_addNumericSort( '' );
14506	
14507	
14508	$.extend( true, DataTable.ext.renderer, {
14509		header: {
14510			_: function ( settings, cell, column, classes ) {
14511				// No additional mark-up required
14512				// Attach a sort listener to update on sort - note that using the
14513				// `DT` namespace will allow the event to be removed automatically
14514				// on destroy, while the `dt` namespaced event is the one we are
14515				// listening for
14516				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14517					if ( settings !== ctx ) { // need to check this this is the host
14518						return;               // table, not a nested one
14519					}
14520	
14521					var colIdx = column.idx;
14522	
14523					cell
14524						.removeClass(
14525							column.sSortingClass +' '+
14526							classes.sSortAsc +' '+
14527							classes.sSortDesc
14528						)
14529						.addClass( columns[ colIdx ] == 'asc' ?
14530							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14531								classes.sSortDesc :
14532								column.sSortingClass
14533						);
14534				} );
14535			},
14536	
14537			jqueryui: function ( settings, cell, column, classes ) {
14538				$('<div/>')
14539					.addClass( classes.sSortJUIWrapper )
14540					.append( cell.contents() )
14541					.append( $('<span/>')
14542						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14543					)
14544					.appendTo( cell );
14545	
14546				// Attach a sort listener to update on sort
14547				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14548					if ( settings !== ctx ) {
14549						return;
14550					}
14551	
14552					var colIdx = column.idx;
14553	
14554					cell
14555						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14556						.addClass( columns[ colIdx ] == 'asc' ?
14557							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14558								classes.sSortDesc :
14559								column.sSortingClass
14560						);
14561	
14562					cell
14563						.find( 'span.'+classes.sSortIcon )
14564						.removeClass(
14565							classes.sSortJUIAsc +" "+
14566							classes.sSortJUIDesc +" "+
14567							classes.sSortJUI +" "+
14568							classes.sSortJUIAscAllowed +" "+
14569							classes.sSortJUIDescAllowed
14570						)
14571						.addClass( columns[ colIdx ] == 'asc' ?
14572							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14573								classes.sSortJUIDesc :
14574								column.sSortingClassJUI
14575						);
14576				} );
14577			}
14578		}
14579	} );
14580	
14581	/*
14582	 * Public helper functions. These aren't used internally by DataTables, or
14583	 * called by any of the options passed into DataTables, but they can be used
14584	 * externally by developers working with DataTables. They are helper functions
14585	 * to make working with DataTables a little bit easier.
14586	 */
14587	
14588	/**
14589	 * Helpers for `columns.render`.
14590	 *
14591	 * The options defined here can be used with the `columns.render` initialisation
14592	 * option to provide a display renderer. The following functions are defined:
14593	 *
14594	 * * `number` - Will format numeric data (defined by `columns.data`) for
14595	 *   display, retaining the original unformatted data for sorting and filtering.
14596	 *   It takes 4 parameters:
14597	 *   * `string` - Thousands grouping separator
14598	 *   * `string` - Decimal point indicator
14599	 *   * `integer` - Number of decimal points to show
14600	 *   * `string` (optional) - Prefix.
14601	 *
14602	 * @example
14603	 *   // Column definition using the number renderer
14604	 *   {
14605	 *     data: "salary",
14606	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14607	 *   }
14608	 *
14609	 * @namespace
14610	 */
14611	DataTable.render = {
14612		number: function ( thousands, decimal, precision, prefix ) {
14613			return {
14614				display: function ( d ) {
14615					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14616						return d;
14617					}
14618	
14619					var negative = d < 0 ? '-' : '';
14620					d = Math.abs( parseFloat( d ) );
14621	
14622					var intPart = parseInt( d, 10 );
14623					var floatPart = precision ?
14624						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14625						'';
14626	
14627					return negative + (prefix||'') +
14628						intPart.toString().replace(
14629							/\B(?=(\d{3})+(?!\d))/g, thousands
14630						) +
14631						floatPart;
14632				}
14633			};
14634		}
14635	};
14636	
14637	
14638	/*
14639	 * This is really a good bit rubbish this method of exposing the internal methods
14640	 * publicly... - To be fixed in 2.0 using methods on the prototype
14641	 */
14642	
14643	
14644	/**
14645	 * Create a wrapper function for exporting an internal functions to an external API.
14646	 *  @param {string} fn API function name
14647	 *  @returns {function} wrapped function
14648	 *  @memberof DataTable#internal
14649	 */
14650	function _fnExternApiFunc (fn)
14651	{
14652		return function() {
14653			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14654				Array.prototype.slice.call(arguments)
14655			);
14656			return DataTable.ext.internal[fn].apply( this, args );
14657		};
14658	}
14659	
14660	
14661	/**
14662	 * Reference to internal functions for use by plug-in developers. Note that
14663	 * these methods are references to internal functions and are considered to be
14664	 * private. If you use these methods, be aware that they are liable to change
14665	 * between versions.
14666	 *  @namespace
14667	 */
14668	$.extend( DataTable.ext.internal, {
14669		_fnExternApiFunc: _fnExternApiFunc,
14670		_fnBuildAjax: _fnBuildAjax,
14671		_fnAjaxUpdate: _fnAjaxUpdate,
14672		_fnAjaxParameters: _fnAjaxParameters,
14673		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14674		_fnAjaxDataSrc: _fnAjaxDataSrc,
14675		_fnAddColumn: _fnAddColumn,
14676		_fnColumnOptions: _fnColumnOptions,
14677		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
14678		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14679		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
14680		_fnVisbleColumns: _fnVisbleColumns,
14681		_fnGetColumns: _fnGetColumns,
14682		_fnColumnTypes: _fnColumnTypes,
14683		_fnApplyColumnDefs: _fnApplyColumnDefs,
14684		_fnHungarianMap: _fnHungarianMap,
14685		_fnCamelToHungarian: _fnCamelToHungarian,
14686		_fnLanguageCompat: _fnLanguageCompat,
14687		_fnBrowserDetect: _fnBrowserDetect,
14688		_fnAddData: _fnAddData,
14689		_fnAddTr: _fnAddTr,
14690		_fnNodeToDataIndex: _fnNodeToDataIndex,
14691		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
14692		_fnGetCellData: _fnGetCellData,
14693		_fnSetCellData: _fnSetCellData,
14694		_fnSplitObjNotation: _fnSplitObjNotation,
14695		_fnGetObjectDataFn: _fnGetObjectDataFn,
14696		_fnSetObjectDataFn: _fnSetObjectDataFn,
14697		_fnGetDataMaster: _fnGetDataMaster,
14698		_fnClearTable: _fnClearTable,
14699		_fnDeleteIndex: _fnDeleteIndex,
14700		_fnInvalidate: _fnInvalidate,
14701		_fnGetRowElements: _fnGetRowElements,
14702		_fnCreateTr: _fnCreateTr,
14703		_fnBuildHead: _fnBuildHead,
14704		_fnDrawHead: _fnDrawHead,
14705		_fnDraw: _fnDraw,
14706		_fnReDraw: _fnReDraw,
14707		_fnAddOptionsHtml: _fnAddOptionsHtml,
14708		_fnDetectHeader: _fnDetectHeader,
14709		_fnGetUniqueThs: _fnGetUniqueThs,
14710		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
14711		_fnFilterComplete: _fnFilterComplete,
14712		_fnFilterCustom: _fnFilterCustom,
14713		_fnFilterColumn: _fnFilterColumn,
14714		_fnFilter: _fnFilter,
14715		_fnFilterCreateSearch: _fnFilterCreateSearch,
14716		_fnEscapeRegex: _fnEscapeRegex,
14717		_fnFilterData: _fnFilterData,
14718		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
14719		_fnUpdateInfo: _fnUpdateInfo,
14720		_fnInfoMacros: _fnInfoMacros,
14721		_fnInitialise: _fnInitialise,
14722		_fnInitComplete: _fnInitComplete,
14723		_fnLengthChange: _fnLengthChange,
14724		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
14725		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
14726		_fnPageChange: _fnPageChange,
14727		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
14728		_fnProcessingDisplay: _fnProcessingDisplay,
14729		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
14730		_fnScrollDraw: _fnScrollDraw,
14731		_fnApplyToChildren: _fnApplyToChildren,
14732		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
14733		_fnThrottle: _fnThrottle,
14734		_fnConvertToWidth: _fnConvertToWidth,
14735		_fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14736		_fnGetWidestNode: _fnGetWidestNode,
14737		_fnGetMaxLenString: _fnGetMaxLenString,
14738		_fnStringToCss: _fnStringToCss,
14739		_fnScrollBarWidth: _fnScrollBarWidth,
14740		_fnSortFlatten: _fnSortFlatten,
14741		_fnSort: _fnSort,
14742		_fnSortAria: _fnSortAria,
14743		_fnSortListener: _fnSortListener,
14744		_fnSortAttachListener: _fnSortAttachListener,
14745		_fnSortingClasses: _fnSortingClasses,
14746		_fnSortData: _fnSortData,
14747		_fnSaveState: _fnSaveState,
14748		_fnLoadState: _fnLoadState,
14749		_fnSettingsFromNode: _fnSettingsFromNode,
14750		_fnLog: _fnLog,
14751		_fnMap: _fnMap,
14752		_fnBindAction: _fnBindAction,
14753		_fnCallbackReg: _fnCallbackReg,
14754		_fnCallbackFire: _fnCallbackFire,
14755		_fnLengthOverflow: _fnLengthOverflow,
14756		_fnRenderer: _fnRenderer,
14757		_fnDataSource: _fnDataSource,
14758		_fnRowAttributes: _fnRowAttributes,
14759		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14760		                                // in 1.10, so this dead-end function is
14761		                                // added to prevent errors
14762	} );
14763	
14764
14765	// jQuery access
14766	$.fn.dataTable = DataTable;
14767
14768	// Legacy aliases
14769	$.fn.dataTableSettings = DataTable.settings;
14770	$.fn.dataTableExt = DataTable.ext;
14771
14772	// With a capital `D` we return a DataTables API instance rather than a
14773	// jQuery object
14774	$.fn.DataTable = function ( opts ) {
14775		return $(this).dataTable( opts ).api();
14776	};
14777
14778	// All properties that are available to $.fn.dataTable should also be
14779	// available on $.fn.DataTable
14780	$.each( DataTable, function ( prop, val ) {
14781		$.fn.DataTable[ prop ] = val;
14782	} );
14783
14784
14785	// Information about events fired by DataTables - for documentation.
14786	/**
14787	 * Draw event, fired whenever the table is redrawn on the page, at the same
14788	 * point as fnDrawCallback. This may be useful for binding events or
14789	 * performing calculations when the table is altered at all.
14790	 *  @name DataTable#draw.dt
14791	 *  @event
14792	 *  @param {event} e jQuery event object
14793	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14794	 */
14795
14796	/**
14797	 * Search event, fired when the searching applied to the table (using the
14798	 * built-in global search, or column filters) is altered.
14799	 *  @name DataTable#search.dt
14800	 *  @event
14801	 *  @param {event} e jQuery event object
14802	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14803	 */
14804
14805	/**
14806	 * Page change event, fired when the paging of the table is altered.
14807	 *  @name DataTable#page.dt
14808	 *  @event
14809	 *  @param {event} e jQuery event object
14810	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14811	 */
14812
14813	/**
14814	 * Order event, fired when the ordering applied to the table is altered.
14815	 *  @name DataTable#order.dt
14816	 *  @event
14817	 *  @param {event} e jQuery event object
14818	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14819	 */
14820
14821	/**
14822	 * DataTables initialisation complete event, fired when the table is fully
14823	 * drawn, including Ajax data loaded, if Ajax data is required.
14824	 *  @name DataTable#init.dt
14825	 *  @event
14826	 *  @param {event} e jQuery event object
14827	 *  @param {object} oSettings DataTables settings object
14828	 *  @param {object} json The JSON object request from the server - only
14829	 *    present if client-side Ajax sourced data is used</li></ol>
14830	 */
14831
14832	/**
14833	 * State save event, fired when the table has changed state a new state save
14834	 * is required. This event allows modification of the state saving object
14835	 * prior to actually doing the save, including addition or other state
14836	 * properties (for plug-ins) or modification of a DataTables core property.
14837	 *  @name DataTable#stateSaveParams.dt
14838	 *  @event
14839	 *  @param {event} e jQuery event object
14840	 *  @param {object} oSettings DataTables settings object
14841	 *  @param {object} json The state information to be saved
14842	 */
14843
14844	/**
14845	 * State load event, fired when the table is loading state from the stored
14846	 * data, but prior to the settings object being modified by the saved state
14847	 * - allowing modification of the saved state is required or loading of
14848	 * state for a plug-in.
14849	 *  @name DataTable#stateLoadParams.dt
14850	 *  @event
14851	 *  @param {event} e jQuery event object
14852	 *  @param {object} oSettings DataTables settings object
14853	 *  @param {object} json The saved state information
14854	 */
14855
14856	/**
14857	 * State loaded event, fired when state has been loaded from stored data and
14858	 * the settings object has been modified by the loaded data.
14859	 *  @name DataTable#stateLoaded.dt
14860	 *  @event
14861	 *  @param {event} e jQuery event object
14862	 *  @param {object} oSettings DataTables settings object
14863	 *  @param {object} json The saved state information
14864	 */
14865
14866	/**
14867	 * Processing event, fired when DataTables is doing some kind of processing
14868	 * (be it, order, searcg or anything else). It can be used to indicate to
14869	 * the end user that there is something happening, or that something has
14870	 * finished.
14871	 *  @name DataTable#processing.dt
14872	 *  @event
14873	 *  @param {event} e jQuery event object
14874	 *  @param {object} oSettings DataTables settings object
14875	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
14876	 */
14877
14878	/**
14879	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
14880	 * request to made to the server for new data. This event is called before
14881	 * DataTables processed the returned data, so it can also be used to pre-
14882	 * process the data returned from the server, if needed.
14883	 *
14884	 * Note that this trigger is called in `fnServerData`, if you override
14885	 * `fnServerData` and which to use this event, you need to trigger it in you
14886	 * success function.
14887	 *  @name DataTable#xhr.dt
14888	 *  @event
14889	 *  @param {event} e jQuery event object
14890	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14891	 *  @param {object} json JSON returned from the server
14892	 *
14893	 *  @example
14894	 *     // Use a custom property returned from the server in another DOM element
14895	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14896	 *       $('#status').html( json.status );
14897	 *     } );
14898	 *
14899	 *  @example
14900	 *     // Pre-process the data returned from the server
14901	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14902	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
14903	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
14904	 *       }
14905	 *       // Note no return - manipulate the data directly in the JSON object.
14906	 *     } );
14907	 */
14908
14909	/**
14910	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
14911	 * or passing the bDestroy:true parameter in the initialisation object. This
14912	 * can be used to remove bound events, added DOM nodes, etc.
14913	 *  @name DataTable#destroy.dt
14914	 *  @event
14915	 *  @param {event} e jQuery event object
14916	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14917	 */
14918
14919	/**
14920	 * Page length change event, fired when number of records to show on each
14921	 * page (the length) is changed.
14922	 *  @name DataTable#length.dt
14923	 *  @event
14924	 *  @param {event} e jQuery event object
14925	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14926	 *  @param {integer} len New length
14927	 */
14928
14929	/**
14930	 * Column sizing has changed.
14931	 *  @name DataTable#column-sizing.dt
14932	 *  @event
14933	 *  @param {event} e jQuery event object
14934	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14935	 */
14936
14937	/**
14938	 * Column visibility has changed.
14939	 *  @name DataTable#column-visibility.dt
14940	 *  @event
14941	 *  @param {event} e jQuery event object
14942	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14943	 *  @param {int} column Column index
14944	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
14945	 */
14946
14947	return $.fn.dataTable;
14948}));
14949
14950}(window, document));
14951

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.