PageSourceSearch

https://asia-guide.biz/wp-content/themes/noo-jobmonster/assets/vendor/DataTables/datatables.min.js

js asia-guide.biz collected 2026-10-08 09:22:36 UTC 488,538 bytes, 16,812 lines download raw bytes

1/*
2 * This combined file was created by the DataTables downloader builder:
3 *   https://datatables.net/download
4 *
5 * To rebuild or modify this file with the latest versions of the included
6 * software please visit:
7 *   https://datatables.net/download/#bs/dt-1.10.16/r-2.2.1
8 *
9 * Included libraries:
10 *   DataTables 1.10.16, Responsive 2.2.1
11 */
12
13/*! DataTables 1.10.16
14 * ©2008-2017 SpryMedia Ltd - datatables.net/license
15 */
16
17/**
18 * @summary     DataTables
19 * @description Paginate, search and order HTML tables
20 * @version     1.10.16
21 * @file        jquery.dataTables.js
22 * @author      SpryMedia Ltd
23 * @contact     www.datatables.net
24 * @copyright   Copyright 2008-2017 SpryMedia Ltd.
25 *
26 * This source file is free software, available under the following license:
27 *   MIT license - http://datatables.net/license
28 *
29 * This source file is distributed in the hope that it will be useful, but
30 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
31 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
32 *
33 * For details please refer to: http://www.datatables.net
34 */
35
36/*jslint evil: true, undef: true, browser: true */
37/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
38
39(function( factory ) {
40	"use strict";
41
42	if ( typeof define === 'function' && define.amd ) {
43		// AMD
44		define( ['jquery'], function ( $ ) {
45			return factory( $, window, document );
46		} );
47	}
48	else if ( typeof exports === 'object' ) {
49		// CommonJS
50		module.exports = function (root, $) {
51			if ( ! root ) {
52				// CommonJS environments without a window global must pass a
53				// root. This will give an error otherwise
54				root = window;
55			}
56
57			if ( ! $ ) {
58				$ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
59					require('jquery') :
60					require('jquery')( root );
61			}
62
63			return factory( $, root, root.document );
64		};
65	}
66	else {
67		// Browser
68		factory( jQuery, window, document );
69	}
70}
71(function( $, window, document, undefined ) {
72	"use strict";
73
74	/**
75	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
76	 * flexible tool, based upon the foundations of progressive enhancement,
77	 * which will add advanced interaction controls to any HTML table. For a
78	 * full list of features please refer to
79	 * [DataTables.net](href="http://datatables.net).
80	 *
81	 * Note that the `DataTable` object is not a global variable but is aliased
82	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
83	 * be  accessed.
84	 *
85	 *  @class
86	 *  @param {object} [init={}] Configuration object for DataTables. Options
87	 *    are defined by {@link DataTable.defaults}
88	 *  @requires jQuery 1.7+
89	 *
90	 *  @example
91	 *    // Basic initialisation
92	 *    $(document).ready( function {
93	 *      $('#example').dataTable();
94	 *    } );
95	 *
96	 *  @example
97	 *    // Initialisation with configuration options - in this case, disable
98	 *    // pagination and sorting.
99	 *    $(document).ready( function {
100	 *      $('#example').dataTable( {
101	 *        "paginate": false,
102	 *        "sort": false
103	 *      } );
104	 *    } );
105	 */
106	var DataTable = function ( options )
107	{
vendor: 6,636 bytes, lines 107-266
107
108		/**
109		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
110		 * return the resulting jQuery object.
111		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
112		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
113		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
114		 *    criterion ("applied") or all TR elements (i.e. no filter).
115		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
116		 *    Can be either 'current', whereby the current sorting of the table is used, or
117		 *    'original' whereby the original order the data was read into the table is used.
118		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
119		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
120		 *    'current' and filter is 'applied', regardless of what they might be given as.
121		 *  @returns {object} jQuery object, filtered by the given selector.
122		 *  @dtopt API
123		 *  @deprecated Since v1.10
124		 *
125		 *  @example
126		 *    $(document).ready(function() {
127		 *      var oTable = $('#example').dataTable();
128		 *
129		 *      // Highlight every second row
130		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
131		 *    } );
132		 *
133		 *  @example
134		 *    $(document).ready(function() {
135		 *      var oTable = $('#example').dataTable();
136		 *
137		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
138		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
139		 *      oTable.fnFilter('Webkit');
140		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
141		 *      oTable.fnFilter('');
142		 *    } );
143		 */
144		this.$ = function ( sSelector, oOpts )
145		{
146			return this.api(true).$( sSelector, oOpts );
147		};
148		
149		
150		/**
151		 * Almost identical to $ in operation, but in this case returns the data for the matched
152		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
153		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
154		 * rows are found, the data returned is the original data array/object that was used to
155		 * create the row (or a generated array if from a DOM source).
156		 *
157		 * This method is often useful in-combination with $ where both functions are given the
158		 * same parameters and the array indexes will match identically.
159		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
160		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
161		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
162		 *    criterion ("applied") or all elements (i.e. no filter).
163		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
164		 *    Can be either 'current', whereby the current sorting of the table is used, or
165		 *    'original' whereby the original order the data was read into the table is used.
166		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
167		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
168		 *    'current' and filter is 'applied', regardless of what they might be given as.
169		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
170		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
171		 *    entry in the array.
172		 *  @dtopt API
173		 *  @deprecated Since v1.10
174		 *
175		 *  @example
176		 *    $(document).ready(function() {
177		 *      var oTable = $('#example').dataTable();
178		 *
179		 *      // Get the data from the first row in the table
180		 *      var data = oTable._('tr:first');
181		 *
182		 *      // Do something useful with the data
183		 *      alert( "First cell is: "+data[0] );
184		 *    } );
185		 *
186		 *  @example
187		 *    $(document).ready(function() {
188		 *      var oTable = $('#example').dataTable();
189		 *
190		 *      // Filter to 'Webkit' and get all data for
191		 *      oTable.fnFilter('Webkit');
192		 *      var data = oTable._('tr', {"search": "applied"});
193		 *
194		 *      // Do something with the data
195		 *      alert( data.length+" rows matched the search" );
196		 *    } );
197		 */
198		this._ = function ( sSelector, oOpts )
199		{
200			return this.api(true).rows( sSelector, oOpts ).data();
201		};
202		
203		
204		/**
205		 * Create a DataTables Api instance, with the currently selected tables for
206		 * the Api's context.
207		 * @param {boolean} [traditional=false] Set the API instance's context to be
208		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
209		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
210		 *   or if all tables captured in the jQuery object should be used.
211		 * @return {DataTables.Api}
212		 */
213		this.api = function ( traditional )
214		{
215			return traditional ?
216				new _Api(
217					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
218				) :
219				new _Api( this );
220		};
221		
222		
223		/**
224		 * Add a single new row or multiple rows of data to the table. Please note
225		 * that this is suitable for client-side processing only - if you are using
226		 * server-side processing (i.e. "bServerSide": true), then to add data, you
227		 * must add it to the data source, i.e. the server-side, through an Ajax call.
228		 *  @param {array|object} data The data to be added to the table. This can be:
229		 *    <ul>
230		 *      <li>1D array of data - add a single row with the data provided</li>
231		 *      <li>2D array of arrays - add multiple rows in a single call</li>
232		 *      <li>object - data object when using <i>mData</i></li>
233		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
234		 *    </ul>
235		 *  @param {bool} [redraw=true] redraw the table or not
236		 *  @returns {array} An array of integers, representing the list of indexes in
237		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
238		 *    the table.
239		 *  @dtopt API
240		 *  @deprecated Since v1.10
241		 *
242		 *  @example
243		 *    // Global var for counter
244		 *    var giCount = 2;
245		 *
246		 *    $(document).ready(function() {
247		 *      $('#example').dataTable();
248		 *    } );
249		 *
250		 *    function fnClickAddRow() {
251		 *      $('#example').dataTable().fnAddData( [
252		 *        giCount+".1",
253		 *        giCount+".2",
254		 *        giCount+".3",
255		 *        giCount+".4" ]
256		 *      );
257		 *
258		 *      giCount++;
259		 *    }
260		 */
261		this.fnAddData = function( data, redraw )
262		{
263			var api = this.api( true );
264		
265			/* Check if we want to add multiple rows or not */
266			var rows = 
266$.isArray(data) && ( $
vendor: 18,409 bytes, lines 266-862
266.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
267				api.rows.add( data ) :
268				api.row.add( data );
269		
270			if ( redraw === undefined || redraw ) {
271				api.draw();
272			}
273		
274			return rows.flatten().toArray();
275		};
276		
277		
278		/**
279		 * This function will make DataTables recalculate the column sizes, based on the data
280		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
281		 * through the sWidth parameter). This can be useful when the width of the table's
282		 * parent element changes (for example a window resize).
283		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
284		 *  @dtopt API
285		 *  @deprecated Since v1.10
286		 *
287		 *  @example
288		 *    $(document).ready(function() {
289		 *      var oTable = $('#example').dataTable( {
290		 *        "sScrollY": "200px",
291		 *        "bPaginate": false
292		 *      } );
293		 *
294		 *      $(window).on('resize', function () {
295		 *        oTable.fnAdjustColumnSizing();
296		 *      } );
297		 *    } );
298		 */
299		this.fnAdjustColumnSizing = function ( bRedraw )
300		{
301			var api = this.api( true ).columns.adjust();
302			var settings = api.settings()[0];
303			var scroll = settings.oScroll;
304		
305			if ( bRedraw === undefined || bRedraw ) {
306				api.draw( false );
307			}
308			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
309				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
310				_fnScrollDraw( settings );
311			}
312		};
313		
314		
315		/**
316		 * Quickly and simply clear a table
317		 *  @param {bool} [bRedraw=true] redraw the table or not
318		 *  @dtopt API
319		 *  @deprecated Since v1.10
320		 *
321		 *  @example
322		 *    $(document).ready(function() {
323		 *      var oTable = $('#example').dataTable();
324		 *
325		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
326		 *      oTable.fnClearTable();
327		 *    } );
328		 */
329		this.fnClearTable = function( bRedraw )
330		{
331			var api = this.api( true ).clear();
332		
333			if ( bRedraw === undefined || bRedraw ) {
334				api.draw();
335			}
336		};
337		
338		
339		/**
340		 * The exact opposite of 'opening' a row, this function will close any rows which
341		 * are currently 'open'.
342		 *  @param {node} nTr the table row to 'close'
343		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
344		 *  @dtopt API
345		 *  @deprecated Since v1.10
346		 *
347		 *  @example
348		 *    $(document).ready(function() {
349		 *      var oTable;
350		 *
351		 *      // 'open' an information row when a row is clicked on
352		 *      $('#example tbody tr').click( function () {
353		 *        if ( oTable.fnIsOpen(this) ) {
354		 *          oTable.fnClose( this );
355		 *        } else {
356		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
357		 *        }
358		 *      } );
359		 *
360		 *      oTable = $('#example').dataTable();
361		 *    } );
362		 */
363		this.fnClose = function( nTr )
364		{
365			this.api( true ).row( nTr ).child.hide();
366		};
367		
368		
369		/**
370		 * Remove a row for the table
371		 *  @param {mixed} target The index of the row from aoData to be deleted, or
372		 *    the TR element you want to delete
373		 *  @param {function|null} [callBack] Callback function
374		 *  @param {bool} [redraw=true] Redraw the table or not
375		 *  @returns {array} The row that was deleted
376		 *  @dtopt API
377		 *  @deprecated Since v1.10
378		 *
379		 *  @example
380		 *    $(document).ready(function() {
381		 *      var oTable = $('#example').dataTable();
382		 *
383		 *      // Immediately remove the first row
384		 *      oTable.fnDeleteRow( 0 );
385		 *    } );
386		 */
387		this.fnDeleteRow = function( target, callback, redraw )
388		{
389			var api = this.api( true );
390			var rows = api.rows( target );
391			var settings = rows.settings()[0];
392			var data = settings.aoData[ rows[0][0] ];
393		
394			rows.remove();
395		
396			if ( callback ) {
397				callback.call( this, settings, data );
398			}
399		
400			if ( redraw === undefined || redraw ) {
401				api.draw();
402			}
403		
404			return data;
405		};
406		
407		
408		/**
409		 * Restore the table to it's original state in the DOM by removing all of DataTables
410		 * enhancements, alterations to the DOM structure of the table and event listeners.
411		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
412		 *  @dtopt API
413		 *  @deprecated Since v1.10
414		 *
415		 *  @example
416		 *    $(document).ready(function() {
417		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
418		 *      var oTable = $('#example').dataTable();
419		 *      oTable.fnDestroy();
420		 *    } );
421		 */
422		this.fnDestroy = function ( remove )
423		{
424			this.api( true ).destroy( remove );
425		};
426		
427		
428		/**
429		 * Redraw the table
430		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
431		 *  @dtopt API
432		 *  @deprecated Since v1.10
433		 *
434		 *  @example
435		 *    $(document).ready(function() {
436		 *      var oTable = $('#example').dataTable();
437		 *
438		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
439		 *      oTable.fnDraw();
440		 *    } );
441		 */
442		this.fnDraw = function( complete )
443		{
444			// Note that this isn't an exact match to the old call to _fnDraw - it takes
445			// into account the new data, but can hold position.
446			this.api( true ).draw( complete );
447		};
448		
449		
450		/**
451		 * Filter the input based on data
452		 *  @param {string} sInput String to filter the table on
453		 *  @param {int|null} [iColumn] Column to limit filtering to
454		 *  @param {bool} [bRegex=false] Treat as regular expression or not
455		 *  @param {bool} [bSmart=true] Perform smart filtering or not
456		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
457		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
458		 *  @dtopt API
459		 *  @deprecated Since v1.10
460		 *
461		 *  @example
462		 *    $(document).ready(function() {
463		 *      var oTable = $('#example').dataTable();
464		 *
465		 *      // Sometime later - filter...
466		 *      oTable.fnFilter( 'test string' );
467		 *    } );
468		 */
469		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
470		{
471			var api = this.api( true );
472		
473			if ( iColumn === null || iColumn === undefined ) {
474				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
475			}
476			else {
477				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
478			}
479		
480			api.draw();
481		};
482		
483		
484		/**
485		 * Get the data for the whole table, an individual row or an individual cell based on the
486		 * provided parameters.
487		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
488		 *    a TR node then the data source for the whole row will be returned. If given as a
489		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
490		 *    cell returned. If given as an integer, then this is treated as the aoData internal
491		 *    data index for the row (see fnGetPosition) and the data for that row used.
492		 *  @param {int} [col] Optional column index that you want the data of.
493		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
494		 *    returned. If mRow is defined, just data for that row, and is iCol is
495		 *    defined, only data for the designated cell is returned.
496		 *  @dtopt API
497		 *  @deprecated Since v1.10
498		 *
499		 *  @example
500		 *    // Row data
501		 *    $(document).ready(function() {
502		 *      oTable = $('#example').dataTable();
503		 *
504		 *      oTable.$('tr').click( function () {
505		 *        var data = oTable.fnGetData( this );
506		 *        // ... do something with the array / object of data for the row
507		 *      } );
508		 *    } );
509		 *
510		 *  @example
511		 *    // Individual cell data
512		 *    $(document).ready(function() {
513		 *      oTable = $('#example').dataTable();
514		 *
515		 *      oTable.$('td').click( function () {
516		 *        var sData = oTable.fnGetData( this );
517		 *        alert( 'The cell clicked on had the value of '+sData );
518		 *      } );
519		 *    } );
520		 */
521		this.fnGetData = function( src, col )
522		{
523			var api = this.api( true );
524		
525			if ( src !== undefined ) {
526				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
527		
528				return col !== undefined || type == 'td' || type == 'th' ?
529					api.cell( src, col ).data() :
530					api.row( src ).data() || null;
531			}
532		
533			return api.data().toArray();
534		};
535		
536		
537		/**
538		 * Get an array of the TR nodes that are used in the table's body. Note that you will
539		 * typically want to use the '$' API method in preference to this as it is more
540		 * flexible.
541		 *  @param {int} [iRow] Optional row index for the TR element you want
542		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
543		 *    in the table's body, or iRow is defined, just the TR element requested.
544		 *  @dtopt API
545		 *  @deprecated Since v1.10
546		 *
547		 *  @example
548		 *    $(document).ready(function() {
549		 *      var oTable = $('#example').dataTable();
550		 *
551		 *      // Get the nodes from the table
552		 *      var nNodes = oTable.fnGetNodes( );
553		 *    } );
554		 */
555		this.fnGetNodes = function( iRow )
556		{
557			var api = this.api( true );
558		
559			return iRow !== undefined ?
560				api.row( iRow ).node() :
561				api.rows().nodes().flatten().toArray();
562		};
563		
564		
565		/**
566		 * Get the array indexes of a particular cell from it's DOM element
567		 * and column index including hidden columns
568		 *  @param {node} node this can either be a TR, TD or TH in the table's body
569		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
570		 *    if given as a cell, an array of [row index, column index (visible),
571		 *    column index (all)] is given.
572		 *  @dtopt API
573		 *  @deprecated Since v1.10
574		 *
575		 *  @example
576		 *    $(document).ready(function() {
577		 *      $('#example tbody td').click( function () {
578		 *        // Get the position of the current data from the node
579		 *        var aPos = oTable.fnGetPosition( this );
580		 *
581		 *        // Get the data array for this row
582		 *        var aData = oTable.fnGetData( aPos[0] );
583		 *
584		 *        // Update the data array and return the value
585		 *        aData[ aPos[1] ] = 'clicked';
586		 *        this.innerHTML = 'clicked';
587		 *      } );
588		 *
589		 *      // Init DataTables
590		 *      oTable = $('#example').dataTable();
591		 *    } );
592		 */
593		this.fnGetPosition = function( node )
594		{
595			var api = this.api( true );
596			var nodeName = node.nodeName.toUpperCase();
597		
598			if ( nodeName == 'TR' ) {
599				return api.row( node ).index();
600			}
601			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
602				var cell = api.cell( node ).index();
603		
604				return [
605					cell.row,
606					cell.columnVisible,
607					cell.column
608				];
609			}
610			return null;
611		};
612		
613		
614		/**
615		 * Check to see if a row is 'open' or not.
616		 *  @param {node} nTr the table row to check
617		 *  @returns {boolean} true if the row is currently open, false otherwise
618		 *  @dtopt API
619		 *  @deprecated Since v1.10
620		 *
621		 *  @example
622		 *    $(document).ready(function() {
623		 *      var oTable;
624		 *
625		 *      // 'open' an information row when a row is clicked on
626		 *      $('#example tbody tr').click( function () {
627		 *        if ( oTable.fnIsOpen(this) ) {
628		 *          oTable.fnClose( this );
629		 *        } else {
630		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
631		 *        }
632		 *      } );
633		 *
634		 *      oTable = $('#example').dataTable();
635		 *    } );
636		 */
637		this.fnIsOpen = function( nTr )
638		{
639			return this.api( true ).row( nTr ).child.isShown();
640		};
641		
642		
643		/**
644		 * This function will place a new row directly after a row which is currently
645		 * on display on the page, with the HTML contents that is passed into the
646		 * function. This can be used, for example, to ask for confirmation that a
647		 * particular record should be deleted.
648		 *  @param {node} nTr The table row to 'open'
649		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
650		 *  @param {string} sClass Class to give the new TD cell
651		 *  @returns {node} The row opened. Note that if the table row passed in as the
652		 *    first parameter, is not found in the table, this method will silently
653		 *    return.
654		 *  @dtopt API
655		 *  @deprecated Since v1.10
656		 *
657		 *  @example
658		 *    $(document).ready(function() {
659		 *      var oTable;
660		 *
661		 *      // 'open' an information row when a row is clicked on
662		 *      $('#example tbody tr').click( function () {
663		 *        if ( oTable.fnIsOpen(this) ) {
664		 *          oTable.fnClose( this );
665		 *        } else {
666		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
667		 *        }
668		 *      } );
669		 *
670		 *      oTable = $('#example').dataTable();
671		 *    } );
672		 */
673		this.fnOpen = function( nTr, mHtml, sClass )
674		{
675			return this.api( true )
676				.row( nTr )
677				.child( mHtml, sClass )
678				.show()
679				.child()[0];
680		};
681		
682		
683		/**
684		 * Change the pagination - provides the internal logic for pagination in a simple API
685		 * function. With this function you can have a DataTables table go to the next,
686		 * previous, first or last pages.
687		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
688		 *    or page number to jump to (integer), note that page 0 is the first page.
689		 *  @param {bool} [bRedraw=true] Redraw the table or not
690		 *  @dtopt API
691		 *  @deprecated Since v1.10
692		 *
693		 *  @example
694		 *    $(document).ready(function() {
695		 *      var oTable = $('#example').dataTable();
696		 *      oTable.fnPageChange( 'next' );
697		 *    } );
698		 */
699		this.fnPageChange = function ( mAction, bRedraw )
700		{
701			var api = this.api( true ).page( mAction );
702		
703			if ( bRedraw === undefined || bRedraw ) {
704				api.draw(false);
705			}
706		};
707		
708		
709		/**
710		 * Show a particular column
711		 *  @param {int} iCol The column whose display should be changed
712		 *  @param {bool} bShow Show (true) or hide (false) the column
713		 *  @param {bool} [bRedraw=true] Redraw the table or not
714		 *  @dtopt API
715		 *  @deprecated Since v1.10
716		 *
717		 *  @example
718		 *    $(document).ready(function() {
719		 *      var oTable = $('#example').dataTable();
720		 *
721		 *      // Hide the second column after initialisation
722		 *      oTable.fnSetColumnVis( 1, false );
723		 *    } );
724		 */
725		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
726		{
727			var api = this.api( true ).column( iCol ).visible( bShow );
728		
729			if ( bRedraw === undefined || bRedraw ) {
730				api.columns.adjust().draw();
731			}
732		};
733		
734		
735		/**
736		 * Get the settings for a particular table for external manipulation
737		 *  @returns {object} DataTables settings object. See
738		 *    {@link DataTable.models.oSettings}
739		 *  @dtopt API
740		 *  @deprecated Since v1.10
741		 *
742		 *  @example
743		 *    $(document).ready(function() {
744		 *      var oTable = $('#example').dataTable();
745		 *      var oSettings = oTable.fnSettings();
746		 *
747		 *      // Show an example parameter from the settings
748		 *      alert( oSettings._iDisplayStart );
749		 *    } );
750		 */
751		this.fnSettings = function()
752		{
753			return _fnSettingsFromNode( this[_ext.iApiIndex] );
754		};
755		
756		
757		/**
758		 * Sort the table by a particular column
759		 *  @param {int} iCol the data index to sort on. Note that this will not match the
760		 *    'display index' if you have hidden data entries
761		 *  @dtopt API
762		 *  @deprecated Since v1.10
763		 *
764		 *  @example
765		 *    $(document).ready(function() {
766		 *      var oTable = $('#example').dataTable();
767		 *
768		 *      // Sort immediately with columns 0 and 1
769		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
770		 *    } );
771		 */
772		this.fnSort = function( aaSort )
773		{
774			this.api( true ).order( aaSort ).draw();
775		};
776		
777		
778		/**
779		 * Attach a sort listener to an element for a given column
780		 *  @param {node} nNode the element to attach the sort listener to
781		 *  @param {int} iColumn the column that a click on this node will sort on
782		 *  @param {function} [fnCallback] callback function when sort is run
783		 *  @dtopt API
784		 *  @deprecated Since v1.10
785		 *
786		 *  @example
787		 *    $(document).ready(function() {
788		 *      var oTable = $('#example').dataTable();
789		 *
790		 *      // Sort on column 1, when 'sorter' is clicked on
791		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
792		 *    } );
793		 */
794		this.fnSortListener = function( nNode, iColumn, fnCallback )
795		{
796			this.api( true ).order.listener( nNode, iColumn, fnCallback );
797		};
798		
799		
800		/**
801		 * Update a table cell or row - this method will accept either a single value to
802		 * update the cell with, an array of values with one element for each column or
803		 * an object in the same format as the original data source. The function is
804		 * self-referencing in order to make the multi column updates easier.
805		 *  @param {object|array|string} mData Data to update the cell/row with
806		 *  @param {node|int} mRow TR element you want to update or the aoData index
807		 *  @param {int} [iColumn] The column to update, give as null or undefined to
808		 *    update a whole row.
809		 *  @param {bool} [bRedraw=true] Redraw the table or not
810		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
811		 *  @returns {int} 0 on success, 1 on error
812		 *  @dtopt API
813		 *  @deprecated Since v1.10
814		 *
815		 *  @example
816		 *    $(document).ready(function() {
817		 *      var oTable = $('#example').dataTable();
818		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
819		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
820		 *    } );
821		 */
822		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
823		{
824			var api = this.api( true );
825		
826			if ( iColumn === undefined || iColumn === null ) {
827				api.row( mRow ).data( mData );
828			}
829			else {
830				api.cell( mRow, iColumn ).data( mData );
831			}
832		
833			if ( bAction === undefined || bAction ) {
834				api.columns.adjust();
835			}
836		
837			if ( bRedraw === undefined || bRedraw ) {
838				api.draw();
839			}
840			return 0;
841		};
842		
843		
844		/**
845		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
846		 * to ensure compatibility.
847		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
848		 *    formats "X" and "X.Y" are also acceptable.
849		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
850		 *    version, or false if this version of DataTales is not suitable
851		 *  @method
852		 *  @dtopt API
853		 *  @deprecated Since v1.10
854		 *
855		 *  @example
856		 *    $(document).ready(function() {
857		 *      var oTable = $('#example').dataTable();
858		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
859		 *    } );
860		 */
861		this.fnVersionCheck = _ext.fnVersionCheck;
862		
vendor: 57,429 bytes, lines 863-2872
863
864		var _that = this;
865		var emptyInit = options === undefined;
866		var len = this.length;
867
868		if ( emptyInit ) {
869			options = {};
870		}
871
872		this.oApi = this.internal = _ext.internal;
873
874		// Extend with old style plug-in API methods
875		for ( var fn in DataTable.ext.internal ) {
876			if ( fn ) {
877				this[fn] = _fnExternApiFunc(fn);
878			}
879		}
880
881		this.each(function() {
882			// For each initialisation we want to give it a clean initialisation
883			// object that can be bashed around
884			var o = {};
885			var oInit = len > 1 ? // optimisation for single table case
886				_fnExtend( o, options, true ) :
887				options;
888
889			/*global oInit,_that,emptyInit*/
890			var i=0, iLen, j, jLen, k, kLen;
891			var sId = this.getAttribute( 'id' );
892			var bInitHandedOff = false;
893			var defaults = DataTable.defaults;
894			var $this = $(this);
895			
896			
897			/* Sanity check */
898			if ( this.nodeName.toLowerCase() != 'table' )
899			{
900				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
901				return;
902			}
903			
904			/* Backwards compatibility for the defaults */
905			_fnCompatOpts( defaults );
906			_fnCompatCols( defaults.column );
907			
908			/* Convert the camel-case defaults to Hungarian */
909			_fnCamelToHungarian( defaults, defaults, true );
910			_fnCamelToHungarian( defaults.column, defaults.column, true );
911			
912			/* Setting up the initialisation object */
913			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
914			
915			
916			
917			/* Check to see if we are re-initialising a table */
918			var allSettings = DataTable.settings;
919			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
920			{
921				var s = allSettings[i];
922			
923				/* Base check on table node */
924				if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
925				{
926					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
927					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
928			
929					if ( emptyInit || bRetrieve )
930					{
931						return s.oInstance;
932					}
933					else if ( bDestroy )
934					{
935						s.oInstance.fnDestroy();
936						break;
937					}
938					else
939					{
940						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
941						return;
942					}
943				}
944			
945				/* If the element we are initialising has the same ID as a table which was previously
946				 * initialised, but the table nodes don't match (from before) then we destroy the old
947				 * instance by simply deleting it. This is under the assumption that the table has been
948				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
949				 */
950				if ( s.sTableId == this.id )
951				{
952					allSettings.splice( i, 1 );
953					break;
954				}
955			}
956			
957			/* Ensure the table has an ID - required for accessibility */
958			if ( sId === null || sId === "" )
959			{
960				sId = "DataTables_Table_"+(DataTable.ext._unique++);
961				this.id = sId;
962			}
963			
964			/* Create the settings object for this table and set some of the default parameters */
965			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
966				"sDestroyWidth": $this[0].style.width,
967				"sInstance":     sId,
968				"sTableId":      sId
969			} );
970			oSettings.nTable = this;
971			oSettings.oApi   = _that.internal;
972			oSettings.oInit  = oInit;
973			
974			allSettings.push( oSettings );
975			
976			// Need to add the instance after the instance after the settings object has been added
977			// to the settings array, so we can self reference the table instance if more than one
978			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
979			
980			// Backwards compatibility, before we apply all the defaults
981			_fnCompatOpts( oInit );
982			
983			if ( oInit.oLanguage )
984			{
985				_fnLanguageCompat( oInit.oLanguage );
986			}
987			
988			// If the length menu is given, but the init display length is not, use the length menu
989			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
990			{
991				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
992					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
993			}
994			
995			// Apply the defaults and init options to make a single init object will all
996			// options defined from defaults and instance options.
997			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
998			
999			
1000			// Map the initialisation options onto the settings object
1001			_fnMap( oSettings.oFeatures, oInit, [
1002				"bPaginate",
1003				"bLengthChange",
1004				"bFilter",
1005				"bSort",
1006				"bSortMulti",
1007				"bInfo",
1008				"bProcessing",
1009				"bAutoWidth",
1010				"bSortClasses",
1011				"bServerSide",
1012				"bDeferRender"
1013			] );
1014			_fnMap( oSettings, oInit, [
1015				"asStripeClasses",
1016				"ajax",
1017				"fnServerData",
1018				"fnFormatNumber",
1019				"sServerMethod",
1020				"aaSorting",
1021				"aaSortingFixed",
1022				"aLengthMenu",
1023				"sPaginationType",
1024				"sAjaxSource",
1025				"sAjaxDataProp",
1026				"iStateDuration",
1027				"sDom",
1028				"bSortCellsTop",
1029				"iTabIndex",
1030				"fnStateLoadCallback",
1031				"fnStateSaveCallback",
1032				"renderer",
1033				"searchDelay",
1034				"rowId",
1035				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1036				[ "oSearch", "oPreviousSearch" ],
1037				[ "aoSearchCols", "aoPreSearchCols" ],
1038				[ "iDisplayLength", "_iDisplayLength" ]
1039			] );
1040			_fnMap( oSettings.oScroll, oInit, [
1041				[ "sScrollX", "sX" ],
1042				[ "sScrollXInner", "sXInner" ],
1043				[ "sScrollY", "sY" ],
1044				[ "bScrollCollapse", "bCollapse" ]
1045			] );
1046			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1047			
1048			/* Callback functions which are array driven */
1049			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1050			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1051			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1052			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1053			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1054			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1055			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1056			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1057			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1058			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1059			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1060			
1061			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1062			
1063			/* Browser support detection */
1064			_fnBrowserDetect( oSettings );
1065			
1066			var oClasses = oSettings.oClasses;
1067			
1068			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1069			$this.addClass( oClasses.sTable );
1070			
1071			
1072			if ( oSettings.iInitDisplayStart === undefined )
1073			{
1074				/* Display start point, taking into account the save saving */
1075				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1076				oSettings._iDisplayStart = oInit.iDisplayStart;
1077			}
1078			
1079			if ( oInit.iDeferLoading !== null )
1080			{
1081				oSettings.bDeferLoading = true;
1082				var tmp = $.isArray( oInit.iDeferLoading );
1083				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1084				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1085			}
1086			
1087			/* Language definitions */
1088			var oLanguage = oSettings.oLanguage;
1089			$.extend( true, oLanguage, oInit.oLanguage );
1090			
1091			if ( oLanguage.sUrl )
1092			{
1093				/* Get the language definitions from a file - because this Ajax call makes the language
1094				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1095				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1096				 */
1097				$.ajax( {
1098					dataType: 'json',
1099					url: oLanguage.sUrl,
1100					success: function ( json ) {
1101						_fnLanguageCompat( json );
1102						_fnCamelToHungarian( defaults.oLanguage, json );
1103						$.extend( true, oLanguage, json );
1104						_fnInitialise( oSettings );
1105					},
1106					error: function () {
1107						// Error occurred loading language file, continue on as best we can
1108						_fnInitialise( oSettings );
1109					}
1110				} );
1111				bInitHandedOff = true;
1112			}
1113			
1114			/*
1115			 * Stripes
1116			 */
1117			if ( oInit.asStripeClasses === null )
1118			{
1119				oSettings.asStripeClasses =[
1120					oClasses.sStripeOdd,
1121					oClasses.sStripeEven
1122				];
1123			}
1124			
1125			/* Remove row stripe classes if they are already on the table row */
1126			var stripeClasses = oSettings.asStripeClasses;
1127			var rowOne = $this.children('tbody').find('tr').eq(0);
1128			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1129				return rowOne.hasClass(el);
1130			} ) ) !== -1 ) {
1131				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1132				oSettings.asDestroyStripes = stripeClasses.slice();
1133			}
1134			
1135			/*
1136			 * Columns
1137			 * See if we should load columns automatically or use defined ones
1138			 */
1139			var anThs = [];
1140			var aoColumnsInit;
1141			var nThead = this.getElementsByTagName('thead');
1142			if ( nThead.length !== 0 )
1143			{
1144				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1145				anThs = _fnGetUniqueThs( oSettings );
1146			}
1147			
1148			/* If not given a column array, generate one with nulls */
1149			if ( oInit.aoColumns === null )
1150			{
1151				aoColumnsInit = [];
1152				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1153				{
1154					aoColumnsInit.push( null );
1155				}
1156			}
1157			else
1158			{
1159				aoColumnsInit = oInit.aoColumns;
1160			}
1161			
1162			/* Add the columns */
1163			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1164			{
1165				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1166			}
1167			
1168			/* Apply the column definitions */
1169			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1170				_fnColumnOptions( oSettings, iCol, oDef );
1171			} );
1172			
1173			/* HTML5 attribute detection - build an mData object automatically if the
1174			 * attributes are found
1175			 */
1176			if ( rowOne.length ) {
1177				var a = function ( cell, name ) {
1178					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1179				};
1180			
1181				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1182					var col = oSettings.aoColumns[i];
1183			
1184					if ( col.mData === i ) {
1185						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1186						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1187			
1188						if ( sort !== null || filter !== null ) {
1189							col.mData = {
1190								_:      i+'.display',
1191								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1192								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1193								filter: filter !== null ? i+'.@data-'+filter : undefined
1194							};
1195			
1196							_fnColumnOptions( oSettings, i );
1197						}
1198					}
1199				} );
1200			}
1201			
1202			var features = oSettings.oFeatures;
1203			var loadedInit = function () {
1204				/*
1205				 * Sorting
1206				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1207				 */
1208			
1209				// If aaSorting is not defined, then we use the first indicator in asSorting
1210				// in case that has been altered, so the default sort reflects that option
1211				if ( oInit.aaSorting === undefined ) {
1212					var sorting = oSettings.aaSorting;
1213					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1214						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1215					}
1216				}
1217			
1218				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1219				 * account, and also will apply sorting disabled classes if disabled
1220				 */
1221				_fnSortingClasses( oSettings );
1222			
1223				if ( features.bSort ) {
1224					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1225						if ( oSettings.bSorted ) {
1226							var aSort = _fnSortFlatten( oSettings );
1227							var sortedColumns = {};
1228			
1229							$.each( aSort, function (i, val) {
1230								sortedColumns[ val.src ] = val.dir;
1231							} );
1232			
1233							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1234							_fnSortAria( oSettings );
1235						}
1236					} );
1237				}
1238			
1239				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1240					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1241						_fnSortingClasses( oSettings );
1242					}
1243				}, 'sc' );
1244			
1245			
1246				/*
1247				 * Final init
1248				 * Cache the header, body and footer as required, creating them if needed
1249				 */
1250			
1251				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1252				var captions = $this.children('caption').each( function () {
1253					this._captionSide = $(this).css('caption-side');
1254				} );
1255			
1256				var thead = $this.children('thead');
1257				if ( thead.length === 0 ) {
1258					thead = $('<thead/>').appendTo($this);
1259				}
1260				oSettings.nTHead = thead[0];
1261			
1262				var tbody = $this.children('tbody');
1263				if ( tbody.length === 0 ) {
1264					tbody = $('<tbody/>').appendTo($this);
1265				}
1266				oSettings.nTBody = tbody[0];
1267			
1268				var tfoot = $this.children('tfoot');
1269				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1270					// If we are a scrolling table, and no footer has been given, then we need to create
1271					// a tfoot element for the caption element to be appended to
1272					tfoot = $('<tfoot/>').appendTo($this);
1273				}
1274			
1275				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1276					$this.addClass( oClasses.sNoFooter );
1277				}
1278				else if ( tfoot.length > 0 ) {
1279					oSettings.nTFoot = tfoot[0];
1280					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1281				}
1282			
1283				/* Check if there is data passing into the constructor */
1284				if ( oInit.aaData ) {
1285					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1286						_fnAddData( oSettings, oInit.aaData[ i ] );
1287					}
1288				}
1289				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1290					/* Grab the data from the page - only do this when deferred loading or no Ajax
1291					 * source since there is no point in reading the DOM data if we are then going
1292					 * to replace it with Ajax data
1293					 */
1294					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1295				}
1296			
1297				/* Copy the data index array */
1298				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1299			
1300				/* Initialisation complete - table can be drawn */
1301				oSettings.bInitialised = true;
1302			
1303				/* Check if we need to initialise the table (it might not have been handed off to the
1304				 * language processor)
1305				 */
1306				if ( bInitHandedOff === false ) {
1307					_fnInitialise( oSettings );
1308				}
1309			};
1310			
1311			/* Must be done after everything which can be overridden by the state saving! */
1312			if ( oInit.bStateSave )
1313			{
1314				features.bStateSave = true;
1315				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1316				_fnLoadState( oSettings, oInit, loadedInit );
1317			}
1318			else {
1319				loadedInit();
1320			}
1321			
1322		} );
1323		_that = null;
1324		return this;
1325	};
1326
1327	
1328	/*
1329	 * It is useful to have variables which are scoped locally so only the
1330	 * DataTables functions can access them and they don't leak into global space.
1331	 * At the same time these functions are often useful over multiple files in the
1332	 * core and API, so we list, or at least document, all variables which are used
1333	 * by DataTables as private variables here. This also ensures that there is no
1334	 * clashing of variable names and that they can easily referenced for reuse.
1335	 */
1336	
1337	
1338	// Defined else where
1339	//  _selector_run
1340	//  _selector_opts
1341	//  _selector_first
1342	//  _selector_row_indexes
1343	
1344	var _ext; // DataTable.ext
1345	var _Api; // DataTable.Api
1346	var _api_register; // DataTable.Api.register
1347	var _api_registerPlural; // DataTable.Api.registerPlural
1348	
1349	var _re_dic = {};
1350	var _re_new_lines = /[\r\n]/g;
1351	var _re_html = /<.*?>/g;
1352	
1353	// This is not strict ISO8601 - Date.parse() is quite lax, although
1354	// implementations differ between browsers.
1355	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1356	
1357	// Escape regular expression special characters
1358	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1359	
1360	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1361	// - \u20BD - Russian ruble.
1362	// - \u20a9 - South Korean Won
1363	// - \u20BA - Turkish Lira
1364	// - \u20B9 - Indian Rupee
1365	// - R - Brazil (R$) and South Africa
1366	// - fr - Swiss Franc
1367	// - kr - Swedish krona, Norwegian krone and Danish krone
1368	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1369	//   standards as thousands separators.
1370	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
1371	
1372	
1373	var _empty = function ( d ) {
1374		return !d || d === true || d === '-' ? true : false;
1375	};
1376	
1377	
1378	var _intVal = function ( s ) {
1379		var integer = parseInt( s, 10 );
1380		return !isNaN(integer) && isFinite(s) ? integer : null;
1381	};
1382	
1383	// Convert from a formatted number with characters other than `.` as the
1384	// decimal place, to a Javascript number
1385	var _numToDecimal = function ( num, decimalPoint ) {
1386		// Cache created regular expressions for speed as this function is called often
1387		if ( ! _re_dic[ decimalPoint ] ) {
1388			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1389		}
1390		return typeof num === 'string' && decimalPoint !== '.' ?
1391			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1392			num;
1393	};
1394	
1395	
1396	var _isNumber = function ( d, decimalPoint, formatted ) {
1397		var strType = typeof d === 'string';
1398	
1399		// If empty return immediately so there must be a number if it is a
1400		// formatted string (this stops the string "k", or "kr", etc being detected
1401		// as a formatted number for currency
1402		if ( _empty( d ) ) {
1403			return true;
1404		}
1405	
1406		if ( decimalPoint && strType ) {
1407			d = _numToDecimal( d, decimalPoint );
1408		}
1409	
1410		if ( formatted && strType ) {
1411			d = d.replace( _re_formatted_numeric, '' );
1412		}
1413	
1414		return !isNaN( parseFloat(d) ) && isFinite( d );
1415	};
1416	
1417	
1418	// A string without HTML in it can be considered to be HTML still
1419	var _isHtml = function ( d ) {
1420		return _empty( d ) || typeof d === 'string';
1421	};
1422	
1423	
1424	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1425		if ( _empty( d ) ) {
1426			return true;
1427		}
1428	
1429		var html = _isHtml( d );
1430		return ! html ?
1431			null :
1432			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1433				true :
1434				null;
1435	};
1436	
1437	
1438	var _pluck = function ( a, prop, prop2 ) {
1439		var out = [];
1440		var i=0, ien=a.length;
1441	
1442		// Could have the test in the loop for slightly smaller code, but speed
1443		// is essential here
1444		if ( prop2 !== undefined ) {
1445			for ( ; i<ien ; i++ ) {
1446				if ( a[i] && a[i][ prop ] ) {
1447					out.push( a[i][ prop ][ prop2 ] );
1448				}
1449			}
1450		}
1451		else {
1452			for ( ; i<ien ; i++ ) {
1453				if ( a[i] ) {
1454					out.push( a[i][ prop ] );
1455				}
1456			}
1457		}
1458	
1459		return out;
1460	};
1461	
1462	
1463	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1464	// as the indexes to pick from `a`
1465	var _pluck_order = function ( a, order, prop, prop2 )
1466	{
1467		var out = [];
1468		var i=0, ien=order.length;
1469	
1470		// Could have the test in the loop for slightly smaller code, but speed
1471		// is essential here
1472		if ( prop2 !== undefined ) {
1473			for ( ; i<ien ; i++ ) {
1474				if ( a[ order[i] ][ prop ] ) {
1475					out.push( a[ order[i] ][ prop ][ prop2 ] );
1476				}
1477			}
1478		}
1479		else {
1480			for ( ; i<ien ; i++ ) {
1481				out.push( a[ order[i] ][ prop ] );
1482			}
1483		}
1484	
1485		return out;
1486	};
1487	
1488	
1489	var _range = function ( len, start )
1490	{
1491		var out = [];
1492		var end;
1493	
1494		if ( start === undefined ) {
1495			start = 0;
1496			end = len;
1497		}
1498		else {
1499			end = start;
1500			start = len;
1501		}
1502	
1503		for ( var i=start ; i<end ; i++ ) {
1504			out.push( i );
1505		}
1506	
1507		return out;
1508	};
1509	
1510	
1511	var _removeEmpty = function ( a )
1512	{
1513		var out = [];
1514	
1515		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1516			if ( a[i] ) { // careful - will remove all falsy values!
1517				out.push( a[i] );
1518			}
1519		}
1520	
1521		return out;
1522	};
1523	
1524	
1525	var _stripHtml = function ( d ) {
1526		return d.replace( _re_html, '' );
1527	};
1528	
1529	
1530	/**
1531	 * Determine if all values in the array are unique. This means we can short
1532	 * cut the _unique method at the cost of a single loop. A sorted array is used
1533	 * to easily check the values.
1534	 *
1535	 * @param  {array} src Source array
1536	 * @return {boolean} true if all unique, false otherwise
1537	 * @ignore
1538	 */
1539	var _areAllUnique = function ( src ) {
1540		if ( src.length < 2 ) {
1541			return true;
1542		}
1543	
1544		var sorted = src.slice().sort();
1545		var last = sorted[0];
1546	
1547		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1548			if ( sorted[i] === last ) {
1549				return false;
1550			}
1551	
1552			last = sorted[i];
1553		}
1554	
1555		return true;
1556	};
1557	
1558	
1559	/**
1560	 * Find the unique elements in a source array.
1561	 *
1562	 * @param  {array} src Source array
1563	 * @return {array} Array of unique items
1564	 * @ignore
1565	 */
1566	var _unique = function ( src )
1567	{
1568		if ( _areAllUnique( src ) ) {
1569			return src.slice();
1570		}
1571	
1572		// A faster unique method is to use object keys to identify used values,
1573		// but this doesn't work with arrays or objects, which we must also
1574		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1575		// information.
1576		var
1577			out = [],
1578			val,
1579			i, ien=src.length,
1580			j, k=0;
1581	
1582		again: for ( i=0 ; i<ien ; i++ ) {
1583			val = src[i];
1584	
1585			for ( j=0 ; j<k ; j++ ) {
1586				if ( out[j] === val ) {
1587					continue again;
1588				}
1589			}
1590	
1591			out.push( val );
1592			k++;
1593		}
1594	
1595		return out;
1596	};
1597	
1598	
1599	/**
1600	 * DataTables utility methods
1601	 * 
1602	 * This namespace provides helper methods that DataTables uses internally to
1603	 * create a DataTable, but which are not exclusively used only for DataTables.
1604	 * These methods can be used by extension authors to save the duplication of
1605	 * code.
1606	 *
1607	 *  @namespace
1608	 */
1609	DataTable.util = {
1610		/**
1611		 * Throttle the calls to a function. Arguments and context are maintained
1612		 * for the throttled function.
1613		 *
1614		 * @param {function} fn Function to be called
1615		 * @param {integer} freq Call frequency in mS
1616		 * @return {function} Wrapped function
1617		 */
1618		throttle: function ( fn, freq ) {
1619			var
1620				frequency = freq !== undefined ? freq : 200,
1621				last,
1622				timer;
1623	
1624			return function () {
1625				var
1626					that = this,
1627					now  = +new Date(),
1628					args = arguments;
1629	
1630				if ( last && now < last + frequency ) {
1631					clearTimeout( timer );
1632	
1633					timer = setTimeout( function () {
1634						last = undefined;
1635						fn.apply( that, args );
1636					}, frequency );
1637				}
1638				else {
1639					last = now;
1640					fn.apply( that, args );
1641				}
1642			};
1643		},
1644	
1645	
1646		/**
1647		 * Escape a string such that it can be used in a regular expression
1648		 *
1649		 *  @param {string} val string to escape
1650		 *  @returns {string} escaped string
1651		 */
1652		escapeRegex: function ( val ) {
1653			return val.replace( _re_escape_regex, '\\$1' );
1654		}
1655	};
1656	
1657	
1658	
1659	/**
1660	 * Create a mapping object that allows camel case parameters to be looked up
1661	 * for their Hungarian counterparts. The mapping is stored in a private
1662	 * parameter called `_hungarianMap` which can be accessed on the source object.
1663	 *  @param {object} o
1664	 *  @memberof DataTable#oApi
1665	 */
1666	function _fnHungarianMap ( o )
1667	{
1668		var
1669			hungarian = 'a aa ai ao as b fn i m o s ',
1670			match,
1671			newKey,
1672			map = {};
1673	
1674		$.each( o, function (key, val) {
1675			match = key.match(/^([^A-Z]+?)([A-Z])/);
1676	
1677			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1678			{
1679				newKey = key.replace( match[0], match[2].toLowerCase() );
1680				map[ newKey ] = key;
1681	
1682				if ( match[1] === 'o' )
1683				{
1684					_fnHungarianMap( o[key] );
1685				}
1686			}
1687		} );
1688	
1689		o._hungarianMap = map;
1690	}
1691	
1692	
1693	/**
1694	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1695	 * created by _fnHungarianMap.
1696	 *  @param {object} src The model object which holds all parameters that can be
1697	 *    mapped.
1698	 *  @param {object} user The object to convert from camel case to Hungarian.
1699	 *  @param {boolean} force When set to `true`, properties which already have a
1700	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1701	 *    won't be.
1702	 *  @memberof DataTable#oApi
1703	 */
1704	function _fnCamelToHungarian ( src, user, force )
1705	{
1706		if ( ! src._hungarianMap ) {
1707			_fnHungarianMap( src );
1708		}
1709	
1710		var hungarianKey;
1711	
1712		$.each( user, function (key, val) {
1713			hungarianKey = src._hungarianMap[ key ];
1714	
1715			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1716			{
1717				// For objects, we need to buzz down into the object to copy parameters
1718				if ( hungarianKey.charAt(0) === 'o' )
1719				{
1720					// Copy the camelCase options over to the hungarian
1721					if ( ! user[ hungarianKey ] ) {
1722						user[ hungarianKey ] = {};
1723					}
1724					$.extend( true, user[hungarianKey], user[key] );
1725	
1726					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1727				}
1728				else {
1729					user[hungarianKey] = user[ key ];
1730				}
1731			}
1732		} );
1733	}
1734	
1735	
1736	/**
1737	 * Language compatibility - when certain options are given, and others aren't, we
1738	 * need to duplicate the values over, in order to provide backwards compatibility
1739	 * with older language files.
1740	 *  @param {object} oSettings dataTables settings object
1741	 *  @memberof DataTable#oApi
1742	 */
1743	function _fnLanguageCompat( lang )
1744	{
1745		var defaults = DataTable.defaults.oLanguage;
1746		var zeroRecords = lang.sZeroRecords;
1747	
1748		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
1749		 * sZeroRecords - assuming that is given.
1750		 */
1751		if ( ! lang.sEmptyTable && zeroRecords &&
1752			defaults.sEmptyTable === "No data available in table" )
1753		{
1754			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1755		}
1756	
1757		/* Likewise with loading records */
1758		if ( ! lang.sLoadingRecords && zeroRecords &&
1759			defaults.sLoadingRecords === "Loading..." )
1760		{
1761			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1762		}
1763	
1764		// Old parameter name of the thousands separator mapped onto the new
1765		if ( lang.sInfoThousands ) {
1766			lang.sThousands = lang.sInfoThousands;
1767		}
1768	
1769		var decimal = lang.sDecimal;
1770		if ( decimal ) {
1771			_addNumericSort( decimal );
1772		}
1773	}
1774	
1775	
1776	/**
1777	 * Map one parameter onto another
1778	 *  @param {object} o Object to map
1779	 *  @param {*} knew The new parameter name
1780	 *  @param {*} old The old parameter name
1781	 */
1782	var _fnCompatMap = function ( o, knew, old ) {
1783		if ( o[ knew ] !== undefined ) {
1784			o[ old ] = o[ knew ];
1785		}
1786	};
1787	
1788	
1789	/**
1790	 * Provide backwards compatibility for the main DT options. Note that the new
1791	 * options are mapped onto the old parameters, so this is an external interface
1792	 * change only.
1793	 *  @param {object} init Object to map
1794	 */
1795	function _fnCompatOpts ( init )
1796	{
1797		_fnCompatMap( init, 'ordering',      'bSort' );
1798		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1799		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1800		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1801		_fnCompatMap( init, 'order',         'aaSorting' );
1802		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1803		_fnCompatMap( init, 'paging',        'bPaginate' );
1804		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
1805		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1806		_fnCompatMap( init, 'searching',     'bFilter' );
1807	
1808		// Boolean initialisation of x-scrolling
1809		if ( typeof init.sScrollX === 'boolean' ) {
1810			init.sScrollX = init.sScrollX ? '100%' : '';
1811		}
1812		if ( typeof init.scrollX === 'boolean' ) {
1813			init.scrollX = init.scrollX ? '100%' : '';
1814		}
1815	
1816		// Column search objects are in an array, so it needs to be converted
1817		// element by element
1818		var searchCols = init.aoSearchCols;
1819	
1820		if ( searchCols ) {
1821			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1822				if ( searchCols[i] ) {
1823					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1824				}
1825			}
1826		}
1827	}
1828	
1829	
1830	/**
1831	 * Provide backwards compatibility for column options. Note that the new options
1832	 * are mapped onto the old parameters, so this is an external interface change
1833	 * only.
1834	 *  @param {object} init Object to map
1835	 */
1836	function _fnCompatCols ( init )
1837	{
1838		_fnCompatMap( init, 'orderable',     'bSortable' );
1839		_fnCompatMap( init, 'orderData',     'aDataSort' );
1840		_fnCompatMap( init, 'orderSequence', 'asSorting' );
1841		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
1842	
1843		// orderData can be given as an integer
1844		var dataSort = init.aDataSort;
1845		if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
1846			init.aDataSort = [ dataSort ];
1847		}
1848	}
1849	
1850	
1851	/**
1852	 * Browser feature detection for capabilities, quirks
1853	 *  @param {object} settings dataTables settings object
1854	 *  @memberof DataTable#oApi
1855	 */
1856	function _fnBrowserDetect( settings )
1857	{
1858		// We don't need to do this every time DataTables is constructed, the values
1859		// calculated are specific to the browser and OS configuration which we
1860		// don't expect to change between initialisations
1861		if ( ! DataTable.__browser ) {
1862			var browser = {};
1863			DataTable.__browser = browser;
1864	
1865			// Scrolling feature / quirks detection
1866			var n = $('<div/>')
1867				.css( {
1868					position: 'fixed',
1869					top: 0,
1870					left: $(window).scrollLeft()*-1, // allow for scrolling
1871					height: 1,
1872					width: 1,
1873					overflow: 'hidden'
1874				} )
1875				.append(
1876					$('<div/>')
1877						.css( {
1878							position: 'absolute',
1879							top: 1,
1880							left: 1,
1881							width: 100,
1882							overflow: 'scroll'
1883						} )
1884						.append(
1885							$('<div/>')
1886								.css( {
1887									width: '100%',
1888									height: 10
1889								} )
1890						)
1891				)
1892				.appendTo( 'body' );
1893	
1894			var outer = n.children();
1895			var inner = outer.children();
1896	
1897			// Numbers below, in order, are:
1898			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1899			//
1900			// IE6 XP:                           100 100 100  83
1901			// IE7 Vista:                        100 100 100  83
1902			// IE 8+ Windows:                     83  83 100  83
1903			// Evergreen Windows:                 83  83 100  83
1904			// Evergreen Mac with scrollbars:     85  85 100  85
1905			// Evergreen Mac without scrollbars: 100 100 100 100
1906	
1907			// Get scrollbar width
1908			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1909	
1910			// IE6/7 will oversize a width 100% element inside a scrolling element, to
1911			// include the width of the scrollbar, while other browsers ensure the inner
1912			// element is contained without forcing scrolling
1913			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1914	
1915			// In rtl text layout, some browsers (most, but not all) will place the
1916			// scrollbar on the left, rather than the right.
1917			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1918	
1919			// IE8- don't provide height and width for getBoundingClientRect
1920			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1921	
1922			n.remove();
1923		}
1924	
1925		$.extend( settings.oBrowser, DataTable.__browser );
1926		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1927	}
1928	
1929	
1930	/**
1931	 * Array.prototype reduce[Right] method, used for browsers which don't support
1932	 * JS 1.6. Done this way to reduce code size, since we iterate either way
1933	 *  @param {object} settings dataTables settings object
1934	 *  @memberof DataTable#oApi
1935	 */
1936	function _fnReduce ( that, fn, init, start, end, inc )
1937	{
1938		var
1939			i = start,
1940			value,
1941			isSet = false;
1942	
1943		if ( init !== undefined ) {
1944			value = init;
1945			isSet = true;
1946		}
1947	
1948		while ( i !== end ) {
1949			if ( ! that.hasOwnProperty(i) ) {
1950				continue;
1951			}
1952	
1953			value = isSet ?
1954				fn( value, that[i], i, that ) :
1955				that[i];
1956	
1957			isSet = true;
1958			i += inc;
1959		}
1960	
1961		return value;
1962	}
1963	
1964	/**
1965	 * Add a column to the list used for the table with default values
1966	 *  @param {object} oSettings dataTables settings object
1967	 *  @param {node} nTh The th element for this column
1968	 *  @memberof DataTable#oApi
1969	 */
1970	function _fnAddColumn( oSettings, nTh )
1971	{
1972		// Add column to aoColumns array
1973		var oDefaults = DataTable.defaults.column;
1974		var iCol = oSettings.aoColumns.length;
1975		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1976			"nTh": nTh ? nTh : document.createElement('th'),
1977			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1978			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1979			"mData": oDefaults.mData ? oDefaults.mData : iCol,
1980			idx: iCol
1981		} );
1982		oSettings.aoColumns.push( oCol );
1983	
1984		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
1985		// passed into extend can be undefined. This allows the user to give a default
1986		// with only some of the parameters defined, and also not give a default
1987		var searchCols = oSettings.aoPreSearchCols;
1988		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
1989	
1990		// Use the default column options function to initialise classes etc
1991		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
1992	}
1993	
1994	
1995	/**
1996	 * Apply options for a column
1997	 *  @param {object} oSettings dataTables settings object
1998	 *  @param {int} iCol column index to consider
1999	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2000	 *  @memberof DataTable#oApi
2001	 */
2002	function _fnColumnOptions( oSettings, iCol, oOptions )
2003	{
2004		var oCol = oSettings.aoColumns[ iCol ];
2005		var oClasses = oSettings.oClasses;
2006		var th = $(oCol.nTh);
2007	
2008		// Try to get width information from the DOM. We can't get it from CSS
2009		// as we'd need to parse the CSS stylesheet. `width` option can override
2010		if ( ! oCol.sWidthOrig ) {
2011			// Width attribute
2012			oCol.sWidthOrig = th.attr('width') || null;
2013	
2014			// Style attribute
2015			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2016			if ( t ) {
2017				oCol.sWidthOrig = t[1];
2018			}
2019		}
2020	
2021		/* User specified column options */
2022		if ( oOptions !== undefined && oOptions !== null )
2023		{
2024			// Backwards compatibility
2025			_fnCompatCols( oOptions );
2026	
2027			// Map camel case parameters to their Hungarian counterparts
2028			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
2029	
2030			/* Backwards compatibility for mDataProp */
2031			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2032			{
2033				oOptions.mData = oOptions.mDataProp;
2034			}
2035	
2036			if ( oOptions.sType )
2037			{
2038				oCol._sManualType = oOptions.sType;
2039			}
2040	
2041			// `class` is a reserved word in Javascript, so we need to provide
2042			// the ability to use a valid name for the camel case input
2043			if ( oOptions.className && ! oOptions.sClass )
2044			{
2045				oOptions.sClass = oOptions.className;
2046			}
2047			if ( oOptions.sClass ) {
2048				th.addClass( oOptions.sClass );
2049			}
2050	
2051			$.extend( oCol, oOptions );
2052			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2053	
2054			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2055			 * priority if defined
2056			 */
2057			if ( oOptions.iDataSort !== undefined )
2058			{
2059				oCol.aDataSort = [ oOptions.iDataSort ];
2060			}
2061			_fnMap( oCol, oOptions, "aDataSort" );
2062		}
2063	
2064		/* Cache the data get and set functions for speed */
2065		var mDataSrc = oCol.mData;
2066		var mData = _fnGetObjectDataFn( mDataSrc );
2067		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2068	
2069		var attrTest = function( src ) {
2070			return typeof src === 'string' && src.indexOf('@') !== -1;
2071		};
2072		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2073			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2074		);
2075		oCol._setter = null;
2076	
2077		oCol.fnGetData = function (rowData, type, meta) {
2078			var innerData = mData( rowData, type, undefined, meta );
2079	
2080			return mRender && type ?
2081				mRender( innerData, type, rowData, meta ) :
2082				innerData;
2083		};
2084		oCol.fnSetData = function ( rowData, val, meta ) {
2085			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2086		};
2087	
2088		// Indicate if DataTables should read DOM data as an object or array
2089		// Used in _fnGetRowElements
2090		if ( typeof mDataSrc !== 'number' ) {
2091			oSettings._rowReadObject = true;
2092		}
2093	
2094		/* Feature sorting overrides column specific when off */
2095		if ( !oSettings.oFeatures.bSort )
2096		{
2097			oCol.bSortable = false;
2098			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2099		}
2100	
2101		/* Check that the class assignment is correct for sorting */
2102		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2103		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2104		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2105		{
2106			oCol.sSortingClass = oClasses.sSortableNone;
2107			oCol.sSortingClassJUI = "";
2108		}
2109		else if ( bAsc && !bDesc )
2110		{
2111			oCol.sSortingClass = oClasses.sSortableAsc;
2112			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2113		}
2114		else if ( !bAsc && bDesc )
2115		{
2116			oCol.sSortingClass = oClasses.sSortableDesc;
2117			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2118		}
2119		else
2120		{
2121			oCol.sSortingClass = oClasses.sSortable;
2122			oCol.sSortingClassJUI = oClasses.sSortJUI;
2123		}
2124	}
2125	
2126	
2127	/**
2128	 * Adjust the table column widths for new data. Note: you would probably want to
2129	 * do a redraw after calling this function!
2130	 *  @param {object} settings dataTables settings object
2131	 *  @memberof DataTable#oApi
2132	 */
2133	function _fnAdjustColumnSizing ( settings )
2134	{
2135		/* Not interested in doing column width calculation if auto-width is disabled */
2136		if ( settings.oFeatures.bAutoWidth !== false )
2137		{
2138			var columns = settings.aoColumns;
2139	
2140			_fnCalculateColumnWidths( settings );
2141			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2142			{
2143				columns[i].nTh.style.width = columns[i].sWidth;
2144			}
2145		}
2146	
2147		var scroll = settings.oScroll;
2148		if ( scroll.sY !== '' || scroll.sX !== '')
2149		{
2150			_fnScrollDraw( settings );
2151		}
2152	
2153		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2154	}
2155	
2156	
2157	/**
2158	 * Covert the index of a visible column to the index in the data array (take account
2159	 * of hidden columns)
2160	 *  @param {object} oSettings dataTables settings object
2161	 *  @param {int} iMatch Visible column index to lookup
2162	 *  @returns {int} i the data index
2163	 *  @memberof DataTable#oApi
2164	 */
2165	function _fnVisibleToColumnIndex( oSettings, iMatch )
2166	{
2167		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2168	
2169		return typeof aiVis[iMatch] === 'number' ?
2170			aiVis[iMatch] :
2171			null;
2172	}
2173	
2174	
2175	/**
2176	 * Covert the index of an index in the data array and convert it to the visible
2177	 *   column index (take account of hidden columns)
2178	 *  @param {int} iMatch Column index to lookup
2179	 *  @param {object} oSettings dataTables settings object
2180	 *  @returns {int} i the data index
2181	 *  @memberof DataTable#oApi
2182	 */
2183	function _fnColumnIndexToVisible( oSettings, iMatch )
2184	{
2185		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2186		var iPos = $.inArray( iMatch, aiVis );
2187	
2188		return iPos !== -1 ? iPos : null;
2189	}
2190	
2191	
2192	/**
2193	 * Get the number of visible columns
2194	 *  @param {object} oSettings dataTables settings object
2195	 *  @returns {int} i the number of visible columns
2196	 *  @memberof DataTable#oApi
2197	 */
2198	function _fnVisbleColumns( oSettings )
2199	{
2200		var vis = 0;
2201	
2202		// No reduce in IE8, use a loop for now
2203		$.each( oSettings.aoColumns, function ( i, col ) {
2204			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2205				vis++;
2206			}
2207		} );
2208	
2209		return vis;
2210	}
2211	
2212	
2213	/**
2214	 * Get an array of column indexes that match a given property
2215	 *  @param {object} oSettings dataTables settings object
2216	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2217	 *    bVisible or bSearchable
2218	 *  @returns {array} Array of indexes with matched properties
2219	 *  @memberof DataTable#oApi
2220	 */
2221	function _fnGetColumns( oSettings, sParam )
2222	{
2223		var a = [];
2224	
2225		$.map( oSettings.aoColumns, function(val, i) {
2226			if ( val[sParam] ) {
2227				a.push( i );
2228			}
2229		} );
2230	
2231		return a;
2232	}
2233	
2234	
2235	/**
2236	 * Calculate the 'type' of a column
2237	 *  @param {object} settings dataTables settings object
2238	 *  @memberof DataTable#oApi
2239	 */
2240	function _fnColumnTypes ( settings )
2241	{
2242		var columns = settings.aoColumns;
2243		var data = settings.aoData;
2244		var types = DataTable.ext.type.detect;
2245		var i, ien, j, jen, k, ken;
2246		var col, cell, detectedType, cache;
2247	
2248		// For each column, spin over the 
2249		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2250			col = columns[i];
2251			cache = [];
2252	
2253			if ( ! col.sType && col._sManualType ) {
2254				col.sType = col._sManualType;
2255			}
2256			else if ( ! col.sType ) {
2257				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2258					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2259						// Use a cache array so we only need to get the type data
2260						// from the formatter once (when using multiple detectors)
2261						if ( cache[k] === undefined ) {
2262							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2263						}
2264	
2265						detectedType = types[j]( cache[k], settings );
2266	
2267						// If null, then this type can't apply to this column, so
2268						// rather than testing all cells, break out. There is an
2269						// exception for the last type which is `html`. We need to
2270						// scan all rows since it is possible to mix string and HTML
2271						// types
2272						if ( ! detectedType && j !== types.length-1 ) {
2273							break;
2274						}
2275	
2276						// Only a single match is needed for html type since it is
2277						// bottom of the pile and very similar to string
2278						if ( detectedType === 'html' ) {
2279							break;
2280						}
2281					}
2282	
2283					// Type is valid for all data points in the column - use this
2284					// type
2285					if ( detectedType ) {
2286						col.sType = detectedType;
2287						break;
2288					}
2289				}
2290	
2291				// Fall back - if no type was detected, always use string
2292				if ( ! col.sType ) {
2293					col.sType = 'string';
2294				}
2295			}
2296		}
2297	}
2298	
2299	
2300	/**
2301	 * Take the column definitions and static columns arrays and calculate how
2302	 * they relate to column indexes. The callback function will then apply the
2303	 * definition found for a column to a suitable configuration object.
2304	 *  @param {object} oSettings dataTables settings object
2305	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2306	 *  @param {array} aoCols The aoColumns array that defines columns individually
2307	 *  @param {function} fn Callback function - takes two parameters, the calculated
2308	 *    column index and the definition for that column.
2309	 *  @memberof DataTable#oApi
2310	 */
2311	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2312	{
2313		var i, iLen, j, jLen, k, kLen, def;
2314		var columns = oSettings.aoColumns;
2315	
2316		// Column definitions with aTargets
2317		if ( aoColDefs )
2318		{
2319			/* Loop over the definitions array - loop in reverse so first instance has priority */
2320			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2321			{
2322				def = aoColDefs[i];
2323	
2324				/* Each definition can target multiple columns, as it is an array */
2325				var aTargets = def.targets !== undefined ?
2326					def.targets :
2327					def.aTargets;
2328	
2329				if ( ! $.isArray( aTargets ) )
2330				{
2331					aTargets = [ aTargets ];
2332				}
2333	
2334				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2335				{
2336					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2337					{
2338						/* Add columns that we don't yet know about */
2339						while( columns.length <= aTargets[j] )
2340						{
2341							_fnAddColumn( oSettings );
2342						}
2343	
2344						/* Integer, basic index */
2345						fn( aTargets[j], def );
2346					}
2347					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2348					{
2349						/* Negative integer, right to left column counting */
2350						fn( columns.length+aTargets[j], def );
2351					}
2352					else if ( typeof aTargets[j] === 'string' )
2353					{
2354						/* Class name matching on TH element */
2355						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2356						{
2357							if ( aTargets[j] == "_all" ||
2358							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2359							{
2360								fn( k, def );
2361							}
2362						}
2363					}
2364				}
2365			}
2366		}
2367	
2368		// Statically defined columns array
2369		if ( aoCols )
2370		{
2371			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2372			{
2373				fn( i, aoCols[i] );
2374			}
2375		}
2376	}
2377	
2378	/**
2379	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2380	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2381	 * DOM source.
2382	 *  @param {object} oSettings dataTables settings object
2383	 *  @param {array} aData data array to be added
2384	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2385	 *    DataTables will create a row automatically
2386	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2387	 *    if nTr is.
2388	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2389	 *  @memberof DataTable#oApi
2390	 */
2391	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2392	{
2393		/* Create the object for storing information about this new row */
2394		var iRow = oSettings.aoData.length;
2395		var oData = $.extend( true, {}, DataTable.models.oRow, {
2396			src: nTr ? 'dom' : 'data',
2397			idx: iRow
2398		} );
2399	
2400		oData._aData = aDataIn;
2401		oSettings.aoData.push( oData );
2402	
2403		/* Create the cells */
2404		var nTd, sThisType;
2405		var columns = oSettings.aoColumns;
2406	
2407		// Invalidate the column types as the new data needs to be revalidated
2408		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2409		{
2410			columns[i].sType = null;
2411		}
2412	
2413		/* Add to the display array */
2414		oSettings.aiDisplayMaster.push( iRow );
2415	
2416		var id = oSettings.rowIdFn( aDataIn );
2417		if ( id !== undefined ) {
2418			oSettings.aIds[ id ] = oData;
2419		}
2420	
2421		/* Create the DOM information, or register it if already present */
2422		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2423		{
2424			_fnCreateTr( oSettings, iRow, nTr, anTds );
2425		}
2426	
2427		return iRow;
2428	}
2429	
2430	
2431	/**
2432	 * Add one or more TR elements to the table. Generally we'd expect to
2433	 * use this for reading data from a DOM sourced table, but it could be
2434	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2435	 * it is not cloned).
2436	 *  @param {object} settings dataTables settings object
2437	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2438	 *  @returns {array} Array of indexes for the added rows
2439	 *  @memberof DataTable#oApi
2440	 */
2441	function _fnAddTr( settings, trs )
2442	{
2443		var row;
2444	
2445		// Allow an individual node to be passed in
2446		if ( ! (trs instanceof $) ) {
2447			trs = $(trs);
2448		}
2449	
2450		return trs.map( function (i, el) {
2451			row = _fnGetRowElements( settings, el );
2452			return _fnAddData( settings, row.data, el, row.cells );
2453		} );
2454	}
2455	
2456	
2457	/**
2458	 * Take a TR element and convert it to an index in aoData
2459	 *  @param {object} oSettings dataTables settings object
2460	 *  @param {node} n the TR element to find
2461	 *  @returns {int} index if the node is found, null if not
2462	 *  @memberof DataTable#oApi
2463	 */
2464	function _fnNodeToDataIndex( oSettings, n )
2465	{
2466		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2467	}
2468	
2469	
2470	/**
2471	 * Take a TD element and convert it into a column data index (not the visible index)
2472	 *  @param {object} oSettings dataTables settings object
2473	 *  @param {int} iRow The row number the TD/TH can be found in
2474	 *  @param {node} n The TD/TH element to find
2475	 *  @returns {int} index if the node is found, -1 if not
2476	 *  @memberof DataTable#oApi
2477	 */
2478	function _fnNodeToColumnIndex( oSettings, iRow, n )
2479	{
2480		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2481	}
2482	
2483	
2484	/**
2485	 * Get the data for a given cell from the internal cache, taking into account data mapping
2486	 *  @param {object} settings dataTables settings object
2487	 *  @param {int} rowIdx aoData row id
2488	 *  @param {int} colIdx Column index
2489	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2490	 *  @returns {*} Cell data
2491	 *  @memberof DataTable#oApi
2492	 */
2493	function _fnGetCellData( settings, rowIdx, colIdx, type )
2494	{
2495		var draw           = settings.iDraw;
2496		var col            = settings.aoColumns[colIdx];
2497		var rowData        = settings.aoData[rowIdx]._aData;
2498		var defaultContent = col.sDefaultContent;
2499		var cellData       = col.fnGetData( rowData, type, {
2500			settings: settings,
2501			row:      rowIdx,
2502			col:      colIdx
2503		} );
2504	
2505		if ( cellData === undefined ) {
2506			if ( settings.iDrawError != draw && defaultContent === null ) {
2507				_fnLog( settings, 0, "Requested unknown parameter "+
2508					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2509					" for row "+rowIdx+", column "+colIdx, 4 );
2510				settings.iDrawError = draw;
2511			}
2512			return defaultContent;
2513		}
2514	
2515		// When the data source is null and a specific data type is requested (i.e.
2516		// not the original data), we can use default column data
2517		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2518			cellData = defaultContent;
2519		}
2520		else if ( typeof cellData === 'function' ) {
2521			// If the data source is a function, then we run it and use the return,
2522			// executing in the scope of the data object (for instances)
2523			return cellData.call( rowData );
2524		}
2525	
2526		if ( cellData === null && type == 'display' ) {
2527			return '';
2528		}
2529		return cellData;
2530	}
2531	
2532	
2533	/**
2534	 * Set the value for a specific cell, into the internal data cache
2535	 *  @param {object} settings dataTables settings object
2536	 *  @param {int} rowIdx aoData row id
2537	 *  @param {int} colIdx Column index
2538	 *  @param {*} val Value to set
2539	 *  @memberof DataTable#oApi
2540	 */
2541	function _fnSetCellData( settings, rowIdx, colIdx, val )
2542	{
2543		var col     = settings.aoColumns[colIdx];
2544		var rowData = settings.aoData[rowIdx]._aData;
2545	
2546		col.fnSetData( rowData, val, {
2547			settings: settings,
2548			row:      rowIdx,
2549			col:      colIdx
2550		}  );
2551	}
2552	
2553	
2554	// Private variable that is used to match action syntax in the data property object
2555	var __reArray = /\[.*?\]$/;
2556	var __reFn = /\(\)$/;
2557	
2558	/**
2559	 * Split string on periods, taking into account escaped periods
2560	 * @param  {string} str String to split
2561	 * @return {array} Split string
2562	 */
2563	function _fnSplitObjNotation( str )
2564	{
2565		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2566			return s.replace(/\\\./g, '.');
2567		} );
2568	}
2569	
2570	
2571	/**
2572	 * Return a function that can be used to get data from a source object, taking
2573	 * into account the ability to use nested objects as a source
2574	 *  @param {string|int|function} mSource The data source for the object
2575	 *  @returns {function} Data get function
2576	 *  @memberof DataTable#oApi
2577	 */
2578	function _fnGetObjectDataFn( mSource )
2579	{
2580		if ( $.isPlainObject( mSource ) )
2581		{
2582			/* Build an object of get functions, and wrap them in a single call */
2583			var o = {};
2584			$.each( mSource, function (key, val) {
2585				if ( val ) {
2586					o[key] = _fnGetObjectDataFn( val );
2587				}
2588			} );
2589	
2590			return function (data, type, row, meta) {
2591				var t = o[type] || o._;
2592				return t !== undefined ?
2593					t(data, type, row, meta) :
2594					data;
2595			};
2596		}
2597		else if ( mSource === null )
2598		{
2599			/* Give an empty string for rendering / sorting etc */
2600			return function (data) { // type, row and meta also passed, but not used
2601				return data;
2602			};
2603		}
2604		else if ( typeof mSource === 'function' )
2605		{
2606			return function (data, type, row, meta) {
2607				return mSource( data, type, row, meta );
2608			};
2609		}
2610		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2611			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2612		{
2613			/* If there is a . in the source string then the data source is in a
2614			 * nested object so we loop over the data for each level to get the next
2615			 * level down. On each loop we test for undefined, and if found immediately
2616			 * return. This allows entire objects to be missing and sDefaultContent to
2617			 * be used if defined, rather than throwing an error
2618			 */
2619			var fetchData = function (data, type, src) {
2620				var arrayNotation, funcNotation, out, innerSrc;
2621	
2622				if ( src !== "" )
2623				{
2624					var a = _fnSplitObjNotation( src );
2625	
2626					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2627					{
2628						// Check if we are dealing with special notation
2629						arrayNotation = a[i].match(__reArray);
2630						funcNotation = a[i].match(__reFn);
2631	
2632						if ( arrayNotation )
2633						{
2634							// Array notation
2635							a[i] = a[i].replace(__reArray, '');
2636	
2637							// Condition allows simply [] to be passed in
2638							if ( a[i] !== "" ) {
2639								data = data[ a[i] ];
2640							}
2641							out = [];
2642	
2643							// Get the remainder of the nested object to get
2644							a.splice( 0, i+1 );
2645							innerSrc = a.join('.');
2646	
2647							// Traverse each entry in the array getting the properties requested
2648							if ( $.isArray( data ) ) {
2649								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2650									out.push( fetchData( data[j], type, innerSrc ) );
2651								}
2652							}
2653	
2654							// If a string is given in between the array notation indicators, that
2655							// is used to join the strings together, otherwise an array is returned
2656							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2657							data = (join==="") ? out : out.join(join);
2658	
2659							// The inner call to fetchData has already traversed through the remainder
2660							// of the source requested, so we exit from the loop
2661							break;
2662						}
2663						else if ( funcNotation )
2664						{
2665							// Function call
2666							a[i] = a[i].replace(__reFn, '');
2667							data = data[ a[i] ]();
2668							continue;
2669						}
2670	
2671						if ( data === null || data[ a[i] ] === undefined )
2672						{
2673							return undefined;
2674						}
2675						data = data[ a[i] ];
2676					}
2677				}
2678	
2679				return data;
2680			};
2681	
2682			return function (data, type) { // row and meta also passed, but not used
2683				return fetchData( data, type, mSource );
2684			};
2685		}
2686		else
2687		{
2688			/* Array or flat object mapping */
2689			return function (data, type) { // row and meta also passed, but not used
2690				return data[mSource];
2691			};
2692		}
2693	}
2694	
2695	
2696	/**
2697	 * Return a function that can be used to set data from a source object, taking
2698	 * into account the ability to use nested objects as a source
2699	 *  @param {string|int|function} mSource The data source for the object
2700	 *  @returns {function} Data set function
2701	 *  @memberof DataTable#oApi
2702	 */
2703	function _fnSetObjectDataFn( mSource )
2704	{
2705		if ( $.isPlainObject( mSource ) )
2706		{
2707			/* Unlike get, only the underscore (global) option is used for for
2708			 * setting data since we don't know the type here. This is why an object
2709			 * option is not documented for `mData` (which is read/write), but it is
2710			 * for `mRender` which is read only.
2711			 */
2712			return _fnSetObjectDataFn( mSource._ );
2713		}
2714		else if ( mSource === null )
2715		{
2716			/* Nothing to do when the data source is null */
2717			return function () {};
2718		}
2719		else if ( typeof mSource === 'function' )
2720		{
2721			return function (data, val, meta) {
2722				mSource( data, 'set', val, meta );
2723			};
2724		}
2725		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2726			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2727		{
2728			/* Like the get, we need to get data from a nested object */
2729			var setData = function (data, val, src) {
2730				var a = _fnSplitObjNotation( src ), b;
2731				var aLast = a[a.length-1];
2732				var arrayNotation, funcNotation, o, innerSrc;
2733	
2734				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2735				{
2736					// Check if we are dealing with an array notation request
2737					arrayNotation = a[i].match(__reArray);
2738					funcNotation = a[i].match(__reFn);
2739	
2740					if ( arrayNotation )
2741					{
2742						a[i] = a[i].replace(__reArray, '');
2743						data[ a[i] ] = [];
2744	
2745						// Get the remainder of the nested object to set so we can recurse
2746						b = a.slice();
2747						b.splice( 0, i+1 );
2748						innerSrc = b.join('.');
2749	
2750						// Traverse each entry in the array setting the properties requested
2751						if ( $.isArray( val ) )
2752						{
2753							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2754							{
2755								o = {};
2756								setData( o, val[j], innerSrc );
2757								data[ a[i] ].push( o );
2758							}
2759						}
2760						else
2761						{
2762							// We've been asked to save data to an array, but it
2763							// isn't array data to be saved. Best that can be done
2764							// is to just save the value.
2765							data[ a[i] ] = val;
2766						}
2767	
2768						// The inner call to setData has already traversed through the remainder
2769						// of the source and has set the data, thus we can exit here
2770						return;
2771					}
2772					else if ( funcNotation )
2773					{
2774						// Function call
2775						a[i] = a[i].replace(__reFn, '');
2776						data = data[ a[i] ]( val );
2777					}
2778	
2779					// If the nested object doesn't currently exist - since we are
2780					// trying to set the value - create it
2781					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2782					{
2783						data[ a[i] ] = {};
2784					}
2785					data = data[ a[i] ];
2786				}
2787	
2788				// Last item in the input - i.e, the actual set
2789				if ( aLast.match(__reFn ) )
2790				{
2791					// Function call
2792					data = data[ aLast.replace(__reFn, '') ]( val );
2793				}
2794				else
2795				{
2796					// If array notation is used, we just want to strip it and use the property name
2797					// and assign the value. If it isn't used, then we get the result we want anyway
2798					data[ aLast.replace(__reArray, '') ] = val;
2799				}
2800			};
2801	
2802			return function (data, val) { // meta is also passed in, but not used
2803				return setData( data, val, mSource );
2804			};
2805		}
2806		else
2807		{
2808			/* Array or flat object mapping */
2809			return function (data, val) { // meta is also passed in, but not used
2810				data[mSource] = val;
2811			};
2812		}
2813	}
2814	
2815	
2816	/**
2817	 * Return an array with the full table data
2818	 *  @param {object} oSettings dataTables settings object
2819	 *  @returns array {array} aData Master data array
2820	 *  @memberof DataTable#oApi
2821	 */
2822	function _fnGetDataMaster ( settings )
2823	{
2824		return _pluck( settings.aoData, '_aData' );
2825	}
2826	
2827	
2828	/**
2829	 * Nuke the table
2830	 *  @param {object} oSettings dataTables settings object
2831	 *  @memberof DataTable#oApi
2832	 */
2833	function _fnClearTable( settings )
2834	{
2835		settings.aoData.length = 0;
2836		settings.aiDisplayMaster.length = 0;
2837		settings.aiDisplay.length = 0;
2838		settings.aIds = {};
2839	}
2840	
2841	
2842	 /**
2843	 * Take an array of integers (index array) and remove a target integer (value - not
2844	 * the key!)
2845	 *  @param {array} a Index array to target
2846	 *  @param {int} iTarget value to find
2847	 *  @memberof DataTable#oApi
2848	 */
2849	function _fnDeleteIndex( a, iTarget, splice )
2850	{
2851		var iTargetIndex = -1;
2852	
2853		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2854		{
2855			if ( a[i] == iTarget )
2856			{
2857				iTargetIndex = i;
2858			}
2859			else if ( a[i] > iTarget )
2860			{
2861				a[i]--;
2862			}
2863		}
2864	
2865		if ( iTargetIndex != -1 && splice === undefined )
2866		{
2867			a.splice( iTargetIndex, 1 );
2868		}
2869	}
2870	
2871	
2872	/**
2873	 * Mark cached data as invalid such that a re-read of the data will occur when
2874	 * the cached data is next requested. Also update from the data source object.
2875	 *
2876	 * @param {object} settings DataTables settings object
2877	 * @param {int}    rowIdx   Row index to invalidate
2878	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2879	 *     or 'data'
2880	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2881	 *     row will be invalidated
2882	 * @memberof DataTable#oApi
2883	 *
2884	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2885	 *   the sort and filter methods can subscribe to it. That will required
2886	 *   initialisation options for sorting, which is why it is not already baked in
2887	 */
2888	function _fnInvalidate( settings, rowIdx, src, colIdx )
2889	{
2890		var row = settings.aoData[ rowIdx ];
2891		var i, ien;
2892		var cellWrite = function ( cell, col ) {
2893			// This is very frustrating, but in IE if you just write directly
2894			// to innerHTML, and elements that are overwritten are GC'ed,
2895			// even if there is a reference to them elsewhere
2896			while ( cell.childNodes.length ) {
2897				cell.removeChild( cell.firstChild );
2898			}
2899	
2900			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2901		};
2902	
2903		// Are we reading last data from DOM or the data object?
2904		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2905			// Read the data from the DOM
2906			row._aData = _fnGetRowElements(
2907					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2908				)
2909				.data;
2910		}
2911		else {
2912			// Reading from data object, update the DOM
2913			var cells = row.anCells;
2914	
2915			if ( cells ) {
2916				if ( colIdx !== undefined ) {
2917					cellWrite( cells[colIdx], colIdx );
2918				}
2919				else {
2920					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2921						cellWrite( cells[i], i );
2922					}
2923				}
2924			}
2925		}
2926	
2927		// For both row and cell invalidation, the cached data for sorting and
2928		// filtering is nulled out
2929		row._aSortData = null;
2930		row._aFilterData = null;
2931	
2932		// Invalidate the type for a specific column (if given) or all columns since
2933		// the data might have changed
2934		var cols = settings.aoColumns;
2935		if ( colIdx !== undefined ) {
2936			cols[ colIdx ].sType = null;
2937		}
2938		else {
2939			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2940				cols[i].sType = null;
2941			}
2942	
2943			// Update DataTables special `DT_*` attributes for the row
2944			_fnRowAttributes( settings, row );
2945		}
2946	}
2947	
2948	
2949	/**
2950	 * Build a data source object from an HTML row, reading the contents of the
2951	 * cells that are in the row.
2952	 *
2953	 * @param {object} settings DataTables settings object
2954	 * @param {node|object} TR element from which to read data or existing row
2955	 *   object from which to re-read the data from the cells
2956	 * @param {int} [colIdx] Optional column index
2957	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
2958	 *   parameter should also be given and will be used to write the data into.
2959	 *   Only the column in question will be written
2960	 * @returns {object} Object with two parameters: `data` the data read, in
2961	 *   document order, and `cells` and array of nodes (they can be useful to the
2962	 *   caller, so rather than needing a second traversal to get them, just return
2963	 *   them from here).
2964	 * @memberof DataTable#oApi
2965	 */
2966	function _fnGetRowElements( settings, row, colIdx, d )
2967	{
2968		var
2969			tds = [],
2970			td = row.firstChild,
2971			name, col, o, i=0, contents,
2972			columns = settings.aoColumns,
2973			objectRead = settings._rowReadObject;
2974	
2975		// Allow the data object to be passed in, or construct
2976		d = d !== undefined ?
2977			d :
2978			objectRead ?
2979				{} :
2980				[];
2981	
2982		var attr = function ( str, td  ) {
2983			if ( typeof str === 'string' ) {
2984				var idx = str.indexOf('@');
2985	
2986				if ( idx !== -1 ) {
2987					var attr = str.substring( idx+1 );
2988					var setter = _fnSetObjectDataFn( str );
2989					setter( d, td.getAttribute( attr ) );
2990				}
2991			}
2992		};
2993	
2994		// Read data from a cell and store into the data object
2995		var cellProcess = function ( cell ) {
2996			if ( colIdx === undefined || colIdx === i ) {
2997				col = columns[i];
2998				contents = $.trim(cell.innerHTML);
2999	
3000				if ( col && col._bAttrSrc ) {
3001					var setter = _fnSetObjectDataFn( col.mData._ );
3002					setter( d, contents );
3003	
3004					attr( col.mData.sort, cell );
3005					attr( col.mData.type, cell );
3006					attr( col.mData.filter, cell );
3007				}
3008				else {
3009					// Depending on the `data` option for the columns the data can
3010					// be read to either an object or an array.
vendor: 11,978 bytes, lines 3011-3468
3011					if ( objectRead ) {
3012						if ( ! col._setter ) {
3013							// Cache the setter function
3014							col._setter = _fnSetObjectDataFn( col.mData );
3015						}
3016						col._setter( d, contents );
3017					}
3018					else {
3019						d[i] = contents;
3020					}
3021				}
3022			}
3023	
3024			i++;
3025		};
3026	
3027		if ( td ) {
3028			// `tr` element was passed in
3029			while ( td ) {
3030				name = td.nodeName.toUpperCase();
3031	
3032				if ( name == "TD" || name == "TH" ) {
3033					cellProcess( td );
3034					tds.push( td );
3035				}
3036	
3037				td = td.nextSibling;
3038			}
3039		}
3040		else {
3041			// Existing row object passed in
3042			tds = row.anCells;
3043	
3044			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3045				cellProcess( tds[j] );
3046			}
3047		}
3048	
3049		// Read the ID from the DOM if present
3050		var rowNode = row.firstChild ? row : row.nTr;
3051	
3052		if ( rowNode ) {
3053			var id = rowNode.getAttribute( 'id' );
3054	
3055			if ( id ) {
3056				_fnSetObjectDataFn( settings.rowId )( d, id );
3057			}
3058		}
3059	
3060		return {
3061			data: d,
3062			cells: tds
3063		};
3064	}
3065	/**
3066	 * Create a new TR element (and it's TD children) for a row
3067	 *  @param {object} oSettings dataTables settings object
3068	 *  @param {int} iRow Row to consider
3069	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3070	 *    DataTables will create a row automatically
3071	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3072	 *    if nTr is.
3073	 *  @memberof DataTable#oApi
3074	 */
3075	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3076	{
3077		var
3078			row = oSettings.aoData[iRow],
3079			rowData = row._aData,
3080			cells = [],
3081			nTr, nTd, oCol,
3082			i, iLen;
3083	
3084		if ( row.nTr === null )
3085		{
3086			nTr = nTrIn || document.createElement('tr');
3087	
3088			row.nTr = nTr;
3089			row.anCells = cells;
3090	
3091			/* Use a private property on the node to allow reserve mapping from the node
3092			 * to the aoData array for fast look up
3093			 */
3094			nTr._DT_RowIndex = iRow;
3095	
3096			/* Special parameters can be given by the data source to be used on the row */
3097			_fnRowAttributes( oSettings, row );
3098	
3099			/* Process each column */
3100			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3101			{
3102				oCol = oSettings.aoColumns[i];
3103	
3104				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3105				nTd._DT_CellIndex = {
3106					row: iRow,
3107					column: i
3108				};
3109				
3110				cells.push( nTd );
3111	
3112				// Need to create the HTML if new, or if a rendering function is defined
3113				if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3114					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3115				) {
3116					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3117				}
3118	
3119				/* Add user defined class */
3120				if ( oCol.sClass )
3121				{
3122					nTd.className += ' '+oCol.sClass;
3123				}
3124	
3125				// Visibility - add or remove as required
3126				if ( oCol.bVisible && ! nTrIn )
3127				{
3128					nTr.appendChild( nTd );
3129				}
3130				else if ( ! oCol.bVisible && nTrIn )
3131				{
3132					nTd.parentNode.removeChild( nTd );
3133				}
3134	
3135				if ( oCol.fnCreatedCell )
3136				{
3137					oCol.fnCreatedCell.call( oSettings.oInstance,
3138						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3139					);
3140				}
3141			}
3142	
3143			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
3144		}
3145	
3146		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3147		// and deployed
3148		row.nTr.setAttribute( 'role', 'row' );
3149	}
3150	
3151	
3152	/**
3153	 * Add attributes to a row based on the special `DT_*` parameters in a data
3154	 * source object.
3155	 *  @param {object} settings DataTables settings object
3156	 *  @param {object} DataTables row object for the row to be modified
3157	 *  @memberof DataTable#oApi
3158	 */
3159	function _fnRowAttributes( settings, row )
3160	{
3161		var tr = row.nTr;
3162		var data = row._aData;
3163	
3164		if ( tr ) {
3165			var id = settings.rowIdFn( data );
3166	
3167			if ( id ) {
3168				tr.id = id;
3169			}
3170	
3171			if ( data.DT_RowClass ) {
3172				// Remove any classes added by DT_RowClass before
3173				var a = data.DT_RowClass.split(' ');
3174				row.__rowc = row.__rowc ?
3175					_unique( row.__rowc.concat( a ) ) :
3176					a;
3177	
3178				$(tr)
3179					.removeClass( row.__rowc.join(' ') )
3180					.addClass( data.DT_RowClass );
3181			}
3182	
3183			if ( data.DT_RowAttr ) {
3184				$(tr).attr( data.DT_RowAttr );
3185			}
3186	
3187			if ( data.DT_RowData ) {
3188				$(tr).data( data.DT_RowData );
3189			}
3190		}
3191	}
3192	
3193	
3194	/**
3195	 * Create the HTML header for the table
3196	 *  @param {object} oSettings dataTables settings object
3197	 *  @memberof DataTable#oApi
3198	 */
3199	function _fnBuildHead( oSettings )
3200	{
3201		var i, ien, cell, row, column;
3202		var thead = oSettings.nTHead;
3203		var tfoot = oSettings.nTFoot;
3204		var createHeader = $('th, td', thead).length === 0;
3205		var classes = oSettings.oClasses;
3206		var columns = oSettings.aoColumns;
3207	
3208		if ( createHeader ) {
3209			row = $('<tr/>').appendTo( thead );
3210		}
3211	
3212		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3213			column = columns[i];
3214			cell = $( column.nTh ).addClass( column.sClass );
3215	
3216			if ( createHeader ) {
3217				cell.appendTo( row );
3218			}
3219	
3220			// 1.11 move into sorting
3221			if ( oSettings.oFeatures.bSort ) {
3222				cell.addClass( column.sSortingClass );
3223	
3224				if ( column.bSortable !== false ) {
3225					cell
3226						.attr( 'tabindex', oSettings.iTabIndex )
3227						.attr( 'aria-controls', oSettings.sTableId );
3228	
3229					_fnSortAttachListener( oSettings, column.nTh, i );
3230				}
3231			}
3232	
3233			if ( column.sTitle != cell[0].innerHTML ) {
3234				cell.html( column.sTitle );
3235			}
3236	
3237			_fnRenderer( oSettings, 'header' )(
3238				oSettings, cell, column, classes
3239			);
3240		}
3241	
3242		if ( createHeader ) {
3243			_fnDetectHeader( oSettings.aoHeader, thead );
3244		}
3245		
3246		/* ARIA role for the rows */
3247	 	$(thead).find('>tr').attr('role', 'row');
3248	
3249		/* Deal with the footer - add classes if required */
3250		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3251		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3252	
3253		// Cache the footer cells. Note that we only take the cells from the first
3254		// row in the footer. If there is more than one row the user wants to
3255		// interact with, they need to use the table().foot() method. Note also this
3256		// allows cells to be used for multiple columns using colspan
3257		if ( tfoot !== null ) {
3258			var cells = oSettings.aoFooter[0];
3259	
3260			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3261				column = columns[i];
3262				column.nTf = cells[i].cell;
3263	
3264				if ( column.sClass ) {
3265					$(column.nTf).addClass( column.sClass );
3266				}
3267			}
3268		}
3269	}
3270	
3271	
3272	/**
3273	 * Draw the header (or footer) element based on the column visibility states. The
3274	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3275	 * the instantaneous column visibility, to construct the new layout. The grid is
3276	 * traversed over cell at a time in a rows x columns grid fashion, although each
3277	 * cell insert can cover multiple elements in the grid - which is tracks using the
3278	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3279	 * already a cell in that position.
3280	 *  @param {object} oSettings dataTables settings object
3281	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3282	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3283	 *  @memberof DataTable#oApi
3284	 */
3285	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3286	{
3287		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3288		var aoLocal = [];
3289		var aApplied = [];
3290		var iColumns = oSettings.aoColumns.length;
3291		var iRowspan, iColspan;
3292	
3293		if ( ! aoSource )
3294		{
3295			return;
3296		}
3297	
3298		if (  bIncludeHidden === undefined )
3299		{
3300			bIncludeHidden = false;
3301		}
3302	
3303		/* Make a copy of the master layout array, but without the visible columns in it */
3304		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3305		{
3306			aoLocal[i] = aoSource[i].slice();
3307			aoLocal[i].nTr = aoSource[i].nTr;
3308	
3309			/* Remove any columns which are currently hidden */
3310			for ( j=iColumns-1 ; j>=0 ; j-- )
3311			{
3312				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3313				{
3314					aoLocal[i].splice( j, 1 );
3315				}
3316			}
3317	
3318			/* Prep the applied array - it needs an element for each row */
3319			aApplied.push( [] );
3320		}
3321	
3322		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3323		{
3324			nLocalTr = aoLocal[i].nTr;
3325	
3326			/* All cells are going to be replaced, so empty out the row */
3327			if ( nLocalTr )
3328			{
3329				while( (n = nLocalTr.firstChild) )
3330				{
3331					nLocalTr.removeChild( n );
3332				}
3333			}
3334	
3335			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3336			{
3337				iRowspan = 1;
3338				iColspan = 1;
3339	
3340				/* Check to see if there is already a cell (row/colspan) covering our target
3341				 * insert point. If there is, then there is nothing to do.
3342				 */
3343				if ( aApplied[i][j] === undefined )
3344				{
3345					nLocalTr.appendChild( aoLocal[i][j].cell );
3346					aApplied[i][j] = 1;
3347	
3348					/* Expand the cell to cover as many rows as needed */
3349					while ( aoLocal[i+iRowspan] !== undefined &&
3350					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3351					{
3352						aApplied[i+iRowspan][j] = 1;
3353						iRowspan++;
3354					}
3355	
3356					/* Expand the cell to cover as many columns as needed */
3357					while ( aoLocal[i][j+iColspan] !== undefined &&
3358					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3359					{
3360						/* Must update the applied array over the rows for the columns */
3361						for ( k=0 ; k<iRowspan ; k++ )
3362						{
3363							aApplied[i+k][j+iColspan] = 1;
3364						}
3365						iColspan++;
3366					}
3367	
3368					/* Do the actual expansion in the DOM */
3369					$(aoLocal[i][j].cell)
3370						.attr('rowspan', iRowspan)
3371						.attr('colspan', iColspan);
3372				}
3373			}
3374		}
3375	}
3376	
3377	
3378	/**
3379	 * Insert the required TR nodes into the table for display
3380	 *  @param {object} oSettings dataTables settings object
3381	 *  @memberof DataTable#oApi
3382	 */
3383	function _fnDraw( oSettings )
3384	{
3385		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3386		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3387		if ( $.inArray( false, aPreDraw ) !== -1 )
3388		{
3389			_fnProcessingDisplay( oSettings, false );
3390			return;
3391		}
3392	
3393		var i, iLen, n;
3394		var anRows = [];
3395		var iRowCount = 0;
3396		var asStripeClasses = oSettings.asStripeClasses;
3397		var iStripes = asStripeClasses.length;
3398		var iOpenRows = oSettings.aoOpenRows.length;
3399		var oLang = oSettings.oLanguage;
3400		var iInitDisplayStart = oSettings.iInitDisplayStart;
3401		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3402		var aiDisplay = oSettings.aiDisplay;
3403	
3404		oSettings.bDrawing = true;
3405	
3406		/* Check and see if we have an initial draw position from state saving */
3407		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3408		{
3409			oSettings._iDisplayStart = bServerSide ?
3410				iInitDisplayStart :
3411				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3412					0 :
3413					iInitDisplayStart;
3414	
3415			oSettings.iInitDisplayStart = -1;
3416		}
3417	
3418		var iDisplayStart = oSettings._iDisplayStart;
3419		var iDisplayEnd = oSettings.fnDisplayEnd();
3420	
3421		/* Server-side processing draw intercept */
3422		if ( oSettings.bDeferLoading )
3423		{
3424			oSettings.bDeferLoading = false;
3425			oSettings.iDraw++;
3426			_fnProcessingDisplay( oSettings, false );
3427		}
3428		else if ( !bServerSide )
3429		{
3430			oSettings.iDraw++;
3431		}
3432		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3433		{
3434			return;
3435		}
3436	
3437		if ( aiDisplay.length !== 0 )
3438		{
3439			var iStart = bServerSide ? 0 : iDisplayStart;
3440			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3441	
3442			for ( var j=iStart ; j<iEnd ; j++ )
3443			{
3444				var iDataIndex = aiDisplay[j];
3445				var aoData = oSettings.aoData[ iDataIndex ];
3446				if ( aoData.nTr === null )
3447				{
3448					_fnCreateTr( oSettings, iDataIndex );
3449				}
3450	
3451				var nRow = aoData.nTr;
3452	
3453				/* Remove the old striping classes and then add the new one */
3454				if ( iStripes !== 0 )
3455				{
3456					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3457					if ( aoData._sRowStripe != sStripe )
3458					{
3459						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3460						aoData._sRowStripe = sStripe;
3461					}
3462				}
3463	
3464				// Row callback functions - might want to manipulate the row
3465				// iRowCount and j are not currently documented. Are they at all
3466				// useful?
3467				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3468					[nRow, aoData._aData, iRowCount, j
vendor: 9,503 bytes, lines 3468-3822
3468] );
3469	
3470				anRows.push( nRow );
3471				iRowCount++;
3472			}
3473		}
3474		else
3475		{
3476			/* Table is empty - create a row with an empty message in it */
3477			var sZero = oLang.sZeroRecords;
3478			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3479			{
3480				sZero = oLang.sLoadingRecords;
3481			}
3482			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3483			{
3484				sZero = oLang.sEmptyTable;
3485			}
3486	
3487			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3488				.append( $('<td />', {
3489					'valign':  'top',
3490					'colSpan': _fnVisbleColumns( oSettings ),
3491					'class':   oSettings.oClasses.sRowEmpty
3492				} ).html( sZero ) )[0];
3493		}
3494	
3495		/* Header and footer callbacks */
3496		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3497			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3498	
3499		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3500			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3501	
3502		var body = $(oSettings.nTBody);
3503	
3504		body.children().detach();
3505		body.append( $(anRows) );
3506	
3507		/* Call all required callback functions for the end of a draw */
3508		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3509	
3510		/* Draw is complete, sorting and filtering must be as well */
3511		oSettings.bSorted = false;
3512		oSettings.bFiltered = false;
3513		oSettings.bDrawing = false;
3514	}
3515	
3516	
3517	/**
3518	 * Redraw the table - taking account of the various features which are enabled
3519	 *  @param {object} oSettings dataTables settings object
3520	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3521	 *    the paging is reset to the first page
3522	 *  @memberof DataTable#oApi
3523	 */
3524	function _fnReDraw( settings, holdPosition )
3525	{
3526		var
3527			features = settings.oFeatures,
3528			sort     = features.bSort,
3529			filter   = features.bFilter;
3530	
3531		if ( sort ) {
3532			_fnSort( settings );
3533		}
3534	
3535		if ( filter ) {
3536			_fnFilterComplete( settings, settings.oPreviousSearch );
3537		}
3538		else {
3539			// No filtering, so we want to just use the display master
3540			settings.aiDisplay = settings.aiDisplayMaster.slice();
3541		}
3542	
3543		if ( holdPosition !== true ) {
3544			settings._iDisplayStart = 0;
3545		}
3546	
3547		// Let any modules know about the draw hold position state (used by
3548		// scrolling internally)
3549		settings._drawHold = holdPosition;
3550	
3551		_fnDraw( settings );
3552	
3553		settings._drawHold = false;
3554	}
3555	
3556	
3557	/**
3558	 * Add the options to the page HTML for the table
3559	 *  @param {object} oSettings dataTables settings object
3560	 *  @memberof DataTable#oApi
3561	 */
3562	function _fnAddOptionsHtml ( oSettings )
3563	{
3564		var classes = oSettings.oClasses;
3565		var table = $(oSettings.nTable);
3566		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3567		var features = oSettings.oFeatures;
3568	
3569		// All DataTables are wrapped in a div
3570		var insert = $('<div/>', {
3571			id:      oSettings.sTableId+'_wrapper',
3572			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3573		} );
3574	
3575		oSettings.nHolding = holding[0];
3576		oSettings.nTableWrapper = insert[0];
3577		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3578	
3579		/* Loop over the user set positioning and place the elements as needed */
3580		var aDom = oSettings.sDom.split('');
3581		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3582		for ( var i=0 ; i<aDom.length ; i++ )
3583		{
3584			featureNode = null;
3585			cOption = aDom[i];
3586	
3587			if ( cOption == '<' )
3588			{
3589				/* New container div */
3590				nNewNode = $('<div/>')[0];
3591	
3592				/* Check to see if we should append an id and/or a class name to the container */
3593				cNext = aDom[i+1];
3594				if ( cNext == "'" || cNext == '"' )
3595				{
3596					sAttr = "";
3597					j = 2;
3598					while ( aDom[i+j] != cNext )
3599					{
3600						sAttr += aDom[i+j];
3601						j++;
3602					}
3603	
3604					/* Replace jQuery UI constants @todo depreciated */
3605					if ( sAttr == "H" )
3606					{
3607						sAttr = classes.sJUIHeader;
3608					}
3609					else if ( sAttr == "F" )
3610					{
3611						sAttr = classes.sJUIFooter;
3612					}
3613	
3614					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3615					 * breaks the string into parts and applies them as needed
3616					 */
3617					if ( sAttr.indexOf('.') != -1 )
3618					{
3619						var aSplit = sAttr.split('.');
3620						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3621						nNewNode.className = aSplit[1];
3622					}
3623					else if ( sAttr.charAt(0) == "#" )
3624					{
3625						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3626					}
3627					else
3628					{
3629						nNewNode.className = sAttr;
3630					}
3631	
3632					i += j; /* Move along the position array */
3633				}
3634	
3635				insert.append( nNewNode );
3636				insert = $(nNewNode);
3637			}
3638			else if ( cOption == '>' )
3639			{
3640				/* End container div */
3641				insert = insert.parent();
3642			}
3643			// @todo Move options into their own plugins?
3644			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3645			{
3646				/* Length */
3647				featureNode = _fnFeatureHtmlLength( oSettings );
3648			}
3649			else if ( cOption == 'f' && features.bFilter )
3650			{
3651				/* Filter */
3652				featureNode = _fnFeatureHtmlFilter( oSettings );
3653			}
3654			else if ( cOption == 'r' && features.bProcessing )
3655			{
3656				/* pRocessing */
3657				featureNode = _fnFeatureHtmlProcessing( oSettings );
3658			}
3659			else if ( cOption == 't' )
3660			{
3661				/* Table */
3662				featureNode = _fnFeatureHtmlTable( oSettings );
3663			}
3664			else if ( cOption ==  'i' && features.bInfo )
3665			{
3666				/* Info */
3667				featureNode = _fnFeatureHtmlInfo( oSettings );
3668			}
3669			else if ( cOption == 'p' && features.bPaginate )
3670			{
3671				/* Pagination */
3672				featureNode = _fnFeatureHtmlPaginate( oSettings );
3673			}
3674			else if ( DataTable.ext.feature.length !== 0 )
3675			{
3676				/* Plug-in features */
3677				var aoFeatures = DataTable.ext.feature;
3678				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3679				{
3680					if ( cOption == aoFeatures[k].cFeature )
3681					{
3682						featureNode = aoFeatures[k].fnInit( oSettings );
3683						break;
3684					}
3685				}
3686			}
3687	
3688			/* Add to the 2D features array */
3689			if ( featureNode )
3690			{
3691				var aanFeatures = oSettings.aanFeatures;
3692	
3693				if ( ! aanFeatures[cOption] )
3694				{
3695					aanFeatures[cOption] = [];
3696				}
3697	
3698				aanFeatures[cOption].push( featureNode );
3699				insert.append( featureNode );
3700			}
3701		}
3702	
3703		/* Built our DOM structure - replace the holding div with what we want */
3704		holding.replaceWith( insert );
3705		oSettings.nHolding = null;
3706	}
3707	
3708	
3709	/**
3710	 * Use the DOM source to create up an array of header cells. The idea here is to
3711	 * create a layout grid (array) of rows x columns, which contains a reference
3712	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3713	 * any column / row could be removed and the new grid constructed
3714	 *  @param array {object} aLayout Array to store the calculated layout in
3715	 *  @param {node} nThead The header/footer element for the table
3716	 *  @memberof DataTable#oApi
3717	 */
3718	function _fnDetectHeader ( aLayout, nThead )
3719	{
3720		var nTrs = $(nThead).children('tr');
3721		var nTr, nCell;
3722		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3723		var bUnique;
3724		var fnShiftCol = function ( a, i, j ) {
3725			var k = a[i];
3726	                while ( k[j] ) {
3727				j++;
3728			}
3729			return j;
3730		};
3731	
3732		aLayout.splice( 0, aLayout.length );
3733	
3734		/* We know how many rows there are in the layout - so prep it */
3735		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3736		{
3737			aLayout.push( [] );
3738		}
3739	
3740		/* Calculate a layout array */
3741		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3742		{
3743			nTr = nTrs[i];
3744			iColumn = 0;
3745	
3746			/* For every cell in the row... */
3747			nCell = nTr.firstChild;
3748			while ( nCell ) {
3749				if ( nCell.nodeName.toUpperCase() == "TD" ||
3750				     nCell.nodeName.toUpperCase() == "TH" )
3751				{
3752					/* Get the col and rowspan attributes from the DOM and sanitise them */
3753					iColspan = nCell.getAttribute('colspan') * 1;
3754					iRowspan = nCell.getAttribute('rowspan') * 1;
3755					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3756					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3757	
3758					/* There might be colspan cells already in this row, so shift our target
3759					 * accordingly
3760					 */
3761					iColShifted = fnShiftCol( aLayout, i, iColumn );
3762	
3763					/* Cache calculation for unique columns */
3764					bUnique = iColspan === 1 ? true : false;
3765	
3766					/* If there is col / rowspan, copy the information into the layout grid */
3767					for ( l=0 ; l<iColspan ; l++ )
3768					{
3769						for ( k=0 ; k<iRowspan ; k++ )
3770						{
3771							aLayout[i+k][iColShifted+l] = {
3772								"cell": nCell,
3773								"unique": bUnique
3774							};
3775							aLayout[i+k].nTr = nTr;
3776						}
3777					}
3778				}
3779				nCell = nCell.nextSibling;
3780			}
3781		}
3782	}
3783	
3784	
3785	/**
3786	 * Get an array of unique th elements, one for each column
3787	 *  @param {object} oSettings dataTables settings object
3788	 *  @param {node} nHeader automatically detect the layout from this node - optional
3789	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3790	 *  @returns array {node} aReturn list of unique th's
3791	 *  @memberof DataTable#oApi
3792	 */
3793	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3794	{
3795		var aReturn = [];
3796		if ( !aLayout )
3797		{
3798			aLayout = oSettings.aoHeader;
3799			if ( nHeader )
3800			{
3801				aLayout = [];
3802				_fnDetectHeader( aLayout, nHeader );
3803			}
3804		}
3805	
3806		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3807		{
3808			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3809			{
3810				if ( aLayout[i][j].unique &&
3811					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3812				{
3813					aReturn[j] = aLayout[i][j].cell;
3814				}
3815			}
3816		}
3817	
3818		return aReturn;
3819	}
3820	
3821	/**
3822	 * 
3822Create an Ajax call based on the table's settings, taking into account that
3823	 * parameters can have multiple forms, and backwards compatibility.
3824	 *
3825	 * @param {object} oSettings dataTables settings object
3826	 * @param {array} data Data to send to the server, required by
3827	 *     DataTables - may be augmented by developer callbacks
3828	 * @param {function} fn Callback function to run when data is obtained
3829	 */
3830	function _fnBuildAjax( oSettings, data, fn )
3831	{
3832		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3833		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3834	
3835		// Convert to object based for 1.10+ if using the old array scheme which can
3836		// come from server-side processing or serverParams
3837		if ( data && $.isArray(data) ) {
3838			var tmp = {};
3839			var rbracket = /(.*?)\[\]$/;
3840	
3841			$.each( data, function (key, val) {
3842				var match = val.name.match(rbracket);
3843	
3844				if ( match ) {
3845					// Support for arrays
3846					var name = match[0];
3847	
3848					if ( ! tmp[ name ] ) {
3849						tmp[ name ] = [];
3850					}
3851					tmp[ name ].push( val.value );
3852				}
3853				else {
3854					tmp[val.name] = val.value;
3855				}
3856			} );
3857			data = tmp;
3858		}
3859	
3860		var ajaxData;
3861		var ajax = oSettings.ajax;
3862		var instance = oSettings.oInstance;
3863		var callback = function ( json ) {
3864			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3865			fn( json );
3866		};
3867	
3868		if ( $.isPlainObject( ajax ) && ajax.data )
3869		{
3870			ajaxData = ajax.data;
3871	
3872			var newData = $.isFunction( ajaxData ) ?
3873				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3874				ajaxData;                      // an object object or array to merge
3875	
3876			// If the function returned something, use that alone
3877			data = $.isFunction( ajaxData ) && newData ?
3878				newData :
3879				$.extend( true, data, newData );
3880	
3881			// Remove the data property as we've resolved it already and don't want
3882			// jQuery to do it again (it is restored at the end of the function)
3883			delete ajax.data;
3884		}
3885	
3886		var baseAjax = {
3887			"data": data,
3888			"success": function (json) {
3889				var error = json.error || json.sError;
3890				if ( error ) {
3891					_fnLog( oSettings, 0, error );
3892				}
3893	
3894				oSettings.json = json;
3895				callback( json );
3896			},
3897			"dataType": "json",
3898			"cache": false,
3899			"type": oSettings.sServerMethod,
3900			"error": function (xhr, error, thrown) {
3901				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3902	
3903				if ( $.inArray( true, ret ) === -1 ) {
3904					if ( error == "parsererror" ) {
3905						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3906					}
3907					else if ( xhr.readyState === 4 ) {
3908						_fnLog( oSettings, 0, 'Ajax error', 7 );
3909					}
3910				}
3911	
3912				_fnProcessingDisplay( oSettings, false );
3913			}
3914		};
3915	
3916		// Store the data submitted for the API
3917		oSettings.oAjaxData = data;
3918	
3919		// Allow plug-ins and external processes to modify the data
3920		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3921	
3922		if ( oSettings.fnServerData )
3923		{
3924			// DataTables 1.9- compatibility
3925			oSettings.fnServerData.call( instance,
3926				oSettings.sAjaxSource,
3927				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3928					return { name: key, value: val };
3929				} ),
3930				callback,
3931				oSettings
3932			);
3933		}
3934		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3935		{
3936			// DataTables 1.9- compatibility
3937			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3938				url: ajax || oSettings.sAjaxSource
3939			} ) );
3940		}
3941		else if ( $.isFunction( ajax ) )
3942		{
3943			// Is a function - let the caller define what needs to be done
3944			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3945		}
3946		else
3947		{
3948			// Object to extend the base settings
3949			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3950	
3951			// Restore for next time around
3952			ajax.data = ajaxData;
3953		}
3954	}
3955	
3956	
3957	/**
3958	 * Update the table using an Ajax call
3959	 *  @param {object} settings dataTables settings object
3960	 *  @returns {boolean} Block the table drawing or not
3961	 *  @memberof DataTable#oApi
3962	 */
3963	function _fnAjaxUpdate( settings )
3964	{
3965		if ( settings.bAjaxDataGet ) {
3966			settings.iDraw++;
3967			_fnProcessingDisplay( settings, true );
3968	
3969			_fnBuildAjax(
3970				settings,
3971				_fnAjaxParameters( settings ),
3972				function(json) {
3973					_fnAjaxUpdateDraw( settings, json );
3974				}
3975			);
3976	
3977			return false;
vendor: 43,145 bytes, lines 3978-5457
3978		}
3979		return true;
3980	}
3981	
3982	
3983	/**
3984	 * Build up the parameters in an object needed for a server-side processing
3985	 * request. Note that this is basically done twice, is different ways - a modern
3986	 * method which is used by default in DataTables 1.10 which uses objects and
3987	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3988	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
3989	 * option is set.
3990	 *  @param {object} oSettings dataTables settings object
3991	 *  @returns {bool} block the table drawing or not
3992	 *  @memberof DataTable#oApi
3993	 */
3994	function _fnAjaxParameters( settings )
3995	{
3996		var
3997			columns = settings.aoColumns,
3998			columnCount = columns.length,
3999			features = settings.oFeatures,
4000			preSearch = settings.oPreviousSearch,
4001			preColSearch = settings.aoPreSearchCols,
4002			i, data = [], dataProp, column, columnSearch,
4003			sort = _fnSortFlatten( settings ),
4004			displayStart = settings._iDisplayStart,
4005			displayLength = features.bPaginate !== false ?
4006				settings._iDisplayLength :
4007				-1;
4008	
4009		var param = function ( name, value ) {
4010			data.push( { 'name': name, 'value': value } );
4011		};
4012	
4013		// DataTables 1.9- compatible method
4014		param( 'sEcho',          settings.iDraw );
4015		param( 'iColumns',       columnCount );
4016		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4017		param( 'iDisplayStart',  displayStart );
4018		param( 'iDisplayLength', displayLength );
4019	
4020		// DataTables 1.10+ method
4021		var d = {
4022			draw:    settings.iDraw,
4023			columns: [],
4024			order:   [],
4025			start:   displayStart,
4026			length:  displayLength,
4027			search:  {
4028				value: preSearch.sSearch,
4029				regex: preSearch.bRegex
4030			}
4031		};
4032	
4033		for ( i=0 ; i<columnCount ; i++ ) {
4034			column = columns[i];
4035			columnSearch = preColSearch[i];
4036			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4037	
4038			d.columns.push( {
4039				data:       dataProp,
4040				name:       column.sName,
4041				searchable: column.bSearchable,
4042				orderable:  column.bSortable,
4043				search:     {
4044					value: columnSearch.sSearch,
4045					regex: columnSearch.bRegex
4046				}
4047			} );
4048	
4049			param( "mDataProp_"+i, dataProp );
4050	
4051			if ( features.bFilter ) {
4052				param( 'sSearch_'+i,     columnSearch.sSearch );
4053				param( 'bRegex_'+i,      columnSearch.bRegex );
4054				param( 'bSearchable_'+i, column.bSearchable );
4055			}
4056	
4057			if ( features.bSort ) {
4058				param( 'bSortable_'+i, column.bSortable );
4059			}
4060		}
4061	
4062		if ( features.bFilter ) {
4063			param( 'sSearch', preSearch.sSearch );
4064			param( 'bRegex', preSearch.bRegex );
4065		}
4066	
4067		if ( features.bSort ) {
4068			$.each( sort, function ( i, val ) {
4069				d.order.push( { column: val.col, dir: val.dir } );
4070	
4071				param( 'iSortCol_'+i, val.col );
4072				param( 'sSortDir_'+i, val.dir );
4073			} );
4074	
4075			param( 'iSortingCols', sort.length );
4076		}
4077	
4078		// If the legacy.ajax parameter is null, then we automatically decide which
4079		// form to use, based on sAjaxSource
4080		var legacy = DataTable.ext.legacy.ajax;
4081		if ( legacy === null ) {
4082			return settings.sAjaxSource ? data : d;
4083		}
4084	
4085		// Otherwise, if legacy has been specified then we use that to decide on the
4086		// form
4087		return legacy ? data : d;
4088	}
4089	
4090	
4091	/**
4092	 * Data the data from the server (nuking the old) and redraw the table
4093	 *  @param {object} oSettings dataTables settings object
4094	 *  @param {object} json json data return from the server.
4095	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4096	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4097	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4098	 *  @param {array} json.aaData The data to display on this page
4099	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4100	 *  @memberof DataTable#oApi
4101	 */
4102	function _fnAjaxUpdateDraw ( settings, json )
4103	{
4104		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4105		// Support both
4106		var compat = function ( old, modern ) {
4107			return json[old] !== undefined ? json[old] : json[modern];
4108		};
4109	
4110		var data = _fnAjaxDataSrc( settings, json );
4111		var draw            = compat( 'sEcho',                'draw' );
4112		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4113		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4114	
4115		if ( draw ) {
4116			// Protect against out of sequence returns
4117			if ( draw*1 < settings.iDraw ) {
4118				return;
4119			}
4120			settings.iDraw = draw * 1;
4121		}
4122	
4123		_fnClearTable( settings );
4124		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4125		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4126	
4127		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4128			_fnAddData( settings, data[i] );
4129		}
4130		settings.aiDisplay = settings.aiDisplayMaster.slice();
4131	
4132		settings.bAjaxDataGet = false;
4133		_fnDraw( settings );
4134	
4135		if ( ! settings._bInitComplete ) {
4136			_fnInitComplete( settings, json );
4137		}
4138	
4139		settings.bAjaxDataGet = true;
4140		_fnProcessingDisplay( settings, false );
4141	}
4142	
4143	
4144	/**
4145	 * Get the data from the JSON data source to use for drawing a table. Using
4146	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4147	 * source object, or from a processing function.
4148	 *  @param {object} oSettings dataTables settings object
4149	 *  @param  {object} json Data source object / array from the server
4150	 *  @return {array} Array of data to use
4151	 */
4152	function _fnAjaxDataSrc ( oSettings, json )
4153	{
4154		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4155			oSettings.ajax.dataSrc :
4156			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4157	
4158		// Compatibility with 1.9-. In order to read from aaData, check if the
4159		// default has been changed, if not, check for aaData
4160		if ( dataSrc === 'data' ) {
4161			return json.aaData || json[dataSrc];
4162		}
4163	
4164		return dataSrc !== "" ?
4165			_fnGetObjectDataFn( dataSrc )( json ) :
4166			json;
4167	}
4168	
4169	/**
4170	 * Generate the node required for filtering text
4171	 *  @returns {node} Filter control element
4172	 *  @param {object} oSettings dataTables settings object
4173	 *  @memberof DataTable#oApi
4174	 */
4175	function _fnFeatureHtmlFilter ( settings )
4176	{
4177		var classes = settings.oClasses;
4178		var tableId = settings.sTableId;
4179		var language = settings.oLanguage;
4180		var previousSearch = settings.oPreviousSearch;
4181		var features = settings.aanFeatures;
4182		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4183	
4184		var str = language.sSearch;
4185		str = str.match(/_INPUT_/) ?
4186			str.replace('_INPUT_', input) :
4187			str+input;
4188	
4189		var filter = $('<div/>', {
4190				'id': ! features.f ? tableId+'_filter' : null,
4191				'class': classes.sFilter
4192			} )
4193			.append( $('<label/>' ).append( str ) );
4194	
4195		var searchFn = function() {
4196			/* Update all other filter input elements for the new display */
4197			var n = features.f;
4198			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4199	
4200			/* Now do the filter */
4201			if ( val != previousSearch.sSearch ) {
4202				_fnFilterComplete( settings, {
4203					"sSearch": val,
4204					"bRegex": previousSearch.bRegex,
4205					"bSmart": previousSearch.bSmart ,
4206					"bCaseInsensitive": previousSearch.bCaseInsensitive
4207				} );
4208	
4209				// Need to redraw, without resorting
4210				settings._iDisplayStart = 0;
4211				_fnDraw( settings );
4212			}
4213		};
4214	
4215		var searchDelay = settings.searchDelay !== null ?
4216			settings.searchDelay :
4217			_fnDataSource( settings ) === 'ssp' ?
4218				400 :
4219				0;
4220	
4221		var jqFilter = $('input', filter)
4222			.val( previousSearch.sSearch )
4223			.attr( 'placeholder', language.sSearchPlaceholder )
4224			.on(
4225				'keyup.DT search.DT input.DT paste.DT cut.DT',
4226				searchDelay ?
4227					_fnThrottle( searchFn, searchDelay ) :
4228					searchFn
4229			)
4230			.on( 'keypress.DT', function(e) {
4231				/* Prevent form submission */
4232				if ( e.keyCode == 13 ) {
4233					return false;
4234				}
4235			} )
4236			.attr('aria-controls', tableId);
4237	
4238		// Update the input elements whenever the table is filtered
4239		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4240			if ( settings === s ) {
4241				// IE9 throws an 'unknown error' if document.activeElement is used
4242				// inside an iframe or frame...
4243				try {
4244					if ( jqFilter[0] !== document.activeElement ) {
4245						jqFilter.val( previousSearch.sSearch );
4246					}
4247				}
4248				catch ( e ) {}
4249			}
4250		} );
4251	
4252		return filter[0];
4253	}
4254	
4255	
4256	/**
4257	 * Filter the table using both the global filter and column based filtering
4258	 *  @param {object} oSettings dataTables settings object
4259	 *  @param {object} oSearch search information
4260	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4261	 *  @memberof DataTable#oApi
4262	 */
4263	function _fnFilterComplete ( oSettings, oInput, iForce )
4264	{
4265		var oPrevSearch = oSettings.oPreviousSearch;
4266		var aoPrevSearch = oSettings.aoPreSearchCols;
4267		var fnSaveFilter = function ( oFilter ) {
4268			/* Save the filtering values */
4269			oPrevSearch.sSearch = oFilter.sSearch;
4270			oPrevSearch.bRegex = oFilter.bRegex;
4271			oPrevSearch.bSmart = oFilter.bSmart;
4272			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4273		};
4274		var fnRegex = function ( o ) {
4275			// Backwards compatibility with the bEscapeRegex option
4276			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4277		};
4278	
4279		// Resolve any column types that are unknown due to addition or invalidation
4280		// @todo As per sort - can this be moved into an event handler?
4281		_fnColumnTypes( oSettings );
4282	
4283		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4284		if ( _fnDataSource( oSettings ) != 'ssp' )
4285		{
4286			/* Global filter */
4287			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4288			fnSaveFilter( oInput );
4289	
4290			/* Now do the individual column filter */
4291			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4292			{
4293				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4294					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4295			}
4296	
4297			/* Custom filtering */
4298			_fnFilterCustom( oSettings );
4299		}
4300		else
4301		{
4302			fnSaveFilter( oInput );
4303		}
4304	
4305		/* Tell the draw function we have been filtering */
4306		oSettings.bFiltered = true;
4307		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4308	}
4309	
4310	
4311	/**
4312	 * Apply custom filtering functions
4313	 *  @param {object} oSettings dataTables settings object
4314	 *  @memberof DataTable#oApi
4315	 */
4316	function _fnFilterCustom( settings )
4317	{
4318		var filters = DataTable.ext.search;
4319		var displayRows = settings.aiDisplay;
4320		var row, rowIdx;
4321	
4322		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4323			var rows = [];
4324	
4325			// Loop over each row and see if it should be included
4326			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4327				rowIdx = displayRows[ j ];
4328				row = settings.aoData[ rowIdx ];
4329	
4330				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4331					rows.push( rowIdx );
4332				}
4333			}
4334	
4335			// So the array reference doesn't break set the results into the
4336			// existing array
4337			displayRows.length = 0;
4338			$.merge( displayRows, rows );
4339		}
4340	}
4341	
4342	
4343	/**
4344	 * Filter the table on a per-column basis
4345	 *  @param {object} oSettings dataTables settings object
4346	 *  @param {string} sInput string to filter on
4347	 *  @param {int} iColumn column to filter
4348	 *  @param {bool} bRegex treat search string as a regular expression or not
4349	 *  @param {bool} bSmart use smart filtering or not
4350	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4351	 *  @memberof DataTable#oApi
4352	 */
4353	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4354	{
4355		if ( searchStr === '' ) {
4356			return;
4357		}
4358	
4359		var data;
4360		var out = [];
4361		var display = settings.aiDisplay;
4362		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4363	
4364		for ( var i=0 ; i<display.length ; i++ ) {
4365			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4366	
4367			if ( rpSearch.test( data ) ) {
4368				out.push( display[i] );
4369			}
4370		}
4371	
4372		settings.aiDisplay = out;
4373	}
4374	
4375	
4376	/**
4377	 * Filter the data table based on user input and draw the table
4378	 *  @param {object} settings dataTables settings object
4379	 *  @param {string} input string to filter on
4380	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4381	 *  @param {bool} regex treat as a regular expression or not
4382	 *  @param {bool} smart perform smart filtering or not
4383	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4384	 *  @memberof DataTable#oApi
4385	 */
4386	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4387	{
4388		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4389		var prevSearch = settings.oPreviousSearch.sSearch;
4390		var displayMaster = settings.aiDisplayMaster;
4391		var display, invalidated, i;
4392		var filtered = [];
4393	
4394		// Need to take account of custom filtering functions - always filter
4395		if ( DataTable.ext.search.length !== 0 ) {
4396			force = true;
4397		}
4398	
4399		// Check if any of the rows were invalidated
4400		invalidated = _fnFilterData( settings );
4401	
4402		// If the input is blank - we just want the full data set
4403		if ( input.length <= 0 ) {
4404			settings.aiDisplay = displayMaster.slice();
4405		}
4406		else {
4407			// New search - start from the master array
4408			if ( invalidated ||
4409				 force ||
4410				 prevSearch.length > input.length ||
4411				 input.indexOf(prevSearch) !== 0 ||
4412				 settings.bSorted // On resort, the display master needs to be
4413				                  // re-filtered since indexes will have changed
4414			) {
4415				settings.aiDisplay = displayMaster.slice();
4416			}
4417	
4418			// Search the display array
4419			display = settings.aiDisplay;
4420	
4421			for ( i=0 ; i<display.length ; i++ ) {
4422				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4423					filtered.push( display[i] );
4424				}
4425			}
4426	
4427			settings.aiDisplay = filtered;
4428		}
4429	}
4430	
4431	
4432	/**
4433	 * Build a regular expression object suitable for searching a table
4434	 *  @param {string} sSearch string to search for
4435	 *  @param {bool} bRegex treat as a regular expression or not
4436	 *  @param {bool} bSmart perform smart filtering or not
4437	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4438	 *  @returns {RegExp} constructed object
4439	 *  @memberof DataTable#oApi
4440	 */
4441	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4442	{
4443		search = regex ?
4444			search :
4445			_fnEscapeRegex( search );
4446		
4447		if ( smart ) {
4448			/* For smart filtering we want to allow the search to work regardless of
4449			 * word order. We also want double quoted text to be preserved, so word
4450			 * order is important - a la google. So this is what we want to
4451			 * generate:
4452			 * 
4453			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4454			 */
4455			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4456				if ( word.charAt(0) === '"' ) {
4457					var m = word.match( /^"(.*)"$/ );
4458					word = m ? m[1] : word;
4459				}
4460	
4461				return word.replace('"', '');
4462			} );
4463	
4464			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4465		}
4466	
4467		return new RegExp( search, caseInsensitive ? 'i' : '' );
4468	}
4469	
4470	
4471	/**
4472	 * Escape a string such that it can be used in a regular expression
4473	 *  @param {string} sVal string to escape
4474	 *  @returns {string} escaped string
4475	 *  @memberof DataTable#oApi
4476	 */
4477	var _fnEscapeRegex = DataTable.util.escapeRegex;
4478	
4479	var __filter_div = $('<div>')[0];
4480	var __filter_div_textContent = __filter_div.textContent !== undefined;
4481	
4482	// Update the filtering data for each row if needed (by invalidation or first run)
4483	function _fnFilterData ( settings )
4484	{
4485		var columns = settings.aoColumns;
4486		var column;
4487		var i, j, ien, jen, filterData, cellData, row;
4488		var fomatters = DataTable.ext.type.search;
4489		var wasInvalidated = false;
4490	
4491		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4492			row = settings.aoData[i];
4493	
4494			if ( ! row._aFilterData ) {
4495				filterData = [];
4496	
4497				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4498					column = columns[j];
4499	
4500					if ( column.bSearchable ) {
4501						cellData = _fnGetCellData( settings, i, j, 'filter' );
4502	
4503						if ( fomatters[ column.sType ] ) {
4504							cellData = fomatters[ column.sType ]( cellData );
4505						}
4506	
4507						// Search in DataTables 1.10 is string based. In 1.11 this
4508						// should be altered to also allow strict type checking.
4509						if ( cellData === null ) {
4510							cellData = '';
4511						}
4512	
4513						if ( typeof cellData !== 'string' && cellData.toString ) {
4514							cellData = cellData.toString();
4515						}
4516					}
4517					else {
4518						cellData = '';
4519					}
4520	
4521					// If it looks like there is an HTML entity in the string,
4522					// attempt to decode it so sorting works as expected. Note that
4523					// we could use a single line of jQuery to do this, but the DOM
4524					// method used here is much faster http://jsperf.com/html-decode
4525					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4526						__filter_div.innerHTML = cellData;
4527						cellData = __filter_div_textContent ?
4528							__filter_div.textContent :
4529							__filter_div.innerText;
4530					}
4531	
4532					if ( cellData.replace ) {
4533						cellData = cellData.replace(/[\r\n]/g, '');
4534					}
4535	
4536					filterData.push( cellData );
4537				}
4538	
4539				row._aFilterData = filterData;
4540				row._sFilterRow = filterData.join('  ');
4541				wasInvalidated = true;
4542			}
4543		}
4544	
4545		return wasInvalidated;
4546	}
4547	
4548	
4549	/**
4550	 * Convert from the internal Hungarian notation to camelCase for external
4551	 * interaction
4552	 *  @param {object} obj Object to convert
4553	 *  @returns {object} Inverted object
4554	 *  @memberof DataTable#oApi
4555	 */
4556	function _fnSearchToCamel ( obj )
4557	{
4558		return {
4559			search:          obj.sSearch,
4560			smart:           obj.bSmart,
4561			regex:           obj.bRegex,
4562			caseInsensitive: obj.bCaseInsensitive
4563		};
4564	}
4565	
4566	
4567	
4568	/**
4569	 * Convert from camelCase notation to the internal Hungarian. We could use the
4570	 * Hungarian convert function here, but this is cleaner
4571	 *  @param {object} obj Object to convert
4572	 *  @returns {object} Inverted object
4573	 *  @memberof DataTable#oApi
4574	 */
4575	function _fnSearchToHung ( obj )
4576	{
4577		return {
4578			sSearch:          obj.search,
4579			bSmart:           obj.smart,
4580			bRegex:           obj.regex,
4581			bCaseInsensitive: obj.caseInsensitive
4582		};
4583	}
4584	
4585	/**
4586	 * Generate the node required for the info display
4587	 *  @param {object} oSettings dataTables settings object
4588	 *  @returns {node} Information element
4589	 *  @memberof DataTable#oApi
4590	 */
4591	function _fnFeatureHtmlInfo ( settings )
4592	{
4593		var
4594			tid = settings.sTableId,
4595			nodes = settings.aanFeatures.i,
4596			n = $('<div/>', {
4597				'class': settings.oClasses.sInfo,
4598				'id': ! nodes ? tid+'_info' : null
4599			} );
4600	
4601		if ( ! nodes ) {
4602			// Update display on each draw
4603			settings.aoDrawCallback.push( {
4604				"fn": _fnUpdateInfo,
4605				"sName": "information"
4606			} );
4607	
4608			n
4609				.attr( 'role', 'status' )
4610				.attr( 'aria-live', 'polite' );
4611	
4612			// Table is described by our info div
4613			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4614		}
4615	
4616		return n[0];
4617	}
4618	
4619	
4620	/**
4621	 * Update the information elements in the display
4622	 *  @param {object} settings dataTables settings object
4623	 *  @memberof DataTable#oApi
4624	 */
4625	function _fnUpdateInfo ( settings )
4626	{
4627		/* Show information about the table */
4628		var nodes = settings.aanFeatures.i;
4629		if ( nodes.length === 0 ) {
4630			return;
4631		}
4632	
4633		var
4634			lang  = settings.oLanguage,
4635			start = settings._iDisplayStart+1,
4636			end   = settings.fnDisplayEnd(),
4637			max   = settings.fnRecordsTotal(),
4638			total = settings.fnRecordsDisplay(),
4639			out   = total ?
4640				lang.sInfo :
4641				lang.sInfoEmpty;
4642	
4643		if ( total !== max ) {
4644			/* Record set after filtering */
4645			out += ' ' + lang.sInfoFiltered;
4646		}
4647	
4648		// Convert the macros
4649		out += lang.sInfoPostFix;
4650		out = _fnInfoMacros( settings, out );
4651	
4652		var callback = lang.fnInfoCallback;
4653		if ( callback !== null ) {
4654			out = callback.call( settings.oInstance,
4655				settings, start, end, max, total, out
4656			);
4657		}
4658	
4659		$(nodes).html( out );
4660	}
4661	
4662	
4663	function _fnInfoMacros ( settings, str )
4664	{
4665		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4666		// internally
4667		var
4668			formatter  = settings.fnFormatNumber,
4669			start      = settings._iDisplayStart+1,
4670			len        = settings._iDisplayLength,
4671			vis        = settings.fnRecordsDisplay(),
4672			all        = len === -1;
4673	
4674		return str.
4675			replace(/_START_/g, formatter.call( settings, start ) ).
4676			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4677			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4678			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4679			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4680			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4681	}
4682	
4683	
4684	
4685	/**
4686	 * Draw the table for the first time, adding all required features
4687	 *  @param {object} settings dataTables settings object
4688	 *  @memberof DataTable#oApi
4689	 */
4690	function _fnInitialise ( settings )
4691	{
4692		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4693		var columns = settings.aoColumns, column;
4694		var features = settings.oFeatures;
4695		var deferLoading = settings.bDeferLoading; // value modified by the draw
4696	
4697		/* Ensure that the table data is fully initialised */
4698		if ( ! settings.bInitialised ) {
4699			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4700			return;
4701		}
4702	
4703		/* Show the display HTML options */
4704		_fnAddOptionsHtml( settings );
4705	
4706		/* Build and draw the header / footer for the table */
4707		_fnBuildHead( settings );
4708		_fnDrawHead( settings, settings.aoHeader );
4709		_fnDrawHead( settings, settings.aoFooter );
4710	
4711		/* Okay to show that something is going on now */
4712		_fnProcessingDisplay( settings, true );
4713	
4714		/* Calculate sizes for columns */
4715		if ( features.bAutoWidth ) {
4716			_fnCalculateColumnWidths( settings );
4717		}
4718	
4719		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4720			column = columns[i];
4721	
4722			if ( column.sWidth ) {
4723				column.nTh.style.width = _fnStringToCss( column.sWidth );
4724			}
4725		}
4726	
4727		_fnCallbackFire( settings, null, 'preInit', [settings] );
4728	
4729		// If there is default sorting required - let's do it. The sort function
4730		// will do the drawing for us. Otherwise we draw the table regardless of the
4731		// Ajax source - this allows the table to look initialised for Ajax sourcing
4732		// data (show 'loading' message possibly)
4733		_fnReDraw( settings );
4734	
4735		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4736		var dataSrc = _fnDataSource( settings );
4737		if ( dataSrc != 'ssp' || deferLoading ) {
4738			// if there is an ajax source load the data
4739			if ( dataSrc == 'ajax' ) {
4740				_fnBuildAjax( settings, [], function(json) {
4741					var aData = _fnAjaxDataSrc( settings, json );
4742	
4743					// Got the data - add it to the table
4744					for ( i=0 ; i<aData.length ; i++ ) {
4745						_fnAddData( settings, aData[i] );
4746					}
4747	
4748					// Reset the init display for cookie saving. We've already done
4749					// a filter, and therefore cleared it before. So we need to make
4750					// it appear 'fresh'
4751					settings.iInitDisplayStart = iAjaxStart;
4752	
4753					_fnReDraw( settings );
4754	
4755					_fnProcessingDisplay( settings, false );
4756					_fnInitComplete( settings, json );
4757				}, settings );
4758			}
4759			else {
4760				_fnProcessingDisplay( settings, false );
4761				_fnInitComplete( settings );
4762			}
4763		}
4764	}
4765	
4766	
4767	/**
4768	 * Draw the table for the first time, adding all required features
4769	 *  @param {object} oSettings dataTables settings object
4770	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4771	 *    with client-side processing (optional)
4772	 *  @memberof DataTable#oApi
4773	 */
4774	function _fnInitComplete ( settings, json )
4775	{
4776		settings._bInitComplete = true;
4777	
4778		// When data was added after the initialisation (data or Ajax) we need to
4779		// calculate the column sizing
4780		if ( json || settings.oInit.aaData ) {
4781			_fnAdjustColumnSizing( settings );
4782		}
4783	
4784		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4785		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4786	}
4787	
4788	
4789	function _fnLengthChange ( settings, val )
4790	{
4791		var len = parseInt( val, 10 );
4792		settings._iDisplayLength = len;
4793	
4794		_fnLengthOverflow( settings );
4795	
4796		// Fire length change event
4797		_fnCallbackFire( settings, null, 'length', [settings, len] );
4798	}
4799	
4800	
4801	/**
4802	 * Generate the node required for user display length changing
4803	 *  @param {object} settings dataTables settings object
4804	 *  @returns {node} Display length feature node
4805	 *  @memberof DataTable#oApi
4806	 */
4807	function _fnFeatureHtmlLength ( settings )
4808	{
4809		var
4810			classes  = settings.oClasses,
4811			tableId  = settings.sTableId,
4812			menu     = settings.aLengthMenu,
4813			d2       = $.isArray( menu[0] ),
4814			lengths  = d2 ? menu[0] : menu,
4815			language = d2 ? menu[1] : menu;
4816	
4817		var select = $('<select/>', {
4818			'name':          tableId+'_length',
4819			'aria-controls': tableId,
4820			'class':         classes.sLengthSelect
4821		} );
4822	
4823		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4824			select[0][ i ] = new Option(
4825				typeof language[i] === 'number' ?
4826					settings.fnFormatNumber( language[i] ) :
4827					language[i],
4828				lengths[i]
4829			);
4830		}
4831	
4832		var div = $('<div><label/></div>').addClass( classes.sLength );
4833		if ( ! settings.aanFeatures.l ) {
4834			div[0].id = tableId+'_length';
4835		}
4836	
4837		div.children().append(
4838			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4839		);
4840	
4841		// Can't use `select` variable as user might provide their own and the
4842		// reference is broken by the use of outerHTML
4843		$('select', div)
4844			.val( settings._iDisplayLength )
4845			.on( 'change.DT', function(e) {
4846				_fnLengthChange( settings, $(this).val() );
4847				_fnDraw( settings );
4848			} );
4849	
4850		// Update node value whenever anything changes the table's length
4851		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4852			if ( settings === s ) {
4853				$('select', div).val( len );
4854			}
4855		} );
4856	
4857		return div[0];
4858	}
4859	
4860	
4861	
4862	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4863	 * Note that most of the paging logic is done in
4864	 * DataTable.ext.pager
4865	 */
4866	
4867	/**
4868	 * Generate the node required for default pagination
4869	 *  @param {object} oSettings dataTables settings object
4870	 *  @returns {node} Pagination feature node
4871	 *  @memberof DataTable#oApi
4872	 */
4873	function _fnFeatureHtmlPaginate ( settings )
4874	{
4875		var
4876			type   = settings.sPaginationType,
4877			plugin = DataTable.ext.pager[ type ],
4878			modern = typeof plugin === 'function',
4879			redraw = function( settings ) {
4880				_fnDraw( settings );
4881			},
4882			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4883			features = settings.aanFeatures;
4884	
4885		if ( ! modern ) {
4886			plugin.fnInit( settings, node, redraw );
4887		}
4888	
4889		/* Add a draw callback for the pagination on first instance, to update the paging display */
4890		if ( ! features.p )
4891		{
4892			node.id = settings.sTableId+'_paginate';
4893	
4894			settings.aoDrawCallback.push( {
4895				"fn": function( settings ) {
4896					if ( modern ) {
4897						var
4898							start      = settings._iDisplayStart,
4899							len        = settings._iDisplayLength,
4900							visRecords = settings.fnRecordsDisplay(),
4901							all        = len === -1,
4902							page = all ? 0 : Math.ceil( start / len ),
4903							pages = all ? 1 : Math.ceil( visRecords / len ),
4904							buttons = plugin(page, pages),
4905							i, ien;
4906	
4907						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4908							_fnRenderer( settings, 'pageButton' )(
4909								settings, features.p[i], i, buttons, page, pages
4910							);
4911						}
4912					}
4913					else {
4914						plugin.fnUpdate( settings, redraw );
4915					}
4916				},
4917				"sName": "pagination"
4918			} );
4919		}
4920	
4921		return node;
4922	}
4923	
4924	
4925	/**
4926	 * Alter the display settings to change the page
4927	 *  @param {object} settings DataTables settings object
4928	 *  @param {string|int} action Paging action to take: "first", "previous",
4929	 *    "next" or "last" or page number to jump to (integer)
4930	 *  @param [bool] redraw Automatically draw the update or not
4931	 *  @returns {bool} true page has changed, false - no change
4932	 *  @memberof DataTable#oApi
4933	 */
4934	function _fnPageChange ( settings, action, redraw )
4935	{
4936		var
4937			start     = settings._iDisplayStart,
4938			len       = settings._iDisplayLength,
4939			records   = settings.fnRecordsDisplay();
4940	
4941		if ( records === 0 || len === -1 )
4942		{
4943			start = 0;
4944		}
4945		else if ( typeof action === "number" )
4946		{
4947			start = action * len;
4948	
4949			if ( start > records )
4950			{
4951				start = 0;
4952			}
4953		}
4954		else if ( action == "first" )
4955		{
4956			start = 0;
4957		}
4958		else if ( action == "previous" )
4959		{
4960			start = len >= 0 ?
4961				start - len :
4962				0;
4963	
4964			if ( start < 0 )
4965			{
4966			  start = 0;
4967			}
4968		}
4969		else if ( action == "next" )
4970		{
4971			if ( start + len < records )
4972			{
4973				start += len;
4974			}
4975		}
4976		else if ( action == "last" )
4977		{
4978			start = Math.floor( (records-1) / len) * len;
4979		}
4980		else
4981		{
4982			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4983		}
4984	
4985		var changed = settings._iDisplayStart !== start;
4986		settings._iDisplayStart = start;
4987	
4988		if ( changed ) {
4989			_fnCallbackFire( settings, null, 'page', [settings] );
4990	
4991			if ( redraw ) {
4992				_fnDraw( settings );
4993			}
4994		}
4995	
4996		return changed;
4997	}
4998	
4999	
5000	
5001	/**
5002	 * Generate the node required for the processing node
5003	 *  @param {object} settings dataTables settings object
5004	 *  @returns {node} Processing element
5005	 *  @memberof DataTable#oApi
5006	 */
5007	function _fnFeatureHtmlProcessing ( settings )
5008	{
5009		return $('<div/>', {
5010				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5011				'class': settings.oClasses.sProcessing
5012			} )
5013			.html( settings.oLanguage.sProcessing )
5014			.insertBefore( settings.nTable )[0];
5015	}
5016	
5017	
5018	/**
5019	 * Display or hide the processing indicator
5020	 *  @param {object} settings dataTables settings object
5021	 *  @param {bool} show Show the processing indicator (true) or not (false)
5022	 *  @memberof DataTable#oApi
5023	 */
5024	function _fnProcessingDisplay ( settings, show )
5025	{
5026		if ( settings.oFeatures.bProcessing ) {
5027			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5028		}
5029	
5030		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5031	}
5032	
5033	/**
5034	 * Add any control elements for the table - specifically scrolling
5035	 *  @param {object} settings dataTables settings object
5036	 *  @returns {node} Node to add to the DOM
5037	 *  @memberof DataTable#oApi
5038	 */
5039	function _fnFeatureHtmlTable ( settings )
5040	{
5041		var table = $(settings.nTable);
5042	
5043		// Add the ARIA grid role to the table
5044		table.attr( 'role', 'grid' );
5045	
5046		// Scrolling from here on in
5047		var scroll = settings.oScroll;
5048	
5049		if ( scroll.sX === '' && scroll.sY === '' ) {
5050			return settings.nTable;
5051		}
5052	
5053		var scrollX = scroll.sX;
5054		var scrollY = scroll.sY;
5055		var classes = settings.oClasses;
5056		var caption = table.children('caption');
5057		var captionSide = caption.length ? caption[0]._captionSide : null;
5058		var headerClone = $( table[0].cloneNode(false) );
5059		var footerClone = $( table[0].cloneNode(false) );
5060		var footer = table.children('tfoot');
5061		var _div = '<div/>';
5062		var size = function ( s ) {
5063			return !s ? null : _fnStringToCss( s );
5064		};
5065	
5066		if ( ! footer.length ) {
5067			footer = null;
5068		}
5069	
5070		/*
5071		 * The HTML structure that we want to generate in this function is:
5072		 *  div - scroller
5073		 *    div - scroll head
5074		 *      div - scroll head inner
5075		 *        table - scroll head table
5076		 *          thead - thead
5077		 *    div - scroll body
5078		 *      table - table (master table)
5079		 *        thead - thead clone for sizing
5080		 *        tbody - tbody
5081		 *    div - scroll foot
5082		 *      div - scroll foot inner
5083		 *        table - scroll foot table
5084		 *          tfoot - tfoot
5085		 */
5086		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5087			.append(
5088				$(_div, { 'class': classes.sScrollHead } )
5089					.css( {
5090						overflow: 'hidden',
5091						position: 'relative',
5092						border: 0,
5093						width: scrollX ? size(scrollX) : '100%'
5094					} )
5095					.append(
5096						$(_div, { 'class': classes.sScrollHeadInner } )
5097							.css( {
5098								'box-sizing': 'content-box',
5099								width: scroll.sXInner || '100%'
5100							} )
5101							.append(
5102								headerClone
5103									.removeAttr('id')
5104									.css( 'margin-left', 0 )
5105									.append( captionSide === 'top' ? caption : null )
5106									.append(
5107										table.children('thead')
5108									)
5109							)
5110					)
5111			)
5112			.append(
5113				$(_div, { 'class': classes.sScrollBody } )
5114					.css( {
5115						position: 'relative',
5116						overflow: 'auto',
5117						width: size( scrollX )
5118					} )
5119					.append( table )
5120			);
5121	
5122		if ( footer ) {
5123			scroller.append(
5124				$(_div, { 'class': classes.sScrollFoot } )
5125					.css( {
5126						overflow: 'hidden',
5127						border: 0,
5128						width: scrollX ? size(scrollX) : '100%'
5129					} )
5130					.append(
5131						$(_div, { 'class': classes.sScrollFootInner } )
5132							.append(
5133								footerClone
5134									.removeAttr('id')
5135									.css( 'margin-left', 0 )
5136									.append( captionSide === 'bottom' ? caption : null )
5137									.append(
5138										table.children('tfoot')
5139									)
5140							)
5141					)
5142			);
5143		}
5144	
5145		var children = scroller.children();
5146		var scrollHead = children[0];
5147		var scrollBody = children[1];
5148		var scrollFoot = footer ? children[2] : null;
5149	
5150		// When the body is scrolled, then we also want to scroll the headers
5151		if ( scrollX ) {
5152			$(scrollBody).on( 'scroll.DT', function (e) {
5153				var scrollLeft = this.scrollLeft;
5154	
5155				scrollHead.scrollLeft = scrollLeft;
5156	
5157				if ( footer ) {
5158					scrollFoot.scrollLeft = scrollLeft;
5159				}
5160			} );
5161		}
5162	
5163		$(scrollBody).css(
5164			scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5165			scrollY
5166		);
5167	
5168		settings.nScrollHead = scrollHead;
5169		settings.nScrollBody = scrollBody;
5170		settings.nScrollFoot = scrollFoot;
5171	
5172		// On redraw - align columns
5173		settings.aoDrawCallback.push( {
5174			"fn": _fnScrollDraw,
5175			"sName": "scrolling"
5176		} );
5177	
5178		return scroller[0];
5179	}
5180	
5181	
5182	
5183	/**
5184	 * Update the header, footer and body tables for resizing - i.e. column
5185	 * alignment.
5186	 *
5187	 * Welcome to the most horrible function DataTables. The process that this
5188	 * function follows is basically:
5189	 *   1. Re-create the table inside the scrolling div
5190	 *   2. Take live measurements from the DOM
5191	 *   3. Apply the measurements to align the columns
5192	 *   4. Clean up
5193	 *
5194	 *  @param {object} settings dataTables settings object
5195	 *  @memberof DataTable#oApi
5196	 */
5197	function _fnScrollDraw ( settings )
5198	{
5199		// Given that this is such a monster function, a lot of variables are use
5200		// to try and keep the minimised size as small as possible
5201		var
5202			scroll         = settings.oScroll,
5203			scrollX        = scroll.sX,
5204			scrollXInner   = scroll.sXInner,
5205			scrollY        = scroll.sY,
5206			barWidth       = scroll.iBarWidth,
5207			divHeader      = $(settings.nScrollHead),
5208			divHeaderStyle = divHeader[0].style,
5209			divHeaderInner = divHeader.children('div'),
5210			divHeaderInnerStyle = divHeaderInner[0].style,
5211			divHeaderTable = divHeaderInner.children('table'),
5212			divBodyEl      = settings.nScrollBody,
5213			divBody        = $(divBodyEl),
5214			divBodyStyle   = divBodyEl.style,
5215			divFooter      = $(settings.nScrollFoot),
5216			divFooterInner = divFooter.children('div'),
5217			divFooterTable = divFooterInner.children('table'),
5218			header         = $(settings.nTHead),
5219			table          = $(settings.nTable),
5220			tableEl        = table[0],
5221			tableStyle     = tableEl.style,
5222			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5223			browser        = settings.oBrowser,
5224			ie67           = browser.bScrollOversize,
5225			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5226			headerTrgEls, footerTrgEls,
5227			headerSrcEls, footerSrcEls,
5228			headerCopy, footerCopy,
5229			headerWidths=[], footerWidths=[],
5230			headerContent=[], footerContent=[],
5231			idx, correction, sanityWidth,
5232			zeroOut = function(nSizer) {
5233				var style = nSizer.style;
5234				style.paddingTop = "0";
5235				style.paddingBottom = "0";
5236				style.borderTopWidth = "0";
5237				style.borderBottomWidth = "0";
5238				style.height = 0;
5239			};
5240	
5241		// If the scrollbar visibility has changed from the last draw, we need to
5242		// adjust the column sizes as the table width will have changed to account
5243		// for the scrollbar
5244		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5245		
5246		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5247			settings.scrollBarVis = scrollBarVis;
5248			_fnAdjustColumnSizing( settings );
5249			return; // adjust column sizing will call this function again
5250		}
5251		else {
5252			settings.scrollBarVis = scrollBarVis;
5253		}
5254	
5255		/*
5256		 * 1. Re-create the table inside the scrolling div
5257		 */
5258	
5259		// Remove the old minimised thead and tfoot elements in the inner table
5260		table.children('thead, tfoot').remove();
5261	
5262		if ( footer ) {
5263			footerCopy = footer.clone().prependTo( table );
5264			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5265			footerSrcEls = footerCopy.find('tr');
5266		}
5267	
5268		// Clone the current header and footer elements and then place it into the inner table
5269		headerCopy = header.clone().prependTo( table );
5270		headerTrgEls = header.find('tr'); // original header is in its own table
5271		headerSrcEls = headerCopy.find('tr');
5272		headerCopy.find('th, td').removeAttr('tabindex');
5273	
5274	
5275		/*
5276		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5277		 */
5278	
5279		// Remove old sizing and apply the calculated column widths
5280		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5281		// calculated sizes to this header
5282		if ( ! scrollX )
5283		{
5284			divBodyStyle.width = '100%';
5285			divHeader[0].style.width = '100%';
5286		}
5287	
5288		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5289			idx = _fnVisibleToColumnIndex( settings, i );
5290			el.style.width = settings.aoColumns[idx].sWidth;
5291		} );
5292	
5293		if ( footer ) {
5294			_fnApplyToChildren( function(n) {
5295				n.style.width = "";
5296			}, footerSrcEls );
5297		}
5298	
5299		// Size the table as a whole
5300		sanityWidth = table.outerWidth();
5301		if ( scrollX === "" ) {
5302			// No x scrolling
5303			tableStyle.width = "100%";
5304	
5305			// IE7 will make the width of the table when 100% include the scrollbar
5306			// - which is shouldn't. When there is a scrollbar we need to take this
5307			// into account.
5308			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5309				divBody.css('overflow-y') == "scroll")
5310			) {
5311				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5312			}
5313	
5314			// Recalculate the sanity width
5315			sanityWidth = table.outerWidth();
5316		}
5317		else if ( scrollXInner !== "" ) {
5318			// legacy x scroll inner has been given - use it
5319			tableStyle.width = _fnStringToCss(scrollXInner);
5320	
5321			// Recalculate the sanity width
5322			sanityWidth = table.outerWidth();
5323		}
5324	
5325		// Hidden header should have zero height, so remove padding and borders. Then
5326		// set the width based on the real headers
5327	
5328		// Apply all styles in one pass
5329		_fnApplyToChildren( zeroOut, headerSrcEls );
5330	
5331		// Read all widths in next pass
5332		_fnApplyToChildren( function(nSizer) {
5333			headerContent.push( nSizer.innerHTML );
5334			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5335		}, headerSrcEls );
5336	
5337		// Apply all widths in final pass
5338		_fnApplyToChildren( function(nToSize, i) {
5339			// Only apply widths to the DataTables detected header cells - this
5340			// prevents complex headers from having contradictory sizes applied
5341			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5342				nToSize.style.width = headerWidths[i];
5343			}
5344		}, headerTrgEls );
5345	
5346		$(headerSrcEls).height(0);
5347	
5348		/* Same again with the footer if we have one */
5349		if ( footer )
5350		{
5351			_fnApplyToChildren( zeroOut, footerSrcEls );
5352	
5353			_fnApplyToChildren( function(nSizer) {
5354				footerContent.push( nSizer.innerHTML );
5355				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5356			}, footerSrcEls );
5357	
5358			_fnApplyToChildren( function(nToSize, i) {
5359				nToSize.style.width = footerWidths[i];
5360			}, footerTrgEls );
5361	
5362			$(footerSrcEls).height(0);
5363		}
5364	
5365	
5366		/*
5367		 * 3. Apply the measurements
5368		 */
5369	
5370		// "Hide" the header and footer that we used for the sizing. We need to keep
5371		// the content of the cell so that the width applied to the header and body
5372		// both match, but we want to hide it completely. We want to also fix their
5373		// width to what they currently are
5374		_fnApplyToChildren( function(nSizer, i) {
5375			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
5376			nSizer.style.width = headerWidths[i];
5377		}, headerSrcEls );
5378	
5379		if ( footer )
5380		{
5381			_fnApplyToChildren( function(nSizer, i) {
5382				nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';
5383				nSizer.style.width = footerWidths[i];
5384			}, footerSrcEls );
5385		}
5386	
5387		// Sanity check that the table is of a sensible width. If not then we are going to get
5388		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5389		if ( table.outerWidth() < sanityWidth )
5390		{
5391			// The min width depends upon if we have a vertical scrollbar visible or not */
5392			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5393				divBody.css('overflow-y') == "scroll")) ?
5394					sanityWidth+barWidth :
5395					sanityWidth;
5396	
5397			// IE6/7 are a law unto themselves...
5398			if ( ie67 && (divBodyEl.scrollHeight >
5399				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5400			) {
5401				tableStyle.width = _fnStringToCss( correction-barWidth );
5402			}
5403	
5404			// And give the user a warning that we've stopped the table getting too small
5405			if ( scrollX === "" || scrollXInner !== "" ) {
5406				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5407			}
5408		}
5409		else
5410		{
5411			correction = '100%';
5412		}
5413	
5414		// Apply to the container elements
5415		divBodyStyle.width = _fnStringToCss( correction );
5416		divHeaderStyle.width = _fnStringToCss( correction );
5417	
5418		if ( footer ) {
5419			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5420		}
5421	
5422	
5423		/*
5424		 * 4. Clean up
5425		 */
5426		if ( ! scrollY ) {
5427			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5428			 * the scrollbar height from the visible display, rather than adding it on. We need to
5429			 * set the height in order to sort this. Don't want to do it in any other browsers.
5430			 */
5431			if ( ie67 ) {
5432				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5433			}
5434		}
5435	
5436		/* Finally set the width's of the header and footer tables */
5437		var iOuterWidth = table.outerWidth();
5438		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5439		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5440	
5441		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5442		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5443		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5444		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5445		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5446	
5447		if ( footer ) {
5448			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5449			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5450			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5451		}
5452	
5453		// Correct DOM ordering for colgroup - comes before the thead
5454		table.children('colgroup').insertBefore( table.children('thead') );
5455	
5456		/* Adjust the position of the header in case we loose the y-scrollbar */
5457		divBody.scroll(
vendor: 11,594 bytes, lines 5457-5855
5457);
5458	
5459		// If sorting or filtering has occurred, jump the scrolling back to the top
5460		// only if we aren't holding the position
5461		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5462			divBodyEl.scrollTop = 0;
5463		}
5464	}
5465	
5466	
5467	
5468	/**
5469	 * Apply a given function to the display child nodes of an element array (typically
5470	 * TD children of TR rows
5471	 *  @param {function} fn Method to apply to the objects
5472	 *  @param array {nodes} an1 List of elements to look through for display children
5473	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5474	 *  @memberof DataTable#oApi
5475	 */
5476	function _fnApplyToChildren( fn, an1, an2 )
5477	{
5478		var index=0, i=0, iLen=an1.length;
5479		var nNode1, nNode2;
5480	
5481		while ( i < iLen ) {
5482			nNode1 = an1[i].firstChild;
5483			nNode2 = an2 ? an2[i].firstChild : null;
5484	
5485			while ( nNode1 ) {
5486				if ( nNode1.nodeType === 1 ) {
5487					if ( an2 ) {
5488						fn( nNode1, nNode2, index );
5489					}
5490					else {
5491						fn( nNode1, index );
5492					}
5493	
5494					index++;
5495				}
5496	
5497				nNode1 = nNode1.nextSibling;
5498				nNode2 = an2 ? nNode2.nextSibling : null;
5499			}
5500	
5501			i++;
5502		}
5503	}
5504	
5505	
5506	
5507	var __re_html_remove = /<.*?>/g;
5508	
5509	
5510	/**
5511	 * Calculate the width of columns for the table
5512	 *  @param {object} oSettings dataTables settings object
5513	 *  @memberof DataTable#oApi
5514	 */
5515	function _fnCalculateColumnWidths ( oSettings )
5516	{
5517		var
5518			table = oSettings.nTable,
5519			columns = oSettings.aoColumns,
5520			scroll = oSettings.oScroll,
5521			scrollY = scroll.sY,
5522			scrollX = scroll.sX,
5523			scrollXInner = scroll.sXInner,
5524			columnCount = columns.length,
5525			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5526			headerCells = $('th', oSettings.nTHead),
5527			tableWidthAttr = table.getAttribute('width'), // from DOM element
5528			tableContainer = table.parentNode,
5529			userInputs = false,
5530			i, column, columnIdx, width, outerWidth,
5531			browser = oSettings.oBrowser,
5532			ie67 = browser.bScrollOversize;
5533	
5534		var styleWidth = table.style.width;
5535		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5536			tableWidthAttr = styleWidth;
5537		}
5538	
5539		/* Convert any user input sizes into pixel sizes */
5540		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5541			column = columns[ visibleColumns[i] ];
5542	
5543			if ( column.sWidth !== null ) {
5544				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5545	
5546				userInputs = true;
5547			}
5548		}
5549	
5550		/* If the number of columns in the DOM equals the number that we have to
5551		 * process in DataTables, then we can use the offsets that are created by
5552		 * the web- browser. No custom sizes can be set in order for this to happen,
5553		 * nor scrolling used
5554		 */
5555		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5556		     columnCount == _fnVisbleColumns( oSettings ) &&
5557		     columnCount == headerCells.length
5558		) {
5559			for ( i=0 ; i<columnCount ; i++ ) {
5560				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5561	
5562				if ( colIdx !== null ) {
5563					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5564				}
5565			}
5566		}
5567		else
5568		{
5569			// Otherwise construct a single row, worst case, table with the widest
5570			// node in the data, assign any user defined widths, then insert it into
5571			// the DOM and allow the browser to do all the hard work of calculating
5572			// table widths
5573			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5574				.css( 'visibility', 'hidden' )
5575				.removeAttr( 'id' );
5576	
5577			// Clean up the table body
5578			tmpTable.find('tbody tr').remove();
5579			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5580	
5581			// Clone the table header and footer - we can't use the header / footer
5582			// from the cloned table, since if scrolling is active, the table's
5583			// real header and footer are contained in different table tags
5584			tmpTable.find('thead, tfoot').remove();
5585			tmpTable
5586				.append( $(oSettings.nTHead).clone() )
5587				.append( $(oSettings.nTFoot).clone() );
5588	
5589			// Remove any assigned widths from the footer (from scrolling)
5590			tmpTable.find('tfoot th, tfoot td').css('width', '');
5591	
5592			// Apply custom sizing to the cloned header
5593			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5594	
5595			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5596				column = columns[ visibleColumns[i] ];
5597	
5598				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5599					_fnStringToCss( column.sWidthOrig ) :
5600					'';
5601	
5602				// For scrollX we need to force the column width otherwise the
5603				// browser will collapse it. If this width is smaller than the
5604				// width the column requires, then it will have no effect
5605				if ( column.sWidthOrig && scrollX ) {
5606					$( headerCells[i] ).append( $('<div/>').css( {
5607						width: column.sWidthOrig,
5608						margin: 0,
5609						padding: 0,
5610						border: 0,
5611						height: 1
5612					} ) );
5613				}
5614			}
5615	
5616			// Find the widest cell for each column and put it into the table
5617			if ( oSettings.aoData.length ) {
5618				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5619					columnIdx = visibleColumns[i];
5620					column = columns[ columnIdx ];
5621	
5622					$( _fnGetWidestNode( oSettings, columnIdx ) )
5623						.clone( false )
5624						.append( column.sContentPadding )
5625						.appendTo( tr );
5626				}
5627			}
5628	
5629			// Tidy the temporary table - remove name attributes so there aren't
5630			// duplicated in the dom (radio elements for example)
5631			$('[name]', tmpTable).removeAttr('name');
5632	
5633			// Table has been built, attach to the document so we can work with it.
5634			// A holding element is used, positioned at the top of the container
5635			// with minimal height, so it has no effect on if the container scrolls
5636			// or not. Otherwise it might trigger scrolling when it actually isn't
5637			// needed
5638			var holder = $('<div/>').css( scrollX || scrollY ?
5639					{
5640						position: 'absolute',
5641						top: 0,
5642						left: 0,
5643						height: 1,
5644						right: 0,
5645						overflow: 'hidden'
5646					} :
5647					{}
5648				)
5649				.append( tmpTable )
5650				.appendTo( tableContainer );
5651	
5652			// When scrolling (X or Y) we want to set the width of the table as 
5653			// appropriate. However, when not scrolling leave the table width as it
5654			// is. This results in slightly different, but I think correct behaviour
5655			if ( scrollX && scrollXInner ) {
5656				tmpTable.width( scrollXInner );
5657			}
5658			else if ( scrollX ) {
5659				tmpTable.css( 'width', 'auto' );
5660				tmpTable.removeAttr('width');
5661	
5662				// If there is no width attribute or style, then allow the table to
5663				// collapse
5664				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5665					tmpTable.width( tableContainer.clientWidth );
5666				}
5667			}
5668			else if ( scrollY ) {
5669				tmpTable.width( tableContainer.clientWidth );
5670			}
5671			else if ( tableWidthAttr ) {
5672				tmpTable.width( tableWidthAttr );
5673			}
5674	
5675			// Get the width of each column in the constructed table - we need to
5676			// know the inner width (so it can be assigned to the other table's
5677			// cells) and the outer width so we can calculate the full width of the
5678			// table. This is safe since DataTables requires a unique cell for each
5679			// column, but if ever a header can span multiple columns, this will
5680			// need to be modified.
5681			var total = 0;
5682			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5683				var cell = $(headerCells[i]);
5684				var border = cell.outerWidth() - cell.width();
5685	
5686				// Use getBounding... where possible (not IE8-) because it can give
5687				// sub-pixel accuracy, which we then want to round up!
5688				var bounding = browser.bBounding ?
5689					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5690					cell.outerWidth();
5691	
5692				// Total is tracked to remove any sub-pixel errors as the outerWidth
5693				// of the table might not equal the total given here (IE!).
5694				total += bounding;
5695	
5696				// Width for each column to use
5697				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5698			}
5699	
5700			table.style.width = _fnStringToCss( total );
5701	
5702			// Finished with the table - ditch it
5703			holder.remove();
5704		}
5705	
5706		// If there is a width attr, we want to attach an event listener which
5707		// allows the table sizing to automatically adjust when the window is
5708		// resized. Use the width attr rather than CSS, since we can't know if the
5709		// CSS is a relative value or absolute - DOM read is always px.
5710		if ( tableWidthAttr ) {
5711			table.style.width = _fnStringToCss( tableWidthAttr );
5712		}
5713	
5714		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5715			var bindResize = function () {
5716				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5717					_fnAdjustColumnSizing( oSettings );
5718				} ) );
5719			};
5720	
5721			// IE6/7 will crash if we bind a resize event handler on page load.
5722			// To be removed in 1.11 which drops IE6/7 support
5723			if ( ie67 ) {
5724				setTimeout( bindResize, 1000 );
5725			}
5726			else {
5727				bindResize();
5728			}
5729	
5730			oSettings._reszEvt = true;
5731		}
5732	}
5733	
5734	
5735	/**
5736	 * Throttle the calls to a function. Arguments and context are maintained for
5737	 * the throttled function
5738	 *  @param {function} fn Function to be called
5739	 *  @param {int} [freq=200] call frequency in mS
5740	 *  @returns {function} wrapped function
5741	 *  @memberof DataTable#oApi
5742	 */
5743	var _fnThrottle = DataTable.util.throttle;
5744	
5745	
5746	/**
5747	 * Convert a CSS unit width to pixels (e.g. 2em)
5748	 *  @param {string} width width to be converted
5749	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5750	 *  @returns {int} width in pixels
5751	 *  @memberof DataTable#oApi
5752	 */
5753	function _fnConvertToWidth ( width, parent )
5754	{
5755		if ( ! width ) {
5756			return 0;
5757		}
5758	
5759		var n = $('<div/>')
5760			.css( 'width', _fnStringToCss( width ) )
5761			.appendTo( parent || document.body );
5762	
5763		var val = n[0].offsetWidth;
5764		n.remove();
5765	
5766		return val;
5767	}
5768	
5769	
5770	/**
5771	 * Get the widest node
5772	 *  @param {object} settings dataTables settings object
5773	 *  @param {int} colIdx column of interest
5774	 *  @returns {node} widest table node
5775	 *  @memberof DataTable#oApi
5776	 */
5777	function _fnGetWidestNode( settings, colIdx )
5778	{
5779		var idx = _fnGetMaxLenString( settings, colIdx );
5780		if ( idx < 0 ) {
5781			return null;
5782		}
5783	
5784		var data = settings.aoData[ idx ];
5785		return ! data.nTr ? // Might not have been created when deferred rendering
5786			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5787			data.anCells[ colIdx ];
5788	}
5789	
5790	
5791	/**
5792	 * Get the maximum strlen for each data column
5793	 *  @param {object} settings dataTables settings object
5794	 *  @param {int} colIdx column of interest
5795	 *  @returns {string} max string length for each column
5796	 *  @memberof DataTable#oApi
5797	 */
5798	function _fnGetMaxLenString( settings, colIdx )
5799	{
5800		var s, max=-1, maxIdx = -1;
5801	
5802		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5803			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5804			s = s.replace( __re_html_remove, '' );
5805			s = s.replace( /&nbsp;/g, ' ' );
5806	
5807			if ( s.length > max ) {
5808				max = s.length;
5809				maxIdx = i;
5810			}
5811		}
5812	
5813		return maxIdx;
5814	}
5815	
5816	
5817	/**
5818	 * Append a CSS unit (only if required) to a string
5819	 *  @param {string} value to css-ify
5820	 *  @returns {string} value with css unit
5821	 *  @memberof DataTable#oApi
5822	 */
5823	function _fnStringToCss( s )
5824	{
5825		if ( s === null ) {
5826			return '0px';
5827		}
5828	
5829		if ( typeof s == 'number' ) {
5830			return s < 0 ?
5831				'0px' :
5832				s+'px';
5833		}
5834	
5835		// Check it has a unit character already
5836		return s.match(/\d$/) ?
5837			s+'px' :
5838			s;
5839	}
5840	
5841	
5842	
5843	function _fnSortFlatten ( settings )
5844	{
5845		var
5846			i, iLen, k, kLen,
5847			aSort = [],
5848			aiOrig = [],
5849			aoColumns = settings.aoColumns,
5850			aDataSort, iCol, sType, srcCol,
5851			fixed = settings.aaSortingFixed,
5852			fixedObj = $.isPlainObject( fixed ),
5853			nestedSort = [],
5854			add = function ( a ) {
5855				if ( a.length && ! 
vendor: 39,755 bytes, lines 5855-7376
5855$.isArray( a[0] ) ) {
5856					// 1D array
5857					nestedSort.push( a );
5858				}
5859				else {
5860					// 2D array
5861					$.merge( nestedSort, a );
5862				}
5863			};
5864	
5865		// Build the sort array, with pre-fix and post-fix options if they have been
5866		// specified
5867		if ( $.isArray( fixed ) ) {
5868			add( fixed );
5869		}
5870	
5871		if ( fixedObj && fixed.pre ) {
5872			add( fixed.pre );
5873		}
5874	
5875		add( settings.aaSorting );
5876	
5877		if (fixedObj && fixed.post ) {
5878			add( fixed.post );
5879		}
5880	
5881		for ( i=0 ; i<nestedSort.length ; i++ )
5882		{
5883			srcCol = nestedSort[i][0];
5884			aDataSort = aoColumns[ srcCol ].aDataSort;
5885	
5886			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5887			{
5888				iCol = aDataSort[k];
5889				sType = aoColumns[ iCol ].sType || 'string';
5890	
5891				if ( nestedSort[i]._idx === undefined ) {
5892					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5893				}
5894	
5895				aSort.push( {
5896					src:       srcCol,
5897					col:       iCol,
5898					dir:       nestedSort[i][1],
5899					index:     nestedSort[i]._idx,
5900					type:      sType,
5901					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5902				} );
5903			}
5904		}
5905	
5906		return aSort;
5907	}
5908	
5909	/**
5910	 * Change the order of the table
5911	 *  @param {object} oSettings dataTables settings object
5912	 *  @memberof DataTable#oApi
5913	 *  @todo This really needs split up!
5914	 */
5915	function _fnSort ( oSettings )
5916	{
5917		var
5918			i, ien, iLen, j, jLen, k, kLen,
5919			sDataType, nTh,
5920			aiOrig = [],
5921			oExtSort = DataTable.ext.type.order,
5922			aoData = oSettings.aoData,
5923			aoColumns = oSettings.aoColumns,
5924			aDataSort, data, iCol, sType, oSort,
5925			formatters = 0,
5926			sortCol,
5927			displayMaster = oSettings.aiDisplayMaster,
5928			aSort;
5929	
5930		// Resolve any column types that are unknown due to addition or invalidation
5931		// @todo Can this be moved into a 'data-ready' handler which is called when
5932		//   data is going to be used in the table?
5933		_fnColumnTypes( oSettings );
5934	
5935		aSort = _fnSortFlatten( oSettings );
5936	
5937		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5938			sortCol = aSort[i];
5939	
5940			// Track if we can use the fast sort algorithm
5941			if ( sortCol.formatter ) {
5942				formatters++;
5943			}
5944	
5945			// Load the data needed for the sort, for each cell
5946			_fnSortData( oSettings, sortCol.col );
5947		}
5948	
5949		/* No sorting required if server-side or no sorting array */
5950		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5951		{
5952			// Create a value - key array of the current row positions such that we can use their
5953			// current position during the sort, if values match, in order to perform stable sorting
5954			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5955				aiOrig[ displayMaster[i] ] = i;
5956			}
5957	
5958			/* Do the sort - here we want multi-column sorting based on a given data source (column)
5959			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5960			 * follow on it's own, but this is what we want (example two column sorting):
5961			 *  fnLocalSorting = function(a,b){
5962			 *    var iTest;
5963			 *    iTest = oSort['string-asc']('data11', 'data12');
5964			 *      if (iTest !== 0)
5965			 *        return iTest;
5966			 *    iTest = oSort['numeric-desc']('data21', 'data22');
5967			 *    if (iTest !== 0)
5968			 *      return iTest;
5969			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5970			 *  }
5971			 * Basically we have a test for each sorting column, if the data in that column is equal,
5972			 * test the next column. If all columns match, then we use a numeric sort on the row
5973			 * positions in the original data array to provide a stable sort.
5974			 *
5975			 * Note - I know it seems excessive to have two sorting methods, but the first is around
5976			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
5977			 * methods which do not have a pre-sort formatting function.
5978			 */
5979			if ( formatters === aSort.length ) {
5980				// All sort types have formatting functions
5981				displayMaster.sort( function ( a, b ) {
5982					var
5983						x, y, k, test, sort,
5984						len=aSort.length,
5985						dataA = aoData[a]._aSortData,
5986						dataB = aoData[b]._aSortData;
5987	
5988					for ( k=0 ; k<len ; k++ ) {
5989						sort = aSort[k];
5990	
5991						x = dataA[ sort.col ];
5992						y = dataB[ sort.col ];
5993	
5994						test = x<y ? -1 : x>y ? 1 : 0;
5995						if ( test !== 0 ) {
5996							return sort.dir === 'asc' ? test : -test;
5997						}
5998					}
5999	
6000					x = aiOrig[a];
6001					y = aiOrig[b];
6002					return x<y ? -1 : x>y ? 1 : 0;
6003				} );
6004			}
6005			else {
6006				// Depreciated - remove in 1.11 (providing a plug-in option)
6007				// Not all sort types have formatting methods, so we have to call their sorting
6008				// methods.
6009				displayMaster.sort( function ( a, b ) {
6010					var
6011						x, y, k, l, test, sort, fn,
6012						len=aSort.length,
6013						dataA = aoData[a]._aSortData,
6014						dataB = aoData[b]._aSortData;
6015	
6016					for ( k=0 ; k<len ; k++ ) {
6017						sort = aSort[k];
6018	
6019						x = dataA[ sort.col ];
6020						y = dataB[ sort.col ];
6021	
6022						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6023						test = fn( x, y );
6024						if ( test !== 0 ) {
6025							return test;
6026						}
6027					}
6028	
6029					x = aiOrig[a];
6030					y = aiOrig[b];
6031					return x<y ? -1 : x>y ? 1 : 0;
6032				} );
6033			}
6034		}
6035	
6036		/* Tell the draw function that we have sorted the data */
6037		oSettings.bSorted = true;
6038	}
6039	
6040	
6041	function _fnSortAria ( settings )
6042	{
6043		var label;
6044		var nextSort;
6045		var columns = settings.aoColumns;
6046		var aSort = _fnSortFlatten( settings );
6047		var oAria = settings.oLanguage.oAria;
6048	
6049		// ARIA attributes - need to loop all columns, to update all (removing old
6050		// attributes as needed)
6051		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6052		{
6053			var col = columns[i];
6054			var asSorting = col.asSorting;
6055			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6056			var th = col.nTh;
6057	
6058			// IE7 is throwing an error when setting these properties with jQuery's
6059			// attr() and removeAttr() methods...
6060			th.removeAttribute('aria-sort');
6061	
6062			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6063			if ( col.bSortable ) {
6064				if ( aSort.length > 0 && aSort[0].col == i ) {
6065					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6066					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6067				}
6068				else {
6069					nextSort = asSorting[0];
6070				}
6071	
6072				label = sTitle + ( nextSort === "asc" ?
6073					oAria.sSortAscending :
6074					oAria.sSortDescending
6075				);
6076			}
6077			else {
6078				label = sTitle;
6079			}
6080	
6081			th.setAttribute('aria-label', label);
6082		}
6083	}
6084	
6085	
6086	/**
6087	 * Function to run on user sort request
6088	 *  @param {object} settings dataTables settings object
6089	 *  @param {node} attachTo node to attach the handler to
6090	 *  @param {int} colIdx column sorting index
6091	 *  @param {boolean} [append=false] Append the requested sort to the existing
6092	 *    sort if true (i.e. multi-column sort)
6093	 *  @param {function} [callback] callback function
6094	 *  @memberof DataTable#oApi
6095	 */
6096	function _fnSortListener ( settings, colIdx, append, callback )
6097	{
6098		var col = settings.aoColumns[ colIdx ];
6099		var sorting = settings.aaSorting;
6100		var asSorting = col.asSorting;
6101		var nextSortIdx;
6102		var next = function ( a, overflow ) {
6103			var idx = a._idx;
6104			if ( idx === undefined ) {
6105				idx = $.inArray( a[1], asSorting );
6106			}
6107	
6108			return idx+1 < asSorting.length ?
6109				idx+1 :
6110				overflow ?
6111					null :
6112					0;
6113		};
6114	
6115		// Convert to 2D array if needed
6116		if ( typeof sorting[0] === 'number' ) {
6117			sorting = settings.aaSorting = [ sorting ];
6118		}
6119	
6120		// If appending the sort then we are multi-column sorting
6121		if ( append && settings.oFeatures.bSortMulti ) {
6122			// Are we already doing some kind of sort on this column?
6123			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6124	
6125			if ( sortIdx !== -1 ) {
6126				// Yes, modify the sort
6127				nextSortIdx = next( sorting[sortIdx], true );
6128	
6129				if ( nextSortIdx === null && sorting.length === 1 ) {
6130					nextSortIdx = 0; // can't remove sorting completely
6131				}
6132	
6133				if ( nextSortIdx === null ) {
6134					sorting.splice( sortIdx, 1 );
6135				}
6136				else {
6137					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6138					sorting[sortIdx]._idx = nextSortIdx;
6139				}
6140			}
6141			else {
6142				// No sort on this column yet
6143				sorting.push( [ colIdx, asSorting[0], 0 ] );
6144				sorting[sorting.length-1]._idx = 0;
6145			}
6146		}
6147		else if ( sorting.length && sorting[0][0] == colIdx ) {
6148			// Single column - already sorting on this column, modify the sort
6149			nextSortIdx = next( sorting[0] );
6150	
6151			sorting.length = 1;
6152			sorting[0][1] = asSorting[ nextSortIdx ];
6153			sorting[0]._idx = nextSortIdx;
6154		}
6155		else {
6156			// Single column - sort only on this column
6157			sorting.length = 0;
6158			sorting.push( [ colIdx, asSorting[0] ] );
6159			sorting[0]._idx = 0;
6160		}
6161	
6162		// Run the sort by calling a full redraw
6163		_fnReDraw( settings );
6164	
6165		// callback used for async user interaction
6166		if ( typeof callback == 'function' ) {
6167			callback( settings );
6168		}
6169	}
6170	
6171	
6172	/**
6173	 * Attach a sort handler (click) to a node
6174	 *  @param {object} settings dataTables settings object
6175	 *  @param {node} attachTo node to attach the handler to
6176	 *  @param {int} colIdx column sorting index
6177	 *  @param {function} [callback] callback function
6178	 *  @memberof DataTable#oApi
6179	 */
6180	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6181	{
6182		var col = settings.aoColumns[ colIdx ];
6183	
6184		_fnBindAction( attachTo, {}, function (e) {
6185			/* If the column is not sortable - don't to anything */
6186			if ( col.bSortable === false ) {
6187				return;
6188			}
6189	
6190			// If processing is enabled use a timeout to allow the processing
6191			// display to be shown - otherwise to it synchronously
6192			if ( settings.oFeatures.bProcessing ) {
6193				_fnProcessingDisplay( settings, true );
6194	
6195				setTimeout( function() {
6196					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6197	
6198					// In server-side processing, the draw callback will remove the
6199					// processing display
6200					if ( _fnDataSource( settings ) !== 'ssp' ) {
6201						_fnProcessingDisplay( settings, false );
6202					}
6203				}, 0 );
6204			}
6205			else {
6206				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6207			}
6208		} );
6209	}
6210	
6211	
6212	/**
6213	 * Set the sorting classes on table's body, Note: it is safe to call this function
6214	 * when bSort and bSortClasses are false
6215	 *  @param {object} oSettings dataTables settings object
6216	 *  @memberof DataTable#oApi
6217	 */
6218	function _fnSortingClasses( settings )
6219	{
6220		var oldSort = settings.aLastSort;
6221		var sortClass = settings.oClasses.sSortColumn;
6222		var sort = _fnSortFlatten( settings );
6223		var features = settings.oFeatures;
6224		var i, ien, colIdx;
6225	
6226		if ( features.bSort && features.bSortClasses ) {
6227			// Remove old sorting classes
6228			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6229				colIdx = oldSort[i].src;
6230	
6231				// Remove column sorting
6232				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6233					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6234			}
6235	
6236			// Add new column sorting
6237			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6238				colIdx = sort[i].src;
6239	
6240				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6241					.addClass( sortClass + (i<2 ? i+1 : 3) );
6242			}
6243		}
6244	
6245		settings.aLastSort = sort;
6246	}
6247	
6248	
6249	// Get the data to sort a column, be it from cache, fresh (populating the
6250	// cache), or from a sort formatter
6251	function _fnSortData( settings, idx )
6252	{
6253		// Custom sorting function - provided by the sort data type
6254		var column = settings.aoColumns[ idx ];
6255		var customSort = DataTable.ext.order[ column.sSortDataType ];
6256		var customData;
6257	
6258		if ( customSort ) {
6259			customData = customSort.call( settings.oInstance, settings, idx,
6260				_fnColumnIndexToVisible( settings, idx )
6261			);
6262		}
6263	
6264		// Use / populate cache
6265		var row, cellData;
6266		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6267	
6268		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6269			row = settings.aoData[i];
6270	
6271			if ( ! row._aSortData ) {
6272				row._aSortData = [];
6273			}
6274	
6275			if ( ! row._aSortData[idx] || customSort ) {
6276				cellData = customSort ?
6277					customData[i] : // If there was a custom sort function, use data from there
6278					_fnGetCellData( settings, i, idx, 'sort' );
6279	
6280				row._aSortData[ idx ] = formatter ?
6281					formatter( cellData ) :
6282					cellData;
6283			}
6284		}
6285	}
6286	
6287	
6288	
6289	/**
6290	 * Save the state of a table
6291	 *  @param {object} oSettings dataTables settings object
6292	 *  @memberof DataTable#oApi
6293	 */
6294	function _fnSaveState ( settings )
6295	{
6296		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6297		{
6298			return;
6299		}
6300	
6301		/* Store the interesting variables */
6302		var state = {
6303			time:    +new Date(),
6304			start:   settings._iDisplayStart,
6305			length:  settings._iDisplayLength,
6306			order:   $.extend( true, [], settings.aaSorting ),
6307			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6308			columns: $.map( settings.aoColumns, function ( col, i ) {
6309				return {
6310					visible: col.bVisible,
6311					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6312				};
6313			} )
6314		};
6315	
6316		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6317	
6318		settings.oSavedState = state;
6319		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6320	}
6321	
6322	
6323	/**
6324	 * Attempt to load a saved table state
6325	 *  @param {object} oSettings dataTables settings object
6326	 *  @param {object} oInit DataTables init object so we can override settings
6327	 *  @param {function} callback Callback to execute when the state has been loaded
6328	 *  @memberof DataTable#oApi
6329	 */
6330	function _fnLoadState ( settings, oInit, callback )
6331	{
6332		var i, ien;
6333		var columns = settings.aoColumns;
6334		var loaded = function ( s ) {
6335			if ( ! s || ! s.time ) {
6336				callback();
6337				return;
6338			}
6339	
6340			// Allow custom and plug-in manipulation functions to alter the saved data set and
6341			// cancelling of loading by returning false
6342			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6343			if ( $.inArray( false, abStateLoad ) !== -1 ) {
6344				callback();
6345				return;
6346			}
6347	
6348			// Reject old data
6349			var duration = settings.iStateDuration;
6350			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6351				callback();
6352				return;
6353			}
6354	
6355			// Number of columns have changed - all bets are off, no restore of settings
6356			if ( s.columns && columns.length !== s.columns.length ) {
6357				callback();
6358				return;
6359			}
6360	
6361			// Store the saved state so it might be accessed at any time
6362			settings.oLoadedState = $.extend( true, {}, s );
6363	
6364			// Restore key features - todo - for 1.11 this needs to be done by
6365			// subscribed events
6366			if ( s.start !== undefined ) {
6367				settings._iDisplayStart    = s.start;
6368				settings.iInitDisplayStart = s.start;
6369			}
6370			if ( s.length !== undefined ) {
6371				settings._iDisplayLength   = s.length;
6372			}
6373	
6374			// Order
6375			if ( s.order !== undefined ) {
6376				settings.aaSorting = [];
6377				$.each( s.order, function ( i, col ) {
6378					settings.aaSorting.push( col[0] >= columns.length ?
6379						[ 0, col[1] ] :
6380						col
6381					);
6382				} );
6383			}
6384	
6385			// Search
6386			if ( s.search !== undefined ) {
6387				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6388			}
6389	
6390			// Columns
6391			//
6392			if ( s.columns ) {
6393				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6394					var col = s.columns[i];
6395	
6396					// Visibility
6397					if ( col.visible !== undefined ) {
6398						columns[i].bVisible = col.visible;
6399					}
6400	
6401					// Search
6402					if ( col.search !== undefined ) {
6403						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6404					}
6405				}
6406			}
6407	
6408			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6409			callback();
6410		}
6411	
6412		if ( ! settings.oFeatures.bStateSave ) {
6413			callback();
6414			return;
6415		}
6416	
6417		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6418	
6419		if ( state !== undefined ) {
6420			loaded( state );
6421		}
6422		// otherwise, wait for the loaded callback to be executed
6423	}
6424	
6425	
6426	/**
6427	 * Return the settings object for a particular table
6428	 *  @param {node} table table we are using as a dataTable
6429	 *  @returns {object} Settings object - or null if not found
6430	 *  @memberof DataTable#oApi
6431	 */
6432	function _fnSettingsFromNode ( table )
6433	{
6434		var settings = DataTable.settings;
6435		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6436	
6437		return idx !== -1 ?
6438			settings[ idx ] :
6439			null;
6440	}
6441	
6442	
6443	/**
6444	 * Log an error message
6445	 *  @param {object} settings dataTables settings object
6446	 *  @param {int} level log error messages, or display them to the user
6447	 *  @param {string} msg error message
6448	 *  @param {int} tn Technical note id to get more information about the error.
6449	 *  @memberof DataTable#oApi
6450	 */
6451	function _fnLog( settings, level, msg, tn )
6452	{
6453		msg = 'DataTables warning: '+
6454			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6455	
6456		if ( tn ) {
6457			msg += '. For more information about this error, please see '+
6458			'http://datatables.net/tn/'+tn;
6459		}
6460	
6461		if ( ! level  ) {
6462			// Backwards compatibility pre 1.10
6463			var ext = DataTable.ext;
6464			var type = ext.sErrMode || ext.errMode;
6465	
6466			if ( settings ) {
6467				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6468			}
6469	
6470			if ( type == 'alert' ) {
6471				alert( msg );
6472			}
6473			else if ( type == 'throw' ) {
6474				throw new Error(msg);
6475			}
6476			else if ( typeof type == 'function' ) {
6477				type( settings, tn, msg );
6478			}
6479		}
6480		else if ( window.console && console.log ) {
6481			console.log( msg );
6482		}
6483	}
6484	
6485	
6486	/**
6487	 * See if a property is defined on one object, if so assign it to the other object
6488	 *  @param {object} ret target object
6489	 *  @param {object} src source object
6490	 *  @param {string} name property
6491	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6492	 *  @memberof DataTable#oApi
6493	 */
6494	function _fnMap( ret, src, name, mappedName )
6495	{
6496		if ( $.isArray( name ) ) {
6497			$.each( name, function (i, val) {
6498				if ( $.isArray( val ) ) {
6499					_fnMap( ret, src, val[0], val[1] );
6500				}
6501				else {
6502					_fnMap( ret, src, val );
6503				}
6504			} );
6505	
6506			return;
6507		}
6508	
6509		if ( mappedName === undefined ) {
6510			mappedName = name;
6511		}
6512	
6513		if ( src[name] !== undefined ) {
6514			ret[mappedName] = src[name];
6515		}
6516	}
6517	
6518	
6519	/**
6520	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6521	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6522	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6523	 * able to override them, but we do want to deep copy arrays.
6524	 *  @param {object} out Object to extend
6525	 *  @param {object} extender Object from which the properties will be applied to
6526	 *      out
6527	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6528	 *      independent copy with the exception of the `data` or `aaData` parameters
6529	 *      if they are present. This is so you can pass in a collection to
6530	 *      DataTables and have that used as your data source without breaking the
6531	 *      references
6532	 *  @returns {object} out Reference, just for convenience - out === the return.
6533	 *  @memberof DataTable#oApi
6534	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6535	 */
6536	function _fnExtend( out, extender, breakRefs )
6537	{
6538		var val;
6539	
6540		for ( var prop in extender ) {
6541			if ( extender.hasOwnProperty(prop) ) {
6542				val = extender[prop];
6543	
6544				if ( $.isPlainObject( val ) ) {
6545					if ( ! $.isPlainObject( out[prop] ) ) {
6546						out[prop] = {};
6547					}
6548					$.extend( true, out[prop], val );
6549				}
6550				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6551					out[prop] = val.slice();
6552				}
6553				else {
6554					out[prop] = val;
6555				}
6556			}
6557		}
6558	
6559		return out;
6560	}
6561	
6562	
6563	/**
6564	 * Bind an event handers to allow a click or return key to activate the callback.
6565	 * This is good for accessibility since a return on the keyboard will have the
6566	 * same effect as a click, if the element has focus.
6567	 *  @param {element} n Element to bind the action to
6568	 *  @param {object} oData Data object to pass to the triggered function
6569	 *  @param {function} fn Callback function for when the event is triggered
6570	 *  @memberof DataTable#oApi
6571	 */
6572	function _fnBindAction( n, oData, fn )
6573	{
6574		$(n)
6575			.on( 'click.DT', oData, function (e) {
6576					n.blur(); // Remove focus outline for mouse users
6577					fn(e);
6578				} )
6579			.on( 'keypress.DT', oData, function (e){
6580					if ( e.which === 13 ) {
6581						e.preventDefault();
6582						fn(e);
6583					}
6584				} )
6585			.on( 'selectstart.DT', function () {
6586					/* Take the brutal approach to cancelling text selection */
6587					return false;
6588				} );
6589	}
6590	
6591	
6592	/**
6593	 * Register a callback function. Easily allows a callback function to be added to
6594	 * an array store of callback functions that can then all be called together.
6595	 *  @param {object} oSettings dataTables settings object
6596	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6597	 *  @param {function} fn Function to be called back
6598	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6599	 *  @memberof DataTable#oApi
6600	 */
6601	function _fnCallbackReg( oSettings, sStore, fn, sName )
6602	{
6603		if ( fn )
6604		{
6605			oSettings[sStore].push( {
6606				"fn": fn,
6607				"sName": sName
6608			} );
6609		}
6610	}
6611	
6612	
6613	/**
6614	 * Fire callback functions and trigger events. Note that the loop over the
6615	 * callback array store is done backwards! Further note that you do not want to
6616	 * fire off triggers in time sensitive applications (for example cell creation)
6617	 * as its slow.
6618	 *  @param {object} settings dataTables settings object
6619	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6620	 *      oSettings
6621	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6622	 *      null no trigger is fired
6623	 *  @param {array} args Array of arguments to pass to the callback function /
6624	 *      trigger
6625	 *  @memberof DataTable#oApi
6626	 */
6627	function _fnCallbackFire( settings, callbackArr, eventName, args )
6628	{
6629		var ret = [];
6630	
6631		if ( callbackArr ) {
6632			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6633				return val.fn.apply( settings.oInstance, args );
6634			} );
6635		}
6636	
6637		if ( eventName !== null ) {
6638			var e = $.Event( eventName+'.dt' );
6639	
6640			$(settings.nTable).trigger( e, args );
6641	
6642			ret.push( e.result );
6643		}
6644	
6645		return ret;
6646	}
6647	
6648	
6649	function _fnLengthOverflow ( settings )
6650	{
6651		var
6652			start = settings._iDisplayStart,
6653			end = settings.fnDisplayEnd(),
6654			len = settings._iDisplayLength;
6655	
6656		/* If we have space to show extra rows (backing up from the end point - then do so */
6657		if ( start >= end )
6658		{
6659			start = end - len;
6660		}
6661	
6662		// Keep the start record on the current page
6663		start -= (start % len);
6664	
6665		if ( len === -1 || start < 0 )
6666		{
6667			start = 0;
6668		}
6669	
6670		settings._iDisplayStart = start;
6671	}
6672	
6673	
6674	function _fnRenderer( settings, type )
6675	{
6676		var renderer = settings.renderer;
6677		var host = DataTable.ext.renderer[type];
6678	
6679		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6680			// Specific renderer for this type. If available use it, otherwise use
6681			// the default.
6682			return host[renderer[type]] || host._;
6683		}
6684		else if ( typeof renderer === 'string' ) {
6685			// Common renderer - if there is one available for this type use it,
6686			// otherwise use the default
6687			return host[renderer] || host._;
6688		}
6689	
6690		// Use the default
6691		return host._;
6692	}
6693	
6694	
6695	/**
6696	 * Detect the data source being used for the table. Used to simplify the code
6697	 * a little (ajax) and to make it compress a little smaller.
6698	 *
6699	 *  @param {object} settings dataTables settings object
6700	 *  @returns {string} Data source
6701	 *  @memberof DataTable#oApi
6702	 */
6703	function _fnDataSource ( settings )
6704	{
6705		if ( settings.oFeatures.bServerSide ) {
6706			return 'ssp';
6707		}
6708		else if ( settings.ajax || settings.sAjaxSource ) {
6709			return 'ajax';
6710		}
6711		return 'dom';
6712	}
6713	
6714
6715	
6716	
6717	/**
6718	 * Computed structure of the DataTables API, defined by the options passed to
6719	 * `DataTable.Api.register()` when building the API.
6720	 *
6721	 * The structure is built in order to speed creation and extension of the Api
6722	 * objects since the extensions are effectively pre-parsed.
6723	 *
6724	 * The array is an array of objects with the following structure, where this
6725	 * base array represents the Api prototype base:
6726	 *
6727	 *     [
6728	 *       {
6729	 *         name:      'data'                -- string   - Property name
6730	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6731	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6732	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6733	 *       },
6734	 *       {
6735	 *         name:     'row'
6736	 *         val:       {},
6737	 *         methodExt: [ ... ],
6738	 *         propExt:   [
6739	 *           {
6740	 *             name:      'data'
6741	 *             val:       function () {},
6742	 *             methodExt: [ ... ],
6743	 *             propExt:   [ ... ]
6744	 *           },
6745	 *           ...
6746	 *         ]
6747	 *       }
6748	 *     ]
6749	 *
6750	 * @type {Array}
6751	 * @ignore
6752	 */
6753	var __apiStruct = [];
6754	
6755	
6756	/**
6757	 * `Array.prototype` reference.
6758	 *
6759	 * @type object
6760	 * @ignore
6761	 */
6762	var __arrayProto = Array.prototype;
6763	
6764	
6765	/**
6766	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6767	 * take several different forms for ease of use.
6768	 *
6769	 * Each of the input parameter types will be converted to a DataTables settings
6770	 * object where possible.
6771	 *
6772	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6773	 *   of:
6774	 *
6775	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6776	 *     with be found and used.
6777	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6778	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6779	 *   * `object` - DataTables settings object
6780	 *   * `DataTables.Api` - API instance
6781	 * @return {array|null} Matching DataTables settings objects. `null` or
6782	 *   `undefined` is returned if no matching DataTable is found.
6783	 * @ignore
6784	 */
6785	var _toSettings = function ( mixed )
6786	{
6787		var idx, jq;
6788		var settings = DataTable.settings;
6789		var tables = $.map( settings, function (el, i) {
6790			return el.nTable;
6791		} );
6792	
6793		if ( ! mixed ) {
6794			return [];
6795		}
6796		else if ( mixed.nTable && mixed.oApi ) {
6797			// DataTables settings object
6798			return [ mixed ];
6799		}
6800		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6801			// Table node
6802			idx = $.inArray( mixed, tables );
6803			return idx !== -1 ? [ settings[idx] ] : null;
6804		}
6805		else if ( mixed && typeof mixed.settings === 'function' ) {
6806			return mixed.settings().toArray();
6807		}
6808		else if ( typeof mixed === 'string' ) {
6809			// jQuery selector
6810			jq = $(mixed);
6811		}
6812		else if ( mixed instanceof $ ) {
6813			// jQuery object (also DataTables instance)
6814			jq = mixed;
6815		}
6816	
6817		if ( jq ) {
6818			return jq.map( function(i) {
6819				idx = $.inArray( this, tables );
6820				return idx !== -1 ? settings[idx] : null;
6821			} ).toArray();
6822		}
6823	};
6824	
6825	
6826	/**
6827	 * DataTables API class - used to control and interface with  one or more
6828	 * DataTables enhanced tables.
6829	 *
6830	 * The API class is heavily based on jQuery, presenting a chainable interface
6831	 * that you can use to interact with tables. Each instance of the API class has
6832	 * a "context" - i.e. the tables that it will operate on. This could be a single
6833	 * table, all tables on a page or a sub-set thereof.
6834	 *
6835	 * Additionally the API is designed to allow you to easily work with the data in
6836	 * the tables, retrieving and manipulating it as required. This is done by
6837	 * presenting the API class as an array like interface. The contents of the
6838	 * array depend upon the actions requested by each method (for example
6839	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6840	 * return an array of objects or arrays depending upon your table's
6841	 * configuration). The API object has a number of array like methods (`push`,
6842	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6843	 * `unique` etc) to assist your working with the data held in a table.
6844	 *
6845	 * Most methods (those which return an Api instance) are chainable, which means
6846	 * the return from a method call also has all of the methods available that the
6847	 * top level object had. For example, these two calls are equivalent:
6848	 *
6849	 *     // Not chained
6850	 *     api.row.add( {...} );
6851	 *     api.draw();
6852	 *
6853	 *     // Chained
6854	 *     api.row.add( {...} ).draw();
6855	 *
6856	 * @class DataTable.Api
6857	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6858	 *   used to define which DataTables enhanced tables this API will operate on.
6859	 *   Can be one of:
6860	 *
6861	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6862	 *     with be found and used.
6863	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6864	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6865	 *   * `object` - DataTables settings object
6866	 * @param {array} [data] Data to initialise the Api instance with.
6867	 *
6868	 * @example
6869	 *   // Direct initialisation during DataTables construction
6870	 *   var api = $('#example').DataTable();
6871	 *
6872	 * @example
6873	 *   // Initialisation using a DataTables jQuery object
6874	 *   var api = $('#example').dataTable().api();
6875	 *
6876	 * @example
6877	 *   // Initialisation as a constructor
6878	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6879	 */
6880	_Api = function ( context, data )
6881	{
6882		if ( ! (this instanceof _Api) ) {
6883			return new _Api( context, data );
6884		}
6885	
6886		var settings = [];
6887		var ctxSettings = function ( o ) {
6888			var a = _toSettings( o );
6889			if ( a ) {
6890				settings = settings.concat( a );
6891			}
6892		};
6893	
6894		if ( $.isArray( context ) ) {
6895			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6896				ctxSettings( context[i] );
6897			}
6898		}
6899		else {
6900			ctxSettings( context );
6901		}
6902	
6903		// Remove duplicates
6904		this.context = _unique( settings );
6905	
6906		// Initial data
6907		if ( data ) {
6908			$.merge( this, data );
6909		}
6910	
6911		// selector
6912		this.selector = {
6913			rows: null,
6914			cols: null,
6915			opts: null
6916		};
6917	
6918		_Api.extend( this, this, __apiStruct );
6919	};
6920	
6921	DataTable.Api = _Api;
6922	
6923	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6924	// isPlainObject.
6925	$.extend( _Api.prototype, {
6926		any: function ()
6927		{
6928			return this.count() !== 0;
6929		},
6930	
6931	
6932		concat:  __arrayProto.concat,
6933	
6934	
6935		context: [], // array of table settings objects
6936	
6937	
6938		count: function ()
6939		{
6940			return this.flatten().length;
6941		},
6942	
6943	
6944		each: function ( fn )
6945		{
6946			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6947				fn.call( this, this[i], i, this );
6948			}
6949	
6950			return this;
6951		},
6952	
6953	
6954		eq: function ( idx )
6955		{
6956			var ctx = this.context;
6957	
6958			return ctx.length > idx ?
6959				new _Api( ctx[idx], this[idx] ) :
6960				null;
6961		},
6962	
6963	
6964		filter: function ( fn )
6965		{
6966			var a = [];
6967	
6968			if ( __arrayProto.filter ) {
6969				a = __arrayProto.filter.call( this, fn, this );
6970			}
6971			else {
6972				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6973				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6974					if ( fn.call( this, this[i], i, this ) ) {
6975						a.push( this[i] );
6976					}
6977				}
6978			}
6979	
6980			return new _Api( this.context, a );
6981		},
6982	
6983	
6984		flatten: function ()
6985		{
6986			var a = [];
6987			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6988		},
6989	
6990	
6991		join:    __arrayProto.join,
6992	
6993	
6994		indexOf: __arrayProto.indexOf || function (obj, start)
6995		{
6996			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6997				if ( this[i] === obj ) {
6998					return i;
6999				}
7000			}
7001			return -1;
7002		},
7003	
7004		iterator: function ( flatten, type, fn, alwaysNew ) {
7005			var
7006				a = [], ret,
7007				i, ien, j, jen,
7008				context = this.context,
7009				rows, items, item,
7010				selector = this.selector;
7011	
7012			// Argument shifting
7013			if ( typeof flatten === 'string' ) {
7014				alwaysNew = fn;
7015				fn = type;
7016				type = flatten;
7017				flatten = false;
7018			}
7019	
7020			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7021				var apiInst = new _Api( context[i] );
7022	
7023				if ( type === 'table' ) {
7024					ret = fn.call( apiInst, context[i], i );
7025	
7026					if ( ret !== undefined ) {
7027						a.push( ret );
7028					}
7029				}
7030				else if ( type === 'columns' || type === 'rows' ) {
7031					// this has same length as context - one entry for each table
7032					ret = fn.call( apiInst, context[i], this[i], i );
7033	
7034					if ( ret !== undefined ) {
7035						a.push( ret );
7036					}
7037				}
7038				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7039					// columns and rows share the same structure.
7040					// 'this' is an array of column indexes for each context
7041					items = this[i];
7042	
7043					if ( type === 'column-rows' ) {
7044						rows = _selector_row_indexes( context[i], selector.opts );
7045					}
7046	
7047					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7048						item = items[j];
7049	
7050						if ( type === 'cell' ) {
7051							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7052						}
7053						else {
7054							ret = fn.call( apiInst, context[i], item, i, j, rows );
7055						}
7056	
7057						if ( ret !== undefined ) {
7058							a.push( ret );
7059						}
7060					}
7061				}
7062			}
7063	
7064			if ( a.length || alwaysNew ) {
7065				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7066				var apiSelector = api.selector;
7067				apiSelector.rows = selector.rows;
7068				apiSelector.cols = selector.cols;
7069				apiSelector.opts = selector.opts;
7070				return api;
7071			}
7072			return this;
7073		},
7074	
7075	
7076		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7077		{
7078			// Bit cheeky...
7079			return this.indexOf.apply( this.toArray.reverse(), arguments );
7080		},
7081	
7082	
7083		length:  0,
7084	
7085	
7086		map: function ( fn )
7087		{
7088			var a = [];
7089	
7090			if ( __arrayProto.map ) {
7091				a = __arrayProto.map.call( this, fn, this );
7092			}
7093			else {
7094				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7095				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7096					a.push( fn.call( this, this[i], i ) );
7097				}
7098			}
7099	
7100			return new _Api( this.context, a );
7101		},
7102	
7103	
7104		pluck: function ( prop )
7105		{
7106			return this.map( function ( el ) {
7107				return el[ prop ];
7108			} );
7109		},
7110	
7111		pop:     __arrayProto.pop,
7112	
7113	
7114		push:    __arrayProto.push,
7115	
7116	
7117		// Does not return an API instance
7118		reduce: __arrayProto.reduce || function ( fn, init )
7119		{
7120			return _fnReduce( this, fn, init, 0, this.length, 1 );
7121		},
7122	
7123	
7124		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7125		{
7126			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7127		},
7128	
7129	
7130		reverse: __arrayProto.reverse,
7131	
7132	
7133		// Object with rows, columns and opts
7134		selector: null,
7135	
7136	
7137		shift:   __arrayProto.shift,
7138	
7139	
7140		slice: function () {
7141			return new _Api( this.context, this );
7142		},
7143	
7144	
7145		sort:    __arrayProto.sort, // ? name - order?
7146	
7147	
7148		splice:  __arrayProto.splice,
7149	
7150	
7151		toArray: function ()
7152		{
7153			return __arrayProto.slice.call( this );
7154		},
7155	
7156	
7157		to$: function ()
7158		{
7159			return $( this );
7160		},
7161	
7162	
7163		toJQuery: function ()
7164		{
7165			return $( this );
7166		},
7167	
7168	
7169		unique: function ()
7170		{
7171			return new _Api( this.context, _unique(this) );
7172		},
7173	
7174	
7175		unshift: __arrayProto.unshift
7176	} );
7177	
7178	
7179	_Api.extend = function ( scope, obj, ext )
7180	{
7181		// Only extend API instances and static properties of the API
7182		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7183			return;
7184		}
7185	
7186		var
7187			i, ien,
7188			j, jen,
7189			struct, inner,
7190			methodScoping = function ( scope, fn, struc ) {
7191				return function () {
7192					var ret = fn.apply( scope, arguments );
7193	
7194					// Method extension
7195					_Api.extend( ret, ret, struc.methodExt );
7196					return ret;
7197				};
7198			};
7199	
7200		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7201			struct = ext[i];
7202	
7203			// Value
7204			obj[ struct.name ] = typeof struct.val === 'function' ?
7205				methodScoping( scope, struct.val, struct ) :
7206				$.isPlainObject( struct.val ) ?
7207					{} :
7208					struct.val;
7209	
7210			obj[ struct.name ].__dt_wrapper = true;
7211	
7212			// Property extension
7213			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7214		}
7215	};
7216	
7217	
7218	// @todo - Is there need for an augment function?
7219	// _Api.augment = function ( inst, name )
7220	// {
7221	// 	// Find src object in the structure from the name
7222	// 	var parts = name.split('.');
7223	
7224	// 	_Api.extend( inst, obj );
7225	// };
7226	
7227	
7228	//     [
7229	//       {
7230	//         name:      'data'                -- string   - Property name
7231	//         val:       function () {},       -- function - Api method (or undefined if just an object
7232	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7233	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7234	//       },
7235	//       {
7236	//         name:     'row'
7237	//         val:       {},
7238	//         methodExt: [ ... ],
7239	//         propExt:   [
7240	//           {
7241	//             name:      'data'
7242	//             val:       function () {},
7243	//             methodExt: [ ... ],
7244	//             propExt:   [ ... ]
7245	//           },
7246	//           ...
7247	//         ]
7248	//       }
7249	//     ]
7250	
7251	_Api.register = _api_register = function ( name, val )
7252	{
7253		if ( $.isArray( name ) ) {
7254			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7255				_Api.register( name[j], val );
7256			}
7257			return;
7258		}
7259	
7260		var
7261			i, ien,
7262			heir = name.split('.'),
7263			struct = __apiStruct,
7264			key, method;
7265	
7266		var find = function ( src, name ) {
7267			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7268				if ( src[i].name === name ) {
7269					return src[i];
7270				}
7271			}
7272			return null;
7273		};
7274	
7275		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7276			method = heir[i].indexOf('()') !== -1;
7277			key = method ?
7278				heir[i].replace('()', '') :
7279				heir[i];
7280	
7281			var src = find( struct, key );
7282			if ( ! src ) {
7283				src = {
7284					name:      key,
7285					val:       {},
7286					methodExt: [],
7287					propExt:   []
7288				};
7289				struct.push( src );
7290			}
7291	
7292			if ( i === ien-1 ) {
7293				src.val = val;
7294			}
7295			else {
7296				struct = method ?
7297					src.methodExt :
7298					src.propExt;
7299			}
7300		}
7301	};
7302	
7303	
7304	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7305		_Api.register( pluralName, val );
7306	
7307		_Api.register( singularName, function () {
7308			var ret = val.apply( this, arguments );
7309	
7310			if ( ret === this ) {
7311				// Returned item is the API instance that was passed in, return it
7312				return this;
7313			}
7314			else if ( ret instanceof _Api ) {
7315				// New API instance returned, want the value from the first item
7316				// in the returned array for the singular result.
7317				return ret.length ?
7318					$.isArray( ret[0] ) ?
7319						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7320						ret[0] :
7321					undefined;
7322			}
7323	
7324			// Non-API return - just fire it back
7325			return ret;
7326		} );
7327	};
7328	
7329	
7330	/**
7331	 * Selector for HTML tables. Apply the given selector to the give array of
7332	 * DataTables settings objects.
7333	 *
7334	 * @param {string|integer} [selector] jQuery selector string or integer
7335	 * @param  {array} Array of DataTables settings objects to be filtered
7336	 * @return {array}
7337	 * @ignore
7338	 */
7339	var __table_selector = function ( selector, a )
7340	{
7341		// Integer is used to pick out a table by index
7342		if ( typeof selector === 'number' ) {
7343			return [ a[ selector ] ];
7344		}
7345	
7346		// Perform a jQuery selector on the table nodes
7347		var nodes = $.map( a, function (el, i) {
7348			return el.nTable;
7349		} );
7350	
7351		return $(nodes)
7352			.filter( selector )
7353			.map( function (i) {
7354				// Need to translate back from the table node to the settings
7355				var idx = $.inArray( this, nodes );
7356				return a[ idx ];
7357			} )
7358			.toArray();
7359	};
7360	
7361	
7362	
7363	/**
7364	 * Context selector for the API's context (i.e. the tables the API instance
7365	 * refers to.
7366	 *
7367	 * @name    DataTable.Api#tables
7368	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7369	 *   should operate on. If not given, all tables in the current context are
7370	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7371	 *   select multiple tables or as an integer to select a single table.
7372	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7373	 */
7374	_api_register( 'tables()', function ( selector ) {
7375		// A new instance is created if there was a selector specified
7376		return selector
vendor: 9,632 bytes, lines 7376-7724
7376 ?
7377			new _Api( __table_selector( selector, this.context ) ) :
7378			this;
7379	} );
7380	
7381	
7382	_api_register( 'table()', function ( selector ) {
7383		var tables = this.tables( selector );
7384		var ctx = tables.context;
7385	
7386		// Truncate to the first matched table
7387		return ctx.length ?
7388			new _Api( ctx[0] ) :
7389			tables;
7390	} );
7391	
7392	
7393	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7394		return this.iterator( 'table', function ( ctx ) {
7395			return ctx.nTable;
7396		}, 1 );
7397	} );
7398	
7399	
7400	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7401		return this.iterator( 'table', function ( ctx ) {
7402			return ctx.nTBody;
7403		}, 1 );
7404	} );
7405	
7406	
7407	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7408		return this.iterator( 'table', function ( ctx ) {
7409			return ctx.nTHead;
7410		}, 1 );
7411	} );
7412	
7413	
7414	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7415		return this.iterator( 'table', function ( ctx ) {
7416			return ctx.nTFoot;
7417		}, 1 );
7418	} );
7419	
7420	
7421	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7422		return this.iterator( 'table', function ( ctx ) {
7423			return ctx.nTableWrapper;
7424		}, 1 );
7425	} );
7426	
7427	
7428	
7429	/**
7430	 * Redraw the tables in the current context.
7431	 */
7432	_api_register( 'draw()', function ( paging ) {
7433		return this.iterator( 'table', function ( settings ) {
7434			if ( paging === 'page' ) {
7435				_fnDraw( settings );
7436			}
7437			else {
7438				if ( typeof paging === 'string' ) {
7439					paging = paging === 'full-hold' ?
7440						false :
7441						true;
7442				}
7443	
7444				_fnReDraw( settings, paging===false );
7445			}
7446		} );
7447	} );
7448	
7449	
7450	
7451	/**
7452	 * Get the current page index.
7453	 *
7454	 * @return {integer} Current page index (zero based)
7455	 *//**
7456	 * Set the current page.
7457	 *
7458	 * Note that if you attempt to show a page which does not exist, DataTables will
7459	 * not throw an error, but rather reset the paging.
7460	 *
7461	 * @param {integer|string} action The paging action to take. This can be one of:
7462	 *  * `integer` - The page index to jump to
7463	 *  * `string` - An action to take:
7464	 *    * `first` - Jump to first page.
7465	 *    * `next` - Jump to the next page
7466	 *    * `previous` - Jump to previous page
7467	 *    * `last` - Jump to the last page.
7468	 * @returns {DataTables.Api} this
7469	 */
7470	_api_register( 'page()', function ( action ) {
7471		if ( action === undefined ) {
7472			return this.page.info().page; // not an expensive call
7473		}
7474	
7475		// else, have an action to take on all tables
7476		return this.iterator( 'table', function ( settings ) {
7477			_fnPageChange( settings, action );
7478		} );
7479	} );
7480	
7481	
7482	/**
7483	 * Paging information for the first table in the current context.
7484	 *
7485	 * If you require paging information for another table, use the `table()` method
7486	 * with a suitable selector.
7487	 *
7488	 * @return {object} Object with the following properties set:
7489	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7490	 *  * `pages` - Total number of pages
7491	 *  * `start` - Display index for the first record shown on the current page
7492	 *  * `end` - Display index for the last record shown on the current page
7493	 *  * `length` - Display length (number of records). Note that generally `start
7494	 *    + length = end`, but this is not always true, for example if there are
7495	 *    only 2 records to show on the final page, with a length of 10.
7496	 *  * `recordsTotal` - Full data set length
7497	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7498	 *    are applied.
7499	 */
7500	_api_register( 'page.info()', function ( action ) {
7501		if ( this.context.length === 0 ) {
7502			return undefined;
7503		}
7504	
7505		var
7506			settings   = this.context[0],
7507			start      = settings._iDisplayStart,
7508			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7509			visRecords = settings.fnRecordsDisplay(),
7510			all        = len === -1;
7511	
7512		return {
7513			"page":           all ? 0 : Math.floor( start / len ),
7514			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7515			"start":          start,
7516			"end":            settings.fnDisplayEnd(),
7517			"length":         len,
7518			"recordsTotal":   settings.fnRecordsTotal(),
7519			"recordsDisplay": visRecords,
7520			"serverSide":     _fnDataSource( settings ) === 'ssp'
7521		};
7522	} );
7523	
7524	
7525	/**
7526	 * Get the current page length.
7527	 *
7528	 * @return {integer} Current page length. Note `-1` indicates that all records
7529	 *   are to be shown.
7530	 *//**
7531	 * Set the current page length.
7532	 *
7533	 * @param {integer} Page length to set. Use `-1` to show all records.
7534	 * @returns {DataTables.Api} this
7535	 */
7536	_api_register( 'page.len()', function ( len ) {
7537		// Note that we can't call this function 'length()' because `length`
7538		// is a Javascript property of functions which defines how many arguments
7539		// the function expects.
7540		if ( len === undefined ) {
7541			return this.context.length !== 0 ?
7542				this.context[0]._iDisplayLength :
7543				undefined;
7544		}
7545	
7546		// else, set the page length
7547		return this.iterator( 'table', function ( settings ) {
7548			_fnLengthChange( settings, len );
7549		} );
7550	} );
7551	
7552	
7553	
7554	var __reload = function ( settings, holdPosition, callback ) {
7555		// Use the draw event to trigger a callback
7556		if ( callback ) {
7557			var api = new _Api( settings );
7558	
7559			api.one( 'draw', function () {
7560				callback( api.ajax.json() );
7561			} );
7562		}
7563	
7564		if ( _fnDataSource( settings ) == 'ssp' ) {
7565			_fnReDraw( settings, holdPosition );
7566		}
7567		else {
7568			_fnProcessingDisplay( settings, true );
7569	
7570			// Cancel an existing request
7571			var xhr = settings.jqXHR;
7572			if ( xhr && xhr.readyState !== 4 ) {
7573				xhr.abort();
7574			}
7575	
7576			// Trigger xhr
7577			_fnBuildAjax( settings, [], function( json ) {
7578				_fnClearTable( settings );
7579	
7580				var data = _fnAjaxDataSrc( settings, json );
7581				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7582					_fnAddData( settings, data[i] );
7583				}
7584	
7585				_fnReDraw( settings, holdPosition );
7586				_fnProcessingDisplay( settings, false );
7587			} );
7588		}
7589	};
7590	
7591	
7592	/**
7593	 * Get the JSON response from the last Ajax request that DataTables made to the
7594	 * server. Note that this returns the JSON from the first table in the current
7595	 * context.
7596	 *
7597	 * @return {object} JSON received from the server.
7598	 */
7599	_api_register( 'ajax.json()', function () {
7600		var ctx = this.context;
7601	
7602		if ( ctx.length > 0 ) {
7603			return ctx[0].json;
7604		}
7605	
7606		// else return undefined;
7607	} );
7608	
7609	
7610	/**
7611	 * Get the data submitted in the last Ajax request
7612	 */
7613	_api_register( 'ajax.params()', function () {
7614		var ctx = this.context;
7615	
7616		if ( ctx.length > 0 ) {
7617			return ctx[0].oAjaxData;
7618		}
7619	
7620		// else return undefined;
7621	} );
7622	
7623	
7624	/**
7625	 * Reload tables from the Ajax data source. Note that this function will
7626	 * automatically re-draw the table when the remote data has been loaded.
7627	 *
7628	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7629	 *   position. A full re-sort and re-filter is performed when this method is
7630	 *   called, which is why the pagination reset is the default action.
7631	 * @returns {DataTables.Api} this
7632	 */
7633	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7634		return this.iterator( 'table', function (settings) {
7635			__reload( settings, resetPaging===false, callback );
7636		} );
7637	} );
7638	
7639	
7640	/**
7641	 * Get the current Ajax URL. Note that this returns the URL from the first
7642	 * table in the current context.
7643	 *
7644	 * @return {string} Current Ajax source URL
7645	 *//**
7646	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7647	 * current context.
7648	 *
7649	 * @param {string} url URL to set.
7650	 * @returns {DataTables.Api} this
7651	 */
7652	_api_register( 'ajax.url()', function ( url ) {
7653		var ctx = this.context;
7654	
7655		if ( url === undefined ) {
7656			// get
7657			if ( ctx.length === 0 ) {
7658				return undefined;
7659			}
7660			ctx = ctx[0];
7661	
7662			return ctx.ajax ?
7663				$.isPlainObject( ctx.ajax ) ?
7664					ctx.ajax.url :
7665					ctx.ajax :
7666				ctx.sAjaxSource;
7667		}
7668	
7669		// set
7670		return this.iterator( 'table', function ( settings ) {
7671			if ( $.isPlainObject( settings.ajax ) ) {
7672				settings.ajax.url = url;
7673			}
7674			else {
7675				settings.ajax = url;
7676			}
7677			// No need to consider sAjaxSource here since DataTables gives priority
7678			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7679			// value of `sAjaxSource` redundant.
7680		} );
7681	} );
7682	
7683	
7684	/**
7685	 * Load data from the newly set Ajax URL. Note that this method is only
7686	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7687	 * has the same effect as calling `ajax.reload()` but is provided for
7688	 * convenience when setting a new URL. Like `ajax.reload()` it will
7689	 * automatically redraw the table once the remote data has been loaded.
7690	 *
7691	 * @returns {DataTables.Api} this
7692	 */
7693	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7694		// Same as a reload, but makes sense to present it for easy access after a
7695		// url change
7696		return this.iterator( 'table', function ( ctx ) {
7697			__reload( ctx, resetPaging===false, callback );
7698		} );
7699	} );
7700	
7701	
7702	
7703	
7704	var _selector_run = function ( type, selector, selectFn, settings, opts )
7705	{
7706		var
7707			out = [], res,
7708			a, i, ien, j, jen,
7709			selectorType = typeof selector;
7710	
7711		// Can't just check for isArray here, as an API or jQuery instance might be
7712		// given with their array like look
7713		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7714			selector = [ selector ];
7715		}
7716	
7717		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7718			// Only split on simple strings - complex expressions will be jQuery selectors
7719			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7720				selector[i].split(',') :
7721				[ selector[i] ];
7722	
7723			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7724				res = selectFn( typeof a[j] === 'string' ? 
vendor: 45,155 bytes, lines 7724-9427
7724$.trim(a[j]) : a[j] );
7725	
7726				if ( res && res.length ) {
7727					out = out.concat( res );
7728				}
7729			}
7730		}
7731	
7732		// selector extensions
7733		var ext = _ext.selector[ type ];
7734		if ( ext.length ) {
7735			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7736				out = ext[i]( settings, opts, out );
7737			}
7738		}
7739	
7740		return _unique( out );
7741	};
7742	
7743	
7744	var _selector_opts = function ( opts )
7745	{
7746		if ( ! opts ) {
7747			opts = {};
7748		}
7749	
7750		// Backwards compatibility for 1.9- which used the terminology filter rather
7751		// than search
7752		if ( opts.filter && opts.search === undefined ) {
7753			opts.search = opts.filter;
7754		}
7755	
7756		return $.extend( {
7757			search: 'none',
7758			order: 'current',
7759			page: 'all'
7760		}, opts );
7761	};
7762	
7763	
7764	var _selector_first = function ( inst )
7765	{
7766		// Reduce the API instance to the first item found
7767		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7768			if ( inst[i].length > 0 ) {
7769				// Assign the first element to the first item in the instance
7770				// and truncate the instance and context
7771				inst[0] = inst[i];
7772				inst[0].length = 1;
7773				inst.length = 1;
7774				inst.context = [ inst.context[i] ];
7775	
7776				return inst;
7777			}
7778		}
7779	
7780		// Not found - return an empty instance
7781		inst.length = 0;
7782		return inst;
7783	};
7784	
7785	
7786	var _selector_row_indexes = function ( settings, opts )
7787	{
7788		var
7789			i, ien, tmp, a=[],
7790			displayFiltered = settings.aiDisplay,
7791			displayMaster = settings.aiDisplayMaster;
7792	
7793		var
7794			search = opts.search,  // none, applied, removed
7795			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7796			page   = opts.page;    // all, current
7797	
7798		if ( _fnDataSource( settings ) == 'ssp' ) {
7799			// In server-side processing mode, most options are irrelevant since
7800			// rows not shown don't exist and the index order is the applied order
7801			// Removed is a special case - for consistency just return an empty
7802			// array
7803			return search === 'removed' ?
7804				[] :
7805				_range( 0, displayMaster.length );
7806		}
7807		else if ( page == 'current' ) {
7808			// Current page implies that order=current and fitler=applied, since it is
7809			// fairly senseless otherwise, regardless of what order and search actually
7810			// are
7811			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7812				a.push( displayFiltered[i] );
7813			}
7814		}
7815		else if ( order == 'current' || order == 'applied' ) {
7816			a = search == 'none' ?
7817				displayMaster.slice() :                      // no search
7818				search == 'applied' ?
7819					displayFiltered.slice() :                // applied search
7820					$.map( displayMaster, function (el, i) { // removed search
7821						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7822					} );
7823		}
7824		else if ( order == 'index' || order == 'original' ) {
7825			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7826				if ( search == 'none' ) {
7827					a.push( i );
7828				}
7829				else { // applied | removed
7830					tmp = $.inArray( i, displayFiltered );
7831	
7832					if ((tmp === -1 && search == 'removed') ||
7833						(tmp >= 0   && search == 'applied') )
7834					{
7835						a.push( i );
7836					}
7837				}
7838			}
7839		}
7840	
7841		return a;
7842	};
7843	
7844	
7845	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7846	 * Rows
7847	 *
7848	 * {}          - no selector - use all available rows
7849	 * {integer}   - row aoData index
7850	 * {node}      - TR node
7851	 * {string}    - jQuery selector to apply to the TR elements
7852	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7853	 *
7854	 */
7855	
7856	
7857	var __row_selector = function ( settings, selector, opts )
7858	{
7859		var rows;
7860		var run = function ( sel ) {
7861			var selInt = _intVal( sel );
7862			var i, ien;
7863	
7864			// Short cut - selector is a number and no options provided (default is
7865			// all records, so no need to check if the index is in there, since it
7866			// must be - dev error if the index doesn't exist).
7867			if ( selInt !== null && ! opts ) {
7868				return [ selInt ];
7869			}
7870	
7871			if ( ! rows ) {
7872				rows = _selector_row_indexes( settings, opts );
7873			}
7874	
7875			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7876				// Selector - integer
7877				return [ selInt ];
7878			}
7879			else if ( sel === null || sel === undefined || sel === '' ) {
7880				// Selector - none
7881				return rows;
7882			}
7883	
7884			// Selector - function
7885			if ( typeof sel === 'function' ) {
7886				return $.map( rows, function (idx) {
7887					var row = settings.aoData[ idx ];
7888					return sel( idx, row._aData, row.nTr ) ? idx : null;
7889				} );
7890			}
7891	
7892			// Get nodes in the order from the `rows` array with null values removed
7893			var nodes = _removeEmpty(
7894				_pluck_order( settings.aoData, rows, 'nTr' )
7895			);
7896	
7897			// Selector - node
7898			if ( sel.nodeName ) {
7899				if ( sel._DT_RowIndex !== undefined ) {
7900					return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
7901				}
7902				else if ( sel._DT_CellIndex ) {
7903					return [ sel._DT_CellIndex.row ];
7904				}
7905				else {
7906					var host = $(sel).closest('*[data-dt-row]');
7907					return host.length ?
7908						[ host.data('dt-row') ] :
7909						[];
7910				}
7911			}
7912	
7913			// ID selector. Want to always be able to select rows by id, regardless
7914			// of if the tr element has been created or not, so can't rely upon
7915			// jQuery here - hence a custom implementation. This does not match
7916			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7917			// but to select it using a CSS selector engine (like Sizzle or
7918			// querySelect) it would need to need to be escaped for some characters.
7919			// DataTables simplifies this for row selectors since you can select
7920			// only a row. A # indicates an id any anything that follows is the id -
7921			// unescaped.
7922			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7923				// get row index from id
7924				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7925				if ( rowObj !== undefined ) {
7926					return [ rowObj.idx ];
7927				}
7928	
7929				// need to fall through to jQuery in case there is DOM id that
7930				// matches
7931			}
7932	
7933			// Selector - jQuery selector string, array of nodes or jQuery object/
7934			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7935			// it also allows arrays, so this will cope with all three options
7936			return $(nodes)
7937				.filter( sel )
7938				.map( function () {
7939					return this._DT_RowIndex;
7940				} )
7941				.toArray();
7942		};
7943	
7944		return _selector_run( 'row', selector, run, settings, opts );
7945	};
7946	
7947	
7948	_api_register( 'rows()', function ( selector, opts ) {
7949		// argument shifting
7950		if ( selector === undefined ) {
7951			selector = '';
7952		}
7953		else if ( $.isPlainObject( selector ) ) {
7954			opts = selector;
7955			selector = '';
7956		}
7957	
7958		opts = _selector_opts( opts );
7959	
7960		var inst = this.iterator( 'table', function ( settings ) {
7961			return __row_selector( settings, selector, opts );
7962		}, 1 );
7963	
7964		// Want argument shifting here and in __row_selector?
7965		inst.selector.rows = selector;
7966		inst.selector.opts = opts;
7967	
7968		return inst;
7969	} );
7970	
7971	_api_register( 'rows().nodes()', function () {
7972		return this.iterator( 'row', function ( settings, row ) {
7973			return settings.aoData[ row ].nTr || undefined;
7974		}, 1 );
7975	} );
7976	
7977	_api_register( 'rows().data()', function () {
7978		return this.iterator( true, 'rows', function ( settings, rows ) {
7979			return _pluck_order( settings.aoData, rows, '_aData' );
7980		}, 1 );
7981	} );
7982	
7983	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7984		return this.iterator( 'row', function ( settings, row ) {
7985			var r = settings.aoData[ row ];
7986			return type === 'search' ? r._aFilterData : r._aSortData;
7987		}, 1 );
7988	} );
7989	
7990	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7991		return this.iterator( 'row', function ( settings, row ) {
7992			_fnInvalidate( settings, row, src );
7993		} );
7994	} );
7995	
7996	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7997		return this.iterator( 'row', function ( settings, row ) {
7998			return row;
7999		}, 1 );
8000	} );
8001	
8002	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8003		var a = [];
8004		var context = this.context;
8005	
8006		// `iterator` will drop undefined values, but in this case we want them
8007		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8008			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8009				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8010				a.push( (hash === true ? '#' : '' )+ id );
8011			}
8012		}
8013	
8014		return new _Api( context, a );
8015	} );
8016	
8017	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8018		var that = this;
8019	
8020		this.iterator( 'row', function ( settings, row, thatIdx ) {
8021			var data = settings.aoData;
8022			var rowData = data[ row ];
8023			var i, ien, j, jen;
8024			var loopRow, loopCells;
8025	
8026			data.splice( row, 1 );
8027	
8028			// Update the cached indexes
8029			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8030				loopRow = data[i];
8031				loopCells = loopRow.anCells;
8032	
8033				// Rows
8034				if ( loopRow.nTr !== null ) {
8035					loopRow.nTr._DT_RowIndex = i;
8036				}
8037	
8038				// Cells
8039				if ( loopCells !== null ) {
8040					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8041						loopCells[j]._DT_CellIndex.row = i;
8042					}
8043				}
8044			}
8045	
8046			// Delete from the display arrays
8047			_fnDeleteIndex( settings.aiDisplayMaster, row );
8048			_fnDeleteIndex( settings.aiDisplay, row );
8049			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8050	
8051			// For server-side processing tables - subtract the deleted row from the count
8052			if ( settings._iRecordsDisplay > 0 ) {
8053				settings._iRecordsDisplay--;
8054			}
8055	
8056			// Check for an 'overflow' they case for displaying the table
8057			_fnLengthOverflow( settings );
8058	
8059			// Remove the row's ID reference if there is one
8060			var id = settings.rowIdFn( rowData._aData );
8061			if ( id !== undefined ) {
8062				delete settings.aIds[ id ];
8063			}
8064		} );
8065	
8066		this.iterator( 'table', function ( settings ) {
8067			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8068				settings.aoData[i].idx = i;
8069			}
8070		} );
8071	
8072		return this;
8073	} );
8074	
8075	
8076	_api_register( 'rows.add()', function ( rows ) {
8077		var newRows = this.iterator( 'table', function ( settings ) {
8078				var row, i, ien;
8079				var out = [];
8080	
8081				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8082					row = rows[i];
8083	
8084					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8085						out.push( _fnAddTr( settings, row )[0] );
8086					}
8087					else {
8088						out.push( _fnAddData( settings, row ) );
8089					}
8090				}
8091	
8092				return out;
8093			}, 1 );
8094	
8095		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8096		var modRows = this.rows( -1 );
8097		modRows.pop();
8098		$.merge( modRows, newRows );
8099	
8100		return modRows;
8101	} );
8102	
8103	
8104	
8105	
8106	
8107	/**
8108	 *
8109	 */
8110	_api_register( 'row()', function ( selector, opts ) {
8111		return _selector_first( this.rows( selector, opts ) );
8112	} );
8113	
8114	
8115	_api_register( 'row().data()', function ( data ) {
8116		var ctx = this.context;
8117	
8118		if ( data === undefined ) {
8119			// Get
8120			return ctx.length && this.length ?
8121				ctx[0].aoData[ this[0] ]._aData :
8122				undefined;
8123		}
8124	
8125		// Set
8126		ctx[0].aoData[ this[0] ]._aData = data;
8127	
8128		// Automatically invalidate
8129		_fnInvalidate( ctx[0], this[0], 'data' );
8130	
8131		return this;
8132	} );
8133	
8134	
8135	_api_register( 'row().node()', function () {
8136		var ctx = this.context;
8137	
8138		return ctx.length && this.length ?
8139			ctx[0].aoData[ this[0] ].nTr || null :
8140			null;
8141	} );
8142	
8143	
8144	_api_register( 'row.add()', function ( row ) {
8145		// Allow a jQuery object to be passed in - only a single row is added from
8146		// it though - the first element in the set
8147		if ( row instanceof $ && row.length ) {
8148			row = row[0];
8149		}
8150	
8151		var rows = this.iterator( 'table', function ( settings ) {
8152			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8153				return _fnAddTr( settings, row )[0];
8154			}
8155			return _fnAddData( settings, row );
8156		} );
8157	
8158		// Return an Api.rows() extended instance, with the newly added row selected
8159		return this.row( rows[0] );
8160	} );
8161	
8162	
8163	
8164	var __details_add = function ( ctx, row, data, klass )
8165	{
8166		// Convert to array of TR elements
8167		var rows = [];
8168		var addRow = function ( r, k ) {
8169			// Recursion to allow for arrays of jQuery objects
8170			if ( $.isArray( r ) || r instanceof $ ) {
8171				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8172					addRow( r[i], k );
8173				}
8174				return;
8175			}
8176	
8177			// If we get a TR element, then just add it directly - up to the dev
8178			// to add the correct number of columns etc
8179			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8180				rows.push( r );
8181			}
8182			else {
8183				// Otherwise create a row with a wrapper
8184				var created = $('<tr><td/></tr>').addClass( k );
8185				$('td', created)
8186					.addClass( k )
8187					.html( r )
8188					[0].colSpan = _fnVisbleColumns( ctx );
8189	
8190				rows.push( created[0] );
8191			}
8192		};
8193	
8194		addRow( data, klass );
8195	
8196		if ( row._details ) {
8197			row._details.detach();
8198		}
8199	
8200		row._details = $(rows);
8201	
8202		// If the children were already shown, that state should be retained
8203		if ( row._detailsShow ) {
8204			row._details.insertAfter( row.nTr );
8205		}
8206	};
8207	
8208	
8209	var __details_remove = function ( api, idx )
8210	{
8211		var ctx = api.context;
8212	
8213		if ( ctx.length ) {
8214			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8215	
8216			if ( row && row._details ) {
8217				row._details.remove();
8218	
8219				row._detailsShow = undefined;
8220				row._details = undefined;
8221			}
8222		}
8223	};
8224	
8225	
8226	var __details_display = function ( api, show ) {
8227		var ctx = api.context;
8228	
8229		if ( ctx.length && api.length ) {
8230			var row = ctx[0].aoData[ api[0] ];
8231	
8232			if ( row._details ) {
8233				row._detailsShow = show;
8234	
8235				if ( show ) {
8236					row._details.insertAfter( row.nTr );
8237				}
8238				else {
8239					row._details.detach();
8240				}
8241	
8242				__details_events( ctx[0] );
8243			}
8244		}
8245	};
8246	
8247	
8248	var __details_events = function ( settings )
8249	{
8250		var api = new _Api( settings );
8251		var namespace = '.dt.DT_details';
8252		var drawEvent = 'draw'+namespace;
8253		var colvisEvent = 'column-visibility'+namespace;
8254		var destroyEvent = 'destroy'+namespace;
8255		var data = settings.aoData;
8256	
8257		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8258	
8259		if ( _pluck( data, '_details' ).length > 0 ) {
8260			// On each draw, insert the required elements into the document
8261			api.on( drawEvent, function ( e, ctx ) {
8262				if ( settings !== ctx ) {
8263					return;
8264				}
8265	
8266				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8267					// Internal data grab
8268					var row = data[ idx ];
8269	
8270					if ( row._detailsShow ) {
8271						row._details.insertAfter( row.nTr );
8272					}
8273				} );
8274			} );
8275	
8276			// Column visibility change - update the colspan
8277			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8278				if ( settings !== ctx ) {
8279					return;
8280				}
8281	
8282				// Update the colspan for the details rows (note, only if it already has
8283				// a colspan)
8284				var row, visible = _fnVisbleColumns( ctx );
8285	
8286				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8287					row = data[i];
8288	
8289					if ( row._details ) {
8290						row._details.children('td[colspan]').attr('colspan', visible );
8291					}
8292				}
8293			} );
8294	
8295			// Table destroyed - nuke any child rows
8296			api.on( destroyEvent, function ( e, ctx ) {
8297				if ( settings !== ctx ) {
8298					return;
8299				}
8300	
8301				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8302					if ( data[i]._details ) {
8303						__details_remove( api, i );
8304					}
8305				}
8306			} );
8307		}
8308	};
8309	
8310	// Strings for the method names to help minification
8311	var _emp = '';
8312	var _child_obj = _emp+'row().child';
8313	var _child_mth = _child_obj+'()';
8314	
8315	// data can be:
8316	//  tr
8317	//  string
8318	//  jQuery or array of any of the above
8319	_api_register( _child_mth, function ( data, klass ) {
8320		var ctx = this.context;
8321	
8322		if ( data === undefined ) {
8323			// get
8324			return ctx.length && this.length ?
8325				ctx[0].aoData[ this[0] ]._details :
8326				undefined;
8327		}
8328		else if ( data === true ) {
8329			// show
8330			this.child.show();
8331		}
8332		else if ( data === false ) {
8333			// remove
8334			__details_remove( this );
8335		}
8336		else if ( ctx.length && this.length ) {
8337			// set
8338			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8339		}
8340	
8341		return this;
8342	} );
8343	
8344	
8345	_api_register( [
8346		_child_obj+'.show()',
8347		_child_mth+'.show()' // only when `child()` was called with parameters (without
8348	], function ( show ) {   // it returns an object and this method is not executed)
8349		__details_display( this, true );
8350		return this;
8351	} );
8352	
8353	
8354	_api_register( [
8355		_child_obj+'.hide()',
8356		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8357	], function () {         // it returns an object and this method is not executed)
8358		__details_display( this, false );
8359		return this;
8360	} );
8361	
8362	
8363	_api_register( [
8364		_child_obj+'.remove()',
8365		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8366	], function () {           // it returns an object and this method is not executed)
8367		__details_remove( this );
8368		return this;
8369	} );
8370	
8371	
8372	_api_register( _child_obj+'.isShown()', function () {
8373		var ctx = this.context;
8374	
8375		if ( ctx.length && this.length ) {
8376			// _detailsShown as false or undefined will fall through to return false
8377			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8378		}
8379		return false;
8380	} );
8381	
8382	
8383	
8384	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8385	 * Columns
8386	 *
8387	 * {integer}           - column index (>=0 count from left, <0 count from right)
8388	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8389	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8390	 * "{string}:name"     - column name
8391	 * "{string}"          - jQuery selector on column header nodes
8392	 *
8393	 */
8394	
8395	// can be an array of these items, comma separated list, or an array of comma
8396	// separated lists
8397	
8398	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8399	
8400	
8401	// r1 and r2 are redundant - but it means that the parameters match for the
8402	// iterator callback in columns().data()
8403	var __columnData = function ( settings, column, r1, r2, rows ) {
8404		var a = [];
8405		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8406			a.push( _fnGetCellData( settings, rows[row], column ) );
8407		}
8408		return a;
8409	};
8410	
8411	
8412	var __column_selector = function ( settings, selector, opts )
8413	{
8414		var
8415			columns = settings.aoColumns,
8416			names = _pluck( columns, 'sName' ),
8417			nodes = _pluck( columns, 'nTh' );
8418	
8419		var run = function ( s ) {
8420			var selInt = _intVal( s );
8421	
8422			// Selector - all
8423			if ( s === '' ) {
8424				return _range( columns.length );
8425			}
8426	
8427			// Selector - index
8428			if ( selInt !== null ) {
8429				return [ selInt >= 0 ?
8430					selInt : // Count from left
8431					columns.length + selInt // Count from right (+ because its a negative value)
8432				];
8433			}
8434	
8435			// Selector = function
8436			if ( typeof s === 'function' ) {
8437				var rows = _selector_row_indexes( settings, opts );
8438	
8439				return $.map( columns, function (col, idx) {
8440					return s(
8441							idx,
8442							__columnData( settings, idx, 0, 0, rows ),
8443							nodes[ idx ]
8444						) ? idx : null;
8445				} );
8446			}
8447	
8448			// jQuery or string selector
8449			var match = typeof s === 'string' ?
8450				s.match( __re_column_selector ) :
8451				'';
8452	
8453			if ( match ) {
8454				switch( match[2] ) {
8455					case 'visIdx':
8456					case 'visible':
8457						var idx = parseInt( match[1], 10 );
8458						// Visible index given, convert to column index
8459						if ( idx < 0 ) {
8460							// Counting from the right
8461							var visColumns = $.map( columns, function (col,i) {
8462								return col.bVisible ? i : null;
8463							} );
8464							return [ visColumns[ visColumns.length + idx ] ];
8465						}
8466						// Counting from the left
8467						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8468	
8469					case 'name':
8470						// match by name. `names` is column index complete and in order
8471						return $.map( names, function (name, i) {
8472							return name === match[1] ? i : null;
8473						} );
8474	
8475					default:
8476						return [];
8477				}
8478			}
8479	
8480			// Cell in the table body
8481			if ( s.nodeName && s._DT_CellIndex ) {
8482				return [ s._DT_CellIndex.column ];
8483			}
8484	
8485			// jQuery selector on the TH elements for the columns
8486			var jqResult = $( nodes )
8487				.filter( s )
8488				.map( function () {
8489					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8490				} )
8491				.toArray();
8492	
8493			if ( jqResult.length || ! s.nodeName ) {
8494				return jqResult;
8495			}
8496	
8497			// Otherwise a node which might have a `dt-column` data attribute, or be
8498			// a child or such an element
8499			var host = $(s).closest('*[data-dt-column]');
8500			return host.length ?
8501				[ host.data('dt-column') ] :
8502				[];
8503		};
8504	
8505		return _selector_run( 'column', selector, run, settings, opts );
8506	};
8507	
8508	
8509	var __setColumnVis = function ( settings, column, vis ) {
8510		var
8511			cols = settings.aoColumns,
8512			col  = cols[ column ],
8513			data = settings.aoData,
8514			row, cells, i, ien, tr;
8515	
8516		// Get
8517		if ( vis === undefined ) {
8518			return col.bVisible;
8519		}
8520	
8521		// Set
8522		// No change
8523		if ( col.bVisible === vis ) {
8524			return;
8525		}
8526	
8527		if ( vis ) {
8528			// Insert column
8529			// Need to decide if we should use appendChild or insertBefore
8530			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8531	
8532			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8533				tr = data[i].nTr;
8534				cells = data[i].anCells;
8535	
8536				if ( tr ) {
8537					// insertBefore can act like appendChild if 2nd arg is null
8538					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8539				}
8540			}
8541		}
8542		else {
8543			// Remove column
8544			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8545		}
8546	
8547		// Common actions
8548		col.bVisible = vis;
8549		_fnDrawHead( settings, settings.aoHeader );
8550		_fnDrawHead( settings, settings.aoFooter );
8551	
8552		_fnSaveState( settings );
8553	};
8554	
8555	
8556	_api_register( 'columns()', function ( selector, opts ) {
8557		// argument shifting
8558		if ( selector === undefined ) {
8559			selector = '';
8560		}
8561		else if ( $.isPlainObject( selector ) ) {
8562			opts = selector;
8563			selector = '';
8564		}
8565	
8566		opts = _selector_opts( opts );
8567	
8568		var inst = this.iterator( 'table', function ( settings ) {
8569			return __column_selector( settings, selector, opts );
8570		}, 1 );
8571	
8572		// Want argument shifting here and in _row_selector?
8573		inst.selector.cols = selector;
8574		inst.selector.opts = opts;
8575	
8576		return inst;
8577	} );
8578	
8579	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8580		return this.iterator( 'column', function ( settings, column ) {
8581			return settings.aoColumns[column].nTh;
8582		}, 1 );
8583	} );
8584	
8585	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8586		return this.iterator( 'column', function ( settings, column ) {
8587			return settings.aoColumns[column].nTf;
8588		}, 1 );
8589	} );
8590	
8591	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8592		return this.iterator( 'column-rows', __columnData, 1 );
8593	} );
8594	
8595	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8596		return this.iterator( 'column', function ( settings, column ) {
8597			return settings.aoColumns[column].mData;
8598		}, 1 );
8599	} );
8600	
8601	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8602		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8603			return _pluck_order( settings.aoData, rows,
8604				type === 'search' ? '_aFilterData' : '_aSortData', column
8605			);
8606		}, 1 );
8607	} );
8608	
8609	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8610		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8611			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8612		}, 1 );
8613	} );
8614	
8615	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8616		var ret = this.iterator( 'column', function ( settings, column ) {
8617			if ( vis === undefined ) {
8618				return settings.aoColumns[ column ].bVisible;
8619			} // else
8620			__setColumnVis( settings, column, vis );
8621		} );
8622	
8623		// Group the column visibility changes
8624		if ( vis !== undefined ) {
8625			// Second loop once the first is done for events
8626			this.iterator( 'column', function ( settings, column ) {
8627				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8628			} );
8629	
8630			if ( calc === undefined || calc ) {
8631				this.columns.adjust();
8632			}
8633		}
8634	
8635		return ret;
8636	} );
8637	
8638	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8639		return this.iterator( 'column', function ( settings, column ) {
8640			return type === 'visible' ?
8641				_fnColumnIndexToVisible( settings, column ) :
8642				column;
8643		}, 1 );
8644	} );
8645	
8646	_api_register( 'columns.adjust()', function () {
8647		return this.iterator( 'table', function ( settings ) {
8648			_fnAdjustColumnSizing( settings );
8649		}, 1 );
8650	} );
8651	
8652	_api_register( 'column.index()', function ( type, idx ) {
8653		if ( this.context.length !== 0 ) {
8654			var ctx = this.context[0];
8655	
8656			if ( type === 'fromVisible' || type === 'toData' ) {
8657				return _fnVisibleToColumnIndex( ctx, idx );
8658			}
8659			else if ( type === 'fromData' || type === 'toVisible' ) {
8660				return _fnColumnIndexToVisible( ctx, idx );
8661			}
8662		}
8663	} );
8664	
8665	_api_register( 'column()', function ( selector, opts ) {
8666		return _selector_first( this.columns( selector, opts ) );
8667	} );
8668	
8669	
8670	
8671	var __cell_selector = function ( settings, selector, opts )
8672	{
8673		var data = settings.aoData;
8674		var rows = _selector_row_indexes( settings, opts );
8675		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8676		var allCells = $( [].concat.apply([], cells) );
8677		var row;
8678		var columns = settings.aoColumns.length;
8679		var a, i, ien, j, o, host;
8680	
8681		var run = function ( s ) {
8682			var fnSelector = typeof s === 'function';
8683	
8684			if ( s === null || s === undefined || fnSelector ) {
8685				// All cells and function selectors
8686				a = [];
8687	
8688				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8689					row = rows[i];
8690	
8691					for ( j=0 ; j<columns ; j++ ) {
8692						o = {
8693							row: row,
8694							column: j
8695						};
8696	
8697						if ( fnSelector ) {
8698							// Selector - function
8699							host = data[ row ];
8700	
8701							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8702								a.push( o );
8703							}
8704						}
8705						else {
8706							// Selector - all
8707							a.push( o );
8708						}
8709					}
8710				}
8711	
8712				return a;
8713			}
8714			
8715			// Selector - index
8716			if ( $.isPlainObject( s ) ) {
8717				return [s];
8718			}
8719	
8720			// Selector - jQuery filtered cells
8721			var jqResult = allCells
8722				.filter( s )
8723				.map( function (i, el) {
8724					return { // use a new object, in case someone changes the values
8725						row:    el._DT_CellIndex.row,
8726						column: el._DT_CellIndex.column
8727	 				};
8728				} )
8729				.toArray();
8730	
8731			if ( jqResult.length || ! s.nodeName ) {
8732				return jqResult;
8733			}
8734	
8735			// Otherwise the selector is a node, and there is one last option - the
8736			// element might be a child of an element which has dt-row and dt-column
8737			// data attributes
8738			host = $(s).closest('*[data-dt-row]');
8739			return host.length ?
8740				[ {
8741					row: host.data('dt-row'),
8742					column: host.data('dt-column')
8743				} ] :
8744				[];
8745		};
8746	
8747		return _selector_run( 'cell', selector, run, settings, opts );
8748	};
8749	
8750	
8751	
8752	
8753	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8754		// Argument shifting
8755		if ( $.isPlainObject( rowSelector ) ) {
8756			// Indexes
8757			if ( rowSelector.row === undefined ) {
8758				// Selector options in first parameter
8759				opts = rowSelector;
8760				rowSelector = null;
8761			}
8762			else {
8763				// Cell index objects in first parameter
8764				opts = columnSelector;
8765				columnSelector = null;
8766			}
8767		}
8768		if ( $.isPlainObject( columnSelector ) ) {
8769			opts = columnSelector;
8770			columnSelector = null;
8771		}
8772	
8773		// Cell selector
8774		if ( columnSelector === null || columnSelector === undefined ) {
8775			return this.iterator( 'table', function ( settings ) {
8776				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8777			} );
8778		}
8779	
8780		// Row + column selector
8781		var columns = this.columns( columnSelector, opts );
8782		var rows = this.rows( rowSelector, opts );
8783		var a, i, ien, j, jen;
8784	
8785		var cells = this.iterator( 'table', function ( settings, idx ) {
8786			a = [];
8787	
8788			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8789				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8790					a.push( {
8791						row:    rows[idx][i],
8792						column: columns[idx][j]
8793					} );
8794				}
8795			}
8796	
8797			return a;
8798		}, 1 );
8799	
8800		$.extend( cells.selector, {
8801			cols: columnSelector,
8802			rows: rowSelector,
8803			opts: opts
8804		} );
8805	
8806		return cells;
8807	} );
8808	
8809	
8810	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8811		return this.iterator( 'cell', function ( settings, row, column ) {
8812			var data = settings.aoData[ row ];
8813	
8814			return data && data.anCells ?
8815				data.anCells[ column ] :
8816				undefined;
8817		}, 1 );
8818	} );
8819	
8820	
8821	_api_register( 'cells().data()', function () {
8822		return this.iterator( 'cell', function ( settings, row, column ) {
8823			return _fnGetCellData( settings, row, column );
8824		}, 1 );
8825	} );
8826	
8827	
8828	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8829		type = type === 'search' ? '_aFilterData' : '_aSortData';
8830	
8831		return this.iterator( 'cell', function ( settings, row, column ) {
8832			return settings.aoData[ row ][ type ][ column ];
8833		}, 1 );
8834	} );
8835	
8836	
8837	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8838		return this.iterator( 'cell', function ( settings, row, column ) {
8839			return _fnGetCellData( settings, row, column, type );
8840		}, 1 );
8841	} );
8842	
8843	
8844	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8845		return this.iterator( 'cell', function ( settings, row, column ) {
8846			return {
8847				row: row,
8848				column: column,
8849				columnVisible: _fnColumnIndexToVisible( settings, column )
8850			};
8851		}, 1 );
8852	} );
8853	
8854	
8855	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8856		return this.iterator( 'cell', function ( settings, row, column ) {
8857			_fnInvalidate( settings, row, src, column );
8858		} );
8859	} );
8860	
8861	
8862	
8863	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8864		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8865	} );
8866	
8867	
8868	_api_register( 'cell().data()', function ( data ) {
8869		var ctx = this.context;
8870		var cell = this[0];
8871	
8872		if ( data === undefined ) {
8873			// Get
8874			return ctx.length && cell.length ?
8875				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8876				undefined;
8877		}
8878	
8879		// Set
8880		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8881		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8882	
8883		return this;
8884	} );
8885	
8886	
8887	
8888	/**
8889	 * Get current ordering (sorting) that has been applied to the table.
8890	 *
8891	 * @returns {array} 2D array containing the sorting information for the first
8892	 *   table in the current context. Each element in the parent array represents
8893	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8894	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8895	 *   the column index that the sorting condition applies to, the second is the
8896	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8897	 *   index of the sorting order from the `column.sorting` initialisation array.
8898	 *//**
8899	 * Set the ordering for the table.
8900	 *
8901	 * @param {integer} order Column index to sort upon.
8902	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8903	 * @returns {DataTables.Api} this
8904	 *//**
8905	 * Set the ordering for the table.
8906	 *
8907	 * @param {array} order 1D array of sorting information to be applied.
8908	 * @param {array} [...] Optional additional sorting conditions
8909	 * @returns {DataTables.Api} this
8910	 *//**
8911	 * Set the ordering for the table.
8912	 *
8913	 * @param {array} order 2D array of sorting information to be applied.
8914	 * @returns {DataTables.Api} this
8915	 */
8916	_api_register( 'order()', function ( order, dir ) {
8917		var ctx = this.context;
8918	
8919		if ( order === undefined ) {
8920			// get
8921			return ctx.length !== 0 ?
8922				ctx[0].aaSorting :
8923				undefined;
8924		}
8925	
8926		// set
8927		if ( typeof order === 'number' ) {
8928			// Simple column / direction passed in
8929			order = [ [ order, dir ] ];
8930		}
8931		else if ( order.length && ! $.isArray( order[0] ) ) {
8932			// Arguments passed in (list of 1D arrays)
8933			order = Array.prototype.slice.call( arguments );
8934		}
8935		// otherwise a 2D array was passed in
8936	
8937		return this.iterator( 'table', function ( settings ) {
8938			settings.aaSorting = order.slice();
8939		} );
8940	} );
8941	
8942	
8943	/**
8944	 * Attach a sort listener to an element for a given column
8945	 *
8946	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8947	 *   listener to. This can take the form of a single DOM node, a jQuery
8948	 *   collection of nodes or a jQuery selector which will identify the node(s).
8949	 * @param {integer} column the column that a click on this node will sort on
8950	 * @param {function} [callback] callback function when sort is run
8951	 * @returns {DataTables.Api} this
8952	 */
8953	_api_register( 'order.listener()', function ( node, column, callback ) {
8954		return this.iterator( 'table', function ( settings ) {
8955			_fnSortAttachListener( settings, node, column, callback );
8956		} );
8957	} );
8958	
8959	
8960	_api_register( 'order.fixed()', function ( set ) {
8961		if ( ! set ) {
8962			var ctx = this.context;
8963			var fixed = ctx.length ?
8964				ctx[0].aaSortingFixed :
8965				undefined;
8966	
8967			return $.isArray( fixed ) ?
8968				{ pre: fixed } :
8969				fixed;
8970		}
8971	
8972		return this.iterator( 'table', function ( settings ) {
8973			settings.aaSortingFixed = $.extend( true, {}, set );
8974		} );
8975	} );
8976	
8977	
8978	// Order by the selected column(s)
8979	_api_register( [
8980		'columns().order()',
8981		'column().order()'
8982	], function ( dir ) {
8983		var that = this;
8984	
8985		return this.iterator( 'table', function ( settings, i ) {
8986			var sort = [];
8987	
8988			$.each( that[i], function (j, col) {
8989				sort.push( [ col, dir ] );
8990			} );
8991	
8992			settings.aaSorting = sort;
8993		} );
8994	} );
8995	
8996	
8997	
8998	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8999		var ctx = this.context;
9000	
9001		if ( input === undefined ) {
9002			// get
9003			return ctx.length !== 0 ?
9004				ctx[0].oPreviousSearch.sSearch :
9005				undefined;
9006		}
9007	
9008		// set
9009		return this.iterator( 'table', function ( settings ) {
9010			if ( ! settings.oFeatures.bFilter ) {
9011				return;
9012			}
9013	
9014			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9015				"sSearch": input+"",
9016				"bRegex":  regex === null ? false : regex,
9017				"bSmart":  smart === null ? true  : smart,
9018				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9019			} ), 1 );
9020		} );
9021	} );
9022	
9023	
9024	_api_registerPlural(
9025		'columns().search()',
9026		'column().search()',
9027		function ( input, regex, smart, caseInsen ) {
9028			return this.iterator( 'column', function ( settings, column ) {
9029				var preSearch = settings.aoPreSearchCols;
9030	
9031				if ( input === undefined ) {
9032					// get
9033					return preSearch[ column ].sSearch;
9034				}
9035	
9036				// set
9037				if ( ! settings.oFeatures.bFilter ) {
9038					return;
9039				}
9040	
9041				$.extend( preSearch[ column ], {
9042					"sSearch": input+"",
9043					"bRegex":  regex === null ? false : regex,
9044					"bSmart":  smart === null ? true  : smart,
9045					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9046				} );
9047	
9048				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9049			} );
9050		}
9051	);
9052	
9053	/*
9054	 * State API methods
9055	 */
9056	
9057	_api_register( 'state()', function () {
9058		return this.context.length ?
9059			this.context[0].oSavedState :
9060			null;
9061	} );
9062	
9063	
9064	_api_register( 'state.clear()', function () {
9065		return this.iterator( 'table', function ( settings ) {
9066			// Save an empty object
9067			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9068		} );
9069	} );
9070	
9071	
9072	_api_register( 'state.loaded()', function () {
9073		return this.context.length ?
9074			this.context[0].oLoadedState :
9075			null;
9076	} );
9077	
9078	
9079	_api_register( 'state.save()', function () {
9080		return this.iterator( 'table', function ( settings ) {
9081			_fnSaveState( settings );
9082		} );
9083	} );
9084	
9085	
9086	
9087	/**
9088	 * Provide a common method for plug-ins to check the version of DataTables being
9089	 * used, in order to ensure compatibility.
9090	 *
9091	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9092	 *    Note that the formats "X" and "X.Y" are also acceptable.
9093	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9094	 *    the required version, or false if this version of DataTales is not
9095	 *    suitable
9096	 *  @static
9097	 *  @dtopt API-Static
9098	 *
9099	 *  @example
9100	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9101	 */
9102	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9103	{
9104		var aThis = DataTable.version.split('.');
9105		var aThat = version.split('.');
9106		var iThis, iThat;
9107	
9108		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9109			iThis = parseInt( aThis[i], 10 ) || 0;
9110			iThat = parseInt( aThat[i], 10 ) || 0;
9111	
9112			// Parts are the same, keep comparing
9113			if (iThis === iThat) {
9114				continue;
9115			}
9116	
9117			// Parts are different, return immediately
9118			return iThis > iThat;
9119		}
9120	
9121		return true;
9122	};
9123	
9124	
9125	/**
9126	 * Check if a `<table>` node is a DataTable table already or not.
9127	 *
9128	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9129	 *      selector for the table to test. Note that if more than more than one
9130	 *      table is passed on, only the first will be checked
9131	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9132	 *  @static
9133	 *  @dtopt API-Static
9134	 *
9135	 *  @example
9136	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9137	 *      $('#example').dataTable();
9138	 *    }
9139	 */
9140	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9141	{
9142		var t = $(table).get(0);
9143		var is = false;
9144	
9145		if ( table instanceof DataTable.Api ) {
9146			return true;
9147		}
9148	
9149		$.each( DataTable.settings, function (i, o) {
9150			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9151			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9152	
9153			if ( o.nTable === t || head === t || foot === t ) {
9154				is = true;
9155			}
9156		} );
9157	
9158		return is;
9159	};
9160	
9161	
9162	/**
9163	 * Get all DataTable tables that have been initialised - optionally you can
9164	 * select to get only currently visible tables.
9165	 *
9166	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9167	 *    or visible tables only.
9168	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9169	 *    DataTables
9170	 *  @static
9171	 *  @dtopt API-Static
9172	 *
9173	 *  @example
9174	 *    $.each( $.fn.dataTable.tables(true), function () {
9175	 *      $(table).DataTable().columns.adjust();
9176	 *    } );
9177	 */
9178	DataTable.tables = DataTable.fnTables = function ( visible )
9179	{
9180		var api = false;
9181	
9182		if ( $.isPlainObject( visible ) ) {
9183			api = visible.api;
9184			visible = visible.visible;
9185		}
9186	
9187		var a = $.map( DataTable.settings, function (o) {
9188			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9189				return o.nTable;
9190			}
9191		} );
9192	
9193		return api ?
9194			new _Api( a ) :
9195			a;
9196	};
9197	
9198	
9199	/**
9200	 * Convert from camel case parameters to Hungarian notation. This is made public
9201	 * for the extensions to provide the same ability as DataTables core to accept
9202	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9203	 * parameters.
9204	 *
9205	 *  @param {object} src The model object which holds all parameters that can be
9206	 *    mapped.
9207	 *  @param {object} user The object to convert from camel case to Hungarian.
9208	 *  @param {boolean} force When set to `true`, properties which already have a
9209	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9210	 *    won't be.
9211	 */
9212	DataTable.camelToHungarian = _fnCamelToHungarian;
9213	
9214	
9215	
9216	/**
9217	 *
9218	 */
9219	_api_register( '$()', function ( selector, opts ) {
9220		var
9221			rows   = this.rows( opts ).nodes(), // Get all rows
9222			jqRows = $(rows);
9223	
9224		return $( [].concat(
9225			jqRows.filter( selector ).toArray(),
9226			jqRows.find( selector ).toArray()
9227		) );
9228	} );
9229	
9230	
9231	// jQuery functions to operate on the tables
9232	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9233		_api_register( key+'()', function ( /* event, handler */ ) {
9234			var args = Array.prototype.slice.call(arguments);
9235	
9236			// Add the `dt` namespace automatically if it isn't already present
9237			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9238				return ! e.match(/\.dt\b/) ?
9239					e+'.dt' :
9240					e;
9241				} ).join( ' ' );
9242	
9243			var inst = $( this.tables().nodes() );
9244			inst[key].apply( inst, args );
9245			return this;
9246		} );
9247	} );
9248	
9249	
9250	_api_register( 'clear()', function () {
9251		return this.iterator( 'table', function ( settings ) {
9252			_fnClearTable( settings );
9253		} );
9254	} );
9255	
9256	
9257	_api_register( 'settings()', function () {
9258		return new _Api( this.context, this.context );
9259	} );
9260	
9261	
9262	_api_register( 'init()', function () {
9263		var ctx = this.context;
9264		return ctx.length ? ctx[0].oInit : null;
9265	} );
9266	
9267	
9268	_api_register( 'data()', function () {
9269		return this.iterator( 'table', function ( settings ) {
9270			return _pluck( settings.aoData, '_aData' );
9271		} ).flatten();
9272	} );
9273	
9274	
9275	_api_register( 'destroy()', function ( remove ) {
9276		remove = remove || false;
9277	
9278		return this.iterator( 'table', function ( settings ) {
9279			var orig      = settings.nTableWrapper.parentNode;
9280			var classes   = settings.oClasses;
9281			var table     = settings.nTable;
9282			var tbody     = settings.nTBody;
9283			var thead     = settings.nTHead;
9284			var tfoot     = settings.nTFoot;
9285			var jqTable   = $(table);
9286			var jqTbody   = $(tbody);
9287			var jqWrapper = $(settings.nTableWrapper);
9288			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9289			var i, ien;
9290	
9291			// Flag to note that the table is currently being destroyed - no action
9292			// should be taken
9293			settings.bDestroying = true;
9294	
9295			// Fire off the destroy callbacks for plug-ins etc
9296			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9297	
9298			// If not being removed from the document, make all columns visible
9299			if ( ! remove ) {
9300				new _Api( settings ).columns().visible( true );
9301			}
9302	
9303			// Blitz all `DT` namespaced events (these are internal events, the
9304			// lowercase, `dt` events are user subscribed and they are responsible
9305			// for removing them
9306			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9307			$(window).off('.DT-'+settings.sInstance);
9308	
9309			// When scrolling we had to break the table up - restore it
9310			if ( table != thead.parentNode ) {
9311				jqTable.children('thead').detach();
9312				jqTable.append( thead );
9313			}
9314	
9315			if ( tfoot && table != tfoot.parentNode ) {
9316				jqTable.children('tfoot').detach();
9317				jqTable.append( tfoot );
9318			}
9319	
9320			settings.aaSorting = [];
9321			settings.aaSortingFixed = [];
9322			_fnSortingClasses( settings );
9323	
9324			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9325	
9326			$('th, td', thead).removeClass( classes.sSortable+' '+
9327				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9328			);
9329	
9330			// Add the TR elements back into the table in their original order
9331			jqTbody.children().detach();
9332			jqTbody.append( rows );
9333	
9334			// Remove the DataTables generated nodes, events and classes
9335			var removedMethod = remove ? 'remove' : 'detach';
9336			jqTable[ removedMethod ]();
9337			jqWrapper[ removedMethod ]();
9338	
9339			// If we need to reattach the table to the document
9340			if ( ! remove && orig ) {
9341				// insertBefore acts like appendChild if !arg[1]
9342				orig.insertBefore( table, settings.nTableReinsertBefore );
9343	
9344				// Restore the width of the original table - was read from the style property,
9345				// so we can restore directly to that
9346				jqTable
9347					.css( 'width', settings.sDestroyWidth )
9348					.removeClass( classes.sTable );
9349	
9350				// If the were originally stripe classes - then we add them back here.
9351				// Note this is not fool proof (for example if not all rows had stripe
9352				// classes - but it's a good effort without getting carried away
9353				ien = settings.asDestroyStripes.length;
9354	
9355				if ( ien ) {
9356					jqTbody.children().each( function (i) {
9357						$(this).addClass( settings.asDestroyStripes[i % ien] );
9358					} );
9359				}
9360			}
9361	
9362			/* Remove the settings object from the settings array */
9363			var idx = $.inArray( settings, DataTable.settings );
9364			if ( idx !== -1 ) {
9365				DataTable.settings.splice( idx, 1 );
9366			}
9367		} );
9368	} );
9369	
9370	
9371	// Add the `every()` method for rows, columns and cells in a compact form
9372	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9373		_api_register( type+'s().every()', function ( fn ) {
9374			var opts = this.selector.opts;
9375			var api = this;
9376	
9377			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9378				// Rows and columns:
9379				//  arg1 - index
9380				//  arg2 - table counter
9381				//  arg3 - loop counter
9382				//  arg4 - undefined
9383				// Cells:
9384				//  arg1 - row index
9385				//  arg2 - column index
9386				//  arg3 - table counter
9387				//  arg4 - loop counter
9388				fn.call(
9389					api[ type ](
9390						arg1,
9391						type==='cell' ? arg2 : opts,
9392						type==='cell' ? opts : undefined
9393					),
9394					arg1, arg2, arg3, arg4
9395				);
9396			} );
9397		} );
9398	} );
9399	
9400	
9401	// i18n method for extensions to be able to use the language object from the
9402	// DataTable
9403	_api_register( 'i18n()', function ( token, def, plural ) {
9404		var ctx = this.context[0];
9405		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9406	
9407		if ( resolved === undefined ) {
9408			resolved = def;
9409		}
9410	
9411		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9412			resolved = resolved[ plural ] !== undefined ?
9413				resolved[ plural ] :
9414				resolved._;
9415		}
9416	
9417		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9418	} );
9419
9420	/**
9421	 * Version string for plug-ins to check compatibility. Allowed format is
9422	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9423	 * only for non-release builds. See http://semver.org/ for more information.
9424	 *  @member
9425	 *  @type string
9426	 *  @default Version number
9427	 */
9428	DataTable.version = "1.10.16";
9429
9430	/**
9431	 * Private data store, containing all of the settings objects that are
9432	 * created for the tables on a given page.
9433	 *
9434	 * Note that the `DataTable.settings` object is aliased to
9435	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9436	 * manipulated, or `jQuery.fn.dataTable.settings`.
9437	 *  @member
9438	 *  @type array
9439	 *  @default []
9440	 *  @private
9441	 */
9442	DataTable.settings = [];
9443
9444	/**
9445	 * Object models container, for the various models that DataTables has
9446	 * available to it. These models define the objects that are used to hold
9447	 * the active state and configuration of the table.
9448	 *  @namespace
9449	 */
9450	DataTable.models = {};
9451	
9452	
9453	
9454	/**
9455	 * Template object for the way in which DataTables holds information about
9456	 * search information for the global filter and individual column filters.
9457	 *  @namespace
9458	 */
9459	DataTable.models.oSearch = {
9460		/**
9461		 * Flag to indicate if the filtering should be case insensitive or not
9462		 *  @type boolean
9463		 *  @default true
9464		 */
9465		"bCaseInsensitive": true,
9466	
9467		/**
9468		 * Applied search term
9469		 *  @type string
9470		 *  @default <i>Empty string</i>
9471		 */
9472		"sSearch": "",
9473	
9474		/**
9475		 * Flag to indicate if the search term should be interpreted as a
9476		 * regular expression (true) or not (false) and therefore and special
9477		 * regex characters escaped.
9478		 *  @type boolean
9479		 *  @default false
9480		 */
9481		"bRegex": false,
9482	
9483		/**
9484		 * Flag to indicate if DataTables is to use its smart filtering or not.
9485		 *  @type boolean
9486		 *  @default true
9487		 */
9488		"bSmart": true
9489	};
9490	
9491	
9492	
9493	
9494	/**
9495	 * Template object for the way in which DataTables holds information about
9496	 * each individual row. This is the object format used for the settings
9497	 * aoData array.
9498	 *  @namespace
9499	 */
9500	DataTable.models.oRow = {
9501		/**
9502		 * TR element for the row
9503		 *  @type node
9504		 *  @default null
9505		 */
9506		"nTr": null,
9507	
9508		/**
9509		 * Array of TD elements for each row. This is null until the row has been
9510		 * created.
9511		 *  @type array nodes
9512		 *  @default []
9513		 */
9514		"anCells": null,
9515	
9516		/**
9517		 * Data object from the original data source for the row. This is either
9518		 * an array if using the traditional form of DataTables, or an object if
9519		 * using mData options. The exact type will depend on the passed in
9520		 * data from the data source, or will be an array if using DOM a data
9521		 * source.
9522		 *  @type array|object
9523		 *  @default []
9524		 */
9525		"_aData": [],
9526	
9527		/**
9528		 * Sorting data cache - this array is ostensibly the same length as the
9529		 * number of columns (although each index is generated only as it is
9530		 * needed), and holds the data that is used for sorting each column in the
9531		 * row. We do this cache generation at the start of the sort in order that
9532		 * the formatting of the sort data need be done only once for each cell
9533		 * per sort. This array should not be read from or written to by anything
9534		 * other than the master sorting methods.
9535		 *  @type array
9536		 *  @default null
9537		 *  @private
9538		 */
9539		"_aSortData": null,
9540	
9541		/**
9542		 * Per cell filtering data cache. As per the sort data cache, used to
9543		 * increase the performance of the filtering in DataTables
9544		 *  @type array
9545		 *  @default null
9546		 *  @private
9547		 */
9548		"_aFilterData": null,
9549	
9550		/**
9551		 * Filtering data cache. This is the same as the cell filtering cache, but
9552		 * in this case a string rather than an array. This is easily computed with
9553		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9554		 * needed on every search (memory traded for performance)
9555		 *  @type array
9556		 *  @default null
9557		 *  @private
9558		 */
9559		"_sFilterRow": null,
9560	
9561		/**
9562		 * Cache of the class name that DataTables has applied to the row, so we
9563		 * can quickly look at this variable rather than needing to do a DOM check
9564		 * on className for the nTr property.
9565		 *  @type string
9566		 *  @default <i>Empty string</i>
9567		 *  @private
9568		 */
9569		"_sRowStripe": "",
9570	
9571		/**
9572		 * Denote if the original data source was from the DOM, or the data source
9573		 * object. This is used for invalidating data, so DataTables can
9574		 * automatically read data from the original source, unless uninstructed
9575		 * otherwise.
9576		 *  @type string
9577		 *  @default null
9578		 *  @private
9579		 */
9580		"src": null,
9581	
9582		/**
9583		 * Index in the aoData array. This saves an indexOf lookup when we have the
9584		 * object, but want to know the index
9585		 *  @type integer
9586		 *  @default -1
9587		 *  @private
9588		 */
9589		"idx": -1
9590	};
9591	
9592	
9593	/**
9594	 * Template object for the column information object in DataTables. This object
9595	 * is held in the settings aoColumns array and contains all the information that
9596	 * DataTables needs about each individual column.
9597	 *
9598	 * Note that this object is related to {@link DataTable.defaults.column}
9599	 * but this one is the internal data store for DataTables's cache of columns.
9600	 * It should NOT be manipulated outside of DataTables. Any configuration should
9601	 * be done through the initialisation options.
9602	 *  @namespace
9603	 */
9604	DataTable.models.oColumn = {
9605		/**
9606		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9607		 * is faster to just hold it as a variable
9608		 *  @type integer
9609		 *  @default null
9610		 */
9611		"idx": null,
9612	
9613		/**
9614		 * A list of the columns that sorting should occur on when this column
9615		 * is sorted. That this property is an array allows multi-column s
9615orting
9616		 * to be defined for a column (for example first name / last name columns
9617		 * would benefit from this). The values are integers pointing to the
9618		 * columns to be sorted on (typically it will be a single integer pointing
9619		 * at itself, but that doesn't need to be the case).
9620		 *  @type array
9621		 */
9622		"aDataSort": null,
9623	
9624		/**
9625		 * Define the sorting directions that are applied to the column, in sequence
9626		 * as the column is repeatedly sorted upon - i.e. the first value is used
9627		 * as the sorting direction when the column if first sorted (clicked on).
9628		 * Sort it again (click again) and it will move on to the next index.
9629		 * Repeat until loop.
9630		 *  @type array
9631		 */
9632		"asSorting": null,
9633	
9634		/**
9635		 * Flag to indicate if the column is searchable, and thus should be included
9636		 * in the filtering or not.
9637		 *  @type boolean
9638		 */
9639		"bSearchable": null,
9640	
9641		/**
9642		 * Flag to indicate if the column is sortable or not.
9643		 *  @type boolean
9644		 */
9645		"bSortable": null,
9646	
9647		/**
9648		 * Flag to indicate if the column is currently visible in the table or not
9649		 *  @type boolean
9650		 */
9651		"bVisible": null,
9652	
9653		/**
9654		 * Store for manual type assignment using the `column.type` option. This
9655		 * is held in store so we can manipulate the column's `sType` property.
9656		 *  @type string
9657		 *  @default null
9658		 *  @private
9659		 */
9660		"_sManualType": null,
9661	
9662		/**
9663		 * Flag to indicate if HTML5 data attributes should be used as the data
9664		 * source for filtering or sorting. True is either are.
9665		 *  @type boolean
9666		 *  @default false
9667		 *  @private
9668		 */
9669		"_bAttrSrc": false,
9670	
9671		/**
9672		 * Developer definable function that is called whenever a cell is created (Ajax source,
9673		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9674		 * allowing you to modify the DOM element (add background colour for example) when the
9675		 * element is available.
9676		 *  @type function
9677		 *  @param {element} nTd The TD node that has been created
9678		 *  @param {*} sData The Data for the cell
9679		 *  @param {array|object} oData The data for the whole row
9680		 *  @param {int} iRow The row index for the aoData data store
9681		 *  @default null
9682		 */
9683		"fnCreatedCell": null,
9684	
9685		/**
9686		 * Function to get data from a cell in a column. You should <b>never</b>
9687		 * access data directly through _aData internally in DataTables - always use
9688		 * the method attached to this property. It allows mData to function as
9689		 * required. This function is automatically assigned by the column
9690		 * initialisation method
9691		 *  @type function
9692		 *  @param {array|object} oData The data array/object for the array
9693		 *    (i.e. aoData[]._aData)
9694		 *  @param {string} sSpecific The specific data type you want to get -
9695		 *    'display', 'type' 'filter' 'sort'
9696		 *  @returns {*} The data for the cell from the given row's data
9697		 *  @default null
9698		 */
9699		"fnGetData": null,
9700	
9701		/**
9702		 * Function to set data for a cell in the column. You should <b>never</b>
9703		 * set the data directly to _aData internally in DataTables - always use
9704		 * this method. It allows mData to function as required. This function
9705		 * is automatically assigned by the column initialisation method
9706		 *  @type function
9707		 *  @param {array|object} oData The data array/object for the array
9708		 *    (i.e. aoData[]._aData)
9709		 *  @param {*} sValue Value to set
9710		 *  @default null
9711		 */
9712		"fnSetData": null,
9713	
9714		/**
9715		 * Property to read the value for the cells in the column from the data
9716		 * source array / object. If null, then the default content is used, if a
9717		 * function is given then the return from the function is used.
9718		 *  @type function|int|string|null
9719		 *  @default null
9720		 */
9721		"mData": null,
9722	
9723		/**
9724		 * Partner property to mData which is used (only when defined) to get
9725		 * the data - i.e. it is basically the same as mData, but without the
9726		 * 'set' option, and also the data fed to it is the result from mData.
9727		 * This is the rendering method to match the data method of mData.
9728		 *  @type function|int|string|null
9729		 *  @default null
9730		 */
9731		"mRender": null,
9732	
9733		/**
9734		 * Unique header TH/TD element for this column - this is what the sorting
9735		 * listener is attached to (if sorting is enabled.)
9736		 *  @type node
9737		 *  @default null
9738		 */
9739		"nTh": null,
9740	
9741		/**
9742		 * Unique footer TH/TD element for this column (if there is one). Not used
9743		 * in DataTables as such, but can be used for plug-ins to reference the
9744		 * footer for each column.
9745		 *  @type node
9746		 *  @default null
9747		 */
9748		"nTf": null,
9749	
9750		/**
9751		 * The class to apply to all TD elements in the table's TBODY for the column
9752		 *  @type string
9753		 *  @default null
9754		 */
9755		"sClass": null,
9756	
9757		/**
9758		 * When DataTables calculates the column widths to assign to each column,
9759		 * it finds the longest string in each column and then constructs a
9760		 * temporary table and reads the widths from that. The problem with this
9761		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9762		 * string - thus the calculation can go wrong (doing it properly and putting
9763		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9764		 * a "work around" we provide this option. It will append its value to the
9765		 * text that is found to be the longest string for the column - i.e. padding.
9766		 *  @type string
9767		 */
9768		"sContentPadding": null,
9769	
9770		/**
9771		 * Allows a default value to be given for a column's data, and will be used
9772		 * whenever a null data source is encountered (this can be because mData
9773		 * is set to null, or because the data source itself is null).
9774		 *  @type string
9775		 *  @default null
9776		 */
9777		"sDefaultContent": null,
9778	
9779		/**
9780		 * Name for the column, allowing reference to the column by name as well as
9781		 * by index (needs a lookup to work by name).
9782		 *  @type string
9783		 */
9784		"sName": null,
9785	
9786		/**
9787		 * Custom sorting data type - defines which of the available plug-ins in
9788		 * afnSortData the custom sorting will use - if any is defined.
9789		 *  @type string
9790		 *  @default std
9791		 */
9792		"sSortDataType": 'std',
9793	
9794		/**
9795		 * Class to be applied to the header element when sorting on this column
9796		 *  @type string
9797		 *  @default null
9798		 */
9799		"sSortingClass": null,
9800	
9801		/**
9802		 * Class to be applied to the header element when sorting on this column -
9803		 * when jQuery UI theming is used.
9804		 *  @type string
9805		 *  @default null
9806		 */
9807		"sSortingClassJUI": null,
9808	
9809		/**
9810		 * Title of the column - what is seen in the TH element (nTh).
9811		 *  @type string
9812		 */
9813		"sTitle": null,
9814	
9815		/**
9816		 * Column sorting and filtering type
9817		 *  @type string
9818		 *  @default null
9819		 */
9820		"sType": null,
9821	
9822		/**
9823		 * Width of the column
9824		 *  @type string
9825		 *  @default null
9826		 */
9827		"sWidth": null,
9828	
9829		/**
9830		 * Width of the column when it was first "encountered"
9831		 *  @type string
9832		 *  @default null
9833		 */
9834		"sWidthOrig": null
9835	};
9836	
9837	
9838	/*
9839	 * Developer note: The properties of the object below are given in Hungarian
9840	 * notation, that was used as the interface for DataTables prior to v1.10, however
9841	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9842	 * breaking backwards compatibility utterly with this change, the Hungarian
9843	 * version is still, internally the primary interface, but is is not documented
9844	 * - hence the @name tags in each doc comment. This allows a Javascript function
9845	 * to create a map from Hungarian notation to camel case (going the other direction
9846	 * would require each property to be listed, which would at around 3K to the size
9847	 * of DataTables, while this method is about a 0.5K hit
vendor: 57,087 bytes, lines 9847-11623
9847.
9848	 *
9849	 * Ultimately this does pave the way for Hungarian notation to be dropped
9850	 * completely, but that is a massive amount of work and will break current
9851	 * installs (therefore is on-hold until v2).
9852	 */
9853	
9854	/**
9855	 * Initialisation options that can be given to DataTables at initialisation
9856	 * time.
9857	 *  @namespace
9858	 */
9859	DataTable.defaults = {
9860		/**
9861		 * An array of data to use for the table, passed in at initialisation which
9862		 * will be used in preference to any data which is already in the DOM. This is
9863		 * particularly useful for constructing tables purely in Javascript, for
9864		 * example with a custom Ajax call.
9865		 *  @type array
9866		 *  @default null
9867		 *
9868		 *  @dtopt Option
9869		 *  @name DataTable.defaults.data
9870		 *
9871		 *  @example
9872		 *    // Using a 2D array data source
9873		 *    $(document).ready( function () {
9874		 *      $('#example').dataTable( {
9875		 *        "data": [
9876		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9877		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9878		 *        ],
9879		 *        "columns": [
9880		 *          { "title": "Engine" },
9881		 *          { "title": "Browser" },
9882		 *          { "title": "Platform" },
9883		 *          { "title": "Version" },
9884		 *          { "title": "Grade" }
9885		 *        ]
9886		 *      } );
9887		 *    } );
9888		 *
9889		 *  @example
9890		 *    // Using an array of objects as a data source (`data`)
9891		 *    $(document).ready( function () {
9892		 *      $('#example').dataTable( {
9893		 *        "data": [
9894		 *          {
9895		 *            "engine":   "Trident",
9896		 *            "browser":  "Internet Explorer 4.0",
9897		 *            "platform": "Win 95+",
9898		 *            "version":  4,
9899		 *            "grade":    "X"
9900		 *          },
9901		 *          {
9902		 *            "engine":   "Trident",
9903		 *            "browser":  "Internet Explorer 5.0",
9904		 *            "platform": "Win 95+",
9905		 *            "version":  5,
9906		 *            "grade":    "C"
9907		 *          }
9908		 *        ],
9909		 *        "columns": [
9910		 *          { "title": "Engine",   "data": "engine" },
9911		 *          { "title": "Browser",  "data": "browser" },
9912		 *          { "title": "Platform", "data": "platform" },
9913		 *          { "title": "Version",  "data": "version" },
9914		 *          { "title": "Grade",    "data": "grade" }
9915		 *        ]
9916		 *      } );
9917		 *    } );
9918		 */
9919		"aaData": null,
9920	
9921	
9922		/**
9923		 * If ordering is enabled, then DataTables will perform a first pass sort on
9924		 * initialisation. You can define which column(s) the sort is performed
9925		 * upon, and the sorting direction, with this variable. The `sorting` array
9926		 * should contain an array for each column to be sorted initially containing
9927		 * the column's index and a direction string ('asc' or 'desc').
9928		 *  @type array
9929		 *  @default [[0,'asc']]
9930		 *
9931		 *  @dtopt Option
9932		 *  @name DataTable.defaults.order
9933		 *
9934		 *  @example
9935		 *    // Sort by 3rd column first, and then 4th column
9936		 *    $(document).ready( function() {
9937		 *      $('#example').dataTable( {
9938		 *        "order": [[2,'asc'], [3,'desc']]
9939		 *      } );
9940		 *    } );
9941		 *
9942		 *    // No initial sorting
9943		 *    $(document).ready( function() {
9944		 *      $('#example').dataTable( {
9945		 *        "order": []
9946		 *      } );
9947		 *    } );
9948		 */
9949		"aaSorting": [[0,'asc']],
9950	
9951	
9952		/**
9953		 * This parameter is basically identical to the `sorting` parameter, but
9954		 * cannot be overridden by user interaction with the table. What this means
9955		 * is that you could have a column (visible or hidden) which the sorting
9956		 * will always be forced on first - any sorting after that (from the user)
9957		 * will then be performed as required. This can be useful for grouping rows
9958		 * together.
9959		 *  @type array
9960		 *  @default null
9961		 *
9962		 *  @dtopt Option
9963		 *  @name DataTable.defaults.orderFixed
9964		 *
9965		 *  @example
9966		 *    $(document).ready( function() {
9967		 *      $('#example').dataTable( {
9968		 *        "orderFixed": [[0,'asc']]
9969		 *      } );
9970		 *    } )
9971		 */
9972		"aaSortingFixed": [],
9973	
9974	
9975		/**
9976		 * DataTables can be instructed to load data to display in the table from a
9977		 * Ajax source. This option defines how that Ajax call is made and where to.
9978		 *
9979		 * The `ajax` property has three different modes of operation, depending on
9980		 * how it is defined. These are:
9981		 *
9982		 * * `string` - Set the URL from where the data should be loaded from.
9983		 * * `object` - Define properties for `jQuery.ajax`.
9984		 * * `function` - Custom data get function
9985		 *
9986		 * `string`
9987		 * --------
9988		 *
9989		 * As a string, the `ajax` property simply defines the URL from which
9990		 * DataTables will load data.
9991		 *
9992		 * `object`
9993		 * --------
9994		 *
9995		 * As an object, the parameters in the object are passed to
9996		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9997		 * of the Ajax request. DataTables has a number of default parameters which
9998		 * you can override using this option. Please refer to the jQuery
9999		 * documentation for a full description of the options available, although
10000		 * the following parameters provide additional options in DataTables or
10001		 * require special consideration:
10002		 *
10003		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10004		 *   can also be used as a function to manipulate the data DataTables sends
10005		 *   to the server. The function takes a single parameter, an object of
10006		 *   parameters with the values that DataTables has readied for sending. An
10007		 *   object may be returned which will be merged into the DataTables
10008		 *   defaults, or you can add the items to the object that was passed in and
10009		 *   not return anything from the function. This supersedes `fnServerParams`
10010		 *   from DataTables 1.9-.
10011		 *
10012		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10013		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10014		 *   from an Ajax source or for server-side processing - this parameter
10015		 *   allows that property to be changed. You can use Javascript dotted
10016		 *   object notation to get a data source for multiple levels of nesting, or
10017		 *   it my be used as a function. As a function it takes a single parameter,
10018		 *   the JSON returned from the server, which can be manipulated as
10019		 *   required, with the returned value being that used by DataTables as the
10020		 *   data source for the table. This supersedes `sAjaxDataProp` from
10021		 *   DataTables 1.9-.
10022		 *
10023		 * * `success` - Should not be overridden it is used internally in
10024		 *   DataTables. To manipulate / transform the data returned by the server
10025		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10026		 *
10027		 * `function`
10028		 * ----------
10029		 *
10030		 * As a function, making the Ajax call is left up to yourself allowing
10031		 * complete control of the Ajax request. Indeed, if desired, a method other
10032		 * than Ajax could be used to obtain the required data, such as Web storage
10033		 * or an AIR database.
10034		 *
10035		 * The function is given four parameters and no return is required. The
10036		 * parameters are:
10037		 *
10038		 * 1. _object_ - Data to send to the server
10039		 * 2. _function_ - Callback function that must be executed when the required
10040		 *    data has been obtained. That data should be passed into the callback
10041		 *    as the only parameter
10042		 * 3. _object_ - DataTables settings object for the table
10043		 *
10044		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10045		 *
10046		 *  @type string|object|function
10047		 *  @default null
10048		 *
10049		 *  @dtopt Option
10050		 *  @name DataTable.defaults.ajax
10051		 *  @since 1.10.0
10052		 *
10053		 * @example
10054		 *   // Get JSON data from a file via Ajax.
10055		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10056		 *   $('#example').dataTable( {
10057		 *     "ajax": "data.json"
10058		 *   } );
10059		 *
10060		 * @example
10061		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10062		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10063		 *   $('#example').dataTable( {
10064		 *     "ajax": {
10065		 *       "url": "data.json",
10066		 *       "dataSrc": "tableData"
10067		 *     }
10068		 *   } );
10069		 *
10070		 * @example
10071		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10072		 *   // from a plain array rather than an array in an object
10073		 *   $('#example').dataTable( {
10074		 *     "ajax": {
10075		 *       "url": "data.json",
10076		 *       "dataSrc": ""
10077		 *     }
10078		 *   } );
10079		 *
10080		 * @example
10081		 *   // Manipulate the data returned from the server - add a link to data
10082		 *   // (note this can, should, be done using `render` for the column - this
10083		 *   // is just a simple example of how the data can be manipulated).
10084		 *   $('#example').dataTable( {
10085		 *     "ajax": {
10086		 *       "url": "data.json",
10087		 *       "dataSrc": function ( json ) {
10088		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10089		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10090		 *         }
10091		 *         return json;
10092		 *       }
10093		 *     }
10094		 *   } );
10095		 *
10096		 * @example
10097		 *   // Add data to the request
10098		 *   $('#example').dataTable( {
10099		 *     "ajax": {
10100		 *       "url": "data.json",
10101		 *       "data": function ( d ) {
10102		 *         return {
10103		 *           "extra_search": $('#extra').val()
10104		 *         };
10105		 *       }
10106		 *     }
10107		 *   } );
10108		 *
10109		 * @example
10110		 *   // Send request as POST
10111		 *   $('#example').dataTable( {
10112		 *     "ajax": {
10113		 *       "url": "data.json",
10114		 *       "type": "POST"
10115		 *     }
10116		 *   } );
10117		 *
10118		 * @example
10119		 *   // Get the data from localStorage (could interface with a form for
10120		 *   // adding, editing and removing rows).
10121		 *   $('#example').dataTable( {
10122		 *     "ajax": function (data, callback, settings) {
10123		 *       callback(
10124		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10125		 *       );
10126		 *     }
10127		 *   } );
10128		 */
10129		"ajax": null,
10130	
10131	
10132		/**
10133		 * This parameter allows you to readily specify the entries in the length drop
10134		 * down menu that DataTables shows when pagination is enabled. It can be
10135		 * either a 1D array of options which will be used for both the displayed
10136		 * option and the value, or a 2D array which will use the array in the first
10137		 * position as the value, and the array in the second position as the
10138		 * displayed options (useful for language strings such as 'All').
10139		 *
10140		 * Note that the `pageLength` property will be automatically set to the
10141		 * first value given in this array, unless `pageLength` is also provided.
10142		 *  @type array
10143		 *  @default [ 10, 25, 50, 100 ]
10144		 *
10145		 *  @dtopt Option
10146		 *  @name DataTable.defaults.lengthMenu
10147		 *
10148		 *  @example
10149		 *    $(document).ready( function() {
10150		 *      $('#example').dataTable( {
10151		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10152		 *      } );
10153		 *    } );
10154		 */
10155		"aLengthMenu": [ 10, 25, 50, 100 ],
10156	
10157	
10158		/**
10159		 * The `columns` option in the initialisation parameter allows you to define
10160		 * details about the way individual columns behave. For a full list of
10161		 * column options that can be set, please see
10162		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10163		 * define your columns, you must have an entry in the array for every single
10164		 * column that you have in your table (these can be null if you don't which
10165		 * to specify any options).
10166		 *  @member
10167		 *
10168		 *  @name DataTable.defaults.column
10169		 */
10170		"aoColumns": null,
10171	
10172		/**
10173		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10174		 * column, multiple columns, or all columns, using the `targets` property of
10175		 * each object in the array. This allows great flexibility when creating
10176		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10177		 * columns you specifically want. `columnDefs` may use any of the column
10178		 * options available: {@link DataTable.defaults.column}, but it _must_
10179		 * have `targets` defined in each object in the array. Values in the `targets`
10180		 * array may be:
10181		 *   <ul>
10182		 *     <li>a string - class name will be matched on the TH for the column</li>
10183		 *     <li>0 or a positive integer - column index counting from the left</li>
10184		 *     <li>a negative integer - column index counting from the right</li>
10185		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10186		 *   </ul>
10187		 *  @member
10188		 *
10189		 *  @name DataTable.defaults.columnDefs
10190		 */
10191		"aoColumnDefs": null,
10192	
10193	
10194		/**
10195		 * Basically the same as `search`, this parameter defines the individual column
10196		 * filtering state at initialisation time. The array must be of the same size
10197		 * as the number of columns, and each element be an object with the parameters
10198		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10199		 * accepted and the default will be used.
10200		 *  @type array
10201		 *  @default []
10202		 *
10203		 *  @dtopt Option
10204		 *  @name DataTable.defaults.searchCols
10205		 *
10206		 *  @example
10207		 *    $(document).ready( function() {
10208		 *      $('#example').dataTable( {
10209		 *        "searchCols": [
10210		 *          null,
10211		 *          { "search": "My filter" },
10212		 *          null,
10213		 *          { "search": "^[0-9]", "escapeRegex": false }
10214		 *        ]
10215		 *      } );
10216		 *    } )
10217		 */
10218		"aoSearchCols": [],
10219	
10220	
10221		/**
10222		 * An array of CSS classes that should be applied to displayed rows. This
10223		 * array may be of any length, and DataTables will apply each class
10224		 * sequentially, looping when required.
10225		 *  @type array
10226		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10227		 *    options</i>
10228		 *
10229		 *  @dtopt Option
10230		 *  @name DataTable.defaults.stripeClasses
10231		 *
10232		 *  @example
10233		 *    $(document).ready( function() {
10234		 *      $('#example').dataTable( {
10235		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10236		 *      } );
10237		 *    } )
10238		 */
10239		"asStripeClasses": null,
10240	
10241	
10242		/**
10243		 * Enable or disable automatic column width calculation. This can be disabled
10244		 * as an optimisation (it takes some time to calculate the widths) if the
10245		 * tables widths are passed in using `columns`.
10246		 *  @type boolean
10247		 *  @default true
10248		 *
10249		 *  @dtopt Features
10250		 *  @name DataTable.defaults.autoWidth
10251		 *
10252		 *  @example
10253		 *    $(document).ready( function () {
10254		 *      $('#example').dataTable( {
10255		 *        "autoWidth": false
10256		 *      } );
10257		 *    } );
10258		 */
10259		"bAutoWidth": true,
10260	
10261	
10262		/**
10263		 * Deferred rendering can provide DataTables with a huge speed boost when you
10264		 * are using an Ajax or JS data source for the table. This option, when set to
10265		 * true, will cause DataTables to defer the creation of the table elements for
10266		 * each row until they are needed for a draw - saving a significant amount of
10267		 * time.
10268		 *  @type boolean
10269		 *  @default false
10270		 *
10271		 *  @dtopt Features
10272		 *  @name DataTable.defaults.deferRender
10273		 *
10274		 *  @example
10275		 *    $(document).ready( function() {
10276		 *      $('#example').dataTable( {
10277		 *        "ajax": "sources/arrays.txt",
10278		 *        "deferRender": true
10279		 *      } );
10280		 *    } );
10281		 */
10282		"bDeferRender": false,
10283	
10284	
10285		/**
10286		 * Replace a DataTable which matches the given selector and replace it with
10287		 * one which has the properties of the new initialisation object passed. If no
10288		 * table matches the selector, then the new DataTable will be constructed as
10289		 * per normal.
10290		 *  @type boolean
10291		 *  @default false
10292		 *
10293		 *  @dtopt Options
10294		 *  @name DataTable.defaults.destroy
10295		 *
10296		 *  @example
10297		 *    $(document).ready( function() {
10298		 *      $('#example').dataTable( {
10299		 *        "srollY": "200px",
10300		 *        "paginate": false
10301		 *      } );
10302		 *
10303		 *      // Some time later....
10304		 *      $('#example').dataTable( {
10305		 *        "filter": false,
10306		 *        "destroy": true
10307		 *      } );
10308		 *    } );
10309		 */
10310		"bDestroy": false,
10311	
10312	
10313		/**
10314		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10315		 * that it allows the end user to input multiple words (space separated) and
10316		 * will match a row containing those words, even if not in the order that was
10317		 * specified (this allow matching across multiple columns). Note that if you
10318		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10319		 * default filtering input box and retain filtering abilities, please use
10320		 * {@link DataTable.defaults.dom}.
10321		 *  @type boolean
10322		 *  @default true
10323		 *
10324		 *  @dtopt Features
10325		 *  @name DataTable.defaults.searching
10326		 *
10327		 *  @example
10328		 *    $(document).ready( function () {
10329		 *      $('#example').dataTable( {
10330		 *        "searching": false
10331		 *      } );
10332		 *    } );
10333		 */
10334		"bFilter": true,
10335	
10336	
10337		/**
10338		 * Enable or disable the table information display. This shows information
10339		 * about the data that is currently visible on the page, including information
10340		 * about filtered data if that action is being performed.
10341		 *  @type boolean
10342		 *  @default true
10343		 *
10344		 *  @dtopt Features
10345		 *  @name DataTable.defaults.info
10346		 *
10347		 *  @example
10348		 *    $(document).ready( function () {
10349		 *      $('#example').dataTable( {
10350		 *        "info": false
10351		 *      } );
10352		 *    } );
10353		 */
10354		"bInfo": true,
10355	
10356	
10357		/**
10358		 * Allows the end user to select the size of a formatted page from a select
10359		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10360		 *  @type boolean
10361		 *  @default true
10362		 *
10363		 *  @dtopt Features
10364		 *  @name DataTable.defaults.lengthChange
10365		 *
10366		 *  @example
10367		 *    $(document).ready( function () {
10368		 *      $('#example').dataTable( {
10369		 *        "lengthChange": false
10370		 *      } );
10371		 *    } );
10372		 */
10373		"bLengthChange": true,
10374	
10375	
10376		/**
10377		 * Enable or disable pagination.
10378		 *  @type boolean
10379		 *  @default true
10380		 *
10381		 *  @dtopt Features
10382		 *  @name DataTable.defaults.paging
10383		 *
10384		 *  @example
10385		 *    $(document).ready( function () {
10386		 *      $('#example').dataTable( {
10387		 *        "paging": false
10388		 *      } );
10389		 *    } );
10390		 */
10391		"bPaginate": true,
10392	
10393	
10394		/**
10395		 * Enable or disable the display of a 'processing' indicator when the table is
10396		 * being processed (e.g. a sort). This is particularly useful for tables with
10397		 * large amounts of data where it can take a noticeable amount of time to sort
10398		 * the entries.
10399		 *  @type boolean
10400		 *  @default false
10401		 *
10402		 *  @dtopt Features
10403		 *  @name DataTable.defaults.processing
10404		 *
10405		 *  @example
10406		 *    $(document).ready( function () {
10407		 *      $('#example').dataTable( {
10408		 *        "processing": true
10409		 *      } );
10410		 *    } );
10411		 */
10412		"bProcessing": false,
10413	
10414	
10415		/**
10416		 * Retrieve the DataTables object for the given selector. Note that if the
10417		 * table has already been initialised, this parameter will cause DataTables
10418		 * to simply return the object that has already been set up - it will not take
10419		 * account of any changes you might have made to the initialisation object
10420		 * passed to DataTables (setting this parameter to true is an acknowledgement
10421		 * that you understand this). `destroy` can be used to reinitialise a table if
10422		 * you need.
10423		 *  @type boolean
10424		 *  @default false
10425		 *
10426		 *  @dtopt Options
10427		 *  @name DataTable.defaults.retrieve
10428		 *
10429		 *  @example
10430		 *    $(document).ready( function() {
10431		 *      initTable();
10432		 *      tableActions();
10433		 *    } );
10434		 *
10435		 *    function initTable ()
10436		 *    {
10437		 *      return $('#example').dataTable( {
10438		 *        "scrollY": "200px",
10439		 *        "paginate": false,
10440		 *        "retrieve": true
10441		 *      } );
10442		 *    }
10443		 *
10444		 *    function tableActions ()
10445		 *    {
10446		 *      var table = initTable();
10447		 *      // perform API operations with oTable
10448		 *    }
10449		 */
10450		"bRetrieve": false,
10451	
10452	
10453		/**
10454		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10455		 * the table's viewport to the given height at all times (useful for layout).
10456		 * However, this can look odd when filtering data down to a small data set,
10457		 * and the footer is left "floating" further down. This parameter (when
10458		 * enabled) will cause DataTables to collapse the table's viewport down when
10459		 * the result set will fit within the given Y height.
10460		 *  @type boolean
10461		 *  @default false
10462		 *
10463		 *  @dtopt Options
10464		 *  @name DataTable.defaults.scrollCollapse
10465		 *
10466		 *  @example
10467		 *    $(document).ready( function() {
10468		 *      $('#example').dataTable( {
10469		 *        "scrollY": "200",
10470		 *        "scrollCollapse": true
10471		 *      } );
10472		 *    } );
10473		 */
10474		"bScrollCollapse": false,
10475	
10476	
10477		/**
10478		 * Configure DataTables to use server-side processing. Note that the
10479		 * `ajax` parameter must also be given in order to give DataTables a
10480		 * source to obtain the required data for each draw.
10481		 *  @type boolean
10482		 *  @default false
10483		 *
10484		 *  @dtopt Features
10485		 *  @dtopt Server-side
10486		 *  @name DataTable.defaults.serverSide
10487		 *
10488		 *  @example
10489		 *    $(document).ready( function () {
10490		 *      $('#example').dataTable( {
10491		 *        "serverSide": true,
10492		 *        "ajax": "xhr.php"
10493		 *      } );
10494		 *    } );
10495		 */
10496		"bServerSide": false,
10497	
10498	
10499		/**
10500		 * Enable or disable sorting of columns. Sorting of individual columns can be
10501		 * disabled by the `sortable` option for each column.
10502		 *  @type boolean
10503		 *  @default true
10504		 *
10505		 *  @dtopt Features
10506		 *  @name DataTable.defaults.ordering
10507		 *
10508		 *  @example
10509		 *    $(document).ready( function () {
10510		 *      $('#example').dataTable( {
10511		 *        "ordering": false
10512		 *      } );
10513		 *    } );
10514		 */
10515		"bSort": true,
10516	
10517	
10518		/**
10519		 * Enable or display DataTables' ability to sort multiple columns at the
10520		 * same time (activated by shift-click by the user).
10521		 *  @type boolean
10522		 *  @default true
10523		 *
10524		 *  @dtopt Options
10525		 *  @name DataTable.defaults.orderMulti
10526		 *
10527		 *  @example
10528		 *    // Disable multiple column sorting ability
10529		 *    $(document).ready( function () {
10530		 *      $('#example').dataTable( {
10531		 *        "orderMulti": false
10532		 *      } );
10533		 *    } );
10534		 */
10535		"bSortMulti": true,
10536	
10537	
10538		/**
10539		 * Allows control over whether DataTables should use the top (true) unique
10540		 * cell that is found for a single column, or the bottom (false - default).
10541		 * This is useful when using complex headers.
10542		 *  @type boolean
10543		 *  @default false
10544		 *
10545		 *  @dtopt Options
10546		 *  @name DataTable.defaults.orderCellsTop
10547		 *
10548		 *  @example
10549		 *    $(document).ready( function() {
10550		 *      $('#example').dataTable( {
10551		 *        "orderCellsTop": true
10552		 *      } );
10553		 *    } );
10554		 */
10555		"bSortCellsTop": false,
10556	
10557	
10558		/**
10559		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10560		 * `sorting\_3` to the columns which are currently being sorted on. This is
10561		 * presented as a feature switch as it can increase processing time (while
10562		 * classes are removed and added) so for large data sets you might want to
10563		 * turn this off.
10564		 *  @type boolean
10565		 *  @default true
10566		 *
10567		 *  @dtopt Features
10568		 *  @name DataTable.defaults.orderClasses
10569		 *
10570		 *  @example
10571		 *    $(document).ready( function () {
10572		 *      $('#example').dataTable( {
10573		 *        "orderClasses": false
10574		 *      } );
10575		 *    } );
10576		 */
10577		"bSortClasses": true,
10578	
10579	
10580		/**
10581		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10582		 * used to save table display information such as pagination information,
10583		 * display length, filtering and sorting. As such when the end user reloads
10584		 * the page the display display will match what thy had previously set up.
10585		 *
10586		 * Due to the use of `localStorage` the default state saving is not supported
10587		 * in IE6 or 7. If state saving is required in those browsers, use
10588		 * `stateSaveCallback` to provide a storage solution such as cookies.
10589		 *  @type boolean
10590		 *  @default false
10591		 *
10592		 *  @dtopt Features
10593		 *  @name DataTable.defaults.stateSave
10594		 *
10595		 *  @example
10596		 *    $(document).ready( function () {
10597		 *      $('#example').dataTable( {
10598		 *        "stateSave": true
10599		 *      } );
10600		 *    } );
10601		 */
10602		"bStateSave": false,
10603	
10604	
10605		/**
10606		 * This function is called when a TR element is created (and all TD child
10607		 * elements have been inserted), or registered if using a DOM source, allowing
10608		 * manipulation of the TR element (adding classes etc).
10609		 *  @type function
10610		 *  @param {node} row "TR" element for the current row
10611		 *  @param {array} data Raw data array for this row
10612		 *  @param {int} dataIndex The index of this row in the internal aoData array
10613		 *
10614		 *  @dtopt Callbacks
10615		 *  @name DataTable.defaults.createdRow
10616		 *
10617		 *  @example
10618		 *    $(document).ready( function() {
10619		 *      $('#example').dataTable( {
10620		 *        "createdRow": function( row, data, dataIndex ) {
10621		 *          // Bold the grade for all 'A' grade browsers
10622		 *          if ( data[4] == "A" )
10623		 *          {
10624		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10625		 *          }
10626		 *        }
10627		 *      } );
10628		 *    } );
10629		 */
10630		"fnCreatedRow": null,
10631	
10632	
10633		/**
10634		 * This function is called on every 'draw' event, and allows you to
10635		 * dynamically modify any aspect you want about the created DOM.
10636		 *  @type function
10637		 *  @param {object} settings DataTables settings object
10638		 *
10639		 *  @dtopt Callbacks
10640		 *  @name DataTable.defaults.drawCallback
10641		 *
10642		 *  @example
10643		 *    $(document).ready( function() {
10644		 *      $('#example').dataTable( {
10645		 *        "drawCallback": function( settings ) {
10646		 *          alert( 'DataTables has redrawn the table' );
10647		 *        }
10648		 *      } );
10649		 *    } );
10650		 */
10651		"fnDrawCallback": null,
10652	
10653	
10654		/**
10655		 * Identical to fnHeaderCallback() but for the table footer this function
10656		 * allows you to modify the table footer on every 'draw' event.
10657		 *  @type function
10658		 *  @param {node} foot "TR" element for the footer
10659		 *  @param {array} data Full table data (as derived from the original HTML)
10660		 *  @param {int} start Index for the current display starting point in the
10661		 *    display array
10662		 *  @param {int} end Index for the current display ending point in the
10663		 *    display array
10664		 *  @param {array int} display Index array to translate the visual position
10665		 *    to the full data array
10666		 *
10667		 *  @dtopt Callbacks
10668		 *  @name DataTable.defaults.footerCallback
10669		 *
10670		 *  @example
10671		 *    $(document).ready( function() {
10672		 *      $('#example').dataTable( {
10673		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10674		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10675		 *        }
10676		 *      } );
10677		 *    } )
10678		 */
10679		"fnFooterCallback": null,
10680	
10681	
10682		/**
10683		 * When rendering large numbers in the information element for the table
10684		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10685		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10686		 * rendered as "1,000,000") to help readability for the end user. This
10687		 * function will override the default method DataTables uses.
10688		 *  @type function
10689		 *  @member
10690		 *  @param {int} toFormat number to be formatted
10691		 *  @returns {string} formatted string for DataTables to show the number
10692		 *
10693		 *  @dtopt Callbacks
10694		 *  @name DataTable.defaults.formatNumber
10695		 *
10696		 *  @example
10697		 *    // Format a number using a single quote for the separator (note that
10698		 *    // this can also be done with the language.thousands option)
10699		 *    $(document).ready( function() {
10700		 *      $('#example').dataTable( {
10701		 *        "formatNumber": function ( toFormat ) {
10702		 *          return toFormat.toString().replace(
10703		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10704		 *          );
10705		 *        };
10706		 *      } );
10707		 *    } );
10708		 */
10709		"fnFormatNumber": function ( toFormat ) {
10710			return toFormat.toString().replace(
10711				/\B(?=(\d{3})+(?!\d))/g,
10712				this.oLanguage.sThousands
10713			);
10714		},
10715	
10716	
10717		/**
10718		 * This function is called on every 'draw' event, and allows you to
10719		 * dynamically modify the header row. This can be used to calculate and
10720		 * display useful information about the table.
10721		 *  @type function
10722		 *  @param {node} head "TR" element for the header
10723		 *  @param {array} data Full table data (as derived from the original HTML)
10724		 *  @param {int} start Index for the current display starting point in the
10725		 *    display array
10726		 *  @param {int} end Index for the current display ending point in the
10727		 *    display array
10728		 *  @param {array int} display Index array to translate the visual position
10729		 *    to the full data array
10730		 *
10731		 *  @dtopt Callbacks
10732		 *  @name DataTable.defaults.headerCallback
10733		 *
10734		 *  @example
10735		 *    $(document).ready( function() {
10736		 *      $('#example').dataTable( {
10737		 *        "fheaderCallback": function( head, data, start, end, display ) {
10738		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10739		 *        }
10740		 *      } );
10741		 *    } )
10742		 */
10743		"fnHeaderCallback": null,
10744	
10745	
10746		/**
10747		 * The information element can be used to convey information about the current
10748		 * state of the table. Although the internationalisation options presented by
10749		 * DataTables are quite capable of dealing with most customisations, there may
10750		 * be times where you wish to customise the string further. This callback
10751		 * allows you to do exactly that.
10752		 *  @type function
10753		 *  @param {object} oSettings DataTables settings object
10754		 *  @param {int} start Starting position in data for the draw
10755		 *  @param {int} end End position in data for the draw
10756		 *  @param {int} max Total number of rows in the table (regardless of
10757		 *    filtering)
10758		 *  @param {int} total Total number of rows in the data set, after filtering
10759		 *  @param {string} pre The string that DataTables has formatted using it's
10760		 *    own rules
10761		 *  @returns {string} The string to be displayed in the information element.
10762		 *
10763		 *  @dtopt Callbacks
10764		 *  @name DataTable.defaults.infoCallback
10765		 *
10766		 *  @example
10767		 *    $('#example').dataTable( {
10768		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10769		 *        return start +" to "+ end;
10770		 *      }
10771		 *    } );
10772		 */
10773		"fnInfoCallback": null,
10774	
10775	
10776		/**
10777		 * Called when the table has been initialised. Normally DataTables will
10778		 * initialise sequentially and there will be no need for this function,
10779		 * however, this does not hold true when using external language information
10780		 * since that is obtained using an async XHR call.
10781		 *  @type function
10782		 *  @param {object} settings DataTables settings object
10783		 *  @param {object} json The JSON object request from the server - only
10784		 *    present if client-side Ajax sourced data is used
10785		 *
10786		 *  @dtopt Callbacks
10787		 *  @name DataTable.defaults.initComplete
10788		 *
10789		 *  @example
10790		 *    $(document).ready( function() {
10791		 *      $('#example').dataTable( {
10792		 *        "initComplete": function(settings, json) {
10793		 *          alert( 'DataTables has finished its initialisation.' );
10794		 *        }
10795		 *      } );
10796		 *    } )
10797		 */
10798		"fnInitComplete": null,
10799	
10800	
10801		/**
10802		 * Called at the very start of each table draw and can be used to cancel the
10803		 * draw by returning false, any other return (including undefined) results in
10804		 * the full draw occurring).
10805		 *  @type function
10806		 *  @param {object} settings DataTables settings object
10807		 *  @returns {boolean} False will cancel the draw, anything else (including no
10808		 *    return) will allow it to complete.
10809		 *
10810		 *  @dtopt Callbacks
10811		 *  @name DataTable.defaults.preDrawCallback
10812		 *
10813		 *  @example
10814		 *    $(document).ready( function() {
10815		 *      $('#example').dataTable( {
10816		 *        "preDrawCallback": function( settings ) {
10817		 *          if ( $('#test').val() == 1 ) {
10818		 *            return false;
10819		 *          }
10820		 *        }
10821		 *      } );
10822		 *    } );
10823		 */
10824		"fnPreDrawCallback": null,
10825	
10826	
10827		/**
10828		 * This function allows you to 'post process' each row after it have been
10829		 * generated for each table draw, but before it is rendered on screen. This
10830		 * function might be used for setting the row class name etc.
10831		 *  @type function
10832		 *  @param {node} row "TR" element for the current row
10833		 *  @param {array} data Raw data array for this row
10834		 *  @param {int} displayIndex The display index for the current table draw
10835		 *  @param {int} displayIndexFull The index of the data in the full list of
10836		 *    rows (after filtering)
10837		 *
10838		 *  @dtopt Callbacks
10839		 *  @name DataTable.defaults.rowCallback
10840		 *
10841		 *  @example
10842		 *    $(document).ready( function() {
10843		 *      $('#example').dataTable( {
10844		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10845		 *          // Bold the grade for all 'A' grade browsers
10846		 *          if ( data[4] == "A" ) {
10847		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10848		 *          }
10849		 *        }
10850		 *      } );
10851		 *    } );
10852		 */
10853		"fnRowCallback": null,
10854	
10855	
10856		/**
10857		 * __Deprecated__ The functionality provided by this parameter has now been
10858		 * superseded by that provided through `ajax`, which should be used instead.
10859		 *
10860		 * This parameter allows you to override the default function which obtains
10861		 * the data from the server so something more suitable for your application.
10862		 * For example you could use POST data, or pull information from a Gears or
10863		 * AIR database.
10864		 *  @type function
10865		 *  @member
10866		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10867		 *  @param {array} data A key/value pair object containing the data to send
10868		 *    to the server
10869		 *  @param {function} callback to be called on completion of the data get
10870		 *    process that will draw the data on the page.
10871		 *  @param {object} settings DataTables settings object
10872		 *
10873		 *  @dtopt Callbacks
10874		 *  @dtopt Server-side
10875		 *  @name DataTable.defaults.serverData
10876		 *
10877		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10878		 */
10879		"fnServerData": null,
10880	
10881	
10882		/**
10883		 * __Deprecated__ The functionality provided by this parameter has now been
10884		 * superseded by that provided through `ajax`, which should be used instead.
10885		 *
10886		 *  It is often useful to send extra data to the server when making an Ajax
10887		 * request - for example custom filtering information, and this callback
10888		 * function makes it trivial to send extra information to the server. The
10889		 * passed in parameter is the data set that has been constructed by
10890		 * DataTables, and you can add to this or modify it as you require.
10891		 *  @type function
10892		 *  @param {array} data Data array (array of objects which are name/value
10893		 *    pairs) that has been constructed by DataTables and will be sent to the
10894		 *    server. In the case of Ajax sourced data with server-side processing
10895		 *    this will be an empty array, for server-side processing there will be a
10896		 *    significant number of parameters!
10897		 *  @returns {undefined} Ensure that you modify the data array passed in,
10898		 *    as this is passed by reference.
10899		 *
10900		 *  @dtopt Callbacks
10901		 *  @dtopt Server-side
10902		 *  @name DataTable.defaults.serverParams
10903		 *
10904		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10905		 */
10906		"fnServerParams": null,
10907	
10908	
10909		/**
10910		 * Load the table state. With this function you can define from where, and how, the
10911		 * state of a table is loaded. By default DataTables will load from `localStorage`
10912		 * but you might wish to use a server-side database or cookies.
10913		 *  @type function
10914		 *  @member
10915		 *  @param {object} settings DataTables settings object
10916		 *  @param {object} callback Callback that can be executed when done. It
10917		 *    should be passed the loaded state object.
10918		 *  @return {object} The DataTables state object to be loaded
10919		 *
10920		 *  @dtopt Callbacks
10921		 *  @name DataTable.defaults.stateLoadCallback
10922		 *
10923		 *  @example
10924		 *    $(document).ready( function() {
10925		 *      $('#example').dataTable( {
10926		 *        "stateSave": true,
10927		 *        "stateLoadCallback": function (settings, callback) {
10928		 *          $.ajax( {
10929		 *            "url": "/state_load",
10930		 *            "dataType": "json",
10931		 *            "success": function (json) {
10932		 *              callback( json );
10933		 *            }
10934		 *          } );
10935		 *        }
10936		 *      } );
10937		 *    } );
10938		 */
10939		"fnStateLoadCallback": function ( settings ) {
10940			try {
10941				return JSON.parse(
10942					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10943						'DataTables_'+settings.sInstance+'_'+location.pathname
10944					)
10945				);
10946			} catch (e) {}
10947		},
10948	
10949	
10950		/**
10951		 * Callback which allows modification of the saved state prior to loading that state.
10952		 * This callback is called when the table is loading state from the stored data, but
10953		 * prior to the settings object being modified by the saved state. Note that for
10954		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10955		 * a plug-in.
10956		 *  @type function
10957		 *  @param {object} settings DataTables settings object
10958		 *  @param {object} data The state object that is to be loaded
10959		 *
10960		 *  @dtopt Callbacks
10961		 *  @name DataTable.defaults.stateLoadParams
10962		 *
10963		 *  @example
10964		 *    // Remove a saved filter, so filtering is never loaded
10965		 *    $(document).ready( function() {
10966		 *      $('#example').dataTable( {
10967		 *        "stateSave": true,
10968		 *        "stateLoadParams": function (settings, data) {
10969		 *          data.oSearch.sSearch = "";
10970		 *        }
10971		 *      } );
10972		 *    } );
10973		 *
10974		 *  @example
10975		 *    // Disallow state loading by returning false
10976		 *    $(document).ready( function() {
10977		 *      $('#example').dataTable( {
10978		 *        "stateSave": true,
10979		 *        "stateLoadParams": function (settings, data) {
10980		 *          return false;
10981		 *        }
10982		 *      } );
10983		 *    } );
10984		 */
10985		"fnStateLoadParams": null,
10986	
10987	
10988		/**
10989		 * Callback that is called when the state has been loaded from the state saving method
10990		 * and the DataTables settings object has been modified as a result of the loaded state.
10991		 *  @type function
10992		 *  @param {object} settings DataTables settings object
10993		 *  @param {object} data The state object that was loaded
10994		 *
10995		 *  @dtopt Callbacks
10996		 *  @name DataTable.defaults.stateLoaded
10997		 *
10998		 *  @example
10999		 *    // Show an alert with the filtering value that was saved
11000		 *    $(document).ready( function() {
11001		 *      $('#example').dataTable( {
11002		 *        "stateSave": true,
11003		 *        "stateLoaded": function (settings, data) {
11004		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11005		 *        }
11006		 *      } );
11007		 *    } );
11008		 */
11009		"fnStateLoaded": null,
11010	
11011	
11012		/**
11013		 * Save the table state. This function allows you to define where and how the state
11014		 * information for the table is stored By default DataTables will use `localStorage`
11015		 * but you might wish to use a server-side database or cookies.
11016		 *  @type function
11017		 *  @member
11018		 *  @param {object} settings DataTables settings object
11019		 *  @param {object} data The state object to be saved
11020		 *
11021		 *  @dtopt Callbacks
11022		 *  @name DataTable.defaults.stateSaveCallback
11023		 *
11024		 *  @example
11025		 *    $(document).ready( function() {
11026		 *      $('#example').dataTable( {
11027		 *        "stateSave": true,
11028		 *        "stateSaveCallback": function (settings, data) {
11029		 *          // Send an Ajax request to the server with the state object
11030		 *          $.ajax( {
11031		 *            "url": "/state_save",
11032		 *            "data": data,
11033		 *            "dataType": "json",
11034		 *            "method": "POST"
11035		 *            "success": function () {}
11036		 *          } );
11037		 *        }
11038		 *      } );
11039		 *    } );
11040		 */
11041		"fnStateSaveCallback": function ( settings, data ) {
11042			try {
11043				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11044					'DataTables_'+settings.sInstance+'_'+location.pathname,
11045					JSON.stringify( data )
11046				);
11047			} catch (e) {}
11048		},
11049	
11050	
11051		/**
11052		 * Callback which allows modification of the state to be saved. Called when the table
11053		 * has changed state a new state save is required. This method allows modification of
11054		 * the state saving object prior to actually doing the save, including addition or
11055		 * other state properties or modification. Note that for plug-in authors, you should
11056		 * use the `stateSaveParams` event to save parameters for a plug-in.
11057		 *  @type function
11058		 *  @param {object} settings DataTables settings object
11059		 *  @param {object} data The state object to be saved
11060		 *
11061		 *  @dtopt Callbacks
11062		 *  @name DataTable.defaults.stateSaveParams
11063		 *
11064		 *  @example
11065		 *    // Remove a saved filter, so filtering is never saved
11066		 *    $(document).ready( function() {
11067		 *      $('#example').dataTable( {
11068		 *        "stateSave": true,
11069		 *        "stateSaveParams": function (settings, data) {
11070		 *          data.oSearch.sSearch = "";
11071		 *        }
11072		 *      } );
11073		 *    } );
11074		 */
11075		"fnStateSaveParams": null,
11076	
11077	
11078		/**
11079		 * Duration for which the saved state information is considered valid. After this period
11080		 * has elapsed the state will be returned to the default.
11081		 * Value is given in seconds.
11082		 *  @type int
11083		 *  @default 7200 <i>(2 hours)</i>
11084		 *
11085		 *  @dtopt Options
11086		 *  @name DataTable.defaults.stateDuration
11087		 *
11088		 *  @example
11089		 *    $(document).ready( function() {
11090		 *      $('#example').dataTable( {
11091		 *        "stateDuration": 60*60*24; // 1 day
11092		 *      } );
11093		 *    } )
11094		 */
11095		"iStateDuration": 7200,
11096	
11097	
11098		/**
11099		 * When enabled DataTables will not make a request to the server for the first
11100		 * page draw - rather it will use the data already on the page (no sorting etc
11101		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11102		 * is used to indicate that deferred loading is required, but it is also used
11103		 * to tell DataTables how many records there are in the full table (allowing
11104		 * the information element and pagination to be displayed correctly). In the case
11105		 * where a filtering is applied to the table on initial load, this can be
11106		 * indicated by giving the parameter as an array, where the first element is
11107		 * the number of records available after filtering and the second element is the
11108		 * number of records without filtering (allowing the table information element
11109		 * to be shown correctly).
11110		 *  @type int | array
11111		 *  @default null
11112		 *
11113		 *  @dtopt Options
11114		 *  @name DataTable.defaults.deferLoading
11115		 *
11116		 *  @example
11117		 *    // 57 records available in the table, no filtering applied
11118		 *    $(document).ready( function() {
11119		 *      $('#example').dataTable( {
11120		 *        "serverSide": true,
11121		 *        "ajax": "scripts/server_processing.php",
11122		 *        "deferLoading": 57
11123		 *      } );
11124		 *    } );
11125		 *
11126		 *  @example
11127		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11128		 *    $(document).ready( function() {
11129		 *      $('#example').dataTable( {
11130		 *        "serverSide": true,
11131		 *        "ajax": "scripts/server_processing.php",
11132		 *        "deferLoading": [ 57, 100 ],
11133		 *        "search": {
11134		 *          "search": "my_filter"
11135		 *        }
11136		 *      } );
11137		 *    } );
11138		 */
11139		"iDeferLoading": null,
11140	
11141	
11142		/**
11143		 * Number of rows to display on a single page when using pagination. If
11144		 * feature enabled (`lengthChange`) then the end user will be able to override
11145		 * this to a custom setting using a pop-up menu.
11146		 *  @type int
11147		 *  @default 10
11148		 *
11149		 *  @dtopt Options
11150		 *  @name DataTable.defaults.pageLength
11151		 *
11152		 *  @example
11153		 *    $(document).ready( function() {
11154		 *      $('#example').dataTable( {
11155		 *        "pageLength": 50
11156		 *      } );
11157		 *    } )
11158		 */
11159		"iDisplayLength": 10,
11160	
11161	
11162		/**
11163		 * Define the starting point for data display when using DataTables with
11164		 * pagination. Note that this parameter is the number of records, rather than
11165		 * the page number, so if you have 10 records per page and want to start on
11166		 * the third page, it should be "20".
11167		 *  @type int
11168		 *  @default 0
11169		 *
11170		 *  @dtopt Options
11171		 *  @name DataTable.defaults.displayStart
11172		 *
11173		 *  @example
11174		 *    $(document).ready( function() {
11175		 *      $('#example').dataTable( {
11176		 *        "displayStart": 20
11177		 *      } );
11178		 *    } )
11179		 */
11180		"iDisplayStart": 0,
11181	
11182	
11183		/**
11184		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11185		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11186		 * allows you to tab through the controls and press the enter key to activate them.
11187		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11188		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11189		 * disable built-in keyboard navigation.
11190		 *  @type int
11191		 *  @default 0
11192		 *
11193		 *  @dtopt Options
11194		 *  @name DataTable.defaults.tabIndex
11195		 *
11196		 *  @example
11197		 *    $(document).ready( function() {
11198		 *      $('#example').dataTable( {
11199		 *        "tabIndex": 1
11200		 *      } );
11201		 *    } );
11202		 */
11203		"iTabIndex": 0,
11204	
11205	
11206		/**
11207		 * Classes that DataTables assigns to the various components and features
11208		 * that it adds to the HTML table. This allows classes to be configured
11209		 * during initialisation in addition to through the static
11210		 * {@link DataTable.ext.oStdClasses} object).
11211		 *  @namespace
11212		 *  @name DataTable.defaults.classes
11213		 */
11214		"oClasses": {},
11215	
11216	
11217		/**
11218		 * All strings that DataTables uses in the user interface that it creates
11219		 * are defined in this object, allowing you to modified them individually or
11220		 * completely replace them all as required.
11221		 *  @namespace
11222		 *  @name DataTable.defaults.language
11223		 */
11224		"oLanguage": {
11225			/**
11226			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11227			 * actually visible on the page, but will be read by screenreaders, and thus
11228			 * must be internationalised as well).
11229			 *  @namespace
11230			 *  @name DataTable.defaults.language.aria
11231			 */
11232			"oAria": {
11233				/**
11234				 * ARIA label that is added to the table headers when the column may be
11235				 * sorted ascending by activing the column (click or return when focused).
11236				 * Note that the column header is prefixed to this string.
11237				 *  @type string
11238				 *  @default : activate to sort column ascending
11239				 *
11240				 *  @dtopt Language
11241				 *  @name DataTable.defaults.language.aria.sortAscending
11242				 *
11243				 *  @example
11244				 *    $(document).ready( function() {
11245				 *      $('#example').dataTable( {
11246				 *        "language": {
11247				 *          "aria": {
11248				 *            "sortAscending": " - click/return to sort ascending"
11249				 *          }
11250				 *        }
11251				 *      } );
11252				 *    } );
11253				 */
11254				"sSortAscending": ": activate to sort column ascending",
11255	
11256				/**
11257				 * ARIA label that is added to the table headers when the column may be
11258				 * sorted descending by activing the column (click or return when focused).
11259				 * Note that the column header is prefixed to this string.
11260				 *  @type string
11261				 *  @default : activate to sort column ascending
11262				 *
11263				 *  @dtopt Language
11264				 *  @name DataTable.defaults.language.aria.sortDescending
11265				 *
11266				 *  @example
11267				 *    $(document).ready( function() {
11268				 *      $('#example').dataTable( {
11269				 *        "language": {
11270				 *          "aria": {
11271				 *            "sortDescending": " - click/return to sort descending"
11272				 *          }
11273				 *        }
11274				 *      } );
11275				 *    } );
11276				 */
11277				"sSortDescending": ": activate to sort column descending"
11278			},
11279	
11280			/**
11281			 * Pagination string used by DataTables for the built-in pagination
11282			 * control types.
11283			 *  @namespace
11284			 *  @name DataTable.defaults.language.paginate
11285			 */
11286			"oPaginate": {
11287				/**
11288				 * Text to use when using the 'full_numbers' type of pagination for the
11289				 * button to take the user to the first page.
11290				 *  @type string
11291				 *  @default First
11292				 *
11293				 *  @dtopt Language
11294				 *  @name DataTable.defaults.language.paginate.first
11295				 *
11296				 *  @example
11297				 *    $(document).ready( function() {
11298				 *      $('#example').dataTable( {
11299				 *        "language": {
11300				 *          "paginate": {
11301				 *            "first": "First page"
11302				 *          }
11303				 *        }
11304				 *      } );
11305				 *    } );
11306				 */
11307				"sFirst": "First",
11308	
11309	
11310				/**
11311				 * Text to use when using the 'full_numbers' type of pagination for the
11312				 * button to take the user to the last page.
11313				 *  @type string
11314				 *  @default Last
11315				 *
11316				 *  @dtopt Language
11317				 *  @name DataTable.defaults.language.paginate.last
11318				 *
11319				 *  @example
11320				 *    $(document).ready( function() {
11321				 *      $('#example').dataTable( {
11322				 *        "language": {
11323				 *          "paginate": {
11324				 *            "last": "Last page"
11325				 *          }
11326				 *        }
11327				 *      } );
11328				 *    } );
11329				 */
11330				"sLast": "Last",
11331	
11332	
11333				/**
11334				 * Text to use for the 'next' pagination button (to take the user to the
11335				 * next page).
11336				 *  @type string
11337				 *  @default Next
11338				 *
11339				 *  @dtopt Language
11340				 *  @name DataTable.defaults.language.paginate.next
11341				 *
11342				 *  @example
11343				 *    $(document).ready( function() {
11344				 *      $('#example').dataTable( {
11345				 *        "language": {
11346				 *          "paginate": {
11347				 *            "next": "Next page"
11348				 *          }
11349				 *        }
11350				 *      } );
11351				 *    } );
11352				 */
11353				"sNext": "Next",
11354	
11355	
11356				/**
11357				 * Text to use for the 'previous' pagination button (to take the user to
11358				 * the previous page).
11359				 *  @type string
11360				 *  @default Previous
11361				 *
11362				 *  @dtopt Language
11363				 *  @name DataTable.defaults.language.paginate.previous
11364				 *
11365				 *  @example
11366				 *    $(document).ready( function() {
11367				 *      $('#example').dataTable( {
11368				 *        "language": {
11369				 *          "paginate": {
11370				 *            "previous": "Previous page"
11371				 *          }
11372				 *        }
11373				 *      } );
11374				 *    } );
11375				 */
11376				"sPrevious": "Previous"
11377			},
11378	
11379			/**
11380			 * This string is shown in preference to `zeroRecords` when the table is
11381			 * empty of data (regardless of filtering). Note that this is an optional
11382			 * parameter - if it is not given, the value of `zeroRecords` will be used
11383			 * instead (either the default or given value).
11384			 *  @type string
11385			 *  @default No data available in table
11386			 *
11387			 *  @dtopt Language
11388			 *  @name DataTable.defaults.language.emptyTable
11389			 *
11390			 *  @example
11391			 *    $(document).ready( function() {
11392			 *      $('#example').dataTable( {
11393			 *        "language": {
11394			 *          "emptyTable": "No data available in table"
11395			 *        }
11396			 *      } );
11397			 *    } );
11398			 */
11399			"sEmptyTable": "No data available in table",
11400	
11401	
11402			/**
11403			 * This string gives information to the end user about the information
11404			 * that is current on display on the page. The following tokens can be
11405			 * used in the string and will be dynamically replaced as the table
11406			 * display updates. This tokens can be placed anywhere in the string, or
11407			 * removed as needed by the language requires:
11408			 *
11409			 * * `\_START\_` - Display index of the first record on the current page
11410			 * * `\_END\_` - Display index of the last record on the current page
11411			 * * `\_TOTAL\_` - Number of records in the table after filtering
11412			 * * `\_MAX\_` - Number of records in the table without filtering
11413			 * * `\_PAGE\_` - Current page number
11414			 * * `\_PAGES\_` - Total number of pages of data in the table
11415			 *
11416			 *  @type string
11417			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11418			 *
11419			 *  @dtopt Language
11420			 *  @name DataTable.defaults.language.info
11421			 *
11422			 *  @example
11423			 *    $(document).ready( function() {
11424			 *      $('#example').dataTable( {
11425			 *        "language": {
11426			 *          "info": "Showing page _PAGE_ of _PAGES_"
11427			 *        }
11428			 *      } );
11429			 *    } );
11430			 */
11431			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11432	
11433	
11434			/**
11435			 * Display information string for when the table is empty. Typically the
11436			 * format of this string should match `info`.
11437			 *  @type string
11438			 *  @default Showing 0 to 0 of 0 entries
11439			 *
11440			 *  @dtopt Language
11441			 *  @name DataTable.defaults.language.infoEmpty
11442			 *
11443			 *  @example
11444			 *    $(document).ready( function() {
11445			 *      $('#example').dataTable( {
11446			 *        "language": {
11447			 *          "infoEmpty": "No entries to show"
11448			 *        }
11449			 *      } );
11450			 *    } );
11451			 */
11452			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11453	
11454	
11455			/**
11456			 * When a user filters the information in a table, this string is appended
11457			 * to the information (`info`) to give an idea of how strong the filtering
11458			 * is. The variable _MAX_ is dynamically updated.
11459			 *  @type string
11460			 *  @default (filtered from _MAX_ total entries)
11461			 *
11462			 *  @dtopt Language
11463			 *  @name DataTable.defaults.language.infoFiltered
11464			 *
11465			 *  @example
11466			 *    $(document).ready( function() {
11467			 *      $('#example').dataTable( {
11468			 *        "language": {
11469			 *          "infoFiltered": " - filtering from _MAX_ records"
11470			 *        }
11471			 *      } );
11472			 *    } );
11473			 */
11474			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11475	
11476	
11477			/**
11478			 * If can be useful to append extra information to the info string at times,
11479			 * and this variable does exactly that. This information will be appended to
11480			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11481			 * being used) at all times.
11482			 *  @type string
11483			 *  @default <i>Empty string</i>
11484			 *
11485			 *  @dtopt Language
11486			 *  @name DataTable.defaults.language.infoPostFix
11487			 *
11488			 *  @example
11489			 *    $(document).ready( function() {
11490			 *      $('#example').dataTable( {
11491			 *        "language": {
11492			 *          "infoPostFix": "All records shown are derived from real information."
11493			 *        }
11494			 *      } );
11495			 *    } );
11496			 */
11497			"sInfoPostFix": "",
11498	
11499	
11500			/**
11501			 * This decimal place operator is a little different from the other
11502			 * language options since DataTables doesn't output floating point
11503			 * numbers, so it won't ever use this for display of a number. Rather,
11504			 * what this parameter does is modify the sort methods of the table so
11505			 * that numbers which are in a format which has a character other than
11506			 * a period (`.`) as a decimal place will be sorted numerically.
11507			 *
11508			 * Note that numbers with different decimal places cannot be shown in
11509			 * the same table and still be sortable, the table must be consistent.
11510			 * However, multiple different tables on the page can use different
11511			 * decimal place characters.
11512			 *  @type string
11513			 *  @default 
11514			 *
11515			 *  @dtopt Language
11516			 *  @name DataTable.defaults.language.decimal
11517			 *
11518			 *  @example
11519			 *    $(document).ready( function() {
11520			 *      $('#example').dataTable( {
11521			 *        "language": {
11522			 *          "decimal": ","
11523			 *          "thousands": "."
11524			 *        }
11525			 *      } );
11526			 *    } );
11527			 */
11528			"sDecimal": "",
11529	
11530	
11531			/**
11532			 * DataTables has a build in number formatter (`formatNumber`) which is
11533			 * used to format large numbers that are used in the table information.
11534			 * By default a comma is used, but this can be trivially changed to any
11535			 * character you wish with this parameter.
11536			 *  @type string
11537			 *  @default ,
11538			 *
11539			 *  @dtopt Language
11540			 *  @name DataTable.defaults.language.thousands
11541			 *
11542			 *  @example
11543			 *    $(document).ready( function() {
11544			 *      $('#example').dataTable( {
11545			 *        "language": {
11546			 *          "thousands": "'"
11547			 *        }
11548			 *      } );
11549			 *    } );
11550			 */
11551			"sThousands": ",",
11552	
11553	
11554			/**
11555			 * Detail the action that will be taken when the drop down menu for the
11556			 * pagination length option is changed. The '_MENU_' variable is replaced
11557			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11558			 * with a custom select box if required.
11559			 *  @type string
11560			 *  @default Show _MENU_ entries
11561			 *
11562			 *  @dtopt Language
11563			 *  @name DataTable.defaults.language.lengthMenu
11564			 *
11565			 *  @example
11566			 *    // Language change only
11567			 *    $(document).ready( function() {
11568			 *      $('#example').dataTable( {
11569			 *        "language": {
11570			 *          "lengthMenu": "Display _MENU_ records"
11571			 *        }
11572			 *      } );
11573			 *    } );
11574			 *
11575			 *  @example
11576			 *    // Language and options change
11577			 *    $(document).ready( function() {
11578			 *      $('#example').dataTable( {
11579			 *        "language": {
11580			 *          "lengthMenu": 'Display <select>'+
11581			 *            '<option value="10">10</option>'+
11582			 *            '<option value="20">20</option>'+
11583			 *            '<option value="30">30</option>'+
11584			 *            '<option value="40">40</option>'+
11585			 *            '<option value="50">50</option>'+
11586			 *            '<option value="-1">All</option>'+
11587			 *            '</select> records'
11588			 *        }
11589			 *      } );
11590			 *    } );
11591			 */
11592			"sLengthMenu": "Show _MENU_ entries",
11593	
11594	
11595			/**
11596			 * When using Ajax sourced data and during the first draw when DataTables is
11597			 * gathering the data, this message is shown in an empty row in the table to
11598			 * indicate to the end user the the data is being loaded. Note that this
11599			 * parameter is not used when loading data by server-side processing, just
11600			 * Ajax sourced data with client-side processing.
11601			 *  @type string
11602			 *  @default Loading...
11603			 *
11604			 *  @dtopt Language
11605			 *  @name DataTable.defaults.language.loadingRecords
11606			 *
11607			 *  @example
11608			 *    $(document).ready( function() {
11609			 *      $('#example').dataTable( {
11610			 *        "language": {
11611			 *          "loadingRecords": "Please wait - loading..."
11612			 *        }
11613			 *      } );
11614			 *    } );
11615			 */
11616			"sLoadingRecords": "Loading...",
11617	
11618	
11619			/**
11620			 * Text which is displayed when the table is processing a user action
11621			 * (usually a sort command or similar).
11622			 *  @type string
11623			 *
11623  @default Processing...
11624			 *
11625			 *  @dtopt Language
11626			 *  @name DataTable.defaults.language.processing
11627			 *
11628			 *  @example
11629			 *    $(document).ready( function() {
11630			 *      $('#example').dataTable( {
11631			 *        "language": {
11632			 *          "processing": "DataTables is currently busy"
11633			 *        }
11634			 *      } );
11635			 *    } );
11636			 */
11637			"sProcessing": "Processing...
vendor: 24,082 bytes, lines 11637-12366
11637",
11638	
11639	
11640			/**
11641			 * Details the actions that will be taken when the user types into the
11642			 * filtering input text box. The variable "_INPUT_", if used in the string,
11643			 * is replaced with the HTML text box for the filtering input allowing
11644			 * control over where it appears in the string. If "_INPUT_" is not given
11645			 * then the input box is appended to the string automatically.
11646			 *  @type string
11647			 *  @default Search:
11648			 *
11649			 *  @dtopt Language
11650			 *  @name DataTable.defaults.language.search
11651			 *
11652			 *  @example
11653			 *    // Input text box will be appended at the end automatically
11654			 *    $(document).ready( function() {
11655			 *      $('#example').dataTable( {
11656			 *        "language": {
11657			 *          "search": "Filter records:"
11658			 *        }
11659			 *      } );
11660			 *    } );
11661			 *
11662			 *  @example
11663			 *    // Specify where the filter should appear
11664			 *    $(document).ready( function() {
11665			 *      $('#example').dataTable( {
11666			 *        "language": {
11667			 *          "search": "Apply filter _INPUT_ to table"
11668			 *        }
11669			 *      } );
11670			 *    } );
11671			 */
11672			"sSearch": "Search:",
11673	
11674	
11675			/**
11676			 * Assign a `placeholder` attribute to the search `input` element
11677			 *  @type string
11678			 *  @default 
11679			 *
11680			 *  @dtopt Language
11681			 *  @name DataTable.defaults.language.searchPlaceholder
11682			 */
11683			"sSearchPlaceholder": "",
11684	
11685	
11686			/**
11687			 * All of the language information can be stored in a file on the
11688			 * server-side, which DataTables will look up if this parameter is passed.
11689			 * It must store the URL of the language file, which is in a JSON format,
11690			 * and the object has the same properties as the oLanguage object in the
11691			 * initialiser object (i.e. the above parameters). Please refer to one of
11692			 * the example language files to see how this works in action.
11693			 *  @type string
11694			 *  @default <i>Empty string - i.e. disabled</i>
11695			 *
11696			 *  @dtopt Language
11697			 *  @name DataTable.defaults.language.url
11698			 *
11699			 *  @example
11700			 *    $(document).ready( function() {
11701			 *      $('#example').dataTable( {
11702			 *        "language": {
11703			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11704			 *        }
11705			 *      } );
11706			 *    } );
11707			 */
11708			"sUrl": "",
11709	
11710	
11711			/**
11712			 * Text shown inside the table records when the is no information to be
11713			 * displayed after filtering. `emptyTable` is shown when there is simply no
11714			 * information in the table at all (regardless of filtering).
11715			 *  @type string
11716			 *  @default No matching records found
11717			 *
11718			 *  @dtopt Language
11719			 *  @name DataTable.defaults.language.zeroRecords
11720			 *
11721			 *  @example
11722			 *    $(document).ready( function() {
11723			 *      $('#example').dataTable( {
11724			 *        "language": {
11725			 *          "zeroRecords": "No records to display"
11726			 *        }
11727			 *      } );
11728			 *    } );
11729			 */
11730			"sZeroRecords": "No matching records found"
11731		},
11732	
11733	
11734		/**
11735		 * This parameter allows you to have define the global filtering state at
11736		 * initialisation time. As an object the `search` parameter must be
11737		 * defined, but all other parameters are optional. When `regex` is true,
11738		 * the search string will be treated as a regular expression, when false
11739		 * (default) it will be treated as a straight string. When `smart`
11740		 * DataTables will use it's smart filtering methods (to word match at
11741		 * any point in the data), when false this will not be done.
11742		 *  @namespace
11743		 *  @extends DataTable.models.oSearch
11744		 *
11745		 *  @dtopt Options
11746		 *  @name DataTable.defaults.search
11747		 *
11748		 *  @example
11749		 *    $(document).ready( function() {
11750		 *      $('#example').dataTable( {
11751		 *        "search": {"search": "Initial search"}
11752		 *      } );
11753		 *    } )
11754		 */
11755		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11756	
11757	
11758		/**
11759		 * __Deprecated__ The functionality provided by this parameter has now been
11760		 * superseded by that provided through `ajax`, which should be used instead.
11761		 *
11762		 * By default DataTables will look for the property `data` (or `aaData` for
11763		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11764		 * source or for server-side processing - this parameter allows that
11765		 * property to be changed. You can use Javascript dotted object notation to
11766		 * get a data source for multiple levels of nesting.
11767		 *  @type string
11768		 *  @default data
11769		 *
11770		 *  @dtopt Options
11771		 *  @dtopt Server-side
11772		 *  @name DataTable.defaults.ajaxDataProp
11773		 *
11774		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11775		 */
11776		"sAjaxDataProp": "data",
11777	
11778	
11779		/**
11780		 * __Deprecated__ The functionality provided by this parameter has now been
11781		 * superseded by that provided through `ajax`, which should be used instead.
11782		 *
11783		 * You can instruct DataTables to load data from an external
11784		 * source using this parameter (use aData if you want to pass data in you
11785		 * already have). Simply provide a url a JSON object can be obtained from.
11786		 *  @type string
11787		 *  @default null
11788		 *
11789		 *  @dtopt Options
11790		 *  @dtopt Server-side
11791		 *  @name DataTable.defaults.ajaxSource
11792		 *
11793		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11794		 */
11795		"sAjaxSource": null,
11796	
11797	
11798		/**
11799		 * This initialisation variable allows you to specify exactly where in the
11800		 * DOM you want DataTables to inject the various controls it adds to the page
11801		 * (for example you might want the pagination controls at the top of the
11802		 * table). DIV elements (with or without a custom class) can also be added to
11803		 * aid styling. The follow syntax is used:
11804		 *   <ul>
11805		 *     <li>The following options are allowed:
11806		 *       <ul>
11807		 *         <li>'l' - Length changing</li>
11808		 *         <li>'f' - Filtering input</li>
11809		 *         <li>'t' - The table!</li>
11810		 *         <li>'i' - Information</li>
11811		 *         <li>'p' - Pagination</li>
11812		 *         <li>'r' - pRocessing</li>
11813		 *       </ul>
11814		 *     </li>
11815		 *     <li>The following constants are allowed:
11816		 *       <ul>
11817		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11818		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11819		 *       </ul>
11820		 *     </li>
11821		 *     <li>The following syntax is expected:
11822		 *       <ul>
11823		 *         <li>'&lt;' and '&gt;' - div elements</li>
11824		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11825		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11826		 *       </ul>
11827		 *     </li>
11828		 *     <li>Examples:
11829		 *       <ul>
11830		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11831		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11832		 *       </ul>
11833		 *     </li>
11834		 *   </ul>
11835		 *  @type string
11836		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11837		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11838		 *
11839		 *  @dtopt Options
11840		 *  @name DataTable.defaults.dom
11841		 *
11842		 *  @example
11843		 *    $(document).ready( function() {
11844		 *      $('#example').dataTable( {
11845		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11846		 *      } );
11847		 *    } );
11848		 */
11849		"sDom": "lfrtip",
11850	
11851	
11852		/**
11853		 * Search delay option. This will throttle full table searches that use the
11854		 * DataTables provided search input element (it does not effect calls to
11855		 * `dt-api search()`, providing a delay before the search is made.
11856		 *  @type integer
11857		 *  @default 0
11858		 *
11859		 *  @dtopt Options
11860		 *  @name DataTable.defaults.searchDelay
11861		 *
11862		 *  @example
11863		 *    $(document).ready( function() {
11864		 *      $('#example').dataTable( {
11865		 *        "searchDelay": 200
11866		 *      } );
11867		 *    } )
11868		 */
11869		"searchDelay": null,
11870	
11871	
11872		/**
11873		 * DataTables features six different built-in options for the buttons to
11874		 * display for pagination control:
11875		 *
11876		 * * `numbers` - Page number buttons only
11877		 * * `simple` - 'Previous' and 'Next' buttons only
11878		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11879		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11880		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11881		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11882		 *  
11883		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11884		 *  @type string
11885		 *  @default simple_numbers
11886		 *
11887		 *  @dtopt Options
11888		 *  @name DataTable.defaults.pagingType
11889		 *
11890		 *  @example
11891		 *    $(document).ready( function() {
11892		 *      $('#example').dataTable( {
11893		 *        "pagingType": "full_numbers"
11894		 *      } );
11895		 *    } )
11896		 */
11897		"sPaginationType": "simple_numbers",
11898	
11899	
11900		/**
11901		 * Enable horizontal scrolling. When a table is too wide to fit into a
11902		 * certain layout, or you have a large number of columns in the table, you
11903		 * can enable x-scrolling to show the table in a viewport, which can be
11904		 * scrolled. This property can be `true` which will allow the table to
11905		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11906		 * case it will be treated as a pixel measurement). Setting as simply `true`
11907		 * is recommended.
11908		 *  @type boolean|string
11909		 *  @default <i>blank string - i.e. disabled</i>
11910		 *
11911		 *  @dtopt Features
11912		 *  @name DataTable.defaults.scrollX
11913		 *
11914		 *  @example
11915		 *    $(document).ready( function() {
11916		 *      $('#example').dataTable( {
11917		 *        "scrollX": true,
11918		 *        "scrollCollapse": true
11919		 *      } );
11920		 *    } );
11921		 */
11922		"sScrollX": "",
11923	
11924	
11925		/**
11926		 * This property can be used to force a DataTable to use more width than it
11927		 * might otherwise do when x-scrolling is enabled. For example if you have a
11928		 * table which requires to be well spaced, this parameter is useful for
11929		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11930		 * any CSS unit, or a number (in which case it will be treated as a pixel
11931		 * measurement).
11932		 *  @type string
11933		 *  @default <i>blank string - i.e. disabled</i>
11934		 *
11935		 *  @dtopt Options
11936		 *  @name DataTable.defaults.scrollXInner
11937		 *
11938		 *  @example
11939		 *    $(document).ready( function() {
11940		 *      $('#example').dataTable( {
11941		 *        "scrollX": "100%",
11942		 *        "scrollXInner": "110%"
11943		 *      } );
11944		 *    } );
11945		 */
11946		"sScrollXInner": "",
11947	
11948	
11949		/**
11950		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11951		 * to the given height, and enable scrolling for any data which overflows the
11952		 * current viewport. This can be used as an alternative to paging to display
11953		 * a lot of data in a small area (although paging and scrolling can both be
11954		 * enabled at the same time). This property can be any CSS unit, or a number
11955		 * (in which case it will be treated as a pixel measurement).
11956		 *  @type string
11957		 *  @default <i>blank string - i.e. disabled</i>
11958		 *
11959		 *  @dtopt Features
11960		 *  @name DataTable.defaults.scrollY
11961		 *
11962		 *  @example
11963		 *    $(document).ready( function() {
11964		 *      $('#example').dataTable( {
11965		 *        "scrollY": "200px",
11966		 *        "paginate": false
11967		 *      } );
11968		 *    } );
11969		 */
11970		"sScrollY": "",
11971	
11972	
11973		/**
11974		 * __Deprecated__ The functionality provided by this parameter has now been
11975		 * superseded by that provided through `ajax`, which should be used instead.
11976		 *
11977		 * Set the HTTP method that is used to make the Ajax call for server-side
11978		 * processing or Ajax sourced data.
11979		 *  @type string
11980		 *  @default GET
11981		 *
11982		 *  @dtopt Options
11983		 *  @dtopt Server-side
11984		 *  @name DataTable.defaults.serverMethod
11985		 *
11986		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11987		 */
11988		"sServerMethod": "GET",
11989	
11990	
11991		/**
11992		 * DataTables makes use of renderers when displaying HTML elements for
11993		 * a table. These renderers can be added or modified by plug-ins to
11994		 * generate suitable mark-up for a site. For example the Bootstrap
11995		 * integration plug-in for DataTables uses a paging button renderer to
11996		 * display pagination buttons in the mark-up required by Bootstrap.
11997		 *
11998		 * For further information about the renderers available see
11999		 * DataTable.ext.renderer
12000		 *  @type string|object
12001		 *  @default null
12002		 *
12003		 *  @name DataTable.defaults.renderer
12004		 *
12005		 */
12006		"renderer": null,
12007	
12008	
12009		/**
12010		 * Set the data property name that DataTables should use to get a row's id
12011		 * to set as the `id` property in the node.
12012		 *  @type string
12013		 *  @default DT_RowId
12014		 *
12015		 *  @name DataTable.defaults.rowId
12016		 */
12017		"rowId": "DT_RowId"
12018	};
12019	
12020	_fnHungarianMap( DataTable.defaults );
12021	
12022	
12023	
12024	/*
12025	 * Developer note - See note in model.defaults.js about the use of Hungarian
12026	 * notation and camel case.
12027	 */
12028	
12029	/**
12030	 * Column options that can be given to DataTables at initialisation time.
12031	 *  @namespace
12032	 */
12033	DataTable.defaults.column = {
12034		/**
12035		 * Define which column(s) an order will occur on for this column. This
12036		 * allows a column's ordering to take multiple columns into account when
12037		 * doing a sort or use the data from a different column. For example first
12038		 * name / last name columns make sense to do a multi-column sort over the
12039		 * two columns.
12040		 *  @type array|int
12041		 *  @default null <i>Takes the value of the column index automatically</i>
12042		 *
12043		 *  @name DataTable.defaults.column.orderData
12044		 *  @dtopt Columns
12045		 *
12046		 *  @example
12047		 *    // Using `columnDefs`
12048		 *    $(document).ready( function() {
12049		 *      $('#example').dataTable( {
12050		 *        "columnDefs": [
12051		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12052		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12053		 *          { "orderData": 2, "targets": [ 2 ] }
12054		 *        ]
12055		 *      } );
12056		 *    } );
12057		 *
12058		 *  @example
12059		 *    // Using `columns`
12060		 *    $(document).ready( function() {
12061		 *      $('#example').dataTable( {
12062		 *        "columns": [
12063		 *          { "orderData": [ 0, 1 ] },
12064		 *          { "orderData": [ 1, 0 ] },
12065		 *          { "orderData": 2 },
12066		 *          null,
12067		 *          null
12068		 *        ]
12069		 *      } );
12070		 *    } );
12071		 */
12072		"aDataSort": null,
12073		"iDataSort": -1,
12074	
12075	
12076		/**
12077		 * You can control the default ordering direction, and even alter the
12078		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12079		 * using this parameter.
12080		 *  @type array
12081		 *  @default [ 'asc', 'desc' ]
12082		 *
12083		 *  @name DataTable.defaults.column.orderSequence
12084		 *  @dtopt Columns
12085		 *
12086		 *  @example
12087		 *    // Using `columnDefs`
12088		 *    $(document).ready( function() {
12089		 *      $('#example').dataTable( {
12090		 *        "columnDefs": [
12091		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12092		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12093		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12094		 *        ]
12095		 *      } );
12096		 *    } );
12097		 *
12098		 *  @example
12099		 *    // Using `columns`
12100		 *    $(document).ready( function() {
12101		 *      $('#example').dataTable( {
12102		 *        "columns": [
12103		 *          null,
12104		 *          { "orderSequence": [ "asc" ] },
12105		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12106		 *          { "orderSequence": [ "desc" ] },
12107		 *          null
12108		 *        ]
12109		 *      } );
12110		 *    } );
12111		 */
12112		"asSorting": [ 'asc', 'desc' ],
12113	
12114	
12115		/**
12116		 * Enable or disable filtering on the data in this column.
12117		 *  @type boolean
12118		 *  @default true
12119		 *
12120		 *  @name DataTable.defaults.column.searchable
12121		 *  @dtopt Columns
12122		 *
12123		 *  @example
12124		 *    // Using `columnDefs`
12125		 *    $(document).ready( function() {
12126		 *      $('#example').dataTable( {
12127		 *        "columnDefs": [
12128		 *          { "searchable": false, "targets": [ 0 ] }
12129		 *        ] } );
12130		 *    } );
12131		 *
12132		 *  @example
12133		 *    // Using `columns`
12134		 *    $(document).ready( function() {
12135		 *      $('#example').dataTable( {
12136		 *        "columns": [
12137		 *          { "searchable": false },
12138		 *          null,
12139		 *          null,
12140		 *          null,
12141		 *          null
12142		 *        ] } );
12143		 *    } );
12144		 */
12145		"bSearchable": true,
12146	
12147	
12148		/**
12149		 * Enable or disable ordering on this column.
12150		 *  @type boolean
12151		 *  @default true
12152		 *
12153		 *  @name DataTable.defaults.column.orderable
12154		 *  @dtopt Columns
12155		 *
12156		 *  @example
12157		 *    // Using `columnDefs`
12158		 *    $(document).ready( function() {
12159		 *      $('#example').dataTable( {
12160		 *        "columnDefs": [
12161		 *          { "orderable": false, "targets": [ 0 ] }
12162		 *        ] } );
12163		 *    } );
12164		 *
12165		 *  @example
12166		 *    // Using `columns`
12167		 *    $(document).ready( function() {
12168		 *      $('#example').dataTable( {
12169		 *        "columns": [
12170		 *          { "orderable": false },
12171		 *          null,
12172		 *          null,
12173		 *          null,
12174		 *          null
12175		 *        ] } );
12176		 *    } );
12177		 */
12178		"bSortable": true,
12179	
12180	
12181		/**
12182		 * Enable or disable the display of this column.
12183		 *  @type boolean
12184		 *  @default true
12185		 *
12186		 *  @name DataTable.defaults.column.visible
12187		 *  @dtopt Columns
12188		 *
12189		 *  @example
12190		 *    // Using `columnDefs`
12191		 *    $(document).ready( function() {
12192		 *      $('#example').dataTable( {
12193		 *        "columnDefs": [
12194		 *          { "visible": false, "targets": [ 0 ] }
12195		 *        ] } );
12196		 *    } );
12197		 *
12198		 *  @example
12199		 *    // Using `columns`
12200		 *    $(document).ready( function() {
12201		 *      $('#example').dataTable( {
12202		 *        "columns": [
12203		 *          { "visible": false },
12204		 *          null,
12205		 *          null,
12206		 *          null,
12207		 *          null
12208		 *        ] } );
12209		 *    } );
12210		 */
12211		"bVisible": true,
12212	
12213	
12214		/**
12215		 * Developer definable function that is called whenever a cell is created (Ajax source,
12216		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12217		 * allowing you to modify the DOM element (add background colour for example) when the
12218		 * element is available.
12219		 *  @type function
12220		 *  @param {element} td The TD node that has been created
12221		 *  @param {*} cellData The Data for the cell
12222		 *  @param {array|object} rowData The data for the whole row
12223		 *  @param {int} row The row index for the aoData data store
12224		 *  @param {int} col The column index for aoColumns
12225		 *
12226		 *  @name DataTable.defaults.column.createdCell
12227		 *  @dtopt Columns
12228		 *
12229		 *  @example
12230		 *    $(document).ready( function() {
12231		 *      $('#example').dataTable( {
12232		 *        "columnDefs": [ {
12233		 *          "targets": [3],
12234		 *          "createdCell": function (td, cellData, rowData, row, col) {
12235		 *            if ( cellData == "1.7" ) {
12236		 *              $(td).css('color', 'blue')
12237		 *            }
12238		 *          }
12239		 *        } ]
12240		 *      });
12241		 *    } );
12242		 */
12243		"fnCreatedCell": null,
12244	
12245	
12246		/**
12247		 * This parameter has been replaced by `data` in DataTables to ensure naming
12248		 * consistency. `dataProp` can still be used, as there is backwards
12249		 * compatibility in DataTables for this option, but it is strongly
12250		 * recommended that you use `data` in preference to `dataProp`.
12251		 *  @name DataTable.defaults.column.dataProp
12252		 */
12253	
12254	
12255		/**
12256		 * This property can be used to read data from any data source property,
12257		 * including deeply nested objects / properties. `data` can be given in a
12258		 * number of different ways which effect its behaviour:
12259		 *
12260		 * * `integer` - treated as an array index for the data source. This is the
12261		 *   default that DataTables uses (incrementally increased for each column).
12262		 * * `string` - read an object property from the data source. There are
12263		 *   three 'special' options that can be used in the string to alter how
12264		 *   DataTables reads the data from the source object:
12265		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12266		 *      Javascript to read from nested objects, so to can the options
12267		 *      specified in `data`. For example: `browser.version` or
12268		 *      `browser.name`. If your object parameter name contains a period, use
12269		 *      `\\` to escape it - i.e. `first\\.name`.
12270		 *    * `[]` - Array notation. DataTables can automatically combine data
12271		 *      from and array source, joining the data with the characters provided
12272		 *      between the two brackets. For example: `name[, ]` would provide a
12273		 *      comma-space separated list from the source array. If no characters
12274		 *      are provided between the brackets, the original array source is
12275		 *      returned.
12276		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12277		 *      execute a function of the name given. For example: `browser()` for a
12278		 *      simple function on the data source, `browser.version()` for a
12279		 *      function in a nested property or even `browser().version` to get an
12280		 *      object property if the function called returns an object. Note that
12281		 *      function notation is recommended for use in `render` rather than
12282		 *      `data` as it is much simpler to use as a renderer.
12283		 * * `null` - use the original data source for the row rather than plucking
12284		 *   data directly from it. This action has effects on two other
12285		 *   initialisation options:
12286		 *    * `defaultContent` - When null is given as the `data` option and
12287		 *      `defaultContent` is specified for the column, the value defined by
12288		 *      `defaultContent` will be used for the cell.
12289		 *    * `render` - When null is used for the `data` option and the `render`
12290		 *      option is specified for the column, the whole data source for the
12291		 *      row is used for the renderer.
12292		 * * `function` - the function given will be executed whenever DataTables
12293		 *   needs to set or get the data for a cell in the column. The function
12294		 *   takes three parameters:
12295		 *    * Parameters:
12296		 *      * `{array|object}` The data source for the row
12297		 *      * `{string}` The type call data requested - this will be 'set' when
12298		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12299		 *        when gathering data. Note that when `undefined` is given for the
12300		 *        type DataTables expects to get the raw data for the object back<
12301		 *      * `{*}` Data to set when the second parameter is 'set'.
12302		 *    * Return:
12303		 *      * The return value from the function is not required when 'set' is
12304		 *        the type of call, but otherwise the return is what will be used
12305		 *        for the data requested.
12306		 *
12307		 * Note that `data` is a getter and setter option. If you just require
12308		 * formatting of data for output, you will likely want to use `render` which
12309		 * is simply a getter and thus simpler to use.
12310		 *
12311		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12312		 * name change reflects the flexibility of this property and is consistent
12313		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12314		 * be used by DataTables, as it automatically maps the old name to the new
12315		 * if required.
12316		 *
12317		 *  @type string|int|function|null
12318		 *  @default null <i>Use automatically calculated column index</i>
12319		 *
12320		 *  @name DataTable.defaults.column.data
12321		 *  @dtopt Columns
12322		 *
12323		 *  @example
12324		 *    // Read table data from objects
12325		 *    // JSON structure for each row:
12326		 *    //   {
12327		 *    //      "engine": {value},
12328		 *    //      "browser": {value},
12329		 *    //      "platform": {value},
12330		 *    //      "version": {value},
12331		 *    //      "grade": {value}
12332		 *    //   }
12333		 *    $(document).ready( function() {
12334		 *      $('#example').dataTable( {
12335		 *        "ajaxSource": "sources/objects.txt",
12336		 *        "columns": [
12337		 *          { "data": "engine" },
12338		 *          { "data": "browser" },
12339		 *          { "data": "platform" },
12340		 *          { "data": "version" },
12341		 *          { "data": "grade" }
12342		 *        ]
12343		 *      } );
12344		 *    } );
12345		 *
12346		 *  @example
12347		 *    // Read information from deeply nested objects
12348		 *    // JSON structure for each row:
12349		 *    //   {
12350		 *    //      "engine": {value},
12351		 *    //      "browser": {value},
12352		 *    //      "platform": {
12353		 *    //         "inner": {value}
12354		 *    //      },
12355		 *    //      "details": [
12356		 *    //         {value}, {value}
12357		 *    //      ]
12358		 *    //   }
12359		 *    $(document).ready( function() {
12360		 *      $('#example').dataTable( {
12361		 *        "ajaxSource": "sources/deep.txt",
12362		 *        "columns": [
12363		 *          { "data": "engine" },
12364		 *          { "data": "browser" },
12365		 *          { "data": "platform.inner" },
12366		 *          { "data": "
12366platform.details.0" },
12367		 *          { "data": "platform.details.1" }
12368		 *        ]
12369		 *      } );
12370		 *    } );
12371		 *
12372		 *  @example
12373		 *    // Using `data` as a function to provide different information for
12374		 *    // sorting, filtering and display. In this case, currency (price)
12375		 *    $(document).ready( function() {
12376		 *      $('#example').dataTable( {
12377		 *        "columnDefs": [ {
12378		 *          "targets": [ 0 ],
12379		 *          "data": function ( source, type, val ) {
12380		 *            if (type === 'set') {
12381		 *              source.price = val;
12382		 *              // Store the computed dis
vendor: 18,284 bytes, lines 12382-12931
12382lay and filter values for efficiency
12383		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12384		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12385		 *              return;
12386		 *            }
12387		 *            else if (type === 'display') {
12388		 *              return source.price_display;
12389		 *            }
12390		 *            else if (type === 'filter') {
12391		 *              return source.price_filter;
12392		 *            }
12393		 *            // 'sort', 'type' and undefined all just use the integer
12394		 *            return source.price;
12395		 *          }
12396		 *        } ]
12397		 *      } );
12398		 *    } );
12399		 *
12400		 *  @example
12401		 *    // Using default content
12402		 *    $(document).ready( function() {
12403		 *      $('#example').dataTable( {
12404		 *        "columnDefs": [ {
12405		 *          "targets": [ 0 ],
12406		 *          "data": null,
12407		 *          "defaultContent": "Click to edit"
12408		 *        } ]
12409		 *      } );
12410		 *    } );
12411		 *
12412		 *  @example
12413		 *    // Using array notation - outputting a list from an array
12414		 *    $(document).ready( function() {
12415		 *      $('#example').dataTable( {
12416		 *        "columnDefs": [ {
12417		 *          "targets": [ 0 ],
12418		 *          "data": "name[, ]"
12419		 *        } ]
12420		 *      } );
12421		 *    } );
12422		 *
12423		 */
12424		"mData": null,
12425	
12426	
12427		/**
12428		 * This property is the rendering partner to `data` and it is suggested that
12429		 * when you want to manipulate data for display (including filtering,
12430		 * sorting etc) without altering the underlying data for the table, use this
12431		 * property. `render` can be considered to be the the read only companion to
12432		 * `data` which is read / write (then as such more complex). Like `data`
12433		 * this option can be given in a number of different ways to effect its
12434		 * behaviour:
12435		 *
12436		 * * `integer` - treated as an array index for the data source. This is the
12437		 *   default that DataTables uses (incrementally increased for each column).
12438		 * * `string` - read an object property from the data source. There are
12439		 *   three 'special' options that can be used in the string to alter how
12440		 *   DataTables reads the data from the source object:
12441		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12442		 *      Javascript to read from nested objects, so to can the options
12443		 *      specified in `data`. For example: `browser.version` or
12444		 *      `browser.name`. If your object parameter name contains a period, use
12445		 *      `\\` to escape it - i.e. `first\\.name`.
12446		 *    * `[]` - Array notation. DataTables can automatically combine data
12447		 *      from and array source, joining the data with the characters provided
12448		 *      between the two brackets. For example: `name[, ]` would provide a
12449		 *      comma-space separated list from the source array. If no characters
12450		 *      are provided between the brackets, the original array source is
12451		 *      returned.
12452		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12453		 *      execute a function of the name given. For example: `browser()` for a
12454		 *      simple function on the data source, `browser.version()` for a
12455		 *      function in a nested property or even `browser().version` to get an
12456		 *      object property if the function called returns an object.
12457		 * * `object` - use different data for the different data types requested by
12458		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12459		 *   of the object is the data type the property refers to and the value can
12460		 *   defined using an integer, string or function using the same rules as
12461		 *   `render` normally does. Note that an `_` option _must_ be specified.
12462		 *   This is the default value to use if you haven't specified a value for
12463		 *   the data type requested by DataTables.
12464		 * * `function` - the function given will be executed whenever DataTables
12465		 *   needs to set or get the data for a cell in the column. The function
12466		 *   takes three parameters:
12467		 *    * Parameters:
12468		 *      * {array|object} The data source for the row (based on `data`)
12469		 *      * {string} The type call data requested - this will be 'filter',
12470		 *        'display', 'type' or 'sort'.
12471		 *      * {array|object} The full data source for the row (not based on
12472		 *        `data`)
12473		 *    * Return:
12474		 *      * The return value from the function is what will be used for the
12475		 *        data requested.
12476		 *
12477		 *  @type string|int|function|object|null
12478		 *  @default null Use the data source value.
12479		 *
12480		 *  @name DataTable.defaults.column.render
12481		 *  @dtopt Columns
12482		 *
12483		 *  @example
12484		 *    // Create a comma separated list from an array of objects
12485		 *    $(document).ready( function() {
12486		 *      $('#example').dataTable( {
12487		 *        "ajaxSource": "sources/deep.txt",
12488		 *        "columns": [
12489		 *          { "data": "engine" },
12490		 *          { "data": "browser" },
12491		 *          {
12492		 *            "data": "platform",
12493		 *            "render": "[, ].name"
12494		 *          }
12495		 *        ]
12496		 *      } );
12497		 *    } );
12498		 *
12499		 *  @example
12500		 *    // Execute a function to obtain data
12501		 *    $(document).ready( function() {
12502		 *      $('#example').dataTable( {
12503		 *        "columnDefs": [ {
12504		 *          "targets": [ 0 ],
12505		 *          "data": null, // Use the full data source object for the renderer's source
12506		 *          "render": "browserName()"
12507		 *        } ]
12508		 *      } );
12509		 *    } );
12510		 *
12511		 *  @example
12512		 *    // As an object, extracting different data for the different types
12513		 *    // This would be used with a data source such as:
12514		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12515		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12516		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12517		 *    // the formatted phone number is the one that is shown in the table.
12518		 *    $(document).ready( function() {
12519		 *      $('#example').dataTable( {
12520		 *        "columnDefs": [ {
12521		 *          "targets": [ 0 ],
12522		 *          "data": null, // Use the full data source object for the renderer's source
12523		 *          "render": {
12524		 *            "_": "phone",
12525		 *            "filter": "phone_filter",
12526		 *            "display": "phone_display"
12527		 *          }
12528		 *        } ]
12529		 *      } );
12530		 *    } );
12531		 *
12532		 *  @example
12533		 *    // Use as a function to create a link from the data source
12534		 *    $(document).ready( function() {
12535		 *      $('#example').dataTable( {
12536		 *        "columnDefs": [ {
12537		 *          "targets": [ 0 ],
12538		 *          "data": "download_link",
12539		 *          "render": function ( data, type, full ) {
12540		 *            return '<a href="'+data+'">Download</a>';
12541		 *          }
12542		 *        } ]
12543		 *      } );
12544		 *    } );
12545		 */
12546		"mRender": null,
12547	
12548	
12549		/**
12550		 * Change the cell type created for the column - either TD cells or TH cells. This
12551		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12552		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12553		 *  @type string
12554		 *  @default td
12555		 *
12556		 *  @name DataTable.defaults.column.cellType
12557		 *  @dtopt Columns
12558		 *
12559		 *  @example
12560		 *    // Make the first column use TH cells
12561		 *    $(document).ready( function() {
12562		 *      $('#example').dataTable( {
12563		 *        "columnDefs": [ {
12564		 *          "targets": [ 0 ],
12565		 *          "cellType": "th"
12566		 *        } ]
12567		 *      } );
12568		 *    } );
12569		 */
12570		"sCellType": "td",
12571	
12572	
12573		/**
12574		 * Class to give to each cell in this column.
12575		 *  @type string
12576		 *  @default <i>Empty string</i>
12577		 *
12578		 *  @name DataTable.defaults.column.class
12579		 *  @dtopt Columns
12580		 *
12581		 *  @example
12582		 *    // Using `columnDefs`
12583		 *    $(document).ready( function() {
12584		 *      $('#example').dataTable( {
12585		 *        "columnDefs": [
12586		 *          { "class": "my_class", "targets": [ 0 ] }
12587		 *        ]
12588		 *      } );
12589		 *    } );
12590		 *
12591		 *  @example
12592		 *    // Using `columns`
12593		 *    $(document).ready( function() {
12594		 *      $('#example').dataTable( {
12595		 *        "columns": [
12596		 *          { "class": "my_class" },
12597		 *          null,
12598		 *          null,
12599		 *          null,
12600		 *          null
12601		 *        ]
12602		 *      } );
12603		 *    } );
12604		 */
12605		"sClass": "",
12606	
12607		/**
12608		 * When DataTables calculates the column widths to assign to each column,
12609		 * it finds the longest string in each column and then constructs a
12610		 * temporary table and reads the widths from that. The problem with this
12611		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12612		 * string - thus the calculation can go wrong (doing it properly and putting
12613		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12614		 * a "work around" we provide this option. It will append its value to the
12615		 * text that is found to be the longest string for the column - i.e. padding.
12616		 * Generally you shouldn't need this!
12617		 *  @type string
12618		 *  @default <i>Empty string<i>
12619		 *
12620		 *  @name DataTable.defaults.column.contentPadding
12621		 *  @dtopt Columns
12622		 *
12623		 *  @example
12624		 *    // Using `columns`
12625		 *    $(document).ready( function() {
12626		 *      $('#example').dataTable( {
12627		 *        "columns": [
12628		 *          null,
12629		 *          null,
12630		 *          null,
12631		 *          {
12632		 *            "contentPadding": "mmm"
12633		 *          }
12634		 *        ]
12635		 *      } );
12636		 *    } );
12637		 */
12638		"sContentPadding": "",
12639	
12640	
12641		/**
12642		 * Allows a default value to be given for a column's data, and will be used
12643		 * whenever a null data source is encountered (this can be because `data`
12644		 * is set to null, or because the data source itself is null).
12645		 *  @type string
12646		 *  @default null
12647		 *
12648		 *  @name DataTable.defaults.column.defaultContent
12649		 *  @dtopt Columns
12650		 *
12651		 *  @example
12652		 *    // Using `columnDefs`
12653		 *    $(document).ready( function() {
12654		 *      $('#example').dataTable( {
12655		 *        "columnDefs": [
12656		 *          {
12657		 *            "data": null,
12658		 *            "defaultContent": "Edit",
12659		 *            "targets": [ -1 ]
12660		 *          }
12661		 *        ]
12662		 *      } );
12663		 *    } );
12664		 *
12665		 *  @example
12666		 *    // Using `columns`
12667		 *    $(document).ready( function() {
12668		 *      $('#example').dataTable( {
12669		 *        "columns": [
12670		 *          null,
12671		 *          null,
12672		 *          null,
12673		 *          {
12674		 *            "data": null,
12675		 *            "defaultContent": "Edit"
12676		 *          }
12677		 *        ]
12678		 *      } );
12679		 *    } );
12680		 */
12681		"sDefaultContent": null,
12682	
12683	
12684		/**
12685		 * This parameter is only used in DataTables' server-side processing. It can
12686		 * be exceptionally useful to know what columns are being displayed on the
12687		 * client side, and to map these to database fields. When defined, the names
12688		 * also allow DataTables to reorder information from the server if it comes
12689		 * back in an unexpected order (i.e. if you switch your columns around on the
12690		 * client-side, your server-side code does not also need updating).
12691		 *  @type string
12692		 *  @default <i>Empty string</i>
12693		 *
12694		 *  @name DataTable.defaults.column.name
12695		 *  @dtopt Columns
12696		 *
12697		 *  @example
12698		 *    // Using `columnDefs`
12699		 *    $(document).ready( function() {
12700		 *      $('#example').dataTable( {
12701		 *        "columnDefs": [
12702		 *          { "name": "engine", "targets": [ 0 ] },
12703		 *          { "name": "browser", "targets": [ 1 ] },
12704		 *          { "name": "platform", "targets": [ 2 ] },
12705		 *          { "name": "version", "targets": [ 3 ] },
12706		 *          { "name": "grade", "targets": [ 4 ] }
12707		 *        ]
12708		 *      } );
12709		 *    } );
12710		 *
12711		 *  @example
12712		 *    // Using `columns`
12713		 *    $(document).ready( function() {
12714		 *      $('#example').dataTable( {
12715		 *        "columns": [
12716		 *          { "name": "engine" },
12717		 *          { "name": "browser" },
12718		 *          { "name": "platform" },
12719		 *          { "name": "version" },
12720		 *          { "name": "grade" }
12721		 *        ]
12722		 *      } );
12723		 *    } );
12724		 */
12725		"sName": "",
12726	
12727	
12728		/**
12729		 * Defines a data source type for the ordering which can be used to read
12730		 * real-time information from the table (updating the internally cached
12731		 * version) prior to ordering. This allows ordering to occur on user
12732		 * editable elements such as form inputs.
12733		 *  @type string
12734		 *  @default std
12735		 *
12736		 *  @name DataTable.defaults.column.orderDataType
12737		 *  @dtopt Columns
12738		 *
12739		 *  @example
12740		 *    // Using `columnDefs`
12741		 *    $(document).ready( function() {
12742		 *      $('#example').dataTable( {
12743		 *        "columnDefs": [
12744		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12745		 *          { "type": "numeric", "targets": [ 3 ] },
12746		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12747		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12748		 *        ]
12749		 *      } );
12750		 *    } );
12751		 *
12752		 *  @example
12753		 *    // Using `columns`
12754		 *    $(document).ready( function() {
12755		 *      $('#example').dataTable( {
12756		 *        "columns": [
12757		 *          null,
12758		 *          null,
12759		 *          { "orderDataType": "dom-text" },
12760		 *          { "orderDataType": "dom-text", "type": "numeric" },
12761		 *          { "orderDataType": "dom-select" },
12762		 *          { "orderDataType": "dom-checkbox" }
12763		 *        ]
12764		 *      } );
12765		 *    } );
12766		 */
12767		"sSortDataType": "std",
12768	
12769	
12770		/**
12771		 * The title of this column.
12772		 *  @type string
12773		 *  @default null <i>Derived from the 'TH' value for this column in the
12774		 *    original HTML table.</i>
12775		 *
12776		 *  @name DataTable.defaults.column.title
12777		 *  @dtopt Columns
12778		 *
12779		 *  @example
12780		 *    // Using `columnDefs`
12781		 *    $(document).ready( function() {
12782		 *      $('#example').dataTable( {
12783		 *        "columnDefs": [
12784		 *          { "title": "My column title", "targets": [ 0 ] }
12785		 *        ]
12786		 *      } );
12787		 *    } );
12788		 *
12789		 *  @example
12790		 *    // Using `columns`
12791		 *    $(document).ready( function() {
12792		 *      $('#example').dataTable( {
12793		 *        "columns": [
12794		 *          { "title": "My column title" },
12795		 *          null,
12796		 *          null,
12797		 *          null,
12798		 *          null
12799		 *        ]
12800		 *      } );
12801		 *    } );
12802		 */
12803		"sTitle": null,
12804	
12805	
12806		/**
12807		 * The type allows you to specify how the data for this column will be
12808		 * ordered. Four types (string, numeric, date and html (which will strip
12809		 * HTML tags before ordering)) are currently available. Note that only date
12810		 * formats understood by Javascript's Date() object will be accepted as type
12811		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12812		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12813		 * through plug-ins.
12814		 *  @type string
12815		 *  @default null <i>Auto-detected from raw data</i>
12816		 *
12817		 *  @name DataTable.defaults.column.type
12818		 *  @dtopt Columns
12819		 *
12820		 *  @example
12821		 *    // Using `columnDefs`
12822		 *    $(document).ready( function() {
12823		 *      $('#example').dataTable( {
12824		 *        "columnDefs": [
12825		 *          { "type": "html", "targets": [ 0 ] }
12826		 *        ]
12827		 *      } );
12828		 *    } );
12829		 *
12830		 *  @example
12831		 *    // Using `columns`
12832		 *    $(document).ready( function() {
12833		 *      $('#example').dataTable( {
12834		 *        "columns": [
12835		 *          { "type": "html" },
12836		 *          null,
12837		 *          null,
12838		 *          null,
12839		 *          null
12840		 *        ]
12841		 *      } );
12842		 *    } );
12843		 */
12844		"sType": null,
12845	
12846	
12847		/**
12848		 * Defining the width of the column, this parameter may take any CSS value
12849		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12850		 * been given a specific width through this interface ensuring that the table
12851		 * remains readable.
12852		 *  @type string
12853		 *  @default null <i>Automatic</i>
12854		 *
12855		 *  @name DataTable.defaults.column.width
12856		 *  @dtopt Columns
12857		 *
12858		 *  @example
12859		 *    // Using `columnDefs`
12860		 *    $(document).ready( function() {
12861		 *      $('#example').dataTable( {
12862		 *        "columnDefs": [
12863		 *          { "width": "20%", "targets": [ 0 ] }
12864		 *        ]
12865		 *      } );
12866		 *    } );
12867		 *
12868		 *  @example
12869		 *    // Using `columns`
12870		 *    $(document).ready( function() {
12871		 *      $('#example').dataTable( {
12872		 *        "columns": [
12873		 *          { "width": "20%" },
12874		 *          null,
12875		 *          null,
12876		 *          null,
12877		 *          null
12878		 *        ]
12879		 *      } );
12880		 *    } );
12881		 */
12882		"sWidth": null
12883	};
12884	
12885	_fnHungarianMap( DataTable.defaults.column );
12886	
12887	
12888	
12889	/**
12890	 * DataTables settings object - this holds all the information needed for a
12891	 * given table, including configuration, data and current application of the
12892	 * table options. DataTables does not have a single instance for each DataTable
12893	 * with the settings attached to that instance, but rather instances of the
12894	 * DataTable "class" are created on-the-fly as needed (typically by a
12895	 * $().dataTable() call) and the settings object is then applied to that
12896	 * instance.
12897	 *
12898	 * Note that this object is related to {@link DataTable.defaults} but this
12899	 * one is the internal data store for DataTables's cache of columns. It should
12900	 * NOT be manipulated outside of DataTables. Any configuration should be done
12901	 * through the initialisation options.
12902	 *  @namespace
12903	 *  @todo Really should attach the settings object to individual instances so we
12904	 *    don't need to create new instances on each $().dataTable() call (if the
12905	 *    table already exists). It would also save passing oSettings around and
12906	 *    into every single function. However, this is a very significant
12907	 *    architecture change for DataTables and will almost certainly break
12908	 *    backwards compatibility with older installations. This is something that
12909	 *    will be done in 2.0.
12910	 */
12911	DataTable.models.oSettings = {
12912		/**
12913		 * Primary features of DataTables and their enablement state.
12914		 *  @namespace
12915		 */
12916		"oFeatures": {
12917	
12918			/**
12919			 * Flag to say if DataTables should automatically try to calculate the
12920			 * optimum table and columns widths (true) or not (false).
12921			 * Note that this parameter will be set by the initialisation routine. To
12922			 * set a default use {@link DataTable.defaults}.
12923			 *  @type boolean
12924			 */
12925			"bAutoWidth": null,
12926	
12927			/**
12928			 * Delay the creation of TR and TD elements until they are actually
12929			 * needed by a driven page draw. This can give a significant speed
12930			 * increase for Ajax source and Javascript source data, but makes no
12931			 * difference at all f
12931ro
vendor: 14,836 bytes, lines 12931-13508
12931 DOM and server-side processing tables.
12932			 * Note that this parameter will be set by the initialisation routine. To
12933			 * set a default use {@link DataTable.defaults}.
12934			 *  @type boolean
12935			 */
12936			"bDeferRender": null,
12937	
12938			/**
12939			 * Enable filtering on the table or not. Note that if this is disabled
12940			 * then there is no filtering at all on the table, including fnFilter.
12941			 * To just remove the filtering input use sDom and remove the 'f' option.
12942			 * Note that this parameter will be set by the initialisation routine. To
12943			 * set a default use {@link DataTable.defaults}.
12944			 *  @type boolean
12945			 */
12946			"bFilter": null,
12947	
12948			/**
12949			 * Table information element (the 'Showing x of y records' div) enable
12950			 * flag.
12951			 * Note that this parameter will be set by the initialisation routine. To
12952			 * set a default use {@link DataTable.defaults}.
12953			 *  @type boolean
12954			 */
12955			"bInfo": null,
12956	
12957			/**
12958			 * Present a user control allowing the end user to change the page size
12959			 * when pagination is enabled.
12960			 * Note that this parameter will be set by the initialisation routine. To
12961			 * set a default use {@link DataTable.defaults}.
12962			 *  @type boolean
12963			 */
12964			"bLengthChange": null,
12965	
12966			/**
12967			 * Pagination enabled or not. Note that if this is disabled then length
12968			 * changing must also be disabled.
12969			 * Note that this parameter will be set by the initialisation routine. To
12970			 * set a default use {@link DataTable.defaults}.
12971			 *  @type boolean
12972			 */
12973			"bPaginate": null,
12974	
12975			/**
12976			 * Processing indicator enable flag whenever DataTables is enacting a
12977			 * user request - typically an Ajax request for server-side processing.
12978			 * Note that this parameter will be set by the initialisation routine. To
12979			 * set a default use {@link DataTable.defaults}.
12980			 *  @type boolean
12981			 */
12982			"bProcessing": null,
12983	
12984			/**
12985			 * Server-side processing enabled flag - when enabled DataTables will
12986			 * get all data from the server for every draw - there is no filtering,
12987			 * sorting or paging done on the client-side.
12988			 * Note that this parameter will be set by the initialisation routine. To
12989			 * set a default use {@link DataTable.defaults}.
12990			 *  @type boolean
12991			 */
12992			"bServerSide": null,
12993	
12994			/**
12995			 * Sorting enablement flag.
12996			 * Note that this parameter will be set by the initialisation routine. To
12997			 * set a default use {@link DataTable.defaults}.
12998			 *  @type boolean
12999			 */
13000			"bSort": null,
13001	
13002			/**
13003			 * Multi-column sorting
13004			 * Note that this parameter will be set by the initialisation routine. To
13005			 * set a default use {@link DataTable.defaults}.
13006			 *  @type boolean
13007			 */
13008			"bSortMulti": null,
13009	
13010			/**
13011			 * Apply a class to the columns which are being sorted to provide a
13012			 * visual highlight or not. This can slow things down when enabled since
13013			 * there is a lot of DOM interaction.
13014			 * Note that this parameter will be set by the initialisation routine. To
13015			 * set a default use {@link DataTable.defaults}.
13016			 *  @type boolean
13017			 */
13018			"bSortClasses": null,
13019	
13020			/**
13021			 * State saving enablement flag.
13022			 * Note that this parameter will be set by the initialisation routine. To
13023			 * set a default use {@link DataTable.defaults}.
13024			 *  @type boolean
13025			 */
13026			"bStateSave": null
13027		},
13028	
13029	
13030		/**
13031		 * Scrolling settings for a table.
13032		 *  @namespace
13033		 */
13034		"oScroll": {
13035			/**
13036			 * When the table is shorter in height than sScrollY, collapse the
13037			 * table container down to the height of the table (when true).
13038			 * Note that this parameter will be set by the initialisation routine. To
13039			 * set a default use {@link DataTable.defaults}.
13040			 *  @type boolean
13041			 */
13042			"bCollapse": null,
13043	
13044			/**
13045			 * Width of the scrollbar for the web-browser's platform. Calculated
13046			 * during table initialisation.
13047			 *  @type int
13048			 *  @default 0
13049			 */
13050			"iBarWidth": 0,
13051	
13052			/**
13053			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13054			 * disabled if an empty string.
13055			 * Note that this parameter will be set by the initialisation routine. To
13056			 * set a default use {@link DataTable.defaults}.
13057			 *  @type string
13058			 */
13059			"sX": null,
13060	
13061			/**
13062			 * Width to expand the table to when using x-scrolling. Typically you
13063			 * should not need to use this.
13064			 * Note that this parameter will be set by the initialisation routine. To
13065			 * set a default use {@link DataTable.defaults}.
13066			 *  @type string
13067			 *  @deprecated
13068			 */
13069			"sXInner": null,
13070	
13071			/**
13072			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13073			 * if an empty string.
13074			 * Note that this parameter will be set by the initialisation routine. To
13075			 * set a default use {@link DataTable.defaults}.
13076			 *  @type string
13077			 */
13078			"sY": null
13079		},
13080	
13081		/**
13082		 * Language information for the table.
13083		 *  @namespace
13084		 *  @extends DataTable.defaults.oLanguage
13085		 */
13086		"oLanguage": {
13087			/**
13088			 * Information callback function. See
13089			 * {@link DataTable.defaults.fnInfoCallback}
13090			 *  @type function
13091			 *  @default null
13092			 */
13093			"fnInfoCallback": null
13094		},
13095	
13096		/**
13097		 * Browser support parameters
13098		 *  @namespace
13099		 */
13100		"oBrowser": {
13101			/**
13102			 * Indicate if the browser incorrectly calculates width:100% inside a
13103			 * scrolling element (IE6/7)
13104			 *  @type boolean
13105			 *  @default false
13106			 */
13107			"bScrollOversize": false,
13108	
13109			/**
13110			 * Determine if the vertical scrollbar is on the right or left of the
13111			 * scrolling container - needed for rtl language layout, although not
13112			 * all browsers move the scrollbar (Safari).
13113			 *  @type boolean
13114			 *  @default false
13115			 */
13116			"bScrollbarLeft": false,
13117	
13118			/**
13119			 * Flag for if `getBoundingClientRect` is fully supported or not
13120			 *  @type boolean
13121			 *  @default false
13122			 */
13123			"bBounding": false,
13124	
13125			/**
13126			 * Browser scrollbar width
13127			 *  @type integer
13128			 *  @default 0
13129			 */
13130			"barWidth": 0
13131		},
13132	
13133	
13134		"ajax": null,
13135	
13136	
13137		/**
13138		 * Array referencing the nodes which are used for the features. The
13139		 * parameters of this object match what is allowed by sDom - i.e.
13140		 *   <ul>
13141		 *     <li>'l' - Length changing</li>
13142		 *     <li>'f' - Filtering input</li>
13143		 *     <li>'t' - The table!</li>
13144		 *     <li>'i' - Information</li>
13145		 *     <li>'p' - Pagination</li>
13146		 *     <li>'r' - pRocessing</li>
13147		 *   </ul>
13148		 *  @type array
13149		 *  @default []
13150		 */
13151		"aanFeatures": [],
13152	
13153		/**
13154		 * Store data information - see {@link DataTable.models.oRow} for detailed
13155		 * information.
13156		 *  @type array
13157		 *  @default []
13158		 */
13159		"aoData": [],
13160	
13161		/**
13162		 * Array of indexes which are in the current display (after filtering etc)
13163		 *  @type array
13164		 *  @default []
13165		 */
13166		"aiDisplay": [],
13167	
13168		/**
13169		 * Array of indexes for display - no filtering
13170		 *  @type array
13171		 *  @default []
13172		 */
13173		"aiDisplayMaster": [],
13174	
13175		/**
13176		 * Map of row ids to data indexes
13177		 *  @type object
13178		 *  @default {}
13179		 */
13180		"aIds": {},
13181	
13182		/**
13183		 * Store information about each column that is in use
13184		 *  @type array
13185		 *  @default []
13186		 */
13187		"aoColumns": [],
13188	
13189		/**
13190		 * Store information about the table's header
13191		 *  @type array
13192		 *  @default []
13193		 */
13194		"aoHeader": [],
13195	
13196		/**
13197		 * Store information about the table's footer
13198		 *  @type array
13199		 *  @default []
13200		 */
13201		"aoFooter": [],
13202	
13203		/**
13204		 * Store the applied global search information in case we want to force a
13205		 * research or compare the old search to a new one.
13206		 * Note that this parameter will be set by the initialisation routine. To
13207		 * set a default use {@link DataTable.defaults}.
13208		 *  @namespace
13209		 *  @extends DataTable.models.oSearch
13210		 */
13211		"oPreviousSearch": {},
13212	
13213		/**
13214		 * Store the applied search for each column - see
13215		 * {@link DataTable.models.oSearch} for the format that is used for the
13216		 * filtering information for each column.
13217		 *  @type array
13218		 *  @default []
13219		 */
13220		"aoPreSearchCols": [],
13221	
13222		/**
13223		 * Sorting that is applied to the table. Note that the inner arrays are
13224		 * used in the following manner:
13225		 * <ul>
13226		 *   <li>Index 0 - column number</li>
13227		 *   <li>Index 1 - current sorting direction</li>
13228		 * </ul>
13229		 * Note that this parameter will be set by the initialisation routine. To
13230		 * set a default use {@link DataTable.defaults}.
13231		 *  @type array
13232		 *  @todo These inner arrays should really be objects
13233		 */
13234		"aaSorting": null,
13235	
13236		/**
13237		 * Sorting that is always applied to the table (i.e. prefixed in front of
13238		 * aaSorting).
13239		 * Note that this parameter will be set by the initialisation routine. To
13240		 * set a default use {@link DataTable.defaults}.
13241		 *  @type array
13242		 *  @default []
13243		 */
13244		"aaSortingFixed": [],
13245	
13246		/**
13247		 * Classes to use for the striping of a table.
13248		 * Note that this parameter will be set by the initialisation routine. To
13249		 * set a default use {@link DataTable.defaults}.
13250		 *  @type array
13251		 *  @default []
13252		 */
13253		"asStripeClasses": null,
13254	
13255		/**
13256		 * If restoring a table - we should restore its striping classes as well
13257		 *  @type array
13258		 *  @default []
13259		 */
13260		"asDestroyStripes": [],
13261	
13262		/**
13263		 * If restoring a table - we should restore its width
13264		 *  @type int
13265		 *  @default 0
13266		 */
13267		"sDestroyWidth": 0,
13268	
13269		/**
13270		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13271		 *  @type array
13272		 *  @default []
13273		 */
13274		"aoRowCallback": [],
13275	
13276		/**
13277		 * Callback functions for the header on each draw.
13278		 *  @type array
13279		 *  @default []
13280		 */
13281		"aoHeaderCallback": [],
13282	
13283		/**
13284		 * Callback function for the footer on each draw.
13285		 *  @type array
13286		 *  @default []
13287		 */
13288		"aoFooterCallback": [],
13289	
13290		/**
13291		 * Array of callback functions for draw callback functions
13292		 *  @type array
13293		 *  @default []
13294		 */
13295		"aoDrawCallback": [],
13296	
13297		/**
13298		 * Array of callback functions for row created function
13299		 *  @type array
13300		 *  @default []
13301		 */
13302		"aoRowCreatedCallback": [],
13303	
13304		/**
13305		 * Callback functions for just before the table is redrawn. A return of
13306		 * false will be used to cancel the draw.
13307		 *  @type array
13308		 *  @default []
13309		 */
13310		"aoPreDrawCallback": [],
13311	
13312		/**
13313		 * Callback functions for when the table has been initialised.
13314		 *  @type array
13315		 *  @default []
13316		 */
13317		"aoInitComplete": [],
13318	
13319	
13320		/**
13321		 * Callbacks for modifying the settings to be stored for state saving, prior to
13322		 * saving state.
13323		 *  @type array
13324		 *  @default []
13325		 */
13326		"aoStateSaveParams": [],
13327	
13328		/**
13329		 * Callbacks for modifying the settings that have been stored for state saving
13330		 * prior to using the stored values to restore the state.
13331		 *  @type array
13332		 *  @default []
13333		 */
13334		"aoStateLoadParams": [],
13335	
13336		/**
13337		 * Callbacks for operating on the settings object once the saved state has been
13338		 * loaded
13339		 *  @type array
13340		 *  @default []
13341		 */
13342		"aoStateLoaded": [],
13343	
13344		/**
13345		 * Cache the table ID for quick access
13346		 *  @type string
13347		 *  @default <i>Empty string</i>
13348		 */
13349		"sTableId": "",
13350	
13351		/**
13352		 * The TABLE node for the main table
13353		 *  @type node
13354		 *  @default null
13355		 */
13356		"nTable": null,
13357	
13358		/**
13359		 * Permanent ref to the thead element
13360		 *  @type node
13361		 *  @default null
13362		 */
13363		"nTHead": null,
13364	
13365		/**
13366		 * Permanent ref to the tfoot element - if it exists
13367		 *  @type node
13368		 *  @default null
13369		 */
13370		"nTFoot": null,
13371	
13372		/**
13373		 * Permanent ref to the tbody element
13374		 *  @type node
13375		 *  @default null
13376		 */
13377		"nTBody": null,
13378	
13379		/**
13380		 * Cache the wrapper node (contains all DataTables controlled elements)
13381		 *  @type node
13382		 *  @default null
13383		 */
13384		"nTableWrapper": null,
13385	
13386		/**
13387		 * Indicate if when using server-side processing the loading of data
13388		 * should be deferred until the second draw.
13389		 * Note that this parameter will be set by the initialisation routine. To
13390		 * set a default use {@link DataTable.defaults}.
13391		 *  @type boolean
13392		 *  @default false
13393		 */
13394		"bDeferLoading": false,
13395	
13396		/**
13397		 * Indicate if all required information has been read in
13398		 *  @type boolean
13399		 *  @default false
13400		 */
13401		"bInitialised": false,
13402	
13403		/**
13404		 * Information about open rows. Each object in the array has the parameters
13405		 * 'nTr' and 'nParent'
13406		 *  @type array
13407		 *  @default []
13408		 */
13409		"aoOpenRows": [],
13410	
13411		/**
13412		 * Dictate the positioning of DataTables' control elements - see
13413		 * {@link DataTable.model.oInit.sDom}.
13414		 * Note that this parameter will be set by the initialisation routine. To
13415		 * set a default use {@link DataTable.defaults}.
13416		 *  @type string
13417		 *  @default null
13418		 */
13419		"sDom": null,
13420	
13421		/**
13422		 * Search delay (in mS)
13423		 *  @type integer
13424		 *  @default null
13425		 */
13426		"searchDelay": null,
13427	
13428		/**
13429		 * Which type of pagination should be used.
13430		 * Note that this parameter will be set by the initialisation routine. To
13431		 * set a default use {@link DataTable.defaults}.
13432		 *  @type string
13433		 *  @default two_button
13434		 */
13435		"sPaginationType": "two_button",
13436	
13437		/**
13438		 * The state duration (for `stateSave`) in seconds.
13439		 * Note that this parameter will be set by the initialisation routine. To
13440		 * set a default use {@link DataTable.defaults}.
13441		 *  @type int
13442		 *  @default 0
13443		 */
13444		"iStateDuration": 0,
13445	
13446		/**
13447		 * Array of callback functions for state saving. Each array element is an
13448		 * object with the following parameters:
13449		 *   <ul>
13450		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13451		 *       and the JSON string to save that has been thus far created. Returns
13452		 *       a JSON string to be inserted into a json object
13453		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13454		 *     <li>string:sName - name of callback</li>
13455		 *   </ul>
13456		 *  @type array
13457		 *  @default []
13458		 */
13459		"aoStateSave": [],
13460	
13461		/**
13462		 * Array of callback functions for state loading. Each array element is an
13463		 * object with the following parameters:
13464		 *   <ul>
13465		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13466		 *       and the object stored. May return false to cancel state loading</li>
13467		 *     <li>string:sName - name of callback</li>
13468		 *   </ul>
13469		 *  @type array
13470		 *  @default []
13471		 */
13472		"aoStateLoad": [],
13473	
13474		/**
13475		 * State that was saved. Useful for back reference
13476		 *  @type object
13477		 *  @default null
13478		 */
13479		"oSavedState": null,
13480	
13481		/**
13482		 * State that was loaded. Useful for back reference
13483		 *  @type object
13484		 *  @default null
13485		 */
13486		"oLoadedState": null,
13487	
13488		/**
13489		 * Source url for AJAX data for the table.
13490		 * Note that this parameter will be set by the initialisation routine. To
13491		 * set a default use {@link DataTable.defaults}.
13492		 *  @type string
13493		 *  @default null
13494		 */
13495		"sAjaxSource": null,
13496	
13497		/**
13498		 * Property from a given object from which to read the table data from. This
13499		 * can be an empty string (when not server-side processing), in which case
13500		 * it is  assumed an an array is given directly.
13501		 * Note that this parameter will be set by the initialisation routine. To
13502		 * set a default use {@link DataTable.defaults}.
13503		 *  @type string
13504		 */
13505		"sAjaxDataProp": null,
13506	
13507		/**
13508		 * 
13508Note if draw should be blocked while getting data
13509		 *  @type boolean
13510		 *  @default true
13511		 */
13512		"bAjaxDataGet": true,
13513	
13514		/**
13515		 * The last jQuery XHR object that was used for server-side data gathering.
13516		 * This can be used for working with the XHR information in one of the
13517		 * callbacks
13518		 *  @type object
13519		 *  @default null
13520		 */
13521		"jqXHR": null,
13522	
13523		/**
13524		 * JSON returned from the server in the last Ajax request
13525		 *  @type object
13526		 *  @default undefined
13527		 */
13528		"json": undefined,
13529	
13530		/**
13531		 * Data submitted as part of the last Ajax request
13532		 *  @type object
13533		 *  @default undefined
13534		 */
13535		"oAjaxData": undefined,
13536	
13537		/**
13538		 * Function to get the server-side data.
13539		 * Note that this parameter will be set by the initialisation routine. To
13540		 * set a default use {@link DataTable.defaults}.
13541		 *  @type function
13542		 */
13543		"fnServerData": null,
13544	
13545		/**
13546		 * Functions which are called prior to sending an Ajax request so extra
13547		 * parameters can easily be sent to the server
13548		 *  @type array
13549		 *  @default []
13550		 */
13551		"aoServerParams": [],
13552	
13553		/**
13554		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13555		 * required).
13556		 * Note that this parameter will be set by the initialisation routine. To
13557		 * set a default use {@link DataTable.defaults}.
13558		 *  @type string
13559		 */
13560		"sServerMethod": null,
13561	
13562		/**
13563		 * Format numbers for display.
13564		 * Note that this parameter will be set by the initialisation routine. To
13565		 * set a default use {@link DataTable.defaults}.
13566		 *  @type function
13567		 */
13568		"fnFormatNumber": null,
13569	
13570		/**
13571		 * List of options that can be used for the user selectable length menu.
13572		 * Note that this parameter will be set by the initialisation routine. To
13573		 * set a default use {@link DataTable.defaults}.
13574		 *  @type array
13575		 *  @default []
13576		 */
13577		"aLengthMenu": null,
13578	
13579		/**
13580		 * Counter for the draws that the table does. Also used as a tracker for
13581		 * server-side processing
13582		 *  @type int
13583		 *  @default 0
13584		 */
13585		"iDraw": 0,
13586	
13587		/**
13588		 * Indicate if a redraw is being done - useful for Ajax
13589		 *  @type boolean
13590		 *  @default false
13591		 */
13592		"bDrawing": false,
13593	
13594		/**
13595		 * Draw index (iDraw) of the last error when parsing the returned data
13596		 *  @type int
13597		 *  @default -1
13598		 */
13599		"iDrawError": -1,
13600	
13601		/**
13602		 * Paging display length
13603		 *  @type int
13604		 *  @default 10
13605		 */
13606		"_iDisplayLength": 10,
13607	
13608		/**
13609		 * Paging start point - aiDisplay index
13610		 *  @type int
13611		 *  @default 0
13612		 */
13613		"_iDisplayStart": 0,
13614	
13615		/**
13616		 * Server-side processing - number of records in the result set
13617		 * (i.e. before filtering), Use fnRecordsTotal rather than
13618		 * this property to get the value of the number of records, regardless of
13619		 * the server-side processing setting.
13620		 *  @type int
13621		 *  @default 0
13622		 *  @private
13623		 */
13624		"_iRecordsTotal": 0,
13625	
13626		/**
13627		 * Server-side processing - number of records in the current display set
13628		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13629		 * this property to get the value of the number of records, regardless of
13630		 * the server-side processing setting.
13631		 *  @type boolean
13632		 *  @default 0
13633		 *  @private
13634		 */
13635		"_iRecordsDisplay": 0,
13636	
13637		/**
13638		 * The classes to use for the table
13639		 *  @type object
13640		 *  @default {}
13641		 */
vendor: 4,830 bytes, lines 13642-13850
13642		"oClasses": {},
13643	
13644		/**
13645		 * Flag attached to the settings object so you can check in the draw
13646		 * callback if filtering has been done in the draw. Deprecated in favour of
13647		 * events.
13648		 *  @type boolean
13649		 *  @default false
13650		 *  @deprecated
13651		 */
13652		"bFiltered": false,
13653	
13654		/**
13655		 * Flag attached to the settings object so you can check in the draw
13656		 * callback if sorting has been done in the draw. Deprecated in favour of
13657		 * events.
13658		 *  @type boolean
13659		 *  @default false
13660		 *  @deprecated
13661		 */
13662		"bSorted": false,
13663	
13664		/**
13665		 * Indicate that if multiple rows are in the header and there is more than
13666		 * one unique cell per column, if the top one (true) or bottom one (false)
13667		 * should be used for sorting / title by DataTables.
13668		 * Note that this parameter will be set by the initialisation routine. To
13669		 * set a default use {@link DataTable.defaults}.
13670		 *  @type boolean
13671		 */
13672		"bSortCellsTop": null,
13673	
13674		/**
13675		 * Initialisation object that is used for the table
13676		 *  @type object
13677		 *  @default null
13678		 */
13679		"oInit": null,
13680	
13681		/**
13682		 * Destroy callback functions - for plug-ins to attach themselves to the
13683		 * destroy so they can clean up markup and events.
13684		 *  @type array
13685		 *  @default []
13686		 */
13687		"aoDestroyCallback": [],
13688	
13689	
13690		/**
13691		 * Get the number of records in the current record set, before filtering
13692		 *  @type function
13693		 */
13694		"fnRecordsTotal": function ()
13695		{
13696			return _fnDataSource( this ) == 'ssp' ?
13697				this._iRecordsTotal * 1 :
13698				this.aiDisplayMaster.length;
13699		},
13700	
13701		/**
13702		 * Get the number of records in the current record set, after filtering
13703		 *  @type function
13704		 */
13705		"fnRecordsDisplay": function ()
13706		{
13707			return _fnDataSource( this ) == 'ssp' ?
13708				this._iRecordsDisplay * 1 :
13709				this.aiDisplay.length;
13710		},
13711	
13712		/**
13713		 * Get the display end point - aiDisplay index
13714		 *  @type function
13715		 */
13716		"fnDisplayEnd": function ()
13717		{
13718			var
13719				len      = this._iDisplayLength,
13720				start    = this._iDisplayStart,
13721				calc     = start + len,
13722				records  = this.aiDisplay.length,
13723				features = this.oFeatures,
13724				paginate = features.bPaginate;
13725	
13726			if ( features.bServerSide ) {
13727				return paginate === false || len === -1 ?
13728					start + records :
13729					Math.min( start+len, this._iRecordsDisplay );
13730			}
13731			else {
13732				return ! paginate || calc>records || len===-1 ?
13733					records :
13734					calc;
13735			}
13736		},
13737	
13738		/**
13739		 * The DataTables object for this table
13740		 *  @type object
13741		 *  @default null
13742		 */
13743		"oInstance": null,
13744	
13745		/**
13746		 * Unique identifier for each instance of the DataTables object. If there
13747		 * is an ID on the table node, then it takes that value, otherwise an
13748		 * incrementing internal counter is used.
13749		 *  @type string
13750		 *  @default null
13751		 */
13752		"sInstance": null,
13753	
13754		/**
13755		 * tabindex attribute value that is added to DataTables control elements, allowing
13756		 * keyboard navigation of the table and its controls.
13757		 */
13758		"iTabIndex": 0,
13759	
13760		/**
13761		 * DIV container for the footer scrolling table if scrolling
13762		 */
13763		"nScrollHead": null,
13764	
13765		/**
13766		 * DIV container for the footer scrolling table if scrolling
13767		 */
13768		"nScrollFoot": null,
13769	
13770		/**
13771		 * Last applied sort
13772		 *  @type array
13773		 *  @default []
13774		 */
13775		"aLastSort": [],
13776	
13777		/**
13778		 * Stored plug-in instances
13779		 *  @type object
13780		 *  @default {}
13781		 */
13782		"oPlugins": {},
13783	
13784		/**
13785		 * Function used to get a row's id from the row's data
13786		 *  @type function
13787		 *  @default null
13788		 */
13789		"rowIdFn": null,
13790	
13791		/**
13792		 * Data location where to store a row's id
13793		 *  @type string
13794		 *  @default null
13795		 */
13796		"rowId": null
13797	};
13798
13799	/**
13800	 * Extension object for DataTables that is used to provide all extension
13801	 * options.
13802	 *
13803	 * Note that the `DataTable.ext` object is available through
13804	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13805	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13806	 *  @namespace
13807	 *  @extends DataTable.models.ext
13808	 */
13809	
13810	
13811	/**
13812	 * DataTables extensions
13813	 * 
13814	 * This namespace acts as a collection area for plug-ins that can be used to
13815	 * extend DataTables capabilities. Indeed many of the build in methods
13816	 * use this method to provide their own capabilities (sorting methods for
13817	 * example).
13818	 *
13819	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13820	 * reasons
13821	 *
13822	 *  @namespace
13823	 */
13824	DataTable.ext = _ext = {
13825		/**
13826		 * Buttons. For use with the Buttons extension for DataTables. This is
13827		 * defined here so other extensions can define buttons regardless of load
13828		 * order. It is _not_ used by DataTables core.
13829		 *
13830		 *  @type object
13831		 *  @default {}
13832		 */
13833		buttons: {},
13834	
13835	
13836		/**
13837		 * Element class names
13838		 *
13839		 *  @type object
13840		 *  @default {}
13841		 */
13842		classes: {},
13843	
13844	
13845		/**
13846		 * DataTables build type (expanded by the download builder)
13847		 *
13848		 *  @type string
13849		 */
13850		build:"bs/dt-1.10.16/r-2.2.1
vendor: 10,712 bytes, lines 13850-14164
13850",
13851	
13852	
13853		/**
13854		 * Error reporting.
13855		 * 
13856		 * How should DataTables report an error. Can take the value 'alert',
13857		 * 'throw', 'none' or a function.
13858		 *
13859		 *  @type string|function
13860		 *  @default alert
13861		 */
13862		errMode: "alert",
13863	
13864	
13865		/**
13866		 * Feature plug-ins.
13867		 * 
13868		 * This is an array of objects which describe the feature plug-ins that are
13869		 * available to DataTables. These feature plug-ins are then available for
13870		 * use through the `dom` initialisation option.
13871		 * 
13872		 * Each feature plug-in is described by an object which must have the
13873		 * following properties:
13874		 * 
13875		 * * `fnInit` - function that is used to initialise the plug-in,
13876		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13877		 *   instillation option. This is case sensitive.
13878		 *
13879		 * The `fnInit` function has the following input parameters:
13880		 *
13881		 * 1. `{object}` DataTables settings object: see
13882		 *    {@link DataTable.models.oSettings}
13883		 *
13884		 * And the following return is expected:
13885		 * 
13886		 * * {node|null} The element which contains your feature. Note that the
13887		 *   return may also be void if your plug-in does not require to inject any
13888		 *   DOM elements into DataTables control (`dom`) - for example this might
13889		 *   be useful when developing a plug-in which allows table control via
13890		 *   keyboard entry
13891		 *
13892		 *  @type array
13893		 *
13894		 *  @example
13895		 *    $.fn.dataTable.ext.features.push( {
13896		 *      "fnInit": function( oSettings ) {
13897		 *        return new TableTools( { "oDTSettings": oSettings } );
13898		 *      },
13899		 *      "cFeature": "T"
13900		 *    } );
13901		 */
13902		feature: [],
13903	
13904	
13905		/**
13906		 * Row searching.
13907		 * 
13908		 * This method of searching is complimentary to the default type based
13909		 * searching, and a lot more comprehensive as it allows you complete control
13910		 * over the searching logic. Each element in this array is a function
13911		 * (parameters described below) that is called for every row in the table,
13912		 * and your logic decides if it should be included in the searching data set
13913		 * or not.
13914		 *
13915		 * Searching functions have the following input parameters:
13916		 *
13917		 * 1. `{object}` DataTables settings object: see
13918		 *    {@link DataTable.models.oSettings}
13919		 * 2. `{array|object}` Data for the row to be processed (same as the
13920		 *    original format that was passed in as the data source, or an array
13921		 *    from a DOM data source
13922		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13923		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13924		 *
13925		 * And the following return is expected:
13926		 *
13927		 * * {boolean} Include the row in the searched result set (true) or not
13928		 *   (false)
13929		 *
13930		 * Note that as with the main search ability in DataTables, technically this
13931		 * is "filtering", since it is subtractive. However, for consistency in
13932		 * naming we call it searching here.
13933		 *
13934		 *  @type array
13935		 *  @default []
13936		 *
13937		 *  @example
13938		 *    // The following example shows custom search being applied to the
13939		 *    // fourth column (i.e. the data[3] index) based on two input values
13940		 *    // from the end-user, matching the data in a certain range.
13941		 *    $.fn.dataTable.ext.search.push(
13942		 *      function( settings, data, dataIndex ) {
13943		 *        var min = document.getElementById('min').value * 1;
13944		 *        var max = document.getElementById('max').value * 1;
13945		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13946		 *
13947		 *        if ( min == "" && max == "" ) {
13948		 *          return true;
13949		 *        }
13950		 *        else if ( min == "" && version < max ) {
13951		 *          return true;
13952		 *        }
13953		 *        else if ( min < version && "" == max ) {
13954		 *          return true;
13955		 *        }
13956		 *        else if ( min < version && version < max ) {
13957		 *          return true;
13958		 *        }
13959		 *        return false;
13960		 *      }
13961		 *    );
13962		 */
13963		search: [],
13964	
13965	
13966		/**
13967		 * Selector extensions
13968		 *
13969		 * The `selector` option can be used to extend the options available for the
13970		 * selector modifier options (`selector-modifier` object data type) that
13971		 * each of the three built in selector types offer (row, column and cell +
13972		 * their plural counterparts). For example the Select extension uses this
13973		 * mechanism to provide an option to select only rows, columns and cells
13974		 * that have been marked as selected by the end user (`{selected: true}`),
13975		 * which can be used in conjunction with the existing built in selector
13976		 * options.
13977		 *
13978		 * Each property is an array to which functions can be pushed. The functions
13979		 * take three attributes:
13980		 *
13981		 * * Settings object for the host table
13982		 * * Options object (`selector-modifier` object type)
13983		 * * Array of selected item indexes
13984		 *
13985		 * The return is an array of the resulting item indexes after the custom
13986		 * selector has been applied.
13987		 *
13988		 *  @type object
13989		 */
13990		selector: {
13991			cell: [],
13992			column: [],
13993			row: []
13994		},
13995	
13996	
13997		/**
13998		 * Internal functions, exposed for used in plug-ins.
13999		 * 
14000		 * Please note that you should not need to use the internal methods for
14001		 * anything other than a plug-in (and even then, try to avoid if possible).
14002		 * The internal function may change between releases.
14003		 *
14004		 *  @type object
14005		 *  @default {}
14006		 */
14007		internal: {},
14008	
14009	
14010		/**
14011		 * Legacy configuration options. Enable and disable legacy options that
14012		 * are available in DataTables.
14013		 *
14014		 *  @type object
14015		 */
14016		legacy: {
14017			/**
14018			 * Enable / disable DataTables 1.9 compatible server-side processing
14019			 * requests
14020			 *
14021			 *  @type boolean
14022			 *  @default null
14023			 */
14024			ajax: null
14025		},
14026	
14027	
14028		/**
14029		 * Pagination plug-in methods.
14030		 * 
14031		 * Each entry in this object is a function and defines which buttons should
14032		 * be shown by the pagination rendering method that is used for the table:
14033		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14034		 * buttons are displayed in the document, while the functions here tell it
14035		 * what buttons to display. This is done by returning an array of button
14036		 * descriptions (what each button will do).
14037		 *
14038		 * Pagination types (the four built in options and any additional plug-in
14039		 * options defined here) can be used through the `paginationType`
14040		 * initialisation parameter.
14041		 *
14042		 * The functions defined take two parameters:
14043		 *
14044		 * 1. `{int} page` The current page index
14045		 * 2. `{int} pages` The number of pages in the table
14046		 *
14047		 * Each function is expected to return an array where each element of the
14048		 * array can be one of:
14049		 *
14050		 * * `first` - Jump to first page when activated
14051		 * * `last` - Jump to last page when activated
14052		 * * `previous` - Show previous page when activated
14053		 * * `next` - Show next page when activated
14054		 * * `{int}` - Show page of the index given
14055		 * * `{array}` - A nested array containing the above elements to add a
14056		 *   containing 'DIV' element (might be useful for styling).
14057		 *
14058		 * Note that DataTables v1.9- used this object slightly differently whereby
14059		 * an object with two functions would be defined for each plug-in. That
14060		 * ability is still supported by DataTables 1.10+ to provide backwards
14061		 * compatibility, but this option of use is now decremented and no longer
14062		 * documented in DataTables 1.10+.
14063		 *
14064		 *  @type object
14065		 *  @default {}
14066		 *
14067		 *  @example
14068		 *    // Show previous, next and current page buttons only
14069		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14070		 *      return [ 'previous', page, 'next' ];
14071		 *    };
14072		 */
14073		pager: {},
14074	
14075	
14076		renderer: {
14077			pageButton: {},
14078			header: {}
14079		},
14080	
14081	
14082		/**
14083		 * Ordering plug-ins - custom data source
14084		 * 
14085		 * The extension options for ordering of data available here is complimentary
14086		 * to the default type based ordering that DataTables typically uses. It
14087		 * allows much greater control over the the data that is being used to
14088		 * order a column, but is necessarily therefore more complex.
14089		 * 
14090		 * This type of ordering is useful if you want to do ordering based on data
14091		 * live from the DOM (for example the contents of an 'input' element) rather
14092		 * than just the static string that DataTables knows of.
14093		 * 
14094		 * The way these plug-ins work is that you create an array of the values you
14095		 * wish to be ordering for the column in question and then return that
14096		 * array. The data in the array much be in the index order of the rows in
14097		 * the table (not the currently ordering order!). Which order data gathering
14098		 * function is run here depends on the `dt-init columns.orderDataType`
14099		 * parameter that is used for the column (if any).
14100		 *
14101		 * The functions defined take two parameters:
14102		 *
14103		 * 1. `{object}` DataTables settings object: see
14104		 *    {@link DataTable.models.oSettings}
14105		 * 2. `{int}` Target column index
14106		 *
14107		 * Each function is expected to return an array:
14108		 *
14109		 * * `{array}` Data for the column to be ordering upon
14110		 *
14111		 *  @type array
14112		 *
14113		 *  @example
14114		 *    // Ordering using `input` node values
14115		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14116		 *    {
14117		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14118		 *        return $('input', td).val();
14119		 *      } );
14120		 *    }
14121		 */
14122		order: {},
14123	
14124	
14125		/**
14126		 * Type based plug-ins.
14127		 *
14128		 * Each column in DataTables has a type assigned to it, either by automatic
14129		 * detection or by direct assignment using the `type` option for the column.
14130		 * The type of a column will effect how it is ordering and search (plug-ins
14131		 * can also make use of the column type if required).
14132		 *
14133		 * @namespace
14134		 */
14135		type: {
14136			/**
14137			 * Type detection functions.
14138			 *
14139			 * The functions defined in this object are used to automatically detect
14140			 * a column's type, making initialisation of DataTables super easy, even
14141			 * when complex data is in the table.
14142			 *
14143			 * The functions defined take two parameters:
14144			 *
14145		     *  1. `{*}` Data from the column cell to be analysed
14146		     *  2. `{settings}` DataTables settings object. This can be used to
14147		     *     perform context specific type detection - for example detection
14148		     *     based on language settings such as using a comma for a decimal
14149		     *     place. Generally speaking the options from the settings will not
14150		     *     be required
14151			 *
14152			 * Each function is expected to return:
14153			 *
14154			 * * `{string|null}` Data type detected, or null if unknown (and thus
14155			 *   pass it on to the other type detection functions.
14156			 *
14157			 *  @type array
14158			 *
14159			 *  @example
14160			 *    // Currency type detection plug-in:
14161			 *    $.fn.dataTable.ext.type.detect.push(
14162			 *      function ( data, settings ) {
14163			 *        // Check the numeric part
14164			 *        if ( ! 
14164$.isNumeric( data.substring(1) ) ) {
14165			 *          return null;
14166			 *        }
14167			 *
14168			 *        // Check prefixed by currency
14169			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14170			 *          return 'currency';
14171			 *        }
14172			 *        return null;
14173			 *      }
14174			 *    );
14175			 */
14176			detect: [],
14177	
14178	
14179			/**
14180			 * Type based search formatting.
14181			 *
14182			 * The type based searching functions can be used to pre-format the
14183			 * data to be search on. For example, it can be used to strip HTML
14184			 * tags or to de-format telephone numbers for numeric only searching.
14185			 *
14186			 * Note that is a search is not defined for a column of a given type,
14187			 * no search formatting will be performed.
14188			 * 
14189			 * Pre-processing of searching data plug-ins - When you assign the sType
14190			 * for a column (or have it automatically detected for you by DataTables
14191			 * or a type detection plug-in), you will typically be using this for
14192			 * custom sorting, but it can also be used to provide custom searching
14193			 * by allowing you to pre-processing the data and returning the data in
14194			 * the format that should be searched upon. This is done by adding
14195			 * functions this object with a parameter name which matches the sType
14196			 * for that target column. This is the corollary of <i>afnSortData</i>
14197			 * for searching data.
14198			 *
14199			 * The functions defined take a single parameter:
14200			 *
14201		     *  1. `{*}` Data from the column cell to be prepared for searching
14202			 *
14203			 * Each function is expected to return:
14204			 *
14205			 * * `{string|null}` Formatted string that will be used for the searching.
14206			 *
14207			 *  @type object
14208			 *  @default {}
14209			 *
14210			 *  @example
14211			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14212			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14213			 *    }
14214			 */
14215			search: {},
14216	
14217	
14218			/**
14219			 * Type based ordering.
14220			 *
14221			 * The column type tells DataTables what ordering to apply to the table
14222			 * when a column is sorted upon. The order for each type that is defined,
14223			 * is defined by the functions available in this object.
14224			 *
14225			 * Each ordering option can be described by three properties added to
14226			 * this object:
14227			 *
14228			 * * `{type}-pre` - Pre-formatting function
14229			 * * `{type}-asc` - Ascending order function
14230			 * * `{type}-desc` - Descending order function
14231			 *
14232			 * All three can be used together, only `{type}-pre` or only
14233			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14234			 * that only `{type}-pre` is used, as this provides the optimal
14235			 * implementation in terms of speed, although the others are provided
14236			 * for compatibility with existing Javascript sort functions.
14237			 *
14238			 * `{type}-pre`: Functions defined take a single parameter:
14239			 *
14240		     *  1. `{*}` Data from the column cell to be prepared for ordering
14241			 *
14242			 * And return:
14243			 *
14244			 * * `{*}` Data to be sorted upon
14245			 *
14246			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14247			 * functions, taking two parameters:
14248			 *
14249		     *  1. `{*}` Data to compare to the second parameter
14250		     *  2. `{*}` Data to compare to the first parameter
14251			 *
14252			 * And returning:
14253			 *
14254			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14255			 *   than the second parameter, ===0 if the two parameters are equal and
14256			 *   >0 if the first parameter should be sorted height than the second
14257			 *   parameter.
14258			 * 
14259			 *  @type object
14260			 *  @default {}
14261			 *
14262			 *  @example
14263			 *    // Numeric ordering of formatted numbers with a pre-formatter
14264			 *    $.extend( $.fn.dataTable.ext.type.order, {
14265			 *      "string-pre": function(x) {
14266			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14267			 *        return parseFloat( a );
14268			 *      }
14269			 *    } );
14270			 *
14271			 *  @example
14272			 *    // Case-sensitive string ordering, with no pre-formatting method
14273			 *    $.extend( $.fn.dataTable.ext.order, {
14274			 *      "string-case-asc": function(x,y) {
14275			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14276			 *      },
14277			 *      "string-case-desc": function(x,y) {
14278			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14279			 *      }
14280			 *    } );
14281			 */
14282			order: {}
14283		},
14284	
14285		/**
14286		 * Unique DataTables instance counter
14287		 *
14288		 * @type int
14289		 * @private
14290		 */
14291		_unique: 0,
14292	
14293	
14294		//
14295		// Depreciated
14296		// The following properties are retained for backwards compatiblity only.
14297		// The should not be used in new projects and will be removed in a future
14298		// version
14299		//
14300	
14301		/**
14302		 * Version check function.
14303		 *  @type function
14304		 *  @depreciated Since 1.10
14305		 */
14306		fnVersionCheck: DataTable.fnVersionCheck,
14307	
14308	
14309		/**
14310		 * Index for what 'this' index API functions should use
14311		 *  @type int
14312		 *  @deprecated Since v1.10
14313		 */
14314		iApiIndex: 0,
14315	
14316	
14317		/**
14318		 * jQuery UI class container
14319		 *  @type object
14320		 *  @deprecated Since v1.10
14321		 */
14322		oJUIClasses: {},
14323	
14324	
14325		/**
14326		 * Software version
14327		 *  @type string
14328		 *  @deprecated Since v1.10
14329		 */
14330		sVersion: DataTable.version
14331	};
14332	
14333	
14334	//
14335	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14336	//
14337	$.extend( _ext, {
14338		afnFiltering: _ext.search,
14339		aTypes:       _ext.type.detect,
14340		ofnSearch:    _ext.type.search,
14341		oSort:        _ext.type.order,
14342		afnSortData:  _ext.order,
14343		aoFeatures:   _ext.feature,
14344		oApi:         _ext.internal,
14345		oStdClasses:  _ext.classes,
14346		oPagination:  _ext.pager
14347	} );
14348	
14349	
14350	$.extend( DataTable.ext.classes, {
14351		"sTable": "dataTable",
14352		"sNoFooter": "no-footer",
14353	
14354		/* Paging buttons */
14355		"sPageButton": "paginate_button",
14356		"sPageButtonActive": "current",
14357		"sPageButtonDisabled": "disabled",
14358	
14359		/* Striping classes */
14360		"sStripeOdd": "odd",
14361		"sStripeEven": "even",
14362	
14363		/* Empty row */
14364		"sRowEmpty": "dataTables_empty",
14365	
14366		/* Features */
14367		"sWrapper": "dataTables_wrapper",
14368		"sFilter": "dataTables_filter",
14369		"sInfo": "dataTables_info",
14370		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14371		"sLength": "dataTables_length",
14372		"sProcessing": "dataTables_processing",
14373	
14374		/* Sorting */
14375		"sSortAsc": "sorting_asc",
14376		"sSortDesc": "sorting_desc",
14377		"sSortable": "sorting", /* Sortable in both directions */
14378		"sSortableAsc": "sorting_asc_disabled",
14379		"sSortableDesc": "sorting_desc_disabled",
14380		"sSortableNone": "sorting_disabled",
14381		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14382	
14383		/* Filtering */
14384		"sFilterInput": "",
14385	
14386		/* Page length */
14387		"sLengthSelect": "",
14388	
14389		/* Scrolling */
14390		"sScrollWrapper": "dataTables_scroll",
14391		"sScrollHead": "dataTables_scrollHead",
14392		"sScrollHeadInner": "dataTables_scrollHeadInner",
14393		"sScrollBody": "dataTables_scrollBody",
14394		"sScrollFoot": "dataTables_scrollFoot",
14395		"sScrollFootInner": "dataTables_scrollFootInner",
14396	
14397		/* Misc */
14398		"sHeaderTH": "",
14399		"sFooterTH": "",
14400	
14401		// Deprecated
14402		"sSortJUIAsc": "",
14403		"sSortJUIDesc": "",
14404		"sSortJUI": "",
14405		"sSortJUIAscAllowed": "",
14406		"sSortJUIDescAllowed": "",
14407		"sSortJUIWrapper": "",
14408		"sSortIcon": "",
14409		"sJUIHeader": "",
14410		"sJUIFooter": ""
14411	} );
14412	
14413	
14414	var extPagination = DataTable.ext.pager;
14415	
14416	function _numbers ( page, pages ) {
14417		var
14418			numbers = [],
14419			buttons = extPagination.numbers_length,
14420			half = Math.floor( buttons / 2 ),
14421			i = 1;
14422	
14423		if ( pages <= buttons ) {
14424			numbers = _range( 0, pages );
14425		}
14426		else if ( page <= half ) {
14427			numbers = _range( 0, buttons-2 );
14428			numbers.push( 'ellipsis' );
14429			numbers.push( pages-1 );
14430		}
14431		else if ( page >= pages - 1 - half ) {
14432			numbers = _range( pages-(buttons-2), pages );
14433			numbers.splice( 0, 0, 'ellipsis' );
14433 // no unshift in ie6
14434			numbers.splice( 0, 0, 0 );
14435		}
14436		else {
14437			numbers = _range( page-half+2, page+half-1 );
14438			numbers.push( 'ellipsis' );
14439			numbers.push( pages-1 );
14440			numbers.splice( 0, 0, 'ellipsis' );
14441			numbers.splice( 0, 0, 0 );
14442		}
14443	
14444		numbers.DT_el = 'span';
14445		return numbers;
14446	}
14447	
14448	
14449	$.extend( extPagination, {
14450		simple: function ( page, pages ) {
14451			return [ 'previous', 'next' ];
14452		},
14453	
14454		full: function ( page, pages ) {
14455			return [  'first', 'previous', 'next', 'last' ];
14456		},
14457	
14458		numbers: function ( page, pages ) {
14459			return [ _numbers(page, pages) ];
14460		},
14461	
14462		simple_numbers: function ( page, pages ) {
14463			return [ 'previous', _numbers(page, pages), 'next' ];
14464		},
14465	
14466		full_numbers: function ( page, pages ) {
14467			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14468		},
14469		
14470		first_last_numbers: function (page, pages) {
14471	 		return ['first', _numbers(page, pages), 'last'];
14472	 	},
14473	
14474		// For testing and plug-ins to use
14475		_numbers: _numbers,
14476	
14477		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14478		numbers_length: 7
14479	} );
14480	
14481	
14482	$.extend( true, DataTable.ext.renderer, {
14483		pageButton: {
14484			_: function ( settings, host, idx, buttons, page, pages ) {
14485				var classes = settings.oClasses;
14486				var lang = settings.oLanguage.oPaginate;
14487				var aria = settings.oLanguage.oAria.paginate || {};
14488				var btnDisplay, btnClass, counter=0;
14489	
14490				var attach = function( container, buttons ) {
14491					var i, ien, node, button;
14492					var clickHandler = function ( e ) {
14493						_fnPageChange( settings, e.data.action, true );
14494					};
14495	
14496					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14497						button = buttons[i];
14498	
14499						if ( $.isArray( button ) ) {
14500							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14501								.appendTo( container );
14502							attach( inner, button );
14503						}
14504						else {
14505							btnDisplay = null;
14506							btnClass = '';
14507	
14508							switch ( button ) {
14509								case 'ellipsis':
14510									container.append('<span class="ellipsis">&#x2026;</span>');
14511									break;
14512	
14513								case 'first':
14514									btnDisplay = lang.sFirst;
14515									btnClass = button + (page > 0 ?
14516										'' : ' '+classes.sPageButtonDisabled);
14517									break;
14518	
14519								case 'previous':
14520									btnDisplay = lang.sPrevious;
14521									btnClass = button + (page > 0 ?
14522										'' : ' '+classes.sPageButtonDisabled);
14523									break;
14524	
14525								case 'next':
14526									btnDisplay = lang.sNext;
14527									btnClass = button + (page < pages-1 ?
14528										'' : ' '+classes.sPageButtonDisabled);
14529									break;
14530	
14531								case 'last':
14532									btnDisplay = lang.sLast;
14533									btnClass = button + (page < pages-1 ?
14534										'' : ' '+classes.sPageButtonDisabled);
14535									break;
14536	
14537								default:
14538									btnDisplay = button + 1;
14539									btnClass = page === button ?
14540										classes.sPageButtonActive : '';
14541									break;
14542							}
14543	
14544							if ( btnDisplay !== null ) {
14545								node = $('<a>', {
14546										'class': classes.sPageButton+' '+btnClass,
14547										'aria-controls': settings.sTableId,
14548										'aria-label': aria[ button ],
14549										'data-dt-idx': counter,
14550										'tabindex': settings.iTabIndex,
14551										'id': idx === 0 && typeof button === 'string' ?
14552											settings.sTableId +'_'+ button :
14553											null
14554									} )
14555									.html( btnDisplay )
14556									.appendTo( container );
14557	
14558								_fnBindAction(
14559									node, {action: button}, clickHandler
14560								);
14561	
14562								counter++;
14563							}
14564						}
14565					}
14566				};
14567	
14568				// IE9 throws an 'unknown error' if document.activeElement is used
14569				// inside an iframe or frame. Try / catch the error. Not good for
14570				// accessibility, but neither are frames.
14571				var activeEl;
14572	
14573				try {
14574					// Because this approach is destroying and recreating the paging
14575					// elements, focus is lost on the select button which is bad for
14576					// accessibility. So we want to restore focus once the draw has
14577					// completed
14578					activeEl = $(host).find(document.activeElement).data('dt-idx');
14579				}
14580				catch (e) {}
14581	
14582				attach( $(host).empty(), buttons );
14583	
14584				if ( activeEl !== undefined ) {
14585					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14586				}
14587			}
14588		}
14589	} );
14590	
14591	
14592	
14593	// Built in type detection. See model.ext.aTypes for information about
14594	// what is required from this methods.
14595	$.extend( DataTable.ext.type.detect, [
vendor: 18,159 bytes, lines 14596-15190
14596		// Plain numbers - first since V8 detects some plain numbers as dates
14597		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14598		function ( d, settings )
14599		{
14600			var decimal = settings.oLanguage.sDecimal;
14601			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14602		},
14603	
14604		// Dates (only those recognised by the browser's Date.parse)
14605		function ( d, settings )
14606		{
14607			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14608			// valid, so we need to use a regex to restrict date formats. Use a
14609			// plug-in for anything other than ISO8601 style strings
14610			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14611				return null;
14612			}
14613			var parsed = Date.parse(d);
14614			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14615		},
14616	
14617		// Formatted numbers
14618		function ( d, settings )
14619		{
14620			var decimal = settings.oLanguage.sDecimal;
14621			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14622		},
14623	
14624		// HTML numeric
14625		function ( d, settings )
14626		{
14627			var decimal = settings.oLanguage.sDecimal;
14628			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14629		},
14630	
14631		// HTML numeric, formatted
14632		function ( d, settings )
14633		{
14634			var decimal = settings.oLanguage.sDecimal;
14635			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14636		},
14637	
14638		// HTML (this is strict checking - there must be html)
14639		function ( d, settings )
14640		{
14641			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14642				'html' : null;
14643		}
14644	] );
14645	
14646	
14647	
14648	// Filter formatting functions. See model.ext.ofnSearch for information about
14649	// what is required from these methods.
14650	// 
14651	// Note that additional search methods are added for the html numbers and
14652	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14653	// place is
14654	
14655	
14656	$.extend( DataTable.ext.type.search, {
14657		html: function ( data ) {
14658			return _empty(data) ?
14659				data :
14660				typeof data === 'string' ?
14661					data
14662						.replace( _re_new_lines, " " )
14663						.replace( _re_html, "" ) :
14664					'';
14665		},
14666	
14667		string: function ( data ) {
14668			return _empty(data) ?
14669				data :
14670				typeof data === 'string' ?
14671					data.replace( _re_new_lines, " " ) :
14672					data;
14673		}
14674	} );
14675	
14676	
14677	
14678	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14679		if ( d !== 0 && (!d || d === '-') ) {
14680			return -Infinity;
14681		}
14682	
14683		// If a decimal place other than `.` is used, it needs to be given to the
14684		// function so we can detect it and replace with a `.` which is the only
14685		// decimal place Javascript recognises - it is not locale aware.
14686		if ( decimalPlace ) {
14687			d = _numToDecimal( d, decimalPlace );
14688		}
14689	
14690		if ( d.replace ) {
14691			if ( re1 ) {
14692				d = d.replace( re1, '' );
14693			}
14694	
14695			if ( re2 ) {
14696				d = d.replace( re2, '' );
14697			}
14698		}
14699	
14700		return d * 1;
14701	};
14702	
14703	
14704	// Add the numeric 'deformatting' functions for sorting and search. This is done
14705	// in a function to provide an easy ability for the language options to add
14706	// additional methods if a non-period decimal place is used.
14707	function _addNumericSort ( decimalPlace ) {
14708		$.each(
14709			{
14710				// Plain numbers
14711				"num": function ( d ) {
14712					return __numericReplace( d, decimalPlace );
14713				},
14714	
14715				// Formatted numbers
14716				"num-fmt": function ( d ) {
14717					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14718				},
14719	
14720				// HTML numeric
14721				"html-num": function ( d ) {
14722					return __numericReplace( d, decimalPlace, _re_html );
14723				},
14724	
14725				// HTML numeric, formatted
14726				"html-num-fmt": function ( d ) {
14727					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14728				}
14729			},
14730			function ( key, fn ) {
14731				// Add the ordering method
14732				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14733	
14734				// For HTML types add a search formatter that will strip the HTML
14735				if ( key.match(/^html\-/) ) {
14736					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14737				}
14738			}
14739		);
14740	}
14741	
14742	
14743	// Default sort methods
14744	$.extend( _ext.type.order, {
14745		// Dates
14746		"date-pre": function ( d ) {
14747			return Date.parse( d ) || -Infinity;
14748		},
14749	
14750		// html
14751		"html-pre": function ( a ) {
14752			return _empty(a) ?
14753				'' :
14754				a.replace ?
14755					a.replace( /<.*?>/g, "" ).toLowerCase() :
14756					a+'';
14757		},
14758	
14759		// string
14760		"string-pre": function ( a ) {
14761			// This is a little complex, but faster than always calling toString,
14762			// http://jsperf.com/tostring-v-check
14763			return _empty(a) ?
14764				'' :
14765				typeof a === 'string' ?
14766					a.toLowerCase() :
14767					! a.toString ?
14768						'' :
14769						a.toString();
14770		},
14771	
14772		// string-asc and -desc are retained only for compatibility with the old
14773		// sort methods
14774		"string-asc": function ( x, y ) {
14775			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14776		},
14777	
14778		"string-desc": function ( x, y ) {
14779			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14780		}
14781	} );
14782	
14783	
14784	// Numeric sorting types - order doesn't matter here
14785	_addNumericSort( '' );
14786	
14787	
14788	$.extend( true, DataTable.ext.renderer, {
14789		header: {
14790			_: function ( settings, cell, column, classes ) {
14791				// No additional mark-up required
14792				// Attach a sort listener to update on sort - note that using the
14793				// `DT` namespace will allow the event to be removed automatically
14794				// on destroy, while the `dt` namespaced event is the one we are
14795				// listening for
14796				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14797					if ( settings !== ctx ) { // need to check this this is the host
14798						return;               // table, not a nested one
14799					}
14800	
14801					var colIdx = column.idx;
14802	
14803					cell
14804						.removeClass(
14805							column.sSortingClass +' '+
14806							classes.sSortAsc +' '+
14807							classes.sSortDesc
14808						)
14809						.addClass( columns[ colIdx ] == 'asc' ?
14810							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14811								classes.sSortDesc :
14812								column.sSortingClass
14813						);
14814				} );
14815			},
14816	
14817			jqueryui: function ( settings, cell, column, classes ) {
14818				$('<div/>')
14819					.addClass( classes.sSortJUIWrapper )
14820					.append( cell.contents() )
14821					.append( $('<span/>')
14822						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14823					)
14824					.appendTo( cell );
14825	
14826				// Attach a sort listener to update on sort
14827				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14828					if ( settings !== ctx ) {
14829						return;
14830					}
14831	
14832					var colIdx = column.idx;
14833	
14834					cell
14835						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14836						.addClass( columns[ colIdx ] == 'asc' ?
14837							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14838								classes.sSortDesc :
14839								column.sSortingClass
14840						);
14841	
14842					cell
14843						.find( 'span.'+classes.sSortIcon )
14844						.removeClass(
14845							classes.sSortJUIAsc +" "+
14846							classes.sSortJUIDesc +" "+
14847							classes.sSortJUI +" "+
14848							classes.sSortJUIAscAllowed +" "+
14849							classes.sSortJUIDescAllowed
14850						)
14851						.addClass( columns[ colIdx ] == 'asc' ?
14852							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14853								classes.sSortJUIDesc :
14854								column.sSortingClassJUI
14855						);
14856				} );
14857			}
14858		}
14859	} );
14860	
14861	/*
14862	 * Public helper functions. These aren't used internally by DataTables, or
14863	 * called by any of the options passed into DataTables, but they can be used
14864	 * externally by developers working with DataTables. They are helper functions
14865	 * to make working with DataTables a little bit easier.
14866	 */
14867	
14868	var __htmlEscapeEntities = function ( d ) {
14869		return typeof d === 'string' ?
14870			d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14871			d;
14872	};
14873	
14874	/**
14875	 * Helpers for `columns.render`.
14876	 *
14877	 * The options defined here can be used with the `columns.render` initialisation
14878	 * option to provide a display renderer. The following functions are defined:
14879	 *
14880	 * * `number` - Will format numeric data (defined by `columns.data`) for
14881	 *   display, retaining the original unformatted data for sorting and filtering.
14882	 *   It takes 5 parameters:
14883	 *   * `string` - Thousands grouping separator
14884	 *   * `string` - Decimal point indicator
14885	 *   * `integer` - Number of decimal points to show
14886	 *   * `string` (optional) - Prefix.
14887	 *   * `string` (optional) - Postfix (/suffix).
14888	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14889	 *   parameters.
14890	 *
14891	 * @example
14892	 *   // Column definition using the number renderer
14893	 *   {
14894	 *     data: "salary",
14895	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14896	 *   }
14897	 *
14898	 * @namespace
14899	 */
14900	DataTable.render = {
14901		number: function ( thousands, decimal, precision, prefix, postfix ) {
14902			return {
14903				display: function ( d ) {
14904					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14905						return d;
14906					}
14907	
14908					var negative = d < 0 ? '-' : '';
14909					var flo = parseFloat( d );
14910	
14911					// If NaN then there isn't much formatting that we can do - just
14912					// return immediately, escaping any HTML (this was supposed to
14913					// be a number after all)
14914					if ( isNaN( flo ) ) {
14915						return __htmlEscapeEntities( d );
14916					}
14917	
14918					flo = flo.toFixed( precision );
14919					d = Math.abs( flo );
14920	
14921					var intPart = parseInt( d, 10 );
14922					var floatPart = precision ?
14923						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14924						'';
14925	
14926					return negative + (prefix||'') +
14927						intPart.toString().replace(
14928							/\B(?=(\d{3})+(?!\d))/g, thousands
14929						) +
14930						floatPart +
14931						(postfix||'');
14932				}
14933			};
14934		},
14935	
14936		text: function () {
14937			return {
14938				display: __htmlEscapeEntities
14939			};
14940		}
14941	};
14942	
14943	
14944	/*
14945	 * This is really a good bit rubbish this method of exposing the internal methods
14946	 * publicly... - To be fixed in 2.0 using methods on the prototype
14947	 */
14948	
14949	
14950	/**
14951	 * Create a wrapper function for exporting an internal functions to an external API.
14952	 *  @param {string} fn API function name
14953	 *  @returns {function} wrapped function
14954	 *  @memberof DataTable#internal
14955	 */
14956	function _fnExternApiFunc (fn)
14957	{
14958		return function() {
14959			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14960				Array.prototype.slice.call(arguments)
14961			);
14962			return DataTable.ext.internal[fn].apply( this, args );
14963		};
14964	}
14965	
14966	
14967	/**
14968	 * Reference to internal functions for use by plug-in developers. Note that
14969	 * these methods are references to internal functions and are considered to be
14970	 * private. If you use these methods, be aware that they are liable to change
14971	 * between versions.
14972	 *  @namespace
14973	 */
14974	$.extend( DataTable.ext.internal, {
14975		_fnExternApiFunc: _fnExternApiFunc,
14976		_fnBuildAjax: _fnBuildAjax,
14977		_fnAjaxUpdate: _fnAjaxUpdate,
14978		_fnAjaxParameters: _fnAjaxParameters,
14979		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14980		_fnAjaxDataSrc: _fnAjaxDataSrc,
14981		_fnAddColumn: _fnAddColumn,
14982		_fnColumnOptions: _fnColumnOptions,
14983		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
14984		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14985		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
14986		_fnVisbleColumns: _fnVisbleColumns,
14987		_fnGetColumns: _fnGetColumns,
14988		_fnColumnTypes: _fnColumnTypes,
14989		_fnApplyColumnDefs: _fnApplyColumnDefs,
14990		_fnHungarianMap: _fnHungarianMap,
14991		_fnCamelToHungarian: _fnCamelToHungarian,
14992		_fnLanguageCompat: _fnLanguageCompat,
14993		_fnBrowserDetect: _fnBrowserDetect,
14994		_fnAddData: _fnAddData,
14995		_fnAddTr: _fnAddTr,
14996		_fnNodeToDataIndex: _fnNodeToDataIndex,
14997		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
14998		_fnGetCellData: _fnGetCellData,
14999		_fnSetCellData: _fnSetCellData,
15000		_fnSplitObjNotation: _fnSplitObjNotation,
15001		_fnGetObjectDataFn: _fnGetObjectDataFn,
15002		_fnSetObjectDataFn: _fnSetObjectDataFn,
15003		_fnGetDataMaster: _fnGetDataMaster,
15004		_fnClearTable: _fnClearTable,
15005		_fnDeleteIndex: _fnDeleteIndex,
15006		_fnInvalidate: _fnInvalidate,
15007		_fnGetRowElements: _fnGetRowElements,
15008		_fnCreateTr: _fnCreateTr,
15009		_fnBuildHead: _fnBuildHead,
15010		_fnDrawHead: _fnDrawHead,
15011		_fnDraw: _fnDraw,
15012		_fnReDraw: _fnReDraw,
15013		_fnAddOptionsHtml: _fnAddOptionsHtml,
15014		_fnDetectHeader: _fnDetectHeader,
15015		_fnGetUniqueThs: _fnGetUniqueThs,
15016		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15017		_fnFilterComplete: _fnFilterComplete,
15018		_fnFilterCustom: _fnFilterCustom,
15019		_fnFilterColumn: _fnFilterColumn,
15020		_fnFilter: _fnFilter,
15021		_fnFilterCreateSearch: _fnFilterCreateSearch,
15022		_fnEscapeRegex: _fnEscapeRegex,
15023		_fnFilterData: _fnFilterData,
15024		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15025		_fnUpdateInfo: _fnUpdateInfo,
15026		_fnInfoMacros: _fnInfoMacros,
15027		_fnInitialise: _fnInitialise,
15028		_fnInitComplete: _fnInitComplete,
15029		_fnLengthChange: _fnLengthChange,
15030		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15031		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15032		_fnPageChange: _fnPageChange,
15033		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15034		_fnProcessingDisplay: _fnProcessingDisplay,
15035		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15036		_fnScrollDraw: _fnScrollDraw,
15037		_fnApplyToChildren: _fnApplyToChildren,
15038		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15039		_fnThrottle: _fnThrottle,
15040		_fnConvertToWidth: _fnConvertToWidth,
15041		_fnGetWidestNode: _fnGetWidestNode,
15042		_fnGetMaxLenString: _fnGetMaxLenString,
15043		_fnStringToCss: _fnStringToCss,
15044		_fnSortFlatten: _fnSortFlatten,
15045		_fnSort: _fnSort,
15046		_fnSortAria: _fnSortAria,
15047		_fnSortListener: _fnSortListener,
15048		_fnSortAttachListener: _fnSortAttachListener,
15049		_fnSortingClasses: _fnSortingClasses,
15050		_fnSortData: _fnSortData,
15051		_fnSaveState: _fnSaveState,
15052		_fnLoadState: _fnLoadState,
15053		_fnSettingsFromNode: _fnSettingsFromNode,
15054		_fnLog: _fnLog,
15055		_fnMap: _fnMap,
15056		_fnBindAction: _fnBindAction,
15057		_fnCallbackReg: _fnCallbackReg,
15058		_fnCallbackFire: _fnCallbackFire,
15059		_fnLengthOverflow: _fnLengthOverflow,
15060		_fnRenderer: _fnRenderer,
15061		_fnDataSource: _fnDataSource,
15062		_fnRowAttributes: _fnRowAttributes,
15063		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15064		                                // in 1.10, so this dead-end function is
15065		                                // added to prevent errors
15066	} );
15067	
15068
15069	// jQuery access
15070	$.fn.dataTable = DataTable;
15071
15072	// Provide access to the host jQuery object (circular reference)
15073	DataTable.$ = $;
15074
15075	// Legacy aliases
15076	$.fn.dataTableSettings = DataTable.settings;
15077	$.fn.dataTableExt = DataTable.ext;
15078
15079	// With a capital `D` we return a DataTables API instance rather than a
15080	// jQuery object
15081	$.fn.DataTable = function ( opts ) {
15082		return $(this).dataTable( opts ).api();
15083	};
15084
15085	// All properties that are available to $.fn.dataTable should also be
15086	// available on $.fn.DataTable
15087	$.each( DataTable, function ( prop, val ) {
15088		$.fn.DataTable[ prop ] = val;
15089	} );
15090
15091
15092	// Information about events fired by DataTables - for documentation.
15093	/**
15094	 * Draw event, fired whenever the table is redrawn on the page, at the same
15095	 * point as fnDrawCallback. This may be useful for binding events or
15096	 * performing calculations when the table is altered at all.
15097	 *  @name DataTable#draw.dt
15098	 *  @event
15099	 *  @param {event} e jQuery event object
15100	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15101	 */
15102
15103	/**
15104	 * Search event, fired when the searching applied to the table (using the
15105	 * built-in global search, or column filters) is altered.
15106	 *  @name DataTable#search.dt
15107	 *  @event
15108	 *  @param {event} e jQuery event object
15109	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15110	 */
15111
15112	/**
15113	 * Page change event, fired when the paging of the table is altered.
15114	 *  @name DataTable#page.dt
15115	 *  @event
15116	 *  @param {event} e jQuery event object
15117	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15118	 */
15119
15120	/**
15121	 * Order event, fired when the ordering applied to the table is altered.
15122	 *  @name DataTable#order.dt
15123	 *  @event
15124	 *  @param {event} e jQuery event object
15125	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15126	 */
15127
15128	/**
15129	 * DataTables initialisation complete event, fired when the table is fully
15130	 * drawn, including Ajax data loaded, if Ajax data is required.
15131	 *  @name DataTable#init.dt
15132	 *  @event
15133	 *  @param {event} e jQuery event object
15134	 *  @param {object} oSettings DataTables settings object
15135	 *  @param {object} json The JSON object request from the server - only
15136	 *    present if client-side Ajax sourced data is used</li></ol>
15137	 */
15138
15139	/**
15140	 * State save event, fired when the table has changed state a new state save
15141	 * is required. This event allows modification of the state saving object
15142	 * prior to actually doing the save, including addition or other state
15143	 * properties (for plug-ins) or modification of a DataTables core property.
15144	 *  @name DataTable#stateSaveParams.dt
15145	 *  @event
15146	 *  @param {event} e jQuery event object
15147	 *  @param {object} oSettings DataTables settings object
15148	 *  @param {object} json The state information to be saved
15149	 */
15150
15151	/**
15152	 * State load event, fired when the table is loading state from the stored
15153	 * data, but prior to the settings object being modified by the saved state
15154	 * - allowing modification of the saved state is required or loading of
15155	 * state for a plug-in.
15156	 *  @name DataTable#stateLoadParams.dt
15157	 *  @event
15158	 *  @param {event} e jQuery event object
15159	 *  @param {object} oSettings DataTables settings object
15160	 *  @param {object} json The saved state information
15161	 */
15162
15163	/**
15164	 * State loaded event, fired when state has been loaded from stored data and
15165	 * the settings object has been modified by the loaded data.
15166	 *  @name DataTable#stateLoaded.dt
15167	 *  @event
15168	 *  @param {event} e jQuery event object
15169	 *  @param {object} oSettings DataTables settings object
15170	 *  @param {object} json The saved state information
15171	 */
15172
15173	/**
15174	 * Processing event, fired when DataTables is doing some kind of processing
15175	 * (be it, order, searcg or anything else). It can be used to indicate to
15176	 * the end user that there is something happening, or that something has
15177	 * finished.
15178	 *  @name DataTable#processing.dt
15179	 *  @event
15180	 *  @param {event} e jQuery event object
15181	 *  @param {object} oSettings DataTables settings object
15182	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15183	 */
15184
15185	/**
15186	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15187	 * request to made to the server for new data. This event is called before
15188	 * DataTables processed the returned data, so it can also be used to pre-
15189	 * process the data returned from the server, if needed.
15190	 *
15191	 * Note that this trigger is called in `fnServerData`, if you override
15192	 * `fnServerData` and which to use this event, you need to trigger it in you
15193	 * success function.
15194	 *  @name DataTable#xhr.dt
15195	 *  @event
15196	 *  @param {event} e jQuery event object
15197	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15198	 *  @param {object} json JSON returned from the server
15199	 *
15200	 *  @example
15201	 *     // Use a custom property returned from the server in another DOM element
15202	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15203	 *       $('#status').html( json.status );
15204	 *     } );
15205	 *
15206	 *  @example
15207	 *     // Pre-process the data returned from the server
15208	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15209	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15210	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15211	 *       }
15212	 *       // Note no return - manipulate the data directly in the JSON object.
15213	 *     } );
15214	 */
15215
15216	/**
15217	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15218	 * or passing the bDestroy:true parameter in the initialisation object. This
15219	 * can be used to remove bound events, added DOM nodes, etc.
15220	 *  @name DataTable#destroy.dt
15221	 *  @event
15222	 *  @param {event} e jQuery event object
15223	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15224	 */
15225
15226	/**
15227	 * Page length change event, fired when number of records to show on each
15228	 * page (the length) is changed.
15229	 *  @name DataTable#length.dt
15230	 *  @event
15231	 *  @param {event} e jQuery event object
15232	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15233	 *  @param {integer} len New length
15234	 */
15235
15236	/**
15237	 * Column sizing has changed.
15238	 *  @name DataTable#column-sizing.dt
15239	 *  @event
15240	 *  @param {event} e jQuery event object
15241	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15242	 */
15243
15244	/**
15245	 * Column visibility has changed.
15246	 *  @name DataTable#column-visibility.dt
15247	 *  @event
15248	 *  @param {event} e jQuery event object
15249	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15250	 *  @param {int} column Column index
15251	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15252	 */
15253
15254	return $.fn.dataTable;
15255}));
15256
15257
15258/*! DataTables Bootstrap 3 integration
15259 * ©2011-2015 SpryMedia Ltd - datatables.net/license
15260 */
15261
15262/**
15263 * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and
15264 * DataTables 1.10 or newer.
15265 *
15266 * This file sets the defaults and adds options to DataTables to style its
15267 * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
15268 * for further information.
15269 */
15270(function( factory ){
15271	if ( typeof define === 'function' && define.amd ) {
15272		// AMD
15273		define( ['jquery', 'datatables.net'], function ( $ ) {
15274			return factory( $, window, document );
15275		} );
15276	}
15277	else if ( typeof exports === 'object' ) {
15278		// CommonJS
15279		module.exports = function (root, $) {
15280			if ( ! root ) {
15281				root = window;
15282			}
15283
15284			if ( ! $ || ! $.fn.dataTable ) {
15285				// Require DataTables, which attaches to jQuery, including
15286				// jQuery if needed and have a $ property so we can access the
15287				// jQuery object that is used
15288				$ = require('datatables.net')(root, $).$;
15289			}
15290
15291			return factory( $, root, root.document );
15292		};
15293	}
15294	else {
15295		// Browser
15296		factory( jQuery, window, document );
15297	}
15298}(function( $, window, document, undefined ) {
15299'use strict';
15300var DataTable = $.fn.dataTable;
15301
15302
15303/* Set the defaults for DataTables initialisation */
15304$.extend( true, DataTable.defaults, {
15305	dom:
15306		"<'row'<'col-sm-6'l><'col-sm-6'f>>" +
15307		"<'row'<'col-sm-12'tr>>" +
15308		"<'row'<'col-sm-5'i><'col-sm-7'p>>",
15309	renderer: 'bootstrap'
15310} );
15311
15312
15313/* Default class modification */
15314$.extend( DataTable.ext.classes, {
15315	sWrapper:      "dataTables_wrapper form-inline dt-bootstrap",
15316	sFilterInput:  "form-control input-sm",
15317	sLengthSelect: "form-control input-sm",
15318	sProcessing:   "dataTables_processing panel panel-default"
15319} );
15320
15321
15322/* Bootstrap paging button renderer */
15323DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
15324	var api     = new DataTable.Api( settings );
15325	var classes = settings.oClasses;
15326	var lang    = settings.oLanguage.oPaginate;
15327	var aria = settings.oLanguage.oAria.paginate || {};
15328	var btnDisplay, btnClass, counter=0;
15329
15330	var attach = function( container, buttons ) {
15331		var i, ien, node, button;
15332		var clickHandler = function ( e ) {
15333			e.preventDefault();
15334			if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
15335				api.page( e.data.action ).draw( 'page' );
15336			}
15337		};
15338
15339		for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
15340			button = buttons[i];
15341
15342			if ( $.isArray( button ) ) {
15343				attach( container, button );
15344			}
15345			else {
15346				btnDisplay = '';
15347				btnClass = '';
15348
15349				switch ( button ) {
15350					case 'ellipsis':
15351						btnDisplay = '&#x2026;';
15352						btnClass = 'disabled';
15353						break;
15354
15355					case 'first':
15356						btnDisplay = lang.sFirst;
15357						btnClass = button + (page > 0 ?
15358							'' : ' disabled');
15359						break;
15360
15361					case 'previous':
15362						btnDisplay = lang.sPrevious;
15363						btnClass = button + (page > 0 ?
15364							'' : ' disabled');
15365						break;
15366
15367					case 'next':
15368						btnDisplay = lang.sNext;
15369						btnClass = button + (page < pages-1 ?
15370							'' : ' disabled');
15371						break;
15372
15373					case 'last':
15374						btnDisplay = lang.sLast;
15375						btnClass = button + (page < pages-1 ?
15376							'' : ' disabled');
15377						break;
15378
15379					default:
15380						btnDisplay = button + 1;
15381						btnClass = page === button ?
15382							'active' : '';
15383						break;
15384				}
15385
15386				if ( btnDisplay ) {
15387					node = $('<li>', {
15388							'class': classes.sPageButton+' '+btnClass,
15389							'id': idx === 0 && typeof button === 'string' ?
15390								settings.sTableId +'_'+ button :
15391								null
15392						} )
15393						.append( $('<a>', {
15394								'href': '#',
15395								'aria-controls': settings.sTableId,
15396								'aria-label': aria[ button ],
15397								'data-dt-idx': counter,
15398								'tabindex': settings.iTabIndex
15399							} )
15400							.html( btnDisplay )
15401						)
15402						.appendTo( container );
15403
15404					settings.oApi._fnBindAction(
15405						node, {action: button}, clickHandler
15406					);
15407
15408					counter++;
15409				}
15410			}
15411		}
15412	};
15413
15414	// IE9 throws an 'unknown error' if document.activeElement is used
15415	// inside an iframe or frame. 
15416	var activeEl;
15417
15418	try {
15419		// Because this approach is destroying and recreating the paging
15420		// elements, focus is lost on the select button which is bad for
15421		// accessibility. So we want to restore focus once the draw has
15422		// completed
15423		activeEl = $(host).find(document.activeElement).data('dt-idx');
15424	}
15425	catch (e) {}
15426
15427	attach(
15428		$(host).empty().html('<ul class="pagination"/>').children('ul'),
15429		buttons
15430	);
15431
15432	if ( activeEl !== undefined ) {
15433		$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
15434	}
15435};
15436
15437
15438return DataTable;
15439}));
15440
15441
15442/*! Responsive 2.2.1
15443 * 2014-2017 SpryMedia Ltd - datatables.net/license
15444 */
15445
15446/**
15447 * @summary     Responsive
15448 * @description Responsive tables plug-in for DataTables
15449 * @version     2.2.1
15450 * @file        dataTables.responsive.js
15451 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
15452 * @contact     www.sprymedia.co.uk/contact
15453 * @copyright   Copyright 2014-2017 SpryMedia Ltd.
15454 *
15455 * This source file is free software, available under the following license:
15456 *   MIT license - http://datatables.net/license/mit
15457 *
15458 * This source file is distributed in the hope that it will be useful, but
15459 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15460 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
15461 *
15462 * For details please refer to: http://www.datatables.net
15463 */
15464(function( factory ){
15465	if ( typeof define === 'function' && define.amd ) {
15466		// AMD
15467		define( ['jquery', 'datatables.net'], function ( $ ) {
15468			return factory( $, window, document );
15469		} );
15470	}
15471	else if ( typeof exports === 'object' ) {
15472		// CommonJS
15473		module.exports = function (root, $) {
15474			if ( ! root ) {
15475				root = window;
15476			}
15477
15478			if ( ! $ || ! $.fn.dataTable ) {
15479				$ = require('datatables.net')(root, $).$;
15480			}
15481
15482			return factory( $, root, root.document );
15483		};
15484	}
15485	else {
15486		// Browser
15487		factory( jQuery, window, document );
15488	}
15489}(function( $, window, document, undefined ) {
15490'use strict';
15491var DataTable = $.fn.dataTable;
15492
15493
15494/**
15495 * Responsive is a plug-in for the DataTables library that makes use of
15496 * DataTables' ability to change the visibility of columns, changing the
15497 * visibility of columns so the displayed columns fit into the table container.
15498 * The end result is that complex tables will be dynamically adjusted to fit
15499 * into the viewport, be it on a desktop, tablet or mobile browser.
15500 *
15501 * Responsive for DataTables has two modes of operation, which can used
15502 * individually or combined:
15503 *
15504 * * Class name based control - columns assigned class names that match the
15505 *   breakpoint logic can be shown / hidden as required for each breakpoint.
15506 * * Automatic control - columns are automatically hidden when there is no
15507 *   room left to display them. Columns removed from the right.
15508 *
15509 * In additional to column visibility control, Responsive also has built into
15510 * options to use DataTables' child row display to show / hide the information
15511 * from the table that has been hidden. There are also two modes of operation
15512 * for this child row display:
15513 *
15514 * * Inline - when the control element that the user can use to show / hide
15515 *   child rows is displayed inside the first column of the table.
15516 * * Column - where a whole column is dedicated to be the show / hide control.
15517 *
15518 * Initialisation of Responsive is performed by:
15519 *
15520 * * Adding the class `responsive` or `dt-responsive` to the table. In this case
15521 *   Responsive will automatically be initialised with the default configuration
15522 *   options when the DataTable is created.
15523 * * Using the `responsive` option in the DataTables configuration options. This
15524 *   can also be used to specify the configuration options, or simply set to
15525 *   `true` to use the defaults.
15526 *
15527 *  @class
15528 *  @param {object} settings DataTables settings object for the host table
15529 *  @param {object} [opts] Configuration options
15530 *  @requires jQuery 1.7+
15531 *  @requires DataTables 1.10.3+
15532 *
15533 *  @example
15534 *      $('#example').DataTable( {
15535 *        responsive: true
15536 *      } );
15537 *    } );
15538 */
15539var Responsive = function ( settings, opts ) {
15540	// Sanity check that we are using DataTables 1.10 or newer
15541	if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.10' ) ) {
15542		throw 'DataTables Responsive requires DataTables 1.10.10 or newer';
15543	}
15544
15545	this.s = {
15546		dt: new DataTable.Api( settings ),
15547		columns: [],
15548		current: []
15549	};
15550
15551	// Check if responsive has already been initialised on this table
15552	if ( this.s.dt.settings()[0].responsive ) {
15553		return;
15554	}
15555
15556	// details is an object, but for simplicity the user can give it as a string
15557	// or a boolean
15558	if ( opts && typeof opts.details === 'string' ) {
15559		opts.details = { type: opts.details };
15560	}
15561	else if ( opts && opts.details === false ) {
15562		opts.details = { type: false };
15563	}
15564	else if ( opts && opts.details === true ) {
15565		opts.details = { type: 'inline' };
15566	}
15567
15568	this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
15569	settings.responsive = this;
15570	this._constructor();
15571};
15572
15573$.extend( Responsive.prototype, {
15574	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15575	 * Constructor
15576	 */
15577
15578	/**
15579	 * Initialise the Responsive instance
15580	 *
15581	 * @private
15582	 */
15583	_constructor: function ()
15584	{
15585		var that = this;
15586		var dt = this.s.dt;
15587		var dtPrivateSettings = dt.settings()[0];
15588		var oldWindowWidth = $(window).width();
15589
15590		dt.settings()[0]._responsive = this;
15591
15592		// Use DataTables' throttle function to avoid processor thrashing on
15593		// resize
15594		$(window).on( 'resize.dtr orientationchange.dtr', DataTable.util.throttle( function () {
15595			// iOS has a bug whereby resize can fire when only scrolling
15596			// See: http://stackoverflow.com/questions/8898412
15597			var width = $(window).width();
15598
15599			if ( width !== oldWindowWidth ) {
15600				that._resize();
15601				oldWindowWidth = width;
15602			}
15603		} ) );
15604
15605		// DataTables doesn't currently trigger an event when a row is added, so
15606		// we need to hook into its private API to enforce the hidden rows when
15607		// new data is added
15608		dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
15609			if ( $.inArray( false, that.s.current ) !== -1 ) {
15610				$('>td, >th', tr).each( function ( i ) {
15611					var idx = dt.column.index( 'toData', i );
15612
15613					if ( that.s.current[idx] === false ) {
15614						$(this).css('display', 'none');
15615					}
15616				} );
15617			}
15618		} );
15619
15620		// Destroy event handler
15621		dt.on( 'destroy.dtr', function () {
15622			dt.off( '.dtr' );
15623			$( dt.table().body() ).off( '.dtr' );
15624			$(window).off( 'resize.dtr orientationchange.dtr' );
15625
15626			// Restore the columns that we've hidden
15627			$.each( that.s.current, function ( i, val ) {
15628				if ( val === false ) {
15629					that._setColumnVis( i, true );
15630				}
15631			} );
15632		} );
15633
15634		// Reorder the breakpoints array here in case they have been added out
15635		// of order
15636		this.c.breakpoints.sort( function (a, b) {
15637			return a.width < b.width ? 1 :
15638				a.width > b.width ? -1 : 0;
15639		} );
15640
15641		this._classLogic();
15642		this._resizeAuto();
15643
15644		// Details handler
15645		var details = this.c.details;
15646
15647		if ( details.type !== false ) {
15648			that._detailsInit();
15649
15650			// DataTables will trigger this event on every column it shows and
15651			// hides individually
15652			dt.on( 'column-visibility.dtr', function (e, ctx, col, vis, recalc) {
15653				if ( recalc ) {
15654					that._classLogic();
15655					that._resizeAuto();
15656					that._resize();
15657				}
15658			} );
15659
15660			// Redraw the details box on each draw which will happen if the data
15661			// has changed. This is used until DataTables implements a native
15662			// `updated` event for rows
15663			dt.on( 'draw.dtr', function () {
15664				that._redrawChildren();
15665			} );
15666
15667			$(dt.table().node()).addClass( 'dtr-'+details.type );
15668		}
15669
15670		dt.on( 'column-reorder.dtr', function (e, settings, details) {
15671			that._classLogic();
15672			that._resizeAuto();
15673			that._resize();
15674		} );
15675
15676		// Change in column sizes means we need to calc
15677		dt.on( 'column-sizing.dtr', function () {
15678			that._resizeAuto();
15679			that._resize();
15680		});
15681
15682		// On Ajax reload we want to reopen any child rows which are displayed
15683		// by responsive
15684		dt.on( 'preXhr.dtr', function () {
15685			var rowIds = [];
15686			dt.rows().every( function () {
15687				if ( this.child.isShown() ) {
15688					rowIds.push( this.id(true) );
15689				}
15690			} );
15691
15692			dt.one( 'draw.dtr', function () {
15693				that._resizeAuto();
15694				that._resize();
15695
15696				dt.rows( rowIds ).every( function () {
15697					that._detailsDisplay( this, false );
15698				} );
15699			} );
15700		});
15701
15702		dt.on( 'init.dtr', function (e, settings, details) {
15703			that._resizeAuto();
15704			that._resize();
15705
15706			// If columns were hidden, then DataTables needs to adjust the
15707			// column sizing
15708			if ( $.inArray( false, that.s.current ) ) {
15709				dt.columns.adjust();
15710			}
15711		} );
15712
15713		// First pass - draw the table for the current viewport size
15714		this._resize();
15715	},
15716
15717
15718	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15719	 * Private methods
15720	 */
15721
15722	/**
15723	 * Calculate the visibility for the columns in a table for a given
15724	 * breakpoint. The result is pre-determined based on the class logic if
15725	 * class names are used to control all columns, but the width of the table
15726	 * is also used if there are columns which are to be automatically shown
15727	 * and hidden.
15728	 *
15729	 * @param  {string} breakpoint Breakpoint name to use for the calculation
15730	 * @return {array} Array of boolean values initiating the visibility of each
15731	 *   column.
15732	 *  @private
15733	 */
15734	_columnsVisiblity: function ( breakpoint )
15735	{
15736		var dt = this.s.dt;
15737		var columns = this.s.columns;
15738		var i, ien;
15739
15740		// Create an array that defines the column ordering based first on the
15741		// column's priority, and secondly the column index. This allows the
15742		// columns to be removed from the right if the priority matches
15743		var order = columns
15744			.map( function ( col, idx ) {
15745				return {
15746					columnIdx: idx,
15747					priority: col.priority
15748				};
15749			} )
15750			.sort( function ( a, b ) {
15751				if ( a.priority !== b.priority ) {
15752					return a.priority - b.priority;
15753				}
15754				return a.columnIdx - b.columnIdx;
15755			} );
15756
15757		// Class logic - determine which columns are in this breakpoint based
15758		// on the classes. If no class control (i.e. `auto`) then `-` is used
15759		// to indicate this to the rest of the function
15760		var display = $.map( columns, function ( col ) {
15761			return col.auto && col.minWidth === null ?
15762				false :
15763				col.auto === true ?
15764					'-' :
15765					$.inArray( breakpoint, col.includeIn ) !== -1;
15766		} );
15767
15768		// Auto column control - first pass: how much width is taken by the
15769		// ones that must be included from the non-auto columns
15770		var requiredWidth = 0;
15771		for ( i=0, ien=display.length ; i<ien ; i++ ) {
15772			if ( display[i] === true ) {
15773				requiredWidth += columns[i].minWidth;
15774			}
15775		}
15776
15777		// Second pass, use up any remaining width for other columns. For
15778		// scrolling tables we need to subtract the width of the scrollbar. It
15779		// may not be requires which makes this sub-optimal, but it would
15780		// require another full redraw to make complete use of those extra few
15781		// pixels
15782		var scrolling = dt.settings()[0].oScroll;
15783		var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
15784		var widthAvailable = dt.table().container().offsetWidth - bar;
15785		var usedWidth = widthAvailable - requiredWidth;
15786
15787		// Control column needs to always be included. This makes it sub-
15788		// optimal in terms of using the available with, but to stop layout
15789		// thrashing or overflow. Also we need to account for the control column
15790		// width first so we know how much width is available for the other
15791		// columns, since the control column might not be the first one shown
15792		for ( i=0, ien=display.length ; i<ien ; i++ ) {
15793			if ( columns[i].control ) {
15794				usedWidth -= columns[i].minWidth;
15795			}
15796		}
15797
15798		// Allow columns to be shown (counting by priority and then right to
15799		// left) until we run out of room
15800		var empty = false;
15801		for ( i=0, ien=order.length ; i<ien ; i++ ) {
15802			var colIdx = order[i].columnIdx;
15803
15804			if ( display[colIdx] === '-' && ! columns[colIdx].control && columns[colIdx].minWidth ) {
15805				// Once we've found a column that won't fit we don't let any
15806				// others display either, or columns might disappear in the
15807				// middle of the table
15808				if ( empty || usedWidth - columns[colIdx].minWidth < 0 ) {
15809					empty = true;
15810					display[colIdx] = false;
15811				}
15812				else {
15813					display[colIdx] = true;
15814				}
15815
15816				usedWidth -= columns[colIdx].minWidth;
15817			}
15818		}
15819
15820		// Determine if the 'control' column should be shown (if there is one).
15821		// This is the case when there is a hidden column (that is not the
15822		// control column). The two loops look inefficient here, but they are
15823		// trivial and will fly through. We need to know the outcome from the
15824		// first , before the action in the second can be taken
15825		var showControl = false;
15826
15827		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
15828			if ( ! columns[i].control && ! columns[i].never && ! display[i] ) {
15829				showControl = true;
15830				break;
15831			}
15832		}
15833
15834		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
15835			if ( columns[i].control ) {
15836				display[i] = showControl;
15837			}
15838		}
15839
15840		// Finally we need to make sure that there is at least one column that
15841		// is visible
15842		if ( $.inArray( true, display ) === -1 ) {
15843			display[0] = true;
15844		}
15845
15846		return display;
15847	},
15848
15849
15850	/**
15851	 * Create the internal `columns` array with information about the columns
15852	 * for the table. This includes determining which breakpoints the column
15853	 * will appear in, based upon class names in the column, which makes up the
15854	 * vast majority of this method.
15855	 *
15856	 * @private
15857	 */
15858	_classLogic: function ()
15859	{
15860		var that = this;
15861		var calc = {};
15862		var breakpoints = this.c.breakpoints;
15863		var dt = this.s.dt;
15864		var columns = dt.columns().eq(0).map( function (i) {
15865			var column = this.column(i);
15866			var className = column.header().className;
15867			var priority = dt.settings()[0].aoColumns[i].responsivePriority;
15868
15869			if ( priority === undefined ) {
15870				var dataPriority = $(column.header()).data('priority');
15871
15872				priority = dataPriority !== undefined ?
15873					dataPriority * 1 :
15874					10000;
15875			}
15876
15877			return {
15878				className: className,
15879				includeIn: [],
15880				auto:      false,
15881				control:   false,
15882				never:     className.match(/\bnever\b/) ? true : false,
15883				priority:  priority
15884			};
15885		} );
15886
15887		// Simply add a breakpoint to `includeIn` array, ensuring that there are
15888		// no duplicates
15889		var add = function ( colIdx, name ) {
15890			var includeIn = columns[ colIdx ].includeIn;
15891
15892			if ( $.inArray( name, includeIn ) === -1 ) {
15893				includeIn.push( name );
15894			}
15895		};
15896
15897		var column = function ( colIdx, name, operator, matched ) {
15898			var size, i, ien;
15899
15900			if ( ! operator ) {
15901				columns[ colIdx ].includeIn.push( name );
15902			}
15903			else if ( operator === 'max-' ) {
15904				// Add this breakpoint and all smaller
15905				size = that._find( name ).width;
15906
15907				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
15908					if ( breakpoints[i].width <= size ) {
15909						add( colIdx, breakpoints[i].name );
15910					}
15911				}
15912			}
15913			else if ( operator === 'min-' ) {
15914				// Add this breakpoint and all larger
15915				size = that._find( name ).width;
15916
15917				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
15918					if ( breakpoints[i].width >= size ) {
15919						add( colIdx, breakpoints[i].name );
15920					}
15921				}
15922			}
15923			else if ( operator === 'not-' ) {
15924				// Add all but this breakpoint
15925				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
15926					if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
15927						add( colIdx, breakpoints[i].name );
15928					}
15929				}
15930			}
15931		};
15932
15933		// Loop over each column and determine if it has a responsive control
15934		// class
15935		columns.each( function ( col, i ) {
15936			var classNames = col.className.split(' ');
15937			var hasClass = false;
15938
15939			// Split the class name up so multiple rules can be applied if needed
15940			for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
15941				var className = $.trim( classNames[k] );
15942
15943				if ( className === 'all' ) {
15944					// Include in all
15945					hasClass = true;
15946					col.includeIn = $.map( breakpoints, function (a) {
15947						return a.name;
15948					} );
15949					return;
15950				}
15951				else if ( className === 'none' || col.never ) {
15952					// Include in none (default) and no auto
15953					hasClass = true;
15954					return;
15955				}
15956				else if ( className === 'control' ) {
15957					// Special column that is only visible, when one of the other
15958					// columns is hidden. This is used for the details control
15959					hasClass = true;
15960					col.control = true;
15961					return;
15962				}
15963
15964				$.each( breakpoints, function ( j, breakpoint ) {
15965					// Does this column have a class that matches this breakpoint?
15966					var brokenPoint = breakpoint.name.split('-');
15967					var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
15968					var match = className.match( re );
15969
15970					if ( match ) {
15971						hasClass = true;
15972
15973						if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
15974							// Class name matches breakpoint name fully
15975							column( i, breakpoint.name, match[1], match[2]+match[3] );
15976						}
15977						else if ( match[2] === brokenPoint[0] && ! match[3] ) {
15978							// Class name matched primary breakpoint name with no qualifier
15979							column( i, breakpoint.name, match[1], match[2] );
15980						}
15981					}
15982				} );
15983			}
15984
15985			// If there was no control class, then automatic sizing is used
15986			if ( ! hasClass ) {
15987				col.auto = true;
15988			}
15989		} );
15990
15991		this.s.columns = columns;
15992	},
15993
15994
15995	/**
15996	 * Show the details for the child row
15997	 *
15998	 * @param  {DataTables.Api} row    API instance for the row
15999	 * @param  {boolean}        update Update flag
16000	 * @private
16001	 */
16002	_detailsDisplay: function ( row, update )
16003	{
16004		var that = this;
16005		var dt = this.s.dt;
16006		var details = this.c.details;
16007
16008		if ( details && details.type !== false ) {
16009			var res = details.display( row, update, function () {
16010				return details.renderer(
16011					dt, row[0], that._detailsObj(row[0])
16012				);
16013			} );
16014
16015			if ( res === true || res === false ) {
16016				$(dt.table().node()).triggerHandler( 'responsive-display.dt', [dt, row, res, update] );
16017			}
16018		}
16019	},
16020
16021
16022	/**
16023	 * Initialisation for the details handler
16024	 *
16025	 * @private
16026	 */
16027	_detailsInit: function ()
16028	{
16029		var that    = this;
16030		var dt      = this.s.dt;
16031		var details = this.c.details;
16032
16033		// The inline type always uses the first child as the target
16034		if ( details.type === 'inline' ) {
16035			details.target = 'td:first-child, th:first-child';
16036		}
16037
16038		// Keyboard accessibility
16039		dt.on( 'draw.dtr', function () {
16040			that._tabIndexes();
16041		} );
16042		that._tabIndexes(); // Initial draw has already happened
16043
16044		$( dt.table().body() ).on( 'keyup.dtr', 'td, th', function (e) {
16045			if ( e.keyCode === 13 && $(this).data('dtr-keyboard') ) {
16046				$(this).click();
16047			}
16048		} );
16049
16050		// type.target can be a string jQuery selector or a column index
16051		var target   = details.target;
16052		var selector = typeof target === 'string' ? target : 'td, th';
16053
16054		// Click handler to show / hide the details rows when they are available
16055		$( dt.table().body() )
16056			.on( 'click.dtr mousedown.dtr mouseup.dtr', selector, function (e) {
16057				// If the table is not collapsed (i.e. there is no hidden columns)
16058				// then take no action
16059				if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
16060					return;
16061				}
16062
16063				// Check that the row is actually a DataTable's controlled node
16064				if ( $.inArray( $(this).closest('tr').get(0), dt.rows().nodes().toArray() ) === -1 ) {
16065					return;
16066				}
16067
16068				// For column index, we determine if we should act or not in the
16069				// handler - otherwise it is already okay
16070				if ( typeof target === 'number' ) {
16071					var targetIdx = target < 0 ?
16072						dt.columns().eq(0).length + target :
16073						target;
16074
16075					if ( dt.cell( this ).index().column !== targetIdx ) {
16076						return;
16077					}
16078				}
16079
16080				// $().closest() includes itself in its check
16081				var row = dt.row( $(this).closest('tr') );
16082
16083				// Check event type to do an action
16084				if ( e.type === 'click' ) {
16085					// The renderer is given as a function so the caller can execute it
16086					// only when they need (i.e. if hiding there is no point is running
16087					// the renderer)
16088					that._detailsDisplay( row, false );
16089				}
16090				else if ( e.type === 'mousedown' ) {
16091					// For mouse users, prevent the focus ring from showing
16092					$(this).css('outline', 'none');
16093				}
16094				else if ( e.type === 'mouseup' ) {
16095					// And then re-allow at the end of the click
16096					$(this).blur().css('outline', '');
16097				}
16098			} );
16099	},
16100
16101
16102	/**
16103	 * Get the details to pass to a renderer for a row
16104	 * @param  {int} rowIdx Row index
16105	 * @private
16106	 */
16107	_detailsObj: function ( rowIdx )
16108	{
16109		var that = this;
16110		var dt = this.s.dt;
16111
16112		return $.map( this.s.columns, function( col, i ) {
16113			// Never and control columns should not be passed to the renderer
16114			if ( col.never || col.control ) {
16115				return;
16116			}
16117
16118			return {
16119				title:       dt.settings()[0].aoColumns[ i ].sTitle,
16120				data:        dt.cell( rowIdx, i ).render( that.c.orthogonal ),
16121				hidden:      dt.column( i ).visible() && !that.s.current[ i ],
16122				columnIndex: i,
16123				rowIndex:    rowIdx
16124			};
16125		} );
16126	},
16127
16128
16129	/**
16130	 * Find a breakpoint object from a name
16131	 *
16132	 * @param  {string} name Breakpoint name to find
16133	 * @return {object}      Breakpoint description object
16134	 * @private
16135	 */
16136	_find: function ( name )
16137	{
16138		var breakpoints = this.c.breakpoints;
16139
16140		for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
16141			if ( breakpoints[i].name === name ) {
16142				return breakpoints[i];
16143			}
16144		}
16145	},
16146
16147
16148	/**
16149	 * Re-create the contents of the child rows as the display has changed in
16150	 * some way.
16151	 *
16152	 * @private
16153	 */
16154	_redrawChildren: function ()
16155	{
16156		var that = this;
16157		var dt = this.s.dt;
16158
16159		dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
16160			var row = dt.row( idx );
16161
16162			that._detailsDisplay( dt.row( idx ), true );
16163		} );
16164	},
16165
16166
16167	/**
16168	 * Alter the table display for a resized viewport. This involves first
16169	 * determining what breakpoint the window currently is in, getting the
16170	 * column visibilities to apply and then setting them.
16171	 *
16172	 * @private
16173	 */
16174	_resize: function ()
16175	{
16176		var that = this;
16177		var dt = this.s.dt;
16178		var width = $(window).width();
16179		var breakpoints = this.c.breakpoints;
16180		var breakpoint = breakpoints[0].name;
16181		var columns = this.s.columns;
16182		var i, ien;
16183		var oldVis = this.s.current.slice();
16184
16185		// Determine what breakpoint we are currently at
16186		for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
16187			if ( width <= breakpoints[i].width ) {
16188				breakpoint = breakpoints[i].name;
16189				break;
16190			}
16191		}
16192		
16193		// Show the columns for that break point
16194		var columnsVis = this._columnsVisiblity( breakpoint );
16195		this.s.current = columnsVis;
16196
16197		// Set the class before the column visibility is changed so event
16198		// listeners know what the state is. Need to determine if there are
16199		// any columns that are not visible but can be shown
16200		var collapsedClass = false;
16201		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
16202			if ( columnsVis[i] === false && ! columns[i].never && ! columns[i].control ) {
16203				collapsedClass = true;
16204				break;
16205			}
16206		}
16207
16208		$( dt.table().node() ).toggleClass( 'collapsed', collapsedClass );
16209
16210		var changed = false;
16211		var visible = 0;
16212
16213		dt.columns().eq(0).each( function ( colIdx, i ) {
16214			if ( columnsVis[i] === true ) {
16215				visible++;
16216			}
16217
16218			if ( columnsVis[i] !== oldVis[i] ) {
16219				changed = true;
16220				that._setColumnVis( colIdx, columnsVis[i] );
16221			}
16222		} );
16223
16224		if ( changed ) {
16225			this._redrawChildren();
16226
16227			// Inform listeners of the change
16228			$(dt.table().node()).trigger( 'responsive-resize.dt', [dt, this.s.current] );
16229
16230			// If no records, update the "No records" display element
16231			if ( dt.page.info().recordsDisplay === 0 ) {
16232				$('td', dt.table().body()).eq(0).attr('colspan', visible);
16233			}
16234		}
16235	},
16236
16237
16238	/**
16239	 * Determine the width of each column in the table so the auto column hiding
16240	 * has that information to work with. This method is never going to be 100%
16241	 * perfect since column widths can change slightly per page, but without
16242	 * seriously compromising performance this is quite effective.
16243	 *
16244	 * @private
16245	 */
16246	_resizeAuto: function ()
16247	{
16248		var dt = this.s.dt;
16249		var columns = this.s.columns;
16250
16251		// Are we allowed to do auto sizing?
16252		if ( ! this.c.auto ) {
16253			return;
16254		}
16255
16256		// Are there any columns that actually need auto-sizing, or do they all
16257		// have classes defined
16258		if ( $.inArray( true, $.map( columns, function (c) { return c.auto; }
16258 ) ) === -1 ) {
16259			return;
16260		}
16261
16262		// Need to restore all children. They will be reinstated by a re-render
16263		if ( ! $.isEmptyObject( _childNodeStore ) ) {
16264			$.each( _childNodeStore, function ( key ) {
16265				var idx = key.split('-');
16266
16267				_childNodesRestore( dt, idx[0]*1, idx[1]*1 );
16268			} );
16269		}
16270
16271		// Clone the table with the current data in it
16272		var tableWidth   = dt.table().node().offsetWidth;
16273		var columnWidths = dt.columns;
16274		var clonedTable  = dt.table().node().cloneNode( false );
16275		var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
16276		var clonedBody   = $( dt.table().body() ).clone( false, false ).empty().appendTo( clonedTable ); // use jQuery because of IE8
16277
16278		// Header
16279		var headerCells = dt.columns()
16280			.header()
16281			.filter( function (idx) {
16282				return dt.column(idx).visible();
16283			} )
16284			.to$()
16285			.clone( false )
16286			.css( 'display', 'table-cell' )
16287			.css( 'min-width', 0 );
16288
16289		// Body rows - we don't need to take account of DataTables' column
16290		// visibility since we implement our own here (hence the `display` set)
16291		$(clonedBody)
16292			.append( $(dt.rows( { page: 'current' } ).nodes()).clone( false ) )
16293			.find( 'th, td' ).css( 'display', '' );
16294
16295		// Footer
16296		var footer = dt.table().footer();
16297		if ( footer ) {
16298			var clonedFooter = $( footer.cloneNode( false ) ).appendTo( clonedTable );
16299			var footerCells = dt.columns()
16300				.footer()
16301				.filter( function (idx) {
16302					return dt.column(idx).visible();
16303				} )
16304				.to$()
16305				.clone( false )
16306				.css( 'display', 'table-cell' );
16307
16308			$('<tr/>')
16309				.append( footerCells )
16310				.appendTo( clonedFooter );
16311		}
16312
16313		$('<tr/>')
16314			.append( headerCells )
16315			.appendTo( clonedHeader );
16316
16317		// In the inline case extra padding is applied to the first column to
16318		// give space for the show / hide icon. We need to use this in the
16319		// calculation
16320		if ( this.c.details.type === 'inline' ) {
16321			$(clonedTable).addClass( 'dtr-inline collapsed' );
16322		}
16323		
16324		// It is unsafe to insert elements with the same name into the DOM
16325		// multiple times. For example, cloning and inserting a checked radio
16326		// clears the chcecked state of the original radio.
16327		$( clonedTable ).find( '[name]' ).removeAttr( 'name' );
16328		
16329		var inserted = $('<div/>')
16330			.css( {
16331				width: 1,
16332				height: 1,
16333				overflow: 'hidden',
16334				clear: 'both'
16335			} )
16336			.append( clonedTable );
16337
16338		inserted.insertBefore( dt.table().node() );
16339
16340		// The cloned header now contains the smallest that each column can be
16341		headerCells.each( function (i) {
16342			var idx = dt.column.index( 'fromVisible', i );
16343			columns[ idx ].minWidth =  this.offsetWidth || 0;
16344		} );
16345
16346		inserted.remove();
16347	},
16348
16349	/**
16350	 * Set a column's visibility.
16351	 *
16352	 * We don't use DataTables' column visibility controls in order to ensure
16353	 * that column visibility can Responsive can no-exist. Since only IE8+ is
16354	 * supported (and all evergreen browsers of course) the control of the
16355	 * display attribute works well.
16356	 *
16357	 * @param {integer} col      Column index
16358	 * @param {boolean} showHide Show or hide (true or false)
16359	 * @private
16360	 */
16361	_setColumnVis: function ( col, showHide )
16362	{
16363		var dt = this.s.dt;
16364		var display = showHide ? '' : 'none'; // empty string will remove the attr
16365
16366		$( dt.column( col ).header() ).css( 'display', display );
16367		$( dt.column( col ).footer() ).css( 'display', display );
16368		dt.column( col ).nodes().to$().css( 'display', display );
16369
16370		// If the are child nodes stored, we might need to reinsert them
16371		if ( ! $.isEmptyObject( _childNodeStore ) ) {
16372			dt.cells( null, col ).indexes().each( function (idx) {
16373				_childNodesRestore( dt, idx.row, idx.column );
16374			} );
16375		}
16376	},
16377
16378
16379	/**
16380	 * Update the cell tab indexes for keyboard accessibility. This is called on
16381	 * every table draw - that is potentially inefficient, but also the least
16382	 * complex option given that column visibility can change on the fly. Its a
16383	 * shame user-focus was removed from CSS 3 UI, as it would have solved this
16384	 * issue with a single CSS statement.
16385	 *
16386	 * @private
16387	 */
16388	_tabIndexes: function ()
16389	{
16390		var dt = this.s.dt;
16391		var cells = dt.cells( { page: 'current' } ).nodes().to$();
16392		var ctx = dt.settings()[0];
16393		var target = this.c.details.target;
16394
16395		cells.filter( '[data-dtr-keyboard]' ).removeData( '[data-dtr-keyboard]' );
16396
16397		var selector = typeof target === 'number' ?
16398			':eq('+target+')' :
16399			target;
16400
16401		// This is a bit of a hack - we need to limit the selected nodes to just
16402		// those of this table
16403		if ( selector === 'td:first-child, th:first-child' ) {
16404			selector = '>td:first-child, >th:first-child';
16405		}
16406
16407		$( selector, dt.rows( { page: 'current' } ).nodes() )
16408			.attr( 'tabIndex', ctx.iTabIndex )
16409			.data( 'dtr-keyboard', 1 );
16410	}
16411} );
16412
16413
16414/**
16415 * List of default breakpoints. Each item in the array is an object with two
16416 * properties:
16417 *
16418 * * `name` - the breakpoint name.
16419 * * `width` - the breakpoint width
16420 *
16421 * @name Responsive.breakpoints
16422 * @static
16423 */
16424Responsive.breakpoints = [
16425	{ name: 'desktop',  width: Infinity },
16426	{ name: 'tablet-l', width: 1024 },
16427	{ name: 'tablet-p', width: 768 },
16428	{ name: 'mobile-l', width: 480 },
16429	{ name: 'mobile-p', width: 320 }
16430];
16431
16432
16433/**
16434 * Display methods - functions which define how the hidden data should be shown
16435 * in the table.
16436 *
16437 * @namespace
16438 * @name Responsive.defaults
16439 * @static
16440 */
16441Responsive.display = {
16442	childRow: function ( row, update, render ) {
16443		if ( update ) {
16444			if ( $(row.node()).hasClass('parent') ) {
16445				row.child( render(), 'child' ).show();
16446
16447				return true;
16448			}
16449		}
16450		else {
16451			if ( ! row.child.isShown()  ) {
16452				row.child( render(), 'child' ).show();
16453				$( row.node() ).addClass( 'parent' );
16454
16455				return true;
16456			}
16457			else {
16458				row.child( false );
16459				$( row.node() ).removeClass( 'parent' );
16460
16461				return false;
16462			}
16463		}
16464	},
16465
16466	childRowImmediate: function ( row, update, render ) {
16467		if ( (! update && row.child.isShown()) || ! row.responsive.hasHidden() ) {
16468			// User interaction and the row is show, or nothing to show
16469			row.child( false );
16470			$( row.node() ).removeClass( 'parent' );
16471
16472			return false;
16473		}
16474		else {
16475			// Display
16476			row.child( render(), 'child' ).show();
16477			$( row.node() ).addClass( 'parent' );
16478
16479			return true;
16480		}
16481	},
16482
16483	// This is a wrapper so the modal options for Bootstrap and jQuery UI can
16484	// have options passed into them. This specific one doesn't need to be a
16485	// function but it is for consistency in the `modal` name
16486	modal: function ( options ) {
16487		return function ( row, update, render ) {
16488			if ( ! update ) {
16489				// Show a modal
16490				var close = function () {
16491					modal.remove(); // will tidy events for us
16492					$(document).off( 'keypress.dtr' );
16493				};
16494
16495				var modal = $('<div class="dtr-modal"/>')
16496					.append( $('<div class="dtr-modal-display"/>')
16497						.append( $('<div class="dtr-modal-content"/>')
16498							.append( render() )
16499						)
16500						.append( $('<div class="dtr-modal-close">&times;</div>' )
16501							.click( function () {
16502								close();
16503							} )
16504						)
16505					)
16506					.append( $('<div class="dtr-modal-background"/>')
16507						.click( function () {
16508							close();
16509						} )
16510					)
16511					.appendTo( 'body' );
16512
16513				$(document).on( 'keyup.dtr', function (e) {
16514					if ( e.keyCode === 27 ) {
16515						e.stopPropagation();
16516
16517						close();
16518					}
16519				} );
16520			}
16521			else {
16522				$('div.dtr-modal-content')
16523					.empty()
16524					.append( render() );
16525			}
16526
16527			if ( options && options.header ) {
16528				$('div.dtr-modal-content').prepend(
16529					'<h2>'+options.header( row )+'</h2>'
16530				);
16531			}
16532		};
16533	}
16534};
16535
16536
16537var _childNodeStore = {};
16538
16539function _childNodes( dt, row, col ) {
16540	var name = row+'-'+col;
16541
16542	if ( _childNodeStore[ name ] ) {
16543		return _childNodeStore[ name ];
16544	}
16545
16546	// https://jsperf.com/childnodes-array-slice-vs-loop
16547	var nodes = [];
16548	var children = dt.cell( row, col ).node().childNodes;
16549	for ( var i=0, ien=children.length ; i<ien ; i++ ) {
16550		nodes.push( children[i] );
16551	}
16552
16553	_childNodeStore[ name ] = nodes;
16554
16555	return nodes;
16556}
16557
16558function _childNodesRestore( dt, row, col ) {
16559	var name = row+'-'+col;
16560
16561	if ( ! _childNodeStore[ name ] ) {
16562		return;
16563	}
16564
16565	var node = dt.cell( row, col ).node();
16566	var store = _childNodeStore[ name ];
16567	var parent = store[0].parentNode;
16568	var parentChildren = parent.childNodes;
16569	var a = [];
16570
16571	for ( var i=0, ien=parentChildren.length ; i<ien ; i++ ) {
16572		a.push( parentChildren[i] );
16573	}
16574
16575	for ( var j=0, jen=a.length ; j<jen ; j++ ) {
16576		node.appendChild( a[j] );
16577	}
16578
16579	_childNodeStore[ name ] = undefined;
16580}
16581
16582
16583/**
16584 * Display methods - functions which define how the hidden data should be shown
16585 * in the table.
16586 *
16587 * @namespace
16588 * @name Responsive.defaults
16589 * @static
16590 */
16591Responsive.renderer = {
16592	listHiddenNodes: function () {
16593		return function ( api, rowIdx, columns ) {
16594			var ul = $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>');
16595			var found = false;
16596
16597			var data = $.each( columns, function ( i, col ) {
16598				if ( col.hidden ) {
16599					$(
16600						'<li data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
16601							'<span class="dtr-title">'+
16602								col.title+
16603							'</span> '+
16604						'</li>'
16605					)
16606						.append( $('<span class="dtr-data"/>').append( _childNodes( api, col.rowIndex, col.columnIndex ) ) )// api.cell( col.rowIndex, col.columnIndex ).node().childNodes ) )
16607						.appendTo( ul );
16608
16609					found = true;
16610				}
16611			} );
16612
16613			return found ?
16614				ul :
16615				false;
16616		};
16617	},
16618
16619	listHidden: function () {
16620		return function ( api, rowIdx, columns ) {
16621			var data = $.map( columns, function ( col ) {
16622				return col.hidden ?
16623					'<li data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
16624						'<span class="dtr-title">'+
16625							col.title+
16626						'</span> '+
16627						'<span class="dtr-data">'+
16628							col.data+
16629						'</span>'+
16630					'</li>' :
16631					'';
16632			} ).join('');
16633
16634			return data ?
16635				$('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>').append( data ) :
16636				false;
16637		}
16638	},
16639
16640	tableAll: function ( options ) {
16641		options = $.extend( {
16642			tableClass: ''
16643		}, options );
16644
16645		return function ( api, rowIdx, columns ) {
16646			var data = $.map( columns, function ( col ) {
16647				return '<tr data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
16648						'<td>'+col.title+':'+'</td> '+
16649						'<td>'+col.data+'</td>'+
16650					'</tr>';
16651			} ).join('');
16652
16653			return $('<table class="'+options.tableClass+' dtr-details" width="100%"/>').append( data );
16654		}
16655	}
16656};
16657
16658/**
16659 * Responsive default settings for initialisation
16660 *
16661 * @namespace
16662 * @name Responsive.defaults
16663 * @static
16664 */
16665Responsive.defaults = {
16666	/**
16667	 * List of breakpoints for the instance. Note that this means that each
16668	 * instance can have its own breakpoints. Additionally, the breakpoints
16669	 * cannot be changed once an instance has been creased.
16670	 *
16671	 * @type {Array}
16672	 * @default Takes the value of `Responsive.breakpoints`
16673	 */
16674	breakpoints: Responsive.breakpoints,
16675
16676	/**
16677	 * Enable / disable auto hiding calculations. It can help to increase
16678	 * performance slightly if you disable this option, but all columns would
16679	 * need to have breakpoint classes assigned to them
16680	 *
16681	 * @type {Boolean}
16682	 * @default  `true`
16683	 */
16684	auto: true,
16685
16686	/**
16687	 * Details control. If given as a string value, the `type` property of the
16688	 * default object is set to that value, and the defaults used for the rest
16689	 * of the object - this is for ease of implementation.
16690	 *
16691	 * The object consists of the following properties:
16692	 *
16693	 * * `display` - A function that is used to show and hide the hidden details
16694	 * * `renderer` - function that is called for display of the child row data.
16695	 *   The default function will show the data from the hidden columns
16696	 * * `target` - Used as the selector for what objects to attach the child
16697	 *   open / close to
16698	 * * `type` - `false` to disable the details display, `inline` or `column`
16699	 *   for the two control types
16700	 *
16701	 * @type {Object|string}
16702	 */
16703	details: {
16704		display: Responsive.display.childRow,
16705
16706		renderer: Responsive.renderer.listHidden(),
16707
16708		target: 0,
16709
16710		type: 'inline'
16711	},
16712
16713	/**
16714	 * Orthogonal data request option. This is used to define the data type
16715	 * requested when Responsive gets the data to show in the child row.
16716	 *
16717	 * @type {String}
16718	 */
16719	orthogonal: 'display'
16720};
16721
16722
16723/*
16724 * API
16725 */
16726var Api = $.fn.dataTable.Api;
16727
16728// Doesn't do anything - work around for a bug in DT... Not documented
16729Api.register( 'responsive()', function () {
16730	return this;
16731} );
16732
16733Api.register( 'responsive.index()', function ( li ) {
16734	li = $(li);
16735
16736	return {
16737		column: li.data('dtr-index'),
16738		row:    li.parent().data('dtr-index')
16739	};
16740} );
16741
16742Api.register( 'responsive.rebuild()', function () {
16743	return this.iterator( 'table', function ( ctx ) {
16744		if ( ctx._responsive ) {
16745			ctx._responsive._classLogic();
16746		}
16747	} );
16748} );
16749
16750Api.register( 'responsive.recalc()', function () {
16751	return this.iterator( 'table', function ( ctx ) {
16752		if ( ctx._responsive ) {
16753			ctx._responsive._resizeAuto();
16754			ctx._responsive._resize();
16755		}
16756	} );
16757} );
16758
16759Api.register( 'responsive.hasHidden()', function () {
16760	var ctx = this.context[0];
16761
16762	return ctx._responsive ?
16763		$.inArray( false, ctx._responsive.s.current ) !== -1 :
16764		false;
16765} );
16766
16767Api.registerPlural( 'columns().responsiveHidden()', 'column().responsiveHidden()', function () {
16768	return this.iterator( 'column', function ( settings, column ) {
16769		return settings._responsive ?
16770			settings._responsive.s.current[ column ] :
16771			false;
16772	}, 1 );
16773} );
16774
16775
16776/**
16777 * Version information
16778 *
16779 * @name Responsive.version
16780 * @static
16781 */
16782Responsive.version = '2.2.1';
16783
16784
16785$.fn.dataTable.Responsive = Responsive;
16786$.fn.DataTable.Responsive = Responsive;
16787
16788// Attach a listener to the document which listens for DataTables initialisation
16789// events so we can automatically initialise
16790$(document).on( 'preInit.dt.dtr', function (e, settings, json) {
16791	if ( e.namespace !== 'dt' ) {
16792		return;
16793	}
16794
16795	if ( $(settings.nTable).hasClass( 'responsive' ) ||
16796		 $(settings.nTable).hasClass( 'dt-responsive' ) ||
16797		 settings.oInit.responsive ||
16798		 DataTable.defaults.responsive
16799	) {
16800		var init = settings.oInit.responsive;
16801
16802		if ( init !== false ) {
16803			new Responsive( settings, $.isPlainObject( init ) ? init : {}  );
16804		}
16805	}
16806} );
16807
16808
16809return Responsive;
16810}));
16811
16812

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.