lavkach3
15648 строк · 428.1 Кб
1/*! DataTables 1.13.5
2* ©2008-2023 SpryMedia Ltd - datatables.net/license
3*/
4
5import jQuery from 'jquery';6
7// DataTables code uses $ internally, but we want to be able to
8// reassign $ with the `use` method, so it is a regular var.
9var $ = jQuery;10
11
12var DataTable = function ( selector, options )13{
14// Check if called with a window or jQuery object for DOM less applications15// This is for backwards compatibility16if (DataTable.factory(selector, options)) {17return DataTable;18}19
20// When creating with `new`, create a new DataTable, returning the API instance21if (this instanceof DataTable) {22return $(selector).DataTable(options);23}24else {25// Argument switching26options = selector;27}28
29/**30* Perform a jQuery selector action on the table's TR elements (from the tbody) and
31* return the resulting jQuery object.
32* @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
33* @param {object} [oOpts] Optional parameters for modifying the rows to be included
34* @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
35* criterion ("applied") or all TR elements (i.e. no filter).
36* @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
37* Can be either 'current', whereby the current sorting of the table is used, or
38* 'original' whereby the original order the data was read into the table is used.
39* @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
40* ("current") or not ("all"). If 'current' is given, then order is assumed to be
41* 'current' and filter is 'applied', regardless of what they might be given as.
42* @returns {object} jQuery object, filtered by the given selector.
43* @dtopt API
44* @deprecated Since v1.10
45*
46* @example
47* $(document).ready(function() {
48* var oTable = $('#example').dataTable();
49*
50* // Highlight every second row
51* oTable.$('tr:odd').css('backgroundColor', 'blue');
52* } );
53*
54* @example
55* $(document).ready(function() {
56* var oTable = $('#example').dataTable();
57*
58* // Filter to rows with 'Webkit' in them, add a background colour and then
59* // remove the filter, thus highlighting the 'Webkit' rows only.
60* oTable.fnFilter('Webkit');
61* oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
62* oTable.fnFilter('');
63* } );
64*/
65this.$ = function ( sSelector, oOpts )66{67return this.api(true).$( sSelector, oOpts );68};69
70
71/**72* Almost identical to $ in operation, but in this case returns the data for the matched
73* rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
74* rather than any descendants, so the data can be obtained for the row/cell. If matching
75* rows are found, the data returned is the original data array/object that was used to
76* create the row (or a generated array if from a DOM source).
77*
78* This method is often useful in-combination with $ where both functions are given the
79* same parameters and the array indexes will match identically.
80* @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
81* @param {object} [oOpts] Optional parameters for modifying the rows to be included
82* @param {string} [oOpts.filter=none] Select elements that meet the current filter
83* criterion ("applied") or all elements (i.e. no filter).
84* @param {string} [oOpts.order=current] Order of the data in the processed array.
85* Can be either 'current', whereby the current sorting of the table is used, or
86* 'original' whereby the original order the data was read into the table is used.
87* @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
88* ("current") or not ("all"). If 'current' is given, then order is assumed to be
89* 'current' and filter is 'applied', regardless of what they might be given as.
90* @returns {array} Data for the matched elements. If any elements, as a result of the
91* selector, were not TR, TD or TH elements in the DataTable, they will have a null
92* entry in the array.
93* @dtopt API
94* @deprecated Since v1.10
95*
96* @example
97* $(document).ready(function() {
98* var oTable = $('#example').dataTable();
99*
100* // Get the data from the first row in the table
101* var data = oTable._('tr:first');
102*
103* // Do something useful with the data
104* alert( "First cell is: "+data[0] );
105* } );
106*
107* @example
108* $(document).ready(function() {
109* var oTable = $('#example').dataTable();
110*
111* // Filter to 'Webkit' and get all data for
112* oTable.fnFilter('Webkit');
113* var data = oTable._('tr', {"search": "applied"});
114*
115* // Do something with the data
116* alert( data.length+" rows matched the search" );
117* } );
118*/
119this._ = function ( sSelector, oOpts )120{121return this.api(true).rows( sSelector, oOpts ).data();122};123
124
125/**126* Create a DataTables Api instance, with the currently selected tables for
127* the Api's context.
128* @param {boolean} [traditional=false] Set the API instance's context to be
129* only the table referred to by the `DataTable.ext.iApiIndex` option, as was
130* used in the API presented by DataTables 1.9- (i.e. the traditional mode),
131* or if all tables captured in the jQuery object should be used.
132* @return {DataTables.Api}
133*/
134this.api = function ( traditional )135{136return traditional ?137new _Api(138_fnSettingsFromNode( this[ _ext.iApiIndex ] )139) :140new _Api( this );141};142
143
144/**145* Add a single new row or multiple rows of data to the table. Please note
146* that this is suitable for client-side processing only - if you are using
147* server-side processing (i.e. "bServerSide": true), then to add data, you
148* must add it to the data source, i.e. the server-side, through an Ajax call.
149* @param {array|object} data The data to be added to the table. This can be:
150* <ul>
151* <li>1D array of data - add a single row with the data provided</li>
152* <li>2D array of arrays - add multiple rows in a single call</li>
153* <li>object - data object when using <i>mData</i></li>
154* <li>array of objects - multiple data objects when using <i>mData</i></li>
155* </ul>
156* @param {bool} [redraw=true] redraw the table or not
157* @returns {array} An array of integers, representing the list of indexes in
158* <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
159* the table.
160* @dtopt API
161* @deprecated Since v1.10
162*
163* @example
164* // Global var for counter
165* var giCount = 2;
166*
167* $(document).ready(function() {
168* $('#example').dataTable();
169* } );
170*
171* function fnClickAddRow() {
172* $('#example').dataTable().fnAddData( [
173* giCount+".1",
174* giCount+".2",
175* giCount+".3",
176* giCount+".4" ]
177* );
178*
179* giCount++;
180* }
181*/
182this.fnAddData = function( data, redraw )183{184var api = this.api( true );185
186/* Check if we want to add multiple rows or not */187var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?188api.rows.add( data ) :189api.row.add( data );190
191if ( redraw === undefined || redraw ) {192api.draw();193}194
195return rows.flatten().toArray();196};197
198
199/**200* This function will make DataTables recalculate the column sizes, based on the data
201* contained in the table and the sizes applied to the columns (in the DOM, CSS or
202* through the sWidth parameter). This can be useful when the width of the table's
203* parent element changes (for example a window resize).
204* @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
205* @dtopt API
206* @deprecated Since v1.10
207*
208* @example
209* $(document).ready(function() {
210* var oTable = $('#example').dataTable( {
211* "sScrollY": "200px",
212* "bPaginate": false
213* } );
214*
215* $(window).on('resize', function () {
216* oTable.fnAdjustColumnSizing();
217* } );
218* } );
219*/
220this.fnAdjustColumnSizing = function ( bRedraw )221{222var api = this.api( true ).columns.adjust();223var settings = api.settings()[0];224var scroll = settings.oScroll;225
226if ( bRedraw === undefined || bRedraw ) {227api.draw( false );228}229else if ( scroll.sX !== "" || scroll.sY !== "" ) {230/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */231_fnScrollDraw( settings );232}233};234
235
236/**237* Quickly and simply clear a table
238* @param {bool} [bRedraw=true] redraw the table or not
239* @dtopt API
240* @deprecated Since v1.10
241*
242* @example
243* $(document).ready(function() {
244* var oTable = $('#example').dataTable();
245*
246* // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
247* oTable.fnClearTable();
248* } );
249*/
250this.fnClearTable = function( bRedraw )251{252var api = this.api( true ).clear();253
254if ( bRedraw === undefined || bRedraw ) {255api.draw();256}257};258
259
260/**261* The exact opposite of 'opening' a row, this function will close any rows which
262* are currently 'open'.
263* @param {node} nTr the table row to 'close'
264* @returns {int} 0 on success, or 1 if failed (can't find the row)
265* @dtopt API
266* @deprecated Since v1.10
267*
268* @example
269* $(document).ready(function() {
270* var oTable;
271*
272* // 'open' an information row when a row is clicked on
273* $('#example tbody tr').click( function () {
274* if ( oTable.fnIsOpen(this) ) {
275* oTable.fnClose( this );
276* } else {
277* oTable.fnOpen( this, "Temporary row opened", "info_row" );
278* }
279* } );
280*
281* oTable = $('#example').dataTable();
282* } );
283*/
284this.fnClose = function( nTr )285{286this.api( true ).row( nTr ).child.hide();287};288
289
290/**291* Remove a row for the table
292* @param {mixed} target The index of the row from aoData to be deleted, or
293* the TR element you want to delete
294* @param {function|null} [callBack] Callback function
295* @param {bool} [redraw=true] Redraw the table or not
296* @returns {array} The row that was deleted
297* @dtopt API
298* @deprecated Since v1.10
299*
300* @example
301* $(document).ready(function() {
302* var oTable = $('#example').dataTable();
303*
304* // Immediately remove the first row
305* oTable.fnDeleteRow( 0 );
306* } );
307*/
308this.fnDeleteRow = function( target, callback, redraw )309{310var api = this.api( true );311var rows = api.rows( target );312var settings = rows.settings()[0];313var data = settings.aoData[ rows[0][0] ];314
315rows.remove();316
317if ( callback ) {318callback.call( this, settings, data );319}320
321if ( redraw === undefined || redraw ) {322api.draw();323}324
325return data;326};327
328
329/**330* Restore the table to it's original state in the DOM by removing all of DataTables
331* enhancements, alterations to the DOM structure of the table and event listeners.
332* @param {boolean} [remove=false] Completely remove the table from the DOM
333* @dtopt API
334* @deprecated Since v1.10
335*
336* @example
337* $(document).ready(function() {
338* // This example is fairly pointless in reality, but shows how fnDestroy can be used
339* var oTable = $('#example').dataTable();
340* oTable.fnDestroy();
341* } );
342*/
343this.fnDestroy = function ( remove )344{345this.api( true ).destroy( remove );346};347
348
349/**350* Redraw the table
351* @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
352* @dtopt API
353* @deprecated Since v1.10
354*
355* @example
356* $(document).ready(function() {
357* var oTable = $('#example').dataTable();
358*
359* // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
360* oTable.fnDraw();
361* } );
362*/
363this.fnDraw = function( complete )364{365// Note that this isn't an exact match to the old call to _fnDraw - it takes366// into account the new data, but can hold position.367this.api( true ).draw( complete );368};369
370
371/**372* Filter the input based on data
373* @param {string} sInput String to filter the table on
374* @param {int|null} [iColumn] Column to limit filtering to
375* @param {bool} [bRegex=false] Treat as regular expression or not
376* @param {bool} [bSmart=true] Perform smart filtering or not
377* @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
378* @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
379* @dtopt API
380* @deprecated Since v1.10
381*
382* @example
383* $(document).ready(function() {
384* var oTable = $('#example').dataTable();
385*
386* // Sometime later - filter...
387* oTable.fnFilter( 'test string' );
388* } );
389*/
390this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )391{392var api = this.api( true );393
394if ( iColumn === null || iColumn === undefined ) {395api.search( sInput, bRegex, bSmart, bCaseInsensitive );396}397else {398api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );399}400
401api.draw();402};403
404
405/**406* Get the data for the whole table, an individual row or an individual cell based on the
407* provided parameters.
408* @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
409* a TR node then the data source for the whole row will be returned. If given as a
410* TD/TH cell node then iCol will be automatically calculated and the data for the
411* cell returned. If given as an integer, then this is treated as the aoData internal
412* data index for the row (see fnGetPosition) and the data for that row used.
413* @param {int} [col] Optional column index that you want the data of.
414* @returns {array|object|string} If mRow is undefined, then the data for all rows is
415* returned. If mRow is defined, just data for that row, and is iCol is
416* defined, only data for the designated cell is returned.
417* @dtopt API
418* @deprecated Since v1.10
419*
420* @example
421* // Row data
422* $(document).ready(function() {
423* oTable = $('#example').dataTable();
424*
425* oTable.$('tr').click( function () {
426* var data = oTable.fnGetData( this );
427* // ... do something with the array / object of data for the row
428* } );
429* } );
430*
431* @example
432* // Individual cell data
433* $(document).ready(function() {
434* oTable = $('#example').dataTable();
435*
436* oTable.$('td').click( function () {
437* var sData = oTable.fnGetData( this );
438* alert( 'The cell clicked on had the value of '+sData );
439* } );
440* } );
441*/
442this.fnGetData = function( src, col )443{444var api = this.api( true );445
446if ( src !== undefined ) {447var type = src.nodeName ? src.nodeName.toLowerCase() : '';448
449return col !== undefined || type == 'td' || type == 'th' ?450api.cell( src, col ).data() :451api.row( src ).data() || null;452}453
454return api.data().toArray();455};456
457
458/**459* Get an array of the TR nodes that are used in the table's body. Note that you will
460* typically want to use the '$' API method in preference to this as it is more
461* flexible.
462* @param {int} [iRow] Optional row index for the TR element you want
463* @returns {array|node} If iRow is undefined, returns an array of all TR elements
464* in the table's body, or iRow is defined, just the TR element requested.
465* @dtopt API
466* @deprecated Since v1.10
467*
468* @example
469* $(document).ready(function() {
470* var oTable = $('#example').dataTable();
471*
472* // Get the nodes from the table
473* var nNodes = oTable.fnGetNodes( );
474* } );
475*/
476this.fnGetNodes = function( iRow )477{478var api = this.api( true );479
480return iRow !== undefined ?481api.row( iRow ).node() :482api.rows().nodes().flatten().toArray();483};484
485
486/**487* Get the array indexes of a particular cell from it's DOM element
488* and column index including hidden columns
489* @param {node} node this can either be a TR, TD or TH in the table's body
490* @returns {int} If nNode is given as a TR, then a single index is returned, or
491* if given as a cell, an array of [row index, column index (visible),
492* column index (all)] is given.
493* @dtopt API
494* @deprecated Since v1.10
495*
496* @example
497* $(document).ready(function() {
498* $('#example tbody td').click( function () {
499* // Get the position of the current data from the node
500* var aPos = oTable.fnGetPosition( this );
501*
502* // Get the data array for this row
503* var aData = oTable.fnGetData( aPos[0] );
504*
505* // Update the data array and return the value
506* aData[ aPos[1] ] = 'clicked';
507* this.innerHTML = 'clicked';
508* } );
509*
510* // Init DataTables
511* oTable = $('#example').dataTable();
512* } );
513*/
514this.fnGetPosition = function( node )515{516var api = this.api( true );517var nodeName = node.nodeName.toUpperCase();518
519if ( nodeName == 'TR' ) {520return api.row( node ).index();521}522else if ( nodeName == 'TD' || nodeName == 'TH' ) {523var cell = api.cell( node ).index();524
525return [526cell.row,527cell.columnVisible,528cell.column529];530}531return null;532};533
534
535/**536* Check to see if a row is 'open' or not.
537* @param {node} nTr the table row to check
538* @returns {boolean} true if the row is currently open, false otherwise
539* @dtopt API
540* @deprecated Since v1.10
541*
542* @example
543* $(document).ready(function() {
544* var oTable;
545*
546* // 'open' an information row when a row is clicked on
547* $('#example tbody tr').click( function () {
548* if ( oTable.fnIsOpen(this) ) {
549* oTable.fnClose( this );
550* } else {
551* oTable.fnOpen( this, "Temporary row opened", "info_row" );
552* }
553* } );
554*
555* oTable = $('#example').dataTable();
556* } );
557*/
558this.fnIsOpen = function( nTr )559{560return this.api( true ).row( nTr ).child.isShown();561};562
563
564/**565* This function will place a new row directly after a row which is currently
566* on display on the page, with the HTML contents that is passed into the
567* function. This can be used, for example, to ask for confirmation that a
568* particular record should be deleted.
569* @param {node} nTr The table row to 'open'
570* @param {string|node|jQuery} mHtml The HTML to put into the row
571* @param {string} sClass Class to give the new TD cell
572* @returns {node} The row opened. Note that if the table row passed in as the
573* first parameter, is not found in the table, this method will silently
574* return.
575* @dtopt API
576* @deprecated Since v1.10
577*
578* @example
579* $(document).ready(function() {
580* var oTable;
581*
582* // 'open' an information row when a row is clicked on
583* $('#example tbody tr').click( function () {
584* if ( oTable.fnIsOpen(this) ) {
585* oTable.fnClose( this );
586* } else {
587* oTable.fnOpen( this, "Temporary row opened", "info_row" );
588* }
589* } );
590*
591* oTable = $('#example').dataTable();
592* } );
593*/
594this.fnOpen = function( nTr, mHtml, sClass )595{596return this.api( true )597.row( nTr )598.child( mHtml, sClass )599.show()600.child()[0];601};602
603
604/**605* Change the pagination - provides the internal logic for pagination in a simple API
606* function. With this function you can have a DataTables table go to the next,
607* previous, first or last pages.
608* @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
609* or page number to jump to (integer), note that page 0 is the first page.
610* @param {bool} [bRedraw=true] Redraw the table or not
611* @dtopt API
612* @deprecated Since v1.10
613*
614* @example
615* $(document).ready(function() {
616* var oTable = $('#example').dataTable();
617* oTable.fnPageChange( 'next' );
618* } );
619*/
620this.fnPageChange = function ( mAction, bRedraw )621{622var api = this.api( true ).page( mAction );623
624if ( bRedraw === undefined || bRedraw ) {625api.draw(false);626}627};628
629
630/**631* Show a particular column
632* @param {int} iCol The column whose display should be changed
633* @param {bool} bShow Show (true) or hide (false) the column
634* @param {bool} [bRedraw=true] Redraw the table or not
635* @dtopt API
636* @deprecated Since v1.10
637*
638* @example
639* $(document).ready(function() {
640* var oTable = $('#example').dataTable();
641*
642* // Hide the second column after initialisation
643* oTable.fnSetColumnVis( 1, false );
644* } );
645*/
646this.fnSetColumnVis = function ( iCol, bShow, bRedraw )647{648var api = this.api( true ).column( iCol ).visible( bShow );649
650if ( bRedraw === undefined || bRedraw ) {651api.columns.adjust().draw();652}653};654
655
656/**657* Get the settings for a particular table for external manipulation
658* @returns {object} DataTables settings object. See
659* {@link DataTable.models.oSettings}
660* @dtopt API
661* @deprecated Since v1.10
662*
663* @example
664* $(document).ready(function() {
665* var oTable = $('#example').dataTable();
666* var oSettings = oTable.fnSettings();
667*
668* // Show an example parameter from the settings
669* alert( oSettings._iDisplayStart );
670* } );
671*/
672this.fnSettings = function()673{674return _fnSettingsFromNode( this[_ext.iApiIndex] );675};676
677
678/**679* Sort the table by a particular column
680* @param {int} iCol the data index to sort on. Note that this will not match the
681* 'display index' if you have hidden data entries
682* @dtopt API
683* @deprecated Since v1.10
684*
685* @example
686* $(document).ready(function() {
687* var oTable = $('#example').dataTable();
688*
689* // Sort immediately with columns 0 and 1
690* oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
691* } );
692*/
693this.fnSort = function( aaSort )694{695this.api( true ).order( aaSort ).draw();696};697
698
699/**700* Attach a sort listener to an element for a given column
701* @param {node} nNode the element to attach the sort listener to
702* @param {int} iColumn the column that a click on this node will sort on
703* @param {function} [fnCallback] callback function when sort is run
704* @dtopt API
705* @deprecated Since v1.10
706*
707* @example
708* $(document).ready(function() {
709* var oTable = $('#example').dataTable();
710*
711* // Sort on column 1, when 'sorter' is clicked on
712* oTable.fnSortListener( document.getElementById('sorter'), 1 );
713* } );
714*/
715this.fnSortListener = function( nNode, iColumn, fnCallback )716{717this.api( true ).order.listener( nNode, iColumn, fnCallback );718};719
720
721/**722* Update a table cell or row - this method will accept either a single value to
723* update the cell with, an array of values with one element for each column or
724* an object in the same format as the original data source. The function is
725* self-referencing in order to make the multi column updates easier.
726* @param {object|array|string} mData Data to update the cell/row with
727* @param {node|int} mRow TR element you want to update or the aoData index
728* @param {int} [iColumn] The column to update, give as null or undefined to
729* update a whole row.
730* @param {bool} [bRedraw=true] Redraw the table or not
731* @param {bool} [bAction=true] Perform pre-draw actions or not
732* @returns {int} 0 on success, 1 on error
733* @dtopt API
734* @deprecated Since v1.10
735*
736* @example
737* $(document).ready(function() {
738* var oTable = $('#example').dataTable();
739* oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
740* oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
741* } );
742*/
743this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )744{745var api = this.api( true );746
747if ( iColumn === undefined || iColumn === null ) {748api.row( mRow ).data( mData );749}750else {751api.cell( mRow, iColumn ).data( mData );752}753
754if ( bAction === undefined || bAction ) {755api.columns.adjust();756}757
758if ( bRedraw === undefined || bRedraw ) {759api.draw();760}761return 0;762};763
764
765/**766* Provide a common method for plug-ins to check the version of DataTables being used, in order
767* to ensure compatibility.
768* @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
769* formats "X" and "X.Y" are also acceptable.
770* @returns {boolean} true if this version of DataTables is greater or equal to the required
771* version, or false if this version of DataTales is not suitable
772* @method
773* @dtopt API
774* @deprecated Since v1.10
775*
776* @example
777* $(document).ready(function() {
778* var oTable = $('#example').dataTable();
779* alert( oTable.fnVersionCheck( '1.9.0' ) );
780* } );
781*/
782this.fnVersionCheck = _ext.fnVersionCheck;783
784
785var _that = this;786var emptyInit = options === undefined;787var len = this.length;788
789if ( emptyInit ) {790options = {};791}792
793this.oApi = this.internal = _ext.internal;794
795// Extend with old style plug-in API methods796for ( var fn in DataTable.ext.internal ) {797if ( fn ) {798this[fn] = _fnExternApiFunc(fn);799}800}801
802this.each(function() {803// For each initialisation we want to give it a clean initialisation804// object that can be bashed around805var o = {};806var oInit = len > 1 ? // optimisation for single table case807_fnExtend( o, options, true ) :808options;809
810/*global oInit,_that,emptyInit*/811var i=0, iLen, j, jLen, k, kLen;812var sId = this.getAttribute( 'id' );813var bInitHandedOff = false;814var defaults = DataTable.defaults;815var $this = $(this);816
817
818/* Sanity check */819if ( this.nodeName.toLowerCase() != 'table' )820{821_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );822return;823}824
825/* Backwards compatibility for the defaults */826_fnCompatOpts( defaults );827_fnCompatCols( defaults.column );828
829/* Convert the camel-case defaults to Hungarian */830_fnCamelToHungarian( defaults, defaults, true );831_fnCamelToHungarian( defaults.column, defaults.column, true );832
833/* Setting up the initialisation object */834_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );835
836
837
838/* Check to see if we are re-initialising a table */839var allSettings = DataTable.settings;840for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )841{842var s = allSettings[i];843
844/* Base check on table node */845if (846s.nTable == this ||847(s.nTHead && s.nTHead.parentNode == this) ||848(s.nTFoot && s.nTFoot.parentNode == this)849) {850var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;851var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;852
853if ( emptyInit || bRetrieve )854{855return s.oInstance;856}857else if ( bDestroy )858{859s.oInstance.fnDestroy();860break;861}862else863{864_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );865return;866}867}868
869/* If the element we are initialising has the same ID as a table which was previously870* initialised, but the table nodes don't match (from before) then we destroy the old
871* instance by simply deleting it. This is under the assumption that the table has been
872* destroyed by other methods. Anyone using non-id selectors will need to do this manually
873*/
874if ( s.sTableId == this.id )875{876allSettings.splice( i, 1 );877break;878}879}880
881/* Ensure the table has an ID - required for accessibility */882if ( sId === null || sId === "" )883{884sId = "DataTables_Table_"+(DataTable.ext._unique++);885this.id = sId;886}887
888/* Create the settings object for this table and set some of the default parameters */889var oSettings = $.extend( true, {}, DataTable.models.oSettings, {890"sDestroyWidth": $this[0].style.width,891"sInstance": sId,892"sTableId": sId893} );894oSettings.nTable = this;895oSettings.oApi = _that.internal;896oSettings.oInit = oInit;897
898allSettings.push( oSettings );899
900// Need to add the instance after the instance after the settings object has been added901// to the settings array, so we can self reference the table instance if more than one902oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();903
904// Backwards compatibility, before we apply all the defaults905_fnCompatOpts( oInit );906_fnLanguageCompat( oInit.oLanguage );907
908// If the length menu is given, but the init display length is not, use the length menu909if ( oInit.aLengthMenu && ! oInit.iDisplayLength )910{911oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?912oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];913}914
915// Apply the defaults and init options to make a single init object will all916// options defined from defaults and instance options.917oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );918
919
920// Map the initialisation options onto the settings object921_fnMap( oSettings.oFeatures, oInit, [922"bPaginate",923"bLengthChange",924"bFilter",925"bSort",926"bSortMulti",927"bInfo",928"bProcessing",929"bAutoWidth",930"bSortClasses",931"bServerSide",932"bDeferRender"933] );934_fnMap( oSettings, oInit, [935"asStripeClasses",936"ajax",937"fnServerData",938"fnFormatNumber",939"sServerMethod",940"aaSorting",941"aaSortingFixed",942"aLengthMenu",943"sPaginationType",944"sAjaxSource",945"sAjaxDataProp",946"iStateDuration",947"sDom",948"bSortCellsTop",949"iTabIndex",950"fnStateLoadCallback",951"fnStateSaveCallback",952"renderer",953"searchDelay",954"rowId",955[ "iCookieDuration", "iStateDuration" ], // backwards compat956[ "oSearch", "oPreviousSearch" ],957[ "aoSearchCols", "aoPreSearchCols" ],958[ "iDisplayLength", "_iDisplayLength" ]959] );960_fnMap( oSettings.oScroll, oInit, [961[ "sScrollX", "sX" ],962[ "sScrollXInner", "sXInner" ],963[ "sScrollY", "sY" ],964[ "bScrollCollapse", "bCollapse" ]965] );966_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );967
968/* Callback functions which are array driven */969_fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );970_fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );971_fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );972_fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );973_fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );974_fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );975_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );976_fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );977_fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );978_fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );979_fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );980
981oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );982
983/* Browser support detection */984_fnBrowserDetect( oSettings );985
986var oClasses = oSettings.oClasses;987
988$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );989$this.addClass( oClasses.sTable );990
991
992if ( oSettings.iInitDisplayStart === undefined )993{994/* Display start point, taking into account the save saving */995oSettings.iInitDisplayStart = oInit.iDisplayStart;996oSettings._iDisplayStart = oInit.iDisplayStart;997}998
999if ( oInit.iDeferLoading !== null )1000{1001oSettings.bDeferLoading = true;1002var tmp = Array.isArray( oInit.iDeferLoading );1003oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;1004oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;1005}1006
1007/* Language definitions */1008var oLanguage = oSettings.oLanguage;1009$.extend( true, oLanguage, oInit.oLanguage );1010
1011if ( oLanguage.sUrl )1012{1013/* Get the language definitions from a file - because this Ajax call makes the language1014* get async to the remainder of this function we use bInitHandedOff to indicate that
1015* _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1016*/
1017$.ajax( {1018dataType: 'json',1019url: oLanguage.sUrl,1020success: function ( json ) {1021_fnCamelToHungarian( defaults.oLanguage, json );1022_fnLanguageCompat( json );1023$.extend( true, oLanguage, json, oSettings.oInit.oLanguage );1024
1025_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);1026_fnInitialise( oSettings );1027},1028error: function () {1029// Error occurred loading language file, continue on as best we can1030_fnInitialise( oSettings );1031}1032} );1033bInitHandedOff = true;1034}1035else {1036_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);1037}1038
1039/*1040* Stripes
1041*/
1042if ( oInit.asStripeClasses === null )1043{1044oSettings.asStripeClasses =[1045oClasses.sStripeOdd,1046oClasses.sStripeEven1047];1048}1049
1050/* Remove row stripe classes if they are already on the table row */1051var stripeClasses = oSettings.asStripeClasses;1052var rowOne = $this.children('tbody').find('tr').eq(0);1053if ( $.inArray( true, $.map( stripeClasses, function(el, i) {1054return rowOne.hasClass(el);1055} ) ) !== -1 ) {1056$('tbody tr', this).removeClass( stripeClasses.join(' ') );1057oSettings.asDestroyStripes = stripeClasses.slice();1058}1059
1060/*1061* Columns
1062* See if we should load columns automatically or use defined ones
1063*/
1064var anThs = [];1065var aoColumnsInit;1066var nThead = this.getElementsByTagName('thead');1067if ( nThead.length !== 0 )1068{1069_fnDetectHeader( oSettings.aoHeader, nThead[0] );1070anThs = _fnGetUniqueThs( oSettings );1071}1072
1073/* If not given a column array, generate one with nulls */1074if ( oInit.aoColumns === null )1075{1076aoColumnsInit = [];1077for ( i=0, iLen=anThs.length ; i<iLen ; i++ )1078{1079aoColumnsInit.push( null );1080}1081}1082else1083{1084aoColumnsInit = oInit.aoColumns;1085}1086
1087/* Add the columns */1088for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )1089{1090_fnAddColumn( oSettings, anThs ? anThs[i] : null );1091}1092
1093/* Apply the column definitions */1094_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {1095_fnColumnOptions( oSettings, iCol, oDef );1096} );1097
1098/* HTML5 attribute detection - build an mData object automatically if the1099* attributes are found
1100*/
1101if ( rowOne.length ) {1102var a = function ( cell, name ) {1103return cell.getAttribute( 'data-'+name ) !== null ? name : null;1104};1105
1106$( rowOne[0] ).children('th, td').each( function (i, cell) {1107var col = oSettings.aoColumns[i];1108
1109if (! col) {1110_fnLog( oSettings, 0, 'Incorrect column count', 18 );1111}1112
1113if ( col.mData === i ) {1114var sort = a( cell, 'sort' ) || a( cell, 'order' );1115var filter = a( cell, 'filter' ) || a( cell, 'search' );1116
1117if ( sort !== null || filter !== null ) {1118col.mData = {1119_: i+'.display',1120sort: sort !== null ? i+'.@data-'+sort : undefined,1121type: sort !== null ? i+'.@data-'+sort : undefined,1122filter: filter !== null ? i+'.@data-'+filter : undefined1123};1124col._isArrayHost = true;1125
1126_fnColumnOptions( oSettings, i );1127}1128}1129} );1130}1131
1132var features = oSettings.oFeatures;1133var loadedInit = function () {1134/*1135* Sorting
1136* @todo For modularisation (1.11) this needs to do into a sort start up handler
1137*/
1138
1139// If aaSorting is not defined, then we use the first indicator in asSorting1140// in case that has been altered, so the default sort reflects that option1141if ( oInit.aaSorting === undefined ) {1142var sorting = oSettings.aaSorting;1143for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {1144sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];1145}1146}1147
1148/* Do a first pass on the sorting classes (allows any size changes to be taken into1149* account, and also will apply sorting disabled classes if disabled
1150*/
1151_fnSortingClasses( oSettings );1152
1153if ( features.bSort ) {1154_fnCallbackReg( oSettings, 'aoDrawCallback', function () {1155if ( oSettings.bSorted ) {1156var aSort = _fnSortFlatten( oSettings );1157var sortedColumns = {};1158
1159$.each( aSort, function (i, val) {1160sortedColumns[ val.src ] = val.dir;1161} );1162
1163_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );1164_fnSortAria( oSettings );1165}1166} );1167}1168
1169_fnCallbackReg( oSettings, 'aoDrawCallback', function () {1170if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {1171_fnSortingClasses( oSettings );1172}1173}, 'sc' );1174
1175
1176/*1177* Final init
1178* Cache the header, body and footer as required, creating them if needed
1179*/
1180
1181// Work around for Webkit bug 83867 - store the caption-side before removing from doc1182var captions = $this.children('caption').each( function () {1183this._captionSide = $(this).css('caption-side');1184} );1185
1186var thead = $this.children('thead');1187if ( thead.length === 0 ) {1188thead = $('<thead/>').appendTo($this);1189}1190oSettings.nTHead = thead[0];1191
1192var tbody = $this.children('tbody');1193if ( tbody.length === 0 ) {1194tbody = $('<tbody/>').insertAfter(thead);1195}1196oSettings.nTBody = tbody[0];1197
1198var tfoot = $this.children('tfoot');1199if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {1200// If we are a scrolling table, and no footer has been given, then we need to create1201// a tfoot element for the caption element to be appended to1202tfoot = $('<tfoot/>').appendTo($this);1203}1204
1205if ( tfoot.length === 0 || tfoot.children().length === 0 ) {1206$this.addClass( oClasses.sNoFooter );1207}1208else if ( tfoot.length > 0 ) {1209oSettings.nTFoot = tfoot[0];1210_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );1211}1212
1213/* Check if there is data passing into the constructor */1214if ( oInit.aaData ) {1215for ( i=0 ; i<oInit.aaData.length ; i++ ) {1216_fnAddData( oSettings, oInit.aaData[ i ] );1217}1218}1219else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {1220/* Grab the data from the page - only do this when deferred loading or no Ajax1221* source since there is no point in reading the DOM data if we are then going
1222* to replace it with Ajax data
1223*/
1224_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );1225}1226
1227/* Copy the data index array */1228oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();1229
1230/* Initialisation complete - table can be drawn */1231oSettings.bInitialised = true;1232
1233/* Check if we need to initialise the table (it might not have been handed off to the1234* language processor)
1235*/
1236if ( bInitHandedOff === false ) {1237_fnInitialise( oSettings );1238}1239};1240
1241/* Must be done after everything which can be overridden by the state saving! */1242_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );1243
1244if ( oInit.bStateSave )1245{1246features.bStateSave = true;1247_fnLoadState( oSettings, oInit, loadedInit );1248}1249else {1250loadedInit();1251}1252
1253} );1254_that = null;1255return this;1256};1257
1258
1259/*
1260* It is useful to have variables which are scoped locally so only the
1261* DataTables functions can access them and they don't leak into global space.
1262* At the same time these functions are often useful over multiple files in the
1263* core and API, so we list, or at least document, all variables which are used
1264* by DataTables as private variables here. This also ensures that there is no
1265* clashing of variable names and that they can easily referenced for reuse.
1266*/
1267
1268
1269// Defined else where
1270// _selector_run
1271// _selector_opts
1272// _selector_first
1273// _selector_row_indexes
1274
1275var _ext; // DataTable.ext1276var _Api; // DataTable.Api1277var _api_register; // DataTable.Api.register1278var _api_registerPlural; // DataTable.Api.registerPlural1279
1280var _re_dic = {};1281var _re_new_lines = /[\r\n\u2028]/g;1282var _re_html = /<.*?>/g;1283
1284// This is not strict ISO8601 - Date.parse() is quite lax, although
1285// implementations differ between browsers.
1286var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;1287
1288// Escape regular expression special characters
1289var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );1290
1291// http://en.wikipedia.org/wiki/Foreign_exchange_market
1292// - \u20BD - Russian ruble.
1293// - \u20a9 - South Korean Won
1294// - \u20BA - Turkish Lira
1295// - \u20B9 - Indian Rupee
1296// - R - Brazil (R$) and South Africa
1297// - fr - Swiss Franc
1298// - kr - Swedish krona, Norwegian krone and Danish krone
1299// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1300// - Ƀ - Bitcoin
1301// - Ξ - Ethereum
1302// standards as thousands separators.
1303var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;1304
1305
1306var _empty = function ( d ) {1307return !d || d === true || d === '-' ? true : false;1308};1309
1310
1311var _intVal = function ( s ) {1312var integer = parseInt( s, 10 );1313return !isNaN(integer) && isFinite(s) ? integer : null;1314};1315
1316// Convert from a formatted number with characters other than `.` as the
1317// decimal place, to a Javascript number
1318var _numToDecimal = function ( num, decimalPoint ) {1319// Cache created regular expressions for speed as this function is called often1320if ( ! _re_dic[ decimalPoint ] ) {1321_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );1322}1323return typeof num === 'string' && decimalPoint !== '.' ?1324num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :1325num;1326};1327
1328
1329var _isNumber = function ( d, decimalPoint, formatted ) {1330var type = typeof d;1331var strType = type === 'string';1332
1333if ( type === 'number' || type === 'bigint') {1334return true;1335}1336
1337// If empty return immediately so there must be a number if it is a1338// formatted string (this stops the string "k", or "kr", etc being detected1339// as a formatted number for currency1340if ( _empty( d ) ) {1341return true;1342}1343
1344if ( decimalPoint && strType ) {1345d = _numToDecimal( d, decimalPoint );1346}1347
1348if ( formatted && strType ) {1349d = d.replace( _re_formatted_numeric, '' );1350}1351
1352return !isNaN( parseFloat(d) ) && isFinite( d );1353};1354
1355
1356// A string without HTML in it can be considered to be HTML still
1357var _isHtml = function ( d ) {1358return _empty( d ) || typeof d === 'string';1359};1360
1361
1362var _htmlNumeric = function ( d, decimalPoint, formatted ) {1363if ( _empty( d ) ) {1364return true;1365}1366
1367var html = _isHtml( d );1368return ! html ?1369null :1370_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?1371true :1372null;1373};1374
1375
1376var _pluck = function ( a, prop, prop2 ) {1377var out = [];1378var i=0, ien=a.length;1379
1380// Could have the test in the loop for slightly smaller code, but speed1381// is essential here1382if ( prop2 !== undefined ) {1383for ( ; i<ien ; i++ ) {1384if ( a[i] && a[i][ prop ] ) {1385out.push( a[i][ prop ][ prop2 ] );1386}1387}1388}1389else {1390for ( ; i<ien ; i++ ) {1391if ( a[i] ) {1392out.push( a[i][ prop ] );1393}1394}1395}1396
1397return out;1398};1399
1400
1401// Basically the same as _pluck, but rather than looping over `a` we use `order`
1402// as the indexes to pick from `a`
1403var _pluck_order = function ( a, order, prop, prop2 )1404{
1405var out = [];1406var i=0, ien=order.length;1407
1408// Could have the test in the loop for slightly smaller code, but speed1409// is essential here1410if ( prop2 !== undefined ) {1411for ( ; i<ien ; i++ ) {1412if ( a[ order[i] ][ prop ] ) {1413out.push( a[ order[i] ][ prop ][ prop2 ] );1414}1415}1416}1417else {1418for ( ; i<ien ; i++ ) {1419out.push( a[ order[i] ][ prop ] );1420}1421}1422
1423return out;1424};1425
1426
1427var _range = function ( len, start )1428{
1429var out = [];1430var end;1431
1432if ( start === undefined ) {1433start = 0;1434end = len;1435}1436else {1437end = start;1438start = len;1439}1440
1441for ( var i=start ; i<end ; i++ ) {1442out.push( i );1443}1444
1445return out;1446};1447
1448
1449var _removeEmpty = function ( a )1450{
1451var out = [];1452
1453for ( var i=0, ien=a.length ; i<ien ; i++ ) {1454if ( a[i] ) { // careful - will remove all falsy values!1455out.push( a[i] );1456}1457}1458
1459return out;1460};1461
1462
1463var _stripHtml = function ( d ) {1464return d1465.replace( _re_html, '' ) // Complete tags1466.replace(/<script/i, ''); // Safety for incomplete script tag1467};1468
1469
1470/**
1471* Determine if all values in the array are unique. This means we can short
1472* cut the _unique method at the cost of a single loop. A sorted array is used
1473* to easily check the values.
1474*
1475* @param {array} src Source array
1476* @return {boolean} true if all unique, false otherwise
1477* @ignore
1478*/
1479var _areAllUnique = function ( src ) {1480if ( src.length < 2 ) {1481return true;1482}1483
1484var sorted = src.slice().sort();1485var last = sorted[0];1486
1487for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {1488if ( sorted[i] === last ) {1489return false;1490}1491
1492last = sorted[i];1493}1494
1495return true;1496};1497
1498
1499/**
1500* Find the unique elements in a source array.
1501*
1502* @param {array} src Source array
1503* @return {array} Array of unique items
1504* @ignore
1505*/
1506var _unique = function ( src )1507{
1508if ( _areAllUnique( src ) ) {1509return src.slice();1510}1511
1512// A faster unique method is to use object keys to identify used values,1513// but this doesn't work with arrays or objects, which we must also1514// consider. See jsperf.com/compare-array-unique-versions/4 for more1515// information.1516var1517out = [],1518val,1519i, ien=src.length,1520j, k=0;1521
1522again: for ( i=0 ; i<ien ; i++ ) {1523val = src[i];1524
1525for ( j=0 ; j<k ; j++ ) {1526if ( out[j] === val ) {1527continue again;1528}1529}1530
1531out.push( val );1532k++;1533}1534
1535return out;1536};1537
1538// Surprisingly this is faster than [].concat.apply
1539// https://jsperf.com/flatten-an-array-loop-vs-reduce/2
1540var _flatten = function (out, val) {1541if (Array.isArray(val)) {1542for (var i=0 ; i<val.length ; i++) {1543_flatten(out, val[i]);1544}1545}1546else {1547out.push(val);1548}1549
1550return out;1551}
1552
1553var _includes = function (search, start) {1554if (start === undefined) {1555start = 0;1556}1557
1558return this.indexOf(search, start) !== -1;1559};1560
1561// Array.isArray polyfill.
1562// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
1563if (! Array.isArray) {1564Array.isArray = function(arg) {1565return Object.prototype.toString.call(arg) === '[object Array]';1566};1567}
1568
1569if (! Array.prototype.includes) {1570Array.prototype.includes = _includes;1571}
1572
1573// .trim() polyfill
1574// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
1575if (!String.prototype.trim) {1576String.prototype.trim = function () {1577return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');1578};1579}
1580
1581if (! String.prototype.includes) {1582String.prototype.includes = _includes;1583}
1584
1585/**
1586* DataTables utility methods
1587*
1588* This namespace provides helper methods that DataTables uses internally to
1589* create a DataTable, but which are not exclusively used only for DataTables.
1590* These methods can be used by extension authors to save the duplication of
1591* code.
1592*
1593* @namespace
1594*/
1595DataTable.util = {1596/**1597* Throttle the calls to a function. Arguments and context are maintained
1598* for the throttled function.
1599*
1600* @param {function} fn Function to be called
1601* @param {integer} freq Call frequency in mS
1602* @return {function} Wrapped function
1603*/
1604throttle: function ( fn, freq ) {1605var1606frequency = freq !== undefined ? freq : 200,1607last,1608timer;1609
1610return function () {1611var1612that = this,1613now = +new Date(),1614args = arguments;1615
1616if ( last && now < last + frequency ) {1617clearTimeout( timer );1618
1619timer = setTimeout( function () {1620last = undefined;1621fn.apply( that, args );1622}, frequency );1623}1624else {1625last = now;1626fn.apply( that, args );1627}1628};1629},1630
1631
1632/**1633* Escape a string such that it can be used in a regular expression
1634*
1635* @param {string} val string to escape
1636* @returns {string} escaped string
1637*/
1638escapeRegex: function ( val ) {1639return val.replace( _re_escape_regex, '\\$1' );1640},1641
1642/**1643* Create a function that will write to a nested object or array
1644* @param {*} source JSON notation string
1645* @returns Write function
1646*/
1647set: function ( source ) {1648if ( $.isPlainObject( source ) ) {1649/* Unlike get, only the underscore (global) option is used for for1650* setting data since we don't know the type here. This is why an object
1651* option is not documented for `mData` (which is read/write), but it is
1652* for `mRender` which is read only.
1653*/
1654return DataTable.util.set( source._ );1655}1656else if ( source === null ) {1657// Nothing to do when the data source is null1658return function () {};1659}1660else if ( typeof source === 'function' ) {1661return function (data, val, meta) {1662source( data, 'set', val, meta );1663};1664}1665else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||1666source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )1667{1668// Like the get, we need to get data from a nested object1669var setData = function (data, val, src) {1670var a = _fnSplitObjNotation( src ), b;1671var aLast = a[a.length-1];1672var arrayNotation, funcNotation, o, innerSrc;1673
1674for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {1675// Protect against prototype pollution1676if (a[i] === '__proto__' || a[i] === 'constructor') {1677throw new Error('Cannot set prototype values');1678}1679
1680// Check if we are dealing with an array notation request1681arrayNotation = a[i].match(__reArray);1682funcNotation = a[i].match(__reFn);1683
1684if ( arrayNotation ) {1685a[i] = a[i].replace(__reArray, '');1686data[ a[i] ] = [];1687
1688// Get the remainder of the nested object to set so we can recurse1689b = a.slice();1690b.splice( 0, i+1 );1691innerSrc = b.join('.');1692
1693// Traverse each entry in the array setting the properties requested1694if ( Array.isArray( val ) ) {1695for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {1696o = {};1697setData( o, val[j], innerSrc );1698data[ a[i] ].push( o );1699}1700}1701else {1702// We've been asked to save data to an array, but it1703// isn't array data to be saved. Best that can be done1704// is to just save the value.1705data[ a[i] ] = val;1706}1707
1708// The inner call to setData has already traversed through the remainder1709// of the source and has set the data, thus we can exit here1710return;1711}1712else if ( funcNotation ) {1713// Function call1714a[i] = a[i].replace(__reFn, '');1715data = data[ a[i] ]( val );1716}1717
1718// If the nested object doesn't currently exist - since we are1719// trying to set the value - create it1720if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {1721data[ a[i] ] = {};1722}1723data = data[ a[i] ];1724}1725
1726// Last item in the input - i.e, the actual set1727if ( aLast.match(__reFn ) ) {1728// Function call1729data = data[ aLast.replace(__reFn, '') ]( val );1730}1731else {1732// If array notation is used, we just want to strip it and use the property name1733// and assign the value. If it isn't used, then we get the result we want anyway1734data[ aLast.replace(__reArray, '') ] = val;1735}1736};1737
1738return function (data, val) { // meta is also passed in, but not used1739return setData( data, val, source );1740};1741}1742else {1743// Array or flat object mapping1744return function (data, val) { // meta is also passed in, but not used1745data[source] = val;1746};1747}1748},1749
1750/**1751* Create a function that will read nested objects from arrays, based on JSON notation
1752* @param {*} source JSON notation string
1753* @returns Value read
1754*/
1755get: function ( source ) {1756if ( $.isPlainObject( source ) ) {1757// Build an object of get functions, and wrap them in a single call1758var o = {};1759$.each( source, function (key, val) {1760if ( val ) {1761o[key] = DataTable.util.get( val );1762}1763} );1764
1765return function (data, type, row, meta) {1766var t = o[type] || o._;1767return t !== undefined ?1768t(data, type, row, meta) :1769data;1770};1771}1772else if ( source === null ) {1773// Give an empty string for rendering / sorting etc1774return function (data) { // type, row and meta also passed, but not used1775return data;1776};1777}1778else if ( typeof source === 'function' ) {1779return function (data, type, row, meta) {1780return source( data, type, row, meta );1781};1782}1783else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||1784source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )1785{1786/* If there is a . in the source string then the data source is in a1787* nested object so we loop over the data for each level to get the next
1788* level down. On each loop we test for undefined, and if found immediately
1789* return. This allows entire objects to be missing and sDefaultContent to
1790* be used if defined, rather than throwing an error
1791*/
1792var fetchData = function (data, type, src) {1793var arrayNotation, funcNotation, out, innerSrc;1794
1795if ( src !== "" ) {1796var a = _fnSplitObjNotation( src );1797
1798for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {1799// Check if we are dealing with special notation1800arrayNotation = a[i].match(__reArray);1801funcNotation = a[i].match(__reFn);1802
1803if ( arrayNotation ) {1804// Array notation1805a[i] = a[i].replace(__reArray, '');1806
1807// Condition allows simply [] to be passed in1808if ( a[i] !== "" ) {1809data = data[ a[i] ];1810}1811out = [];1812
1813// Get the remainder of the nested object to get1814a.splice( 0, i+1 );1815innerSrc = a.join('.');1816
1817// Traverse each entry in the array getting the properties requested1818if ( Array.isArray( data ) ) {1819for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {1820out.push( fetchData( data[j], type, innerSrc ) );1821}1822}1823
1824// If a string is given in between the array notation indicators, that1825// is used to join the strings together, otherwise an array is returned1826var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);1827data = (join==="") ? out : out.join(join);1828
1829// The inner call to fetchData has already traversed through the remainder1830// of the source requested, so we exit from the loop1831break;1832}1833else if ( funcNotation ) {1834// Function call1835a[i] = a[i].replace(__reFn, '');1836data = data[ a[i] ]();1837continue;1838}1839
1840if (data === null || data[ a[i] ] === null) {1841return null;1842}1843else if ( data === undefined || data[ a[i] ] === undefined ) {1844return undefined;1845}1846
1847data = data[ a[i] ];1848}1849}1850
1851return data;1852};1853
1854return function (data, type) { // row and meta also passed, but not used1855return fetchData( data, type, source );1856};1857}1858else {1859// Array or flat object mapping1860return function (data, type) { // row and meta also passed, but not used1861return data[source];1862};1863}1864}1865};1866
1867
1868
1869/**
1870* Create a mapping object that allows camel case parameters to be looked up
1871* for their Hungarian counterparts. The mapping is stored in a private
1872* parameter called `_hungarianMap` which can be accessed on the source object.
1873* @param {object} o
1874* @memberof DataTable#oApi
1875*/
1876function _fnHungarianMap ( o )1877{
1878var1879hungarian = 'a aa ai ao as b fn i m o s ',1880match,1881newKey,1882map = {};1883
1884$.each( o, function (key, val) {1885match = key.match(/^([^A-Z]+?)([A-Z])/);1886
1887if ( match && hungarian.indexOf(match[1]+' ') !== -1 )1888{1889newKey = key.replace( match[0], match[2].toLowerCase() );1890map[ newKey ] = key;1891
1892if ( match[1] === 'o' )1893{1894_fnHungarianMap( o[key] );1895}1896}1897} );1898
1899o._hungarianMap = map;1900}
1901
1902
1903/**
1904* Convert from camel case parameters to Hungarian, based on a Hungarian map
1905* created by _fnHungarianMap.
1906* @param {object} src The model object which holds all parameters that can be
1907* mapped.
1908* @param {object} user The object to convert from camel case to Hungarian.
1909* @param {boolean} force When set to `true`, properties which already have a
1910* Hungarian value in the `user` object will be overwritten. Otherwise they
1911* won't be.
1912* @memberof DataTable#oApi
1913*/
1914function _fnCamelToHungarian ( src, user, force )1915{
1916if ( ! src._hungarianMap ) {1917_fnHungarianMap( src );1918}1919
1920var hungarianKey;1921
1922$.each( user, function (key, val) {1923hungarianKey = src._hungarianMap[ key ];1924
1925if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )1926{1927// For objects, we need to buzz down into the object to copy parameters1928if ( hungarianKey.charAt(0) === 'o' )1929{1930// Copy the camelCase options over to the hungarian1931if ( ! user[ hungarianKey ] ) {1932user[ hungarianKey ] = {};1933}1934$.extend( true, user[hungarianKey], user[key] );1935
1936_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );1937}1938else {1939user[hungarianKey] = user[ key ];1940}1941}1942} );1943}
1944
1945
1946/**
1947* Language compatibility - when certain options are given, and others aren't, we
1948* need to duplicate the values over, in order to provide backwards compatibility
1949* with older language files.
1950* @param {object} oSettings dataTables settings object
1951* @memberof DataTable#oApi
1952*/
1953function _fnLanguageCompat( lang )1954{
1955// Note the use of the Hungarian notation for the parameters in this method as1956// this is called after the mapping of camelCase to Hungarian1957var defaults = DataTable.defaults.oLanguage;1958
1959// Default mapping1960var defaultDecimal = defaults.sDecimal;1961if ( defaultDecimal ) {1962_addNumericSort( defaultDecimal );1963}1964
1965if ( lang ) {1966var zeroRecords = lang.sZeroRecords;1967
1968// Backwards compatibility - if there is no sEmptyTable given, then use the same as1969// sZeroRecords - assuming that is given.1970if ( ! lang.sEmptyTable && zeroRecords &&1971defaults.sEmptyTable === "No data available in table" )1972{1973_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );1974}1975
1976// Likewise with loading records1977if ( ! lang.sLoadingRecords && zeroRecords &&1978defaults.sLoadingRecords === "Loading..." )1979{1980_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );1981}1982
1983// Old parameter name of the thousands separator mapped onto the new1984if ( lang.sInfoThousands ) {1985lang.sThousands = lang.sInfoThousands;1986}1987
1988var decimal = lang.sDecimal;1989if ( decimal && defaultDecimal !== decimal ) {1990_addNumericSort( decimal );1991}1992}1993}
1994
1995
1996/**
1997* Map one parameter onto another
1998* @param {object} o Object to map
1999* @param {*} knew The new parameter name
2000* @param {*} old The old parameter name
2001*/
2002var _fnCompatMap = function ( o, knew, old ) {2003if ( o[ knew ] !== undefined ) {2004o[ old ] = o[ knew ];2005}2006};2007
2008
2009/**
2010* Provide backwards compatibility for the main DT options. Note that the new
2011* options are mapped onto the old parameters, so this is an external interface
2012* change only.
2013* @param {object} init Object to map
2014*/
2015function _fnCompatOpts ( init )2016{
2017_fnCompatMap( init, 'ordering', 'bSort' );2018_fnCompatMap( init, 'orderMulti', 'bSortMulti' );2019_fnCompatMap( init, 'orderClasses', 'bSortClasses' );2020_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );2021_fnCompatMap( init, 'order', 'aaSorting' );2022_fnCompatMap( init, 'orderFixed', 'aaSortingFixed' );2023_fnCompatMap( init, 'paging', 'bPaginate' );2024_fnCompatMap( init, 'pagingType', 'sPaginationType' );2025_fnCompatMap( init, 'pageLength', 'iDisplayLength' );2026_fnCompatMap( init, 'searching', 'bFilter' );2027
2028// Boolean initialisation of x-scrolling2029if ( typeof init.sScrollX === 'boolean' ) {2030init.sScrollX = init.sScrollX ? '100%' : '';2031}2032if ( typeof init.scrollX === 'boolean' ) {2033init.scrollX = init.scrollX ? '100%' : '';2034}2035
2036// Column search objects are in an array, so it needs to be converted2037// element by element2038var searchCols = init.aoSearchCols;2039
2040if ( searchCols ) {2041for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {2042if ( searchCols[i] ) {2043_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );2044}2045}2046}2047}
2048
2049
2050/**
2051* Provide backwards compatibility for column options. Note that the new options
2052* are mapped onto the old parameters, so this is an external interface change
2053* only.
2054* @param {object} init Object to map
2055*/
2056function _fnCompatCols ( init )2057{
2058_fnCompatMap( init, 'orderable', 'bSortable' );2059_fnCompatMap( init, 'orderData', 'aDataSort' );2060_fnCompatMap( init, 'orderSequence', 'asSorting' );2061_fnCompatMap( init, 'orderDataType', 'sortDataType' );2062
2063// orderData can be given as an integer2064var dataSort = init.aDataSort;2065if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {2066init.aDataSort = [ dataSort ];2067}2068}
2069
2070
2071/**
2072* Browser feature detection for capabilities, quirks
2073* @param {object} settings dataTables settings object
2074* @memberof DataTable#oApi
2075*/
2076function _fnBrowserDetect( settings )2077{
2078// We don't need to do this every time DataTables is constructed, the values2079// calculated are specific to the browser and OS configuration which we2080// don't expect to change between initialisations2081if ( ! DataTable.__browser ) {2082var browser = {};2083DataTable.__browser = browser;2084
2085// Scrolling feature / quirks detection2086var n = $('<div/>')2087.css( {2088position: 'fixed',2089top: 0,2090left: $(window).scrollLeft()*-1, // allow for scrolling2091height: 1,2092width: 1,2093overflow: 'hidden'2094} )2095.append(2096$('<div/>')2097.css( {2098position: 'absolute',2099top: 1,2100left: 1,2101width: 100,2102overflow: 'scroll'2103} )2104.append(2105$('<div/>')2106.css( {2107width: '100%',2108height: 102109} )2110)2111)2112.appendTo( 'body' );2113
2114var outer = n.children();2115var inner = outer.children();2116
2117// Numbers below, in order, are:2118// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth2119//2120// IE6 XP: 100 100 100 832121// IE7 Vista: 100 100 100 832122// IE 8+ Windows: 83 83 100 832123// Evergreen Windows: 83 83 100 832124// Evergreen Mac with scrollbars: 85 85 100 852125// Evergreen Mac without scrollbars: 100 100 100 1002126
2127// Get scrollbar width2128browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;2129
2130// IE6/7 will oversize a width 100% element inside a scrolling element, to2131// include the width of the scrollbar, while other browsers ensure the inner2132// element is contained without forcing scrolling2133browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;2134
2135// In rtl text layout, some browsers (most, but not all) will place the2136// scrollbar on the left, rather than the right.2137browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;2138
2139// IE8- don't provide height and width for getBoundingClientRect2140browser.bBounding = n[0].getBoundingClientRect().width ? true : false;2141
2142n.remove();2143}2144
2145$.extend( settings.oBrowser, DataTable.__browser );2146settings.oScroll.iBarWidth = DataTable.__browser.barWidth;2147}
2148
2149
2150/**
2151* Array.prototype reduce[Right] method, used for browsers which don't support
2152* JS 1.6. Done this way to reduce code size, since we iterate either way
2153* @param {object} settings dataTables settings object
2154* @memberof DataTable#oApi
2155*/
2156function _fnReduce ( that, fn, init, start, end, inc )2157{
2158var2159i = start,2160value,2161isSet = false;2162
2163if ( init !== undefined ) {2164value = init;2165isSet = true;2166}2167
2168while ( i !== end ) {2169if ( ! that.hasOwnProperty(i) ) {2170continue;2171}2172
2173value = isSet ?2174fn( value, that[i], i, that ) :2175that[i];2176
2177isSet = true;2178i += inc;2179}2180
2181return value;2182}
2183
2184/**
2185* Add a column to the list used for the table with default values
2186* @param {object} oSettings dataTables settings object
2187* @param {node} nTh The th element for this column
2188* @memberof DataTable#oApi
2189*/
2190function _fnAddColumn( oSettings, nTh )2191{
2192// Add column to aoColumns array2193var oDefaults = DataTable.defaults.column;2194var iCol = oSettings.aoColumns.length;2195var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {2196"nTh": nTh ? nTh : document.createElement('th'),2197"sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',2198"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],2199"mData": oDefaults.mData ? oDefaults.mData : iCol,2200idx: iCol2201} );2202oSettings.aoColumns.push( oCol );2203
2204// Add search object for column specific search. Note that the `searchCols[ iCol ]`2205// passed into extend can be undefined. This allows the user to give a default2206// with only some of the parameters defined, and also not give a default2207var searchCols = oSettings.aoPreSearchCols;2208searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );2209
2210// Use the default column options function to initialise classes etc2211_fnColumnOptions( oSettings, iCol, $(nTh).data() );2212}
2213
2214
2215/**
2216* Apply options for a column
2217* @param {object} oSettings dataTables settings object
2218* @param {int} iCol column index to consider
2219* @param {object} oOptions object with sType, bVisible and bSearchable etc
2220* @memberof DataTable#oApi
2221*/
2222function _fnColumnOptions( oSettings, iCol, oOptions )2223{
2224var oCol = oSettings.aoColumns[ iCol ];2225var oClasses = oSettings.oClasses;2226var th = $(oCol.nTh);2227
2228// Try to get width information from the DOM. We can't get it from CSS2229// as we'd need to parse the CSS stylesheet. `width` option can override2230if ( ! oCol.sWidthOrig ) {2231// Width attribute2232oCol.sWidthOrig = th.attr('width') || null;2233
2234// Style attribute2235var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);2236if ( t ) {2237oCol.sWidthOrig = t[1];2238}2239}2240
2241/* User specified column options */2242if ( oOptions !== undefined && oOptions !== null )2243{2244// Backwards compatibility2245_fnCompatCols( oOptions );2246
2247// Map camel case parameters to their Hungarian counterparts2248_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );2249
2250/* Backwards compatibility for mDataProp */2251if ( oOptions.mDataProp !== undefined && !oOptions.mData )2252{2253oOptions.mData = oOptions.mDataProp;2254}2255
2256if ( oOptions.sType )2257{2258oCol._sManualType = oOptions.sType;2259}2260
2261// `class` is a reserved word in Javascript, so we need to provide2262// the ability to use a valid name for the camel case input2263if ( oOptions.className && ! oOptions.sClass )2264{2265oOptions.sClass = oOptions.className;2266}2267if ( oOptions.sClass ) {2268th.addClass( oOptions.sClass );2269}2270
2271var origClass = oCol.sClass;2272
2273$.extend( oCol, oOptions );2274_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );2275
2276// Merge class from previously defined classes with this one, rather than just2277// overwriting it in the extend above2278if (origClass !== oCol.sClass) {2279oCol.sClass = origClass + ' ' + oCol.sClass;2280}2281
2282/* iDataSort to be applied (backwards compatibility), but aDataSort will take2283* priority if defined
2284*/
2285if ( oOptions.iDataSort !== undefined )2286{2287oCol.aDataSort = [ oOptions.iDataSort ];2288}2289_fnMap( oCol, oOptions, "aDataSort" );2290}2291
2292/* Cache the data get and set functions for speed */2293var mDataSrc = oCol.mData;2294var mData = _fnGetObjectDataFn( mDataSrc );2295var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;2296
2297var attrTest = function( src ) {2298return typeof src === 'string' && src.indexOf('@') !== -1;2299};2300oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (2301attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)2302);2303oCol._setter = null;2304
2305oCol.fnGetData = function (rowData, type, meta) {2306var innerData = mData( rowData, type, undefined, meta );2307
2308return mRender && type ?2309mRender( innerData, type, rowData, meta ) :2310innerData;2311};2312oCol.fnSetData = function ( rowData, val, meta ) {2313return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );2314};2315
2316// Indicate if DataTables should read DOM data as an object or array2317// Used in _fnGetRowElements2318if ( typeof mDataSrc !== 'number' && ! oCol._isArrayHost ) {2319oSettings._rowReadObject = true;2320}2321
2322/* Feature sorting overrides column specific when off */2323if ( !oSettings.oFeatures.bSort )2324{2325oCol.bSortable = false;2326th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called2327}2328
2329/* Check that the class assignment is correct for sorting */2330var bAsc = $.inArray('asc', oCol.asSorting) !== -1;2331var bDesc = $.inArray('desc', oCol.asSorting) !== -1;2332if ( !oCol.bSortable || (!bAsc && !bDesc) )2333{2334oCol.sSortingClass = oClasses.sSortableNone;2335oCol.sSortingClassJUI = "";2336}2337else if ( bAsc && !bDesc )2338{2339oCol.sSortingClass = oClasses.sSortableAsc;2340oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;2341}2342else if ( !bAsc && bDesc )2343{2344oCol.sSortingClass = oClasses.sSortableDesc;2345oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;2346}2347else2348{2349oCol.sSortingClass = oClasses.sSortable;2350oCol.sSortingClassJUI = oClasses.sSortJUI;2351}2352}
2353
2354
2355/**
2356* Adjust the table column widths for new data. Note: you would probably want to
2357* do a redraw after calling this function!
2358* @param {object} settings dataTables settings object
2359* @memberof DataTable#oApi
2360*/
2361function _fnAdjustColumnSizing ( settings )2362{
2363/* Not interested in doing column width calculation if auto-width is disabled */2364if ( settings.oFeatures.bAutoWidth !== false )2365{2366var columns = settings.aoColumns;2367
2368_fnCalculateColumnWidths( settings );2369for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )2370{2371columns[i].nTh.style.width = columns[i].sWidth;2372}2373}2374
2375var scroll = settings.oScroll;2376if ( scroll.sY !== '' || scroll.sX !== '')2377{2378_fnScrollDraw( settings );2379}2380
2381_fnCallbackFire( settings, null, 'column-sizing', [settings] );2382}
2383
2384
2385/**
2386* Convert the index of a visible column to the index in the data array (take account
2387* of hidden columns)
2388* @param {object} oSettings dataTables settings object
2389* @param {int} iMatch Visible column index to lookup
2390* @returns {int} i the data index
2391* @memberof DataTable#oApi
2392*/
2393function _fnVisibleToColumnIndex( oSettings, iMatch )2394{
2395var aiVis = _fnGetColumns( oSettings, 'bVisible' );2396
2397return typeof aiVis[iMatch] === 'number' ?2398aiVis[iMatch] :2399null;2400}
2401
2402
2403/**
2404* Convert the index of an index in the data array and convert it to the visible
2405* column index (take account of hidden columns)
2406* @param {int} iMatch Column index to lookup
2407* @param {object} oSettings dataTables settings object
2408* @returns {int} i the data index
2409* @memberof DataTable#oApi
2410*/
2411function _fnColumnIndexToVisible( oSettings, iMatch )2412{
2413var aiVis = _fnGetColumns( oSettings, 'bVisible' );2414var iPos = $.inArray( iMatch, aiVis );2415
2416return iPos !== -1 ? iPos : null;2417}
2418
2419
2420/**
2421* Get the number of visible columns
2422* @param {object} oSettings dataTables settings object
2423* @returns {int} i the number of visible columns
2424* @memberof DataTable#oApi
2425*/
2426function _fnVisbleColumns( oSettings )2427{
2428var vis = 0;2429
2430// No reduce in IE8, use a loop for now2431$.each( oSettings.aoColumns, function ( i, col ) {2432if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {2433vis++;2434}2435} );2436
2437return vis;2438}
2439
2440
2441/**
2442* Get an array of column indexes that match a given property
2443* @param {object} oSettings dataTables settings object
2444* @param {string} sParam Parameter in aoColumns to look for - typically
2445* bVisible or bSearchable
2446* @returns {array} Array of indexes with matched properties
2447* @memberof DataTable#oApi
2448*/
2449function _fnGetColumns( oSettings, sParam )2450{
2451var a = [];2452
2453$.map( oSettings.aoColumns, function(val, i) {2454if ( val[sParam] ) {2455a.push( i );2456}2457} );2458
2459return a;2460}
2461
2462
2463/**
2464* Calculate the 'type' of a column
2465* @param {object} settings dataTables settings object
2466* @memberof DataTable#oApi
2467*/
2468function _fnColumnTypes ( settings )2469{
2470var columns = settings.aoColumns;2471var data = settings.aoData;2472var types = DataTable.ext.type.detect;2473var i, ien, j, jen, k, ken;2474var col, cell, detectedType, cache;2475
2476// For each column, spin over the2477for ( i=0, ien=columns.length ; i<ien ; i++ ) {2478col = columns[i];2479cache = [];2480
2481if ( ! col.sType && col._sManualType ) {2482col.sType = col._sManualType;2483}2484else if ( ! col.sType ) {2485for ( j=0, jen=types.length ; j<jen ; j++ ) {2486for ( k=0, ken=data.length ; k<ken ; k++ ) {2487// Use a cache array so we only need to get the type data2488// from the formatter once (when using multiple detectors)2489if ( cache[k] === undefined ) {2490cache[k] = _fnGetCellData( settings, k, i, 'type' );2491}2492
2493detectedType = types[j]( cache[k], settings );2494
2495// If null, then this type can't apply to this column, so2496// rather than testing all cells, break out. There is an2497// exception for the last type which is `html`. We need to2498// scan all rows since it is possible to mix string and HTML2499// types2500if ( ! detectedType && j !== types.length-1 ) {2501break;2502}2503
2504// Only a single match is needed for html type since it is2505// bottom of the pile and very similar to string - but it2506// must not be empty2507if ( detectedType === 'html' && ! _empty(cache[k]) ) {2508break;2509}2510}2511
2512// Type is valid for all data points in the column - use this2513// type2514if ( detectedType ) {2515col.sType = detectedType;2516break;2517}2518}2519
2520// Fall back - if no type was detected, always use string2521if ( ! col.sType ) {2522col.sType = 'string';2523}2524}2525}2526}
2527
2528
2529/**
2530* Take the column definitions and static columns arrays and calculate how
2531* they relate to column indexes. The callback function will then apply the
2532* definition found for a column to a suitable configuration object.
2533* @param {object} oSettings dataTables settings object
2534* @param {array} aoColDefs The aoColumnDefs array that is to be applied
2535* @param {array} aoCols The aoColumns array that defines columns individually
2536* @param {function} fn Callback function - takes two parameters, the calculated
2537* column index and the definition for that column.
2538* @memberof DataTable#oApi
2539*/
2540function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )2541{
2542var i, iLen, j, jLen, k, kLen, def;2543var columns = oSettings.aoColumns;2544
2545// Column definitions with aTargets2546if ( aoColDefs )2547{2548/* Loop over the definitions array - loop in reverse so first instance has priority */2549for ( i=aoColDefs.length-1 ; i>=0 ; i-- )2550{2551def = aoColDefs[i];2552
2553/* Each definition can target multiple columns, as it is an array */2554var aTargets = def.target !== undefined2555? def.target2556: def.targets !== undefined2557? def.targets2558: def.aTargets;2559
2560if ( ! Array.isArray( aTargets ) )2561{2562aTargets = [ aTargets ];2563}2564
2565for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )2566{2567if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )2568{2569/* Add columns that we don't yet know about */2570while( columns.length <= aTargets[j] )2571{2572_fnAddColumn( oSettings );2573}2574
2575/* Integer, basic index */2576fn( aTargets[j], def );2577}2578else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )2579{2580/* Negative integer, right to left column counting */2581fn( columns.length+aTargets[j], def );2582}2583else if ( typeof aTargets[j] === 'string' )2584{2585/* Class name matching on TH element */2586for ( k=0, kLen=columns.length ; k<kLen ; k++ )2587{2588if ( aTargets[j] == "_all" ||2589$(columns[k].nTh).hasClass( aTargets[j] ) )2590{2591fn( k, def );2592}2593}2594}2595}2596}2597}2598
2599// Statically defined columns array2600if ( aoCols )2601{2602for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )2603{2604fn( i, aoCols[i] );2605}2606}2607}
2608
2609/**
2610* Add a data array to the table, creating DOM node etc. This is the parallel to
2611* _fnGatherData, but for adding rows from a Javascript source, rather than a
2612* DOM source.
2613* @param {object} oSettings dataTables settings object
2614* @param {array} aData data array to be added
2615* @param {node} [nTr] TR element to add to the table - optional. If not given,
2616* DataTables will create a row automatically
2617* @param {array} [anTds] Array of TD|TH elements for the row - must be given
2618* if nTr is.
2619* @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2620* @memberof DataTable#oApi
2621*/
2622function _fnAddData ( oSettings, aDataIn, nTr, anTds )2623{
2624/* Create the object for storing information about this new row */2625var iRow = oSettings.aoData.length;2626var oData = $.extend( true, {}, DataTable.models.oRow, {2627src: nTr ? 'dom' : 'data',2628idx: iRow2629} );2630
2631oData._aData = aDataIn;2632oSettings.aoData.push( oData );2633
2634/* Create the cells */2635var nTd, sThisType;2636var columns = oSettings.aoColumns;2637
2638// Invalidate the column types as the new data needs to be revalidated2639for ( var i=0, iLen=columns.length ; i<iLen ; i++ )2640{2641columns[i].sType = null;2642}2643
2644/* Add to the display array */2645oSettings.aiDisplayMaster.push( iRow );2646
2647var id = oSettings.rowIdFn( aDataIn );2648if ( id !== undefined ) {2649oSettings.aIds[ id ] = oData;2650}2651
2652/* Create the DOM information, or register it if already present */2653if ( nTr || ! oSettings.oFeatures.bDeferRender )2654{2655_fnCreateTr( oSettings, iRow, nTr, anTds );2656}2657
2658return iRow;2659}
2660
2661
2662/**
2663* Add one or more TR elements to the table. Generally we'd expect to
2664* use this for reading data from a DOM sourced table, but it could be
2665* used for an TR element. Note that if a TR is given, it is used (i.e.
2666* it is not cloned).
2667* @param {object} settings dataTables settings object
2668* @param {array|node|jQuery} trs The TR element(s) to add to the table
2669* @returns {array} Array of indexes for the added rows
2670* @memberof DataTable#oApi
2671*/
2672function _fnAddTr( settings, trs )2673{
2674var row;2675
2676// Allow an individual node to be passed in2677if ( ! (trs instanceof $) ) {2678trs = $(trs);2679}2680
2681return trs.map( function (i, el) {2682row = _fnGetRowElements( settings, el );2683return _fnAddData( settings, row.data, el, row.cells );2684} );2685}
2686
2687
2688/**
2689* Take a TR element and convert it to an index in aoData
2690* @param {object} oSettings dataTables settings object
2691* @param {node} n the TR element to find
2692* @returns {int} index if the node is found, null if not
2693* @memberof DataTable#oApi
2694*/
2695function _fnNodeToDataIndex( oSettings, n )2696{
2697return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;2698}
2699
2700
2701/**
2702* Take a TD element and convert it into a column data index (not the visible index)
2703* @param {object} oSettings dataTables settings object
2704* @param {int} iRow The row number the TD/TH can be found in
2705* @param {node} n The TD/TH element to find
2706* @returns {int} index if the node is found, -1 if not
2707* @memberof DataTable#oApi
2708*/
2709function _fnNodeToColumnIndex( oSettings, iRow, n )2710{
2711return $.inArray( n, oSettings.aoData[ iRow ].anCells );2712}
2713
2714
2715/**
2716* Get the data for a given cell from the internal cache, taking into account data mapping
2717* @param {object} settings dataTables settings object
2718* @param {int} rowIdx aoData row id
2719* @param {int} colIdx Column index
2720* @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
2721* @returns {*} Cell data
2722* @memberof DataTable#oApi
2723*/
2724function _fnGetCellData( settings, rowIdx, colIdx, type )2725{
2726if (type === 'search') {2727type = 'filter';2728}2729else if (type === 'order') {2730type = 'sort';2731}2732
2733var draw = settings.iDraw;2734var col = settings.aoColumns[colIdx];2735var rowData = settings.aoData[rowIdx]._aData;2736var defaultContent = col.sDefaultContent;2737var cellData = col.fnGetData( rowData, type, {2738settings: settings,2739row: rowIdx,2740col: colIdx2741} );2742
2743if ( cellData === undefined ) {2744if ( settings.iDrawError != draw && defaultContent === null ) {2745_fnLog( settings, 0, "Requested unknown parameter "+2746(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+2747" for row "+rowIdx+", column "+colIdx, 4 );2748settings.iDrawError = draw;2749}2750return defaultContent;2751}2752
2753// When the data source is null and a specific data type is requested (i.e.2754// not the original data), we can use default column data2755if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {2756cellData = defaultContent;2757}2758else if ( typeof cellData === 'function' ) {2759// If the data source is a function, then we run it and use the return,2760// executing in the scope of the data object (for instances)2761return cellData.call( rowData );2762}2763
2764if ( cellData === null && type === 'display' ) {2765return '';2766}2767
2768if ( type === 'filter' ) {2769var fomatters = DataTable.ext.type.search;2770
2771if ( fomatters[ col.sType ] ) {2772cellData = fomatters[ col.sType ]( cellData );2773}2774}2775
2776return cellData;2777}
2778
2779
2780/**
2781* Set the value for a specific cell, into the internal data cache
2782* @param {object} settings dataTables settings object
2783* @param {int} rowIdx aoData row id
2784* @param {int} colIdx Column index
2785* @param {*} val Value to set
2786* @memberof DataTable#oApi
2787*/
2788function _fnSetCellData( settings, rowIdx, colIdx, val )2789{
2790var col = settings.aoColumns[colIdx];2791var rowData = settings.aoData[rowIdx]._aData;2792
2793col.fnSetData( rowData, val, {2794settings: settings,2795row: rowIdx,2796col: colIdx2797} );2798}
2799
2800
2801// Private variable that is used to match action syntax in the data property object
2802var __reArray = /\[.*?\]$/;2803var __reFn = /\(\)$/;2804
2805/**
2806* Split string on periods, taking into account escaped periods
2807* @param {string} str String to split
2808* @return {array} Split string
2809*/
2810function _fnSplitObjNotation( str )2811{
2812return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {2813return s.replace(/\\\./g, '.');2814} );2815}
2816
2817
2818/**
2819* Return a function that can be used to get data from a source object, taking
2820* into account the ability to use nested objects as a source
2821* @param {string|int|function} mSource The data source for the object
2822* @returns {function} Data get function
2823* @memberof DataTable#oApi
2824*/
2825var _fnGetObjectDataFn = DataTable.util.get;2826
2827
2828/**
2829* Return a function that can be used to set data from a source object, taking
2830* into account the ability to use nested objects as a source
2831* @param {string|int|function} mSource The data source for the object
2832* @returns {function} Data set function
2833* @memberof DataTable#oApi
2834*/
2835var _fnSetObjectDataFn = DataTable.util.set;2836
2837
2838/**
2839* Return an array with the full table data
2840* @param {object} oSettings dataTables settings object
2841* @returns array {array} aData Master data array
2842* @memberof DataTable#oApi
2843*/
2844function _fnGetDataMaster ( settings )2845{
2846return _pluck( settings.aoData, '_aData' );2847}
2848
2849
2850/**
2851* Nuke the table
2852* @param {object} oSettings dataTables settings object
2853* @memberof DataTable#oApi
2854*/
2855function _fnClearTable( settings )2856{
2857settings.aoData.length = 0;2858settings.aiDisplayMaster.length = 0;2859settings.aiDisplay.length = 0;2860settings.aIds = {};2861}
2862
2863
2864/**2865* Take an array of integers (index array) and remove a target integer (value - not
2866* the key!)
2867* @param {array} a Index array to target
2868* @param {int} iTarget value to find
2869* @memberof DataTable#oApi
2870*/
2871function _fnDeleteIndex( a, iTarget, splice )2872{
2873var iTargetIndex = -1;2874
2875for ( var i=0, iLen=a.length ; i<iLen ; i++ )2876{2877if ( a[i] == iTarget )2878{2879iTargetIndex = i;2880}2881else if ( a[i] > iTarget )2882{2883a[i]--;2884}2885}2886
2887if ( iTargetIndex != -1 && splice === undefined )2888{2889a.splice( iTargetIndex, 1 );2890}2891}
2892
2893
2894/**
2895* Mark cached data as invalid such that a re-read of the data will occur when
2896* the cached data is next requested. Also update from the data source object.
2897*
2898* @param {object} settings DataTables settings object
2899* @param {int} rowIdx Row index to invalidate
2900* @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
2901* or 'data'
2902* @param {int} [colIdx] Column index to invalidate. If undefined the whole
2903* row will be invalidated
2904* @memberof DataTable#oApi
2905*
2906* @todo For the modularisation of v1.11 this will need to become a callback, so
2907* the sort and filter methods can subscribe to it. That will required
2908* initialisation options for sorting, which is why it is not already baked in
2909*/
2910function _fnInvalidate( settings, rowIdx, src, colIdx )2911{
2912var row = settings.aoData[ rowIdx ];2913var i, ien;2914var cellWrite = function ( cell, col ) {2915// This is very frustrating, but in IE if you just write directly2916// to innerHTML, and elements that are overwritten are GC'ed,2917// even if there is a reference to them elsewhere2918while ( cell.childNodes.length ) {2919cell.removeChild( cell.firstChild );2920}2921
2922cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );2923};2924
2925// Are we reading last data from DOM or the data object?2926if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {2927// Read the data from the DOM2928row._aData = _fnGetRowElements(2929settings, row, colIdx, colIdx === undefined ? undefined : row._aData2930)2931.data;2932}2933else {2934// Reading from data object, update the DOM2935var cells = row.anCells;2936
2937if ( cells ) {2938if ( colIdx !== undefined ) {2939cellWrite( cells[colIdx], colIdx );2940}2941else {2942for ( i=0, ien=cells.length ; i<ien ; i++ ) {2943cellWrite( cells[i], i );2944}2945}2946}2947}2948
2949// For both row and cell invalidation, the cached data for sorting and2950// filtering is nulled out2951row._aSortData = null;2952row._aFilterData = null;2953
2954// Invalidate the type for a specific column (if given) or all columns since2955// the data might have changed2956var cols = settings.aoColumns;2957if ( colIdx !== undefined ) {2958cols[ colIdx ].sType = null;2959}2960else {2961for ( i=0, ien=cols.length ; i<ien ; i++ ) {2962cols[i].sType = null;2963}2964
2965// Update DataTables special `DT_*` attributes for the row2966_fnRowAttributes( settings, row );2967}2968}
2969
2970
2971/**
2972* Build a data source object from an HTML row, reading the contents of the
2973* cells that are in the row.
2974*
2975* @param {object} settings DataTables settings object
2976* @param {node|object} TR element from which to read data or existing row
2977* object from which to re-read the data from the cells
2978* @param {int} [colIdx] Optional column index
2979* @param {array|object} [d] Data source object. If `colIdx` is given then this
2980* parameter should also be given and will be used to write the data into.
2981* Only the column in question will be written
2982* @returns {object} Object with two parameters: `data` the data read, in
2983* document order, and `cells` and array of nodes (they can be useful to the
2984* caller, so rather than needing a second traversal to get them, just return
2985* them from here).
2986* @memberof DataTable#oApi
2987*/
2988function _fnGetRowElements( settings, row, colIdx, d )2989{
2990var2991tds = [],2992td = row.firstChild,2993name, col, o, i=0, contents,2994columns = settings.aoColumns,2995objectRead = settings._rowReadObject;2996
2997// Allow the data object to be passed in, or construct2998d = d !== undefined ?2999d :3000objectRead ?3001{} :3002[];3003
3004var attr = function ( str, td ) {3005if ( typeof str === 'string' ) {3006var idx = str.indexOf('@');3007
3008if ( idx !== -1 ) {3009var attr = str.substring( idx+1 );3010var setter = _fnSetObjectDataFn( str );3011setter( d, td.getAttribute( attr ) );3012}3013}3014};3015
3016// Read data from a cell and store into the data object3017var cellProcess = function ( cell ) {3018if ( colIdx === undefined || colIdx === i ) {3019col = columns[i];3020contents = (cell.innerHTML).trim();3021
3022if ( col && col._bAttrSrc ) {3023var setter = _fnSetObjectDataFn( col.mData._ );3024setter( d, contents );3025
3026attr( col.mData.sort, cell );3027attr( col.mData.type, cell );3028attr( col.mData.filter, cell );3029}3030else {3031// Depending on the `data` option for the columns the data can3032// be read to either an object or an array.3033if ( objectRead ) {3034if ( ! col._setter ) {3035// Cache the setter function3036col._setter = _fnSetObjectDataFn( col.mData );3037}3038col._setter( d, contents );3039}3040else {3041d[i] = contents;3042}3043}3044}3045
3046i++;3047};3048
3049if ( td ) {3050// `tr` element was passed in3051while ( td ) {3052name = td.nodeName.toUpperCase();3053
3054if ( name == "TD" || name == "TH" ) {3055cellProcess( td );3056tds.push( td );3057}3058
3059td = td.nextSibling;3060}3061}3062else {3063// Existing row object passed in3064tds = row.anCells;3065
3066for ( var j=0, jen=tds.length ; j<jen ; j++ ) {3067cellProcess( tds[j] );3068}3069}3070
3071// Read the ID from the DOM if present3072var rowNode = row.firstChild ? row : row.nTr;3073
3074if ( rowNode ) {3075var id = rowNode.getAttribute( 'id' );3076
3077if ( id ) {3078_fnSetObjectDataFn( settings.rowId )( d, id );3079}3080}3081
3082return {3083data: d,3084cells: tds3085};3086}
3087/**
3088* Create a new TR element (and it's TD children) for a row
3089* @param {object} oSettings dataTables settings object
3090* @param {int} iRow Row to consider
3091* @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3092* DataTables will create a row automatically
3093* @param {array} [anTds] Array of TD|TH elements for the row - must be given
3094* if nTr is.
3095* @memberof DataTable#oApi
3096*/
3097function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )3098{
3099var3100row = oSettings.aoData[iRow],3101rowData = row._aData,3102cells = [],3103nTr, nTd, oCol,3104i, iLen, create;3105
3106if ( row.nTr === null )3107{3108nTr = nTrIn || document.createElement('tr');3109
3110row.nTr = nTr;3111row.anCells = cells;3112
3113/* Use a private property on the node to allow reserve mapping from the node3114* to the aoData array for fast look up
3115*/
3116nTr._DT_RowIndex = iRow;3117
3118/* Special parameters can be given by the data source to be used on the row */3119_fnRowAttributes( oSettings, row );3120
3121/* Process each column */3122for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )3123{3124oCol = oSettings.aoColumns[i];3125create = nTrIn ? false : true;3126
3127nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];3128
3129if (! nTd) {3130_fnLog( oSettings, 0, 'Incorrect column count', 18 );3131}3132
3133nTd._DT_CellIndex = {3134row: iRow,3135column: i3136};3137
3138cells.push( nTd );3139
3140// Need to create the HTML if new, or if a rendering function is defined3141if ( create || ((oCol.mRender || oCol.mData !== i) &&3142(!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')3143)) {3144nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );3145}3146
3147/* Add user defined class */3148if ( oCol.sClass )3149{3150nTd.className += ' '+oCol.sClass;3151}3152
3153// Visibility - add or remove as required3154if ( oCol.bVisible && ! nTrIn )3155{3156nTr.appendChild( nTd );3157}3158else if ( ! oCol.bVisible && nTrIn )3159{3160nTd.parentNode.removeChild( nTd );3161}3162
3163if ( oCol.fnCreatedCell )3164{3165oCol.fnCreatedCell.call( oSettings.oInstance,3166nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i3167);3168}3169}3170
3171_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );3172}3173}
3174
3175
3176/**
3177* Add attributes to a row based on the special `DT_*` parameters in a data
3178* source object.
3179* @param {object} settings DataTables settings object
3180* @param {object} DataTables row object for the row to be modified
3181* @memberof DataTable#oApi
3182*/
3183function _fnRowAttributes( settings, row )3184{
3185var tr = row.nTr;3186var data = row._aData;3187
3188if ( tr ) {3189var id = settings.rowIdFn( data );3190
3191if ( id ) {3192tr.id = id;3193}3194
3195if ( data.DT_RowClass ) {3196// Remove any classes added by DT_RowClass before3197var a = data.DT_RowClass.split(' ');3198row.__rowc = row.__rowc ?3199_unique( row.__rowc.concat( a ) ) :3200a;3201
3202$(tr)3203.removeClass( row.__rowc.join(' ') )3204.addClass( data.DT_RowClass );3205}3206
3207if ( data.DT_RowAttr ) {3208$(tr).attr( data.DT_RowAttr );3209}3210
3211if ( data.DT_RowData ) {3212$(tr).data( data.DT_RowData );3213}3214}3215}
3216
3217
3218/**
3219* Create the HTML header for the table
3220* @param {object} oSettings dataTables settings object
3221* @memberof DataTable#oApi
3222*/
3223function _fnBuildHead( oSettings )3224{
3225var i, ien, cell, row, column;3226var thead = oSettings.nTHead;3227var tfoot = oSettings.nTFoot;3228var createHeader = $('th, td', thead).length === 0;3229var classes = oSettings.oClasses;3230var columns = oSettings.aoColumns;3231
3232if ( createHeader ) {3233row = $('<tr/>').appendTo( thead );3234}3235
3236for ( i=0, ien=columns.length ; i<ien ; i++ ) {3237column = columns[i];3238cell = $( column.nTh ).addClass( column.sClass );3239
3240if ( createHeader ) {3241cell.appendTo( row );3242}3243
3244// 1.11 move into sorting3245if ( oSettings.oFeatures.bSort ) {3246cell.addClass( column.sSortingClass );3247
3248if ( column.bSortable !== false ) {3249cell
3250.attr( 'tabindex', oSettings.iTabIndex )3251.attr( 'aria-controls', oSettings.sTableId );3252
3253_fnSortAttachListener( oSettings, column.nTh, i );3254}3255}3256
3257if ( column.sTitle != cell[0].innerHTML ) {3258cell.html( column.sTitle );3259}3260
3261_fnRenderer( oSettings, 'header' )(3262oSettings, cell, column, classes3263);3264}3265
3266if ( createHeader ) {3267_fnDetectHeader( oSettings.aoHeader, thead );3268}3269
3270/* Deal with the footer - add classes if required */3271$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );3272$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );3273
3274// Cache the footer cells. Note that we only take the cells from the first3275// row in the footer. If there is more than one row the user wants to3276// interact with, they need to use the table().foot() method. Note also this3277// allows cells to be used for multiple columns using colspan3278if ( tfoot !== null ) {3279var cells = oSettings.aoFooter[0];3280
3281for ( i=0, ien=cells.length ; i<ien ; i++ ) {3282column = columns[i];3283
3284if (column) {3285column.nTf = cells[i].cell;3286
3287if ( column.sClass ) {3288$(column.nTf).addClass( column.sClass );3289}3290}3291else {3292_fnLog( oSettings, 0, 'Incorrect column count', 18 );3293}3294}3295}3296}
3297
3298
3299/**
3300* Draw the header (or footer) element based on the column visibility states. The
3301* methodology here is to use the layout array from _fnDetectHeader, modified for
3302* the instantaneous column visibility, to construct the new layout. The grid is
3303* traversed over cell at a time in a rows x columns grid fashion, although each
3304* cell insert can cover multiple elements in the grid - which is tracks using the
3305* aApplied array. Cell inserts in the grid will only occur where there isn't
3306* already a cell in that position.
3307* @param {object} oSettings dataTables settings object
3308* @param array {objects} aoSource Layout array from _fnDetectHeader
3309* @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3310* @memberof DataTable#oApi
3311*/
3312function _fnDrawHead( oSettings, aoSource, bIncludeHidden )3313{
3314var i, iLen, j, jLen, k, kLen, n, nLocalTr;3315var aoLocal = [];3316var aApplied = [];3317var iColumns = oSettings.aoColumns.length;3318var iRowspan, iColspan;3319
3320if ( ! aoSource )3321{3322return;3323}3324
3325if ( bIncludeHidden === undefined )3326{3327bIncludeHidden = false;3328}3329
3330/* Make a copy of the master layout array, but without the visible columns in it */3331for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )3332{3333aoLocal[i] = aoSource[i].slice();3334aoLocal[i].nTr = aoSource[i].nTr;3335
3336/* Remove any columns which are currently hidden */3337for ( j=iColumns-1 ; j>=0 ; j-- )3338{3339if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )3340{3341aoLocal[i].splice( j, 1 );3342}3343}3344
3345/* Prep the applied array - it needs an element for each row */3346aApplied.push( [] );3347}3348
3349for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )3350{3351nLocalTr = aoLocal[i].nTr;3352
3353/* All cells are going to be replaced, so empty out the row */3354if ( nLocalTr )3355{3356while( (n = nLocalTr.firstChild) )3357{3358nLocalTr.removeChild( n );3359}3360}3361
3362for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )3363{3364iRowspan = 1;3365iColspan = 1;3366
3367/* Check to see if there is already a cell (row/colspan) covering our target3368* insert point. If there is, then there is nothing to do.
3369*/
3370if ( aApplied[i][j] === undefined )3371{3372nLocalTr.appendChild( aoLocal[i][j].cell );3373aApplied[i][j] = 1;3374
3375/* Expand the cell to cover as many rows as needed */3376while ( aoLocal[i+iRowspan] !== undefined &&3377aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )3378{3379aApplied[i+iRowspan][j] = 1;3380iRowspan++;3381}3382
3383/* Expand the cell to cover as many columns as needed */3384while ( aoLocal[i][j+iColspan] !== undefined &&3385aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )3386{3387/* Must update the applied array over the rows for the columns */3388for ( k=0 ; k<iRowspan ; k++ )3389{3390aApplied[i+k][j+iColspan] = 1;3391}3392iColspan++;3393}3394
3395/* Do the actual expansion in the DOM */3396$(aoLocal[i][j].cell)3397.attr('rowspan', iRowspan)3398.attr('colspan', iColspan);3399}3400}3401}3402}
3403
3404
3405/**
3406* Insert the required TR nodes into the table for display
3407* @param {object} oSettings dataTables settings object
3408* @param ajaxComplete true after ajax call to complete rendering
3409* @memberof DataTable#oApi
3410*/
3411function _fnDraw( oSettings, ajaxComplete )3412{
3413// Allow for state saving and a custom start position3414_fnStart( oSettings );3415
3416/* Provide a pre-callback function which can be used to cancel the draw is false is returned */3417var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );3418if ( $.inArray( false, aPreDraw ) !== -1 )3419{3420_fnProcessingDisplay( oSettings, false );3421return;3422}3423
3424var anRows = [];3425var iRowCount = 0;3426var asStripeClasses = oSettings.asStripeClasses;3427var iStripes = asStripeClasses.length;3428var oLang = oSettings.oLanguage;3429var bServerSide = _fnDataSource( oSettings ) == 'ssp';3430var aiDisplay = oSettings.aiDisplay;3431var iDisplayStart = oSettings._iDisplayStart;3432var iDisplayEnd = oSettings.fnDisplayEnd();3433
3434oSettings.bDrawing = true;3435
3436/* Server-side processing draw intercept */3437if ( oSettings.bDeferLoading )3438{3439oSettings.bDeferLoading = false;3440oSettings.iDraw++;3441_fnProcessingDisplay( oSettings, false );3442}3443else if ( !bServerSide )3444{3445oSettings.iDraw++;3446}3447else if ( !oSettings.bDestroying && !ajaxComplete)3448{3449_fnAjaxUpdate( oSettings );3450return;3451}3452
3453if ( aiDisplay.length !== 0 )3454{3455var iStart = bServerSide ? 0 : iDisplayStart;3456var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;3457
3458for ( var j=iStart ; j<iEnd ; j++ )3459{3460var iDataIndex = aiDisplay[j];3461var aoData = oSettings.aoData[ iDataIndex ];3462if ( aoData.nTr === null )3463{3464_fnCreateTr( oSettings, iDataIndex );3465}3466
3467var nRow = aoData.nTr;3468
3469/* Remove the old striping classes and then add the new one */3470if ( iStripes !== 0 )3471{3472var sStripe = asStripeClasses[ iRowCount % iStripes ];3473if ( aoData._sRowStripe != sStripe )3474{3475$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );3476aoData._sRowStripe = sStripe;3477}3478}3479
3480// Row callback functions - might want to manipulate the row3481// iRowCount and j are not currently documented. Are they at all3482// useful?3483_fnCallbackFire( oSettings, 'aoRowCallback', null,3484[nRow, aoData._aData, iRowCount, j, iDataIndex] );3485
3486anRows.push( nRow );3487iRowCount++;3488}3489}3490else3491{3492/* Table is empty - create a row with an empty message in it */3493var sZero = oLang.sZeroRecords;3494if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' )3495{3496sZero = oLang.sLoadingRecords;3497}3498else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )3499{3500sZero = oLang.sEmptyTable;3501}3502
3503anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )3504.append( $('<td />', {3505'valign': 'top',3506'colSpan': _fnVisbleColumns( oSettings ),3507'class': oSettings.oClasses.sRowEmpty3508} ).html( sZero ) )[0];3509}3510
3511/* Header and footer callbacks */3512_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],3513_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );3514
3515_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],3516_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );3517
3518var body = $(oSettings.nTBody);3519
3520body.children().detach();3521body.append( $(anRows) );3522
3523/* Call all required callback functions for the end of a draw */3524_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );3525
3526/* Draw is complete, sorting and filtering must be as well */3527oSettings.bSorted = false;3528oSettings.bFiltered = false;3529oSettings.bDrawing = false;3530}
3531
3532
3533/**
3534* Redraw the table - taking account of the various features which are enabled
3535* @param {object} oSettings dataTables settings object
3536* @param {boolean} [holdPosition] Keep the current paging position. By default
3537* the paging is reset to the first page
3538* @memberof DataTable#oApi
3539*/
3540function _fnReDraw( settings, holdPosition )3541{
3542var3543features = settings.oFeatures,3544sort = features.bSort,3545filter = features.bFilter;3546
3547if ( sort ) {3548_fnSort( settings );3549}3550
3551if ( filter ) {3552_fnFilterComplete( settings, settings.oPreviousSearch );3553}3554else {3555// No filtering, so we want to just use the display master3556settings.aiDisplay = settings.aiDisplayMaster.slice();3557}3558
3559if ( holdPosition !== true ) {3560settings._iDisplayStart = 0;3561}3562
3563// Let any modules know about the draw hold position state (used by3564// scrolling internally)3565settings._drawHold = holdPosition;3566
3567_fnDraw( settings );3568
3569settings._drawHold = false;3570}
3571
3572
3573/**
3574* Add the options to the page HTML for the table
3575* @param {object} oSettings dataTables settings object
3576* @memberof DataTable#oApi
3577*/
3578function _fnAddOptionsHtml ( oSettings )3579{
3580var classes = oSettings.oClasses;3581var table = $(oSettings.nTable);3582var holding = $('<div/>').insertBefore( table ); // Holding element for speed3583var features = oSettings.oFeatures;3584
3585// All DataTables are wrapped in a div3586var insert = $('<div/>', {3587id: oSettings.sTableId+'_wrapper',3588'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)3589} );3590
3591oSettings.nHolding = holding[0];3592oSettings.nTableWrapper = insert[0];3593oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;3594
3595/* Loop over the user set positioning and place the elements as needed */3596var aDom = oSettings.sDom.split('');3597var featureNode, cOption, nNewNode, cNext, sAttr, j;3598for ( var i=0 ; i<aDom.length ; i++ )3599{3600featureNode = null;3601cOption = aDom[i];3602
3603if ( cOption == '<' )3604{3605/* New container div */3606nNewNode = $('<div/>')[0];3607
3608/* Check to see if we should append an id and/or a class name to the container */3609cNext = aDom[i+1];3610if ( cNext == "'" || cNext == '"' )3611{3612sAttr = "";3613j = 2;3614while ( aDom[i+j] != cNext )3615{3616sAttr += aDom[i+j];3617j++;3618}3619
3620/* Replace jQuery UI constants @todo depreciated */3621if ( sAttr == "H" )3622{3623sAttr = classes.sJUIHeader;3624}3625else if ( sAttr == "F" )3626{3627sAttr = classes.sJUIFooter;3628}3629
3630/* The attribute can be in the format of "#id.class", "#id" or "class" This logic3631* breaks the string into parts and applies them as needed
3632*/
3633if ( sAttr.indexOf('.') != -1 )3634{3635var aSplit = sAttr.split('.');3636nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);3637nNewNode.className = aSplit[1];3638}3639else if ( sAttr.charAt(0) == "#" )3640{3641nNewNode.id = sAttr.substr(1, sAttr.length-1);3642}3643else3644{3645nNewNode.className = sAttr;3646}3647
3648i += j; /* Move along the position array */3649}3650
3651insert.append( nNewNode );3652insert = $(nNewNode);3653}3654else if ( cOption == '>' )3655{3656/* End container div */3657insert = insert.parent();3658}3659// @todo Move options into their own plugins?3660else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )3661{3662/* Length */3663featureNode = _fnFeatureHtmlLength( oSettings );3664}3665else if ( cOption == 'f' && features.bFilter )3666{3667/* Filter */3668featureNode = _fnFeatureHtmlFilter( oSettings );3669}3670else if ( cOption == 'r' && features.bProcessing )3671{3672/* pRocessing */3673featureNode = _fnFeatureHtmlProcessing( oSettings );3674}3675else if ( cOption == 't' )3676{3677/* Table */3678featureNode = _fnFeatureHtmlTable( oSettings );3679}3680else if ( cOption == 'i' && features.bInfo )3681{3682/* Info */3683featureNode = _fnFeatureHtmlInfo( oSettings );3684}3685else if ( cOption == 'p' && features.bPaginate )3686{3687/* Pagination */3688featureNode = _fnFeatureHtmlPaginate( oSettings );3689}3690else if ( DataTable.ext.feature.length !== 0 )3691{3692/* Plug-in features */3693var aoFeatures = DataTable.ext.feature;3694for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )3695{3696if ( cOption == aoFeatures[k].cFeature )3697{3698featureNode = aoFeatures[k].fnInit( oSettings );3699break;3700}3701}3702}3703
3704/* Add to the 2D features array */3705if ( featureNode )3706{3707var aanFeatures = oSettings.aanFeatures;3708
3709if ( ! aanFeatures[cOption] )3710{3711aanFeatures[cOption] = [];3712}3713
3714aanFeatures[cOption].push( featureNode );3715insert.append( featureNode );3716}3717}3718
3719/* Built our DOM structure - replace the holding div with what we want */3720holding.replaceWith( insert );3721oSettings.nHolding = null;3722}
3723
3724
3725/**
3726* Use the DOM source to create up an array of header cells. The idea here is to
3727* create a layout grid (array) of rows x columns, which contains a reference
3728* to the cell that that point in the grid (regardless of col/rowspan), such that
3729* any column / row could be removed and the new grid constructed
3730* @param array {object} aLayout Array to store the calculated layout in
3731* @param {node} nThead The header/footer element for the table
3732* @memberof DataTable#oApi
3733*/
3734function _fnDetectHeader ( aLayout, nThead )3735{
3736var nTrs = $(nThead).children('tr');3737var nTr, nCell;3738var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;3739var bUnique;3740var fnShiftCol = function ( a, i, j ) {3741var k = a[i];3742while ( k[j] ) {3743j++;3744}3745return j;3746};3747
3748aLayout.splice( 0, aLayout.length );3749
3750/* We know how many rows there are in the layout - so prep it */3751for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )3752{3753aLayout.push( [] );3754}3755
3756/* Calculate a layout array */3757for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )3758{3759nTr = nTrs[i];3760iColumn = 0;3761
3762/* For every cell in the row... */3763nCell = nTr.firstChild;3764while ( nCell ) {3765if ( nCell.nodeName.toUpperCase() == "TD" ||3766nCell.nodeName.toUpperCase() == "TH" )3767{3768/* Get the col and rowspan attributes from the DOM and sanitise them */3769iColspan = nCell.getAttribute('colspan') * 1;3770iRowspan = nCell.getAttribute('rowspan') * 1;3771iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;3772iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;3773
3774/* There might be colspan cells already in this row, so shift our target3775* accordingly
3776*/
3777iColShifted = fnShiftCol( aLayout, i, iColumn );3778
3779/* Cache calculation for unique columns */3780bUnique = iColspan === 1 ? true : false;3781
3782/* If there is col / rowspan, copy the information into the layout grid */3783for ( l=0 ; l<iColspan ; l++ )3784{3785for ( k=0 ; k<iRowspan ; k++ )3786{3787aLayout[i+k][iColShifted+l] = {3788"cell": nCell,3789"unique": bUnique3790};3791aLayout[i+k].nTr = nTr;3792}3793}3794}3795nCell = nCell.nextSibling;3796}3797}3798}
3799
3800
3801/**
3802* Get an array of unique th elements, one for each column
3803* @param {object} oSettings dataTables settings object
3804* @param {node} nHeader automatically detect the layout from this node - optional
3805* @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3806* @returns array {node} aReturn list of unique th's
3807* @memberof DataTable#oApi
3808*/
3809function _fnGetUniqueThs ( oSettings, nHeader, aLayout )3810{
3811var aReturn = [];3812if ( !aLayout )3813{3814aLayout = oSettings.aoHeader;3815if ( nHeader )3816{3817aLayout = [];3818_fnDetectHeader( aLayout, nHeader );3819}3820}3821
3822for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )3823{3824for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )3825{3826if ( aLayout[i][j].unique &&3827(!aReturn[j] || !oSettings.bSortCellsTop) )3828{3829aReturn[j] = aLayout[i][j].cell;3830}3831}3832}3833
3834return aReturn;3835}
3836
3837/**
3838* Set the start position for draw
3839* @param {object} oSettings dataTables settings object
3840*/
3841function _fnStart( oSettings )3842{
3843var bServerSide = _fnDataSource( oSettings ) == 'ssp';3844var iInitDisplayStart = oSettings.iInitDisplayStart;3845
3846// Check and see if we have an initial draw position from state saving3847if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )3848{3849oSettings._iDisplayStart = bServerSide ?3850iInitDisplayStart :3851iInitDisplayStart >= oSettings.fnRecordsDisplay() ?38520 :3853iInitDisplayStart;3854
3855oSettings.iInitDisplayStart = -1;3856}3857}
3858
3859/**
3860* Create an Ajax call based on the table's settings, taking into account that
3861* parameters can have multiple forms, and backwards compatibility.
3862*
3863* @param {object} oSettings dataTables settings object
3864* @param {array} data Data to send to the server, required by
3865* DataTables - may be augmented by developer callbacks
3866* @param {function} fn Callback function to run when data is obtained
3867*/
3868function _fnBuildAjax( oSettings, data, fn )3869{
3870// Compatibility with 1.9-, allow fnServerData and event to manipulate3871_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );3872
3873// Convert to object based for 1.10+ if using the old array scheme which can3874// come from server-side processing or serverParams3875if ( data && Array.isArray(data) ) {3876var tmp = {};3877var rbracket = /(.*?)\[\]$/;3878
3879$.each( data, function (key, val) {3880var match = val.name.match(rbracket);3881
3882if ( match ) {3883// Support for arrays3884var name = match[0];3885
3886if ( ! tmp[ name ] ) {3887tmp[ name ] = [];3888}3889tmp[ name ].push( val.value );3890}3891else {3892tmp[val.name] = val.value;3893}3894} );3895data = tmp;3896}3897
3898var ajaxData;3899var ajax = oSettings.ajax;3900var instance = oSettings.oInstance;3901var callback = function ( json ) {3902var status = oSettings.jqXHR3903? oSettings.jqXHR.status3904: null;3905
3906if ( json === null || (typeof status === 'number' && status == 204 ) ) {3907json = {};3908_fnAjaxDataSrc( oSettings, json, [] );3909}3910
3911var error = json.error || json.sError;3912if ( error ) {3913_fnLog( oSettings, 0, error );3914}3915
3916oSettings.json = json;3917
3918_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );3919fn( json );3920};3921
3922if ( $.isPlainObject( ajax ) && ajax.data )3923{3924ajaxData = ajax.data;3925
3926var newData = typeof ajaxData === 'function' ?3927ajaxData( data, oSettings ) : // fn can manipulate data or return3928ajaxData; // an object object or array to merge3929
3930// If the function returned something, use that alone3931data = typeof ajaxData === 'function' && newData ?3932newData :3933$.extend( true, data, newData );3934
3935// Remove the data property as we've resolved it already and don't want3936// jQuery to do it again (it is restored at the end of the function)3937delete ajax.data;3938}3939
3940var baseAjax = {3941"data": data,3942"success": callback,3943"dataType": "json",3944"cache": false,3945"type": oSettings.sServerMethod,3946"error": function (xhr, error, thrown) {3947var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );3948
3949if ( $.inArray( true, ret ) === -1 ) {3950if ( error == "parsererror" ) {3951_fnLog( oSettings, 0, 'Invalid JSON response', 1 );3952}3953else if ( xhr.readyState === 4 ) {3954_fnLog( oSettings, 0, 'Ajax error', 7 );3955}3956}3957
3958_fnProcessingDisplay( oSettings, false );3959}3960};3961
3962// Store the data submitted for the API3963oSettings.oAjaxData = data;3964
3965// Allow plug-ins and external processes to modify the data3966_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );3967
3968if ( oSettings.fnServerData )3969{3970// DataTables 1.9- compatibility3971oSettings.fnServerData.call( instance,3972oSettings.sAjaxSource,3973$.map( data, function (val, key) { // Need to convert back to 1.9 trad format3974return { name: key, value: val };3975} ),3976callback,3977oSettings
3978);3979}3980else if ( oSettings.sAjaxSource || typeof ajax === 'string' )3981{3982// DataTables 1.9- compatibility3983oSettings.jqXHR = $.ajax( $.extend( baseAjax, {3984url: ajax || oSettings.sAjaxSource3985} ) );3986}3987else if ( typeof ajax === 'function' )3988{3989// Is a function - let the caller define what needs to be done3990oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );3991}3992else3993{3994// Object to extend the base settings3995oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );3996
3997// Restore for next time around3998ajax.data = ajaxData;3999}4000}
4001
4002
4003/**
4004* Update the table using an Ajax call
4005* @param {object} settings dataTables settings object
4006* @returns {boolean} Block the table drawing or not
4007* @memberof DataTable#oApi
4008*/
4009function _fnAjaxUpdate( settings )4010{
4011settings.iDraw++;4012_fnProcessingDisplay( settings, true );4013
4014// Keep track of drawHold state to handle scrolling after the Ajax call4015var drawHold = settings._drawHold;4016
4017_fnBuildAjax(4018settings,4019_fnAjaxParameters( settings ),4020function(json) {4021settings._drawHold = drawHold;4022_fnAjaxUpdateDraw( settings, json );4023settings._drawHold = false;4024}4025);4026}
4027
4028
4029/**
4030* Build up the parameters in an object needed for a server-side processing
4031* request. Note that this is basically done twice, is different ways - a modern
4032* method which is used by default in DataTables 1.10 which uses objects and
4033* arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4034* the sAjaxSource option is used in the initialisation, or the legacyAjax
4035* option is set.
4036* @param {object} oSettings dataTables settings object
4037* @returns {bool} block the table drawing or not
4038* @memberof DataTable#oApi
4039*/
4040function _fnAjaxParameters( settings )4041{
4042var4043columns = settings.aoColumns,4044columnCount = columns.length,4045features = settings.oFeatures,4046preSearch = settings.oPreviousSearch,4047preColSearch = settings.aoPreSearchCols,4048i, data = [], dataProp, column, columnSearch,4049sort = _fnSortFlatten( settings ),4050displayStart = settings._iDisplayStart,4051displayLength = features.bPaginate !== false ?4052settings._iDisplayLength :4053-1;4054
4055var param = function ( name, value ) {4056data.push( { 'name': name, 'value': value } );4057};4058
4059// DataTables 1.9- compatible method4060param( 'sEcho', settings.iDraw );4061param( 'iColumns', columnCount );4062param( 'sColumns', _pluck( columns, 'sName' ).join(',') );4063param( 'iDisplayStart', displayStart );4064param( 'iDisplayLength', displayLength );4065
4066// DataTables 1.10+ method4067var d = {4068draw: settings.iDraw,4069columns: [],4070order: [],4071start: displayStart,4072length: displayLength,4073search: {4074value: preSearch.sSearch,4075regex: preSearch.bRegex4076}4077};4078
4079for ( i=0 ; i<columnCount ; i++ ) {4080column = columns[i];4081columnSearch = preColSearch[i];4082dataProp = typeof column.mData=="function" ? 'function' : column.mData ;4083
4084d.columns.push( {4085data: dataProp,4086name: column.sName,4087searchable: column.bSearchable,4088orderable: column.bSortable,4089search: {4090value: columnSearch.sSearch,4091regex: columnSearch.bRegex4092}4093} );4094
4095param( "mDataProp_"+i, dataProp );4096
4097if ( features.bFilter ) {4098param( 'sSearch_'+i, columnSearch.sSearch );4099param( 'bRegex_'+i, columnSearch.bRegex );4100param( 'bSearchable_'+i, column.bSearchable );4101}4102
4103if ( features.bSort ) {4104param( 'bSortable_'+i, column.bSortable );4105}4106}4107
4108if ( features.bFilter ) {4109param( 'sSearch', preSearch.sSearch );4110param( 'bRegex', preSearch.bRegex );4111}4112
4113if ( features.bSort ) {4114$.each( sort, function ( i, val ) {4115d.order.push( { column: val.col, dir: val.dir } );4116
4117param( 'iSortCol_'+i, val.col );4118param( 'sSortDir_'+i, val.dir );4119} );4120
4121param( 'iSortingCols', sort.length );4122}4123
4124// If the legacy.ajax parameter is null, then we automatically decide which4125// form to use, based on sAjaxSource4126var legacy = DataTable.ext.legacy.ajax;4127if ( legacy === null ) {4128return settings.sAjaxSource ? data : d;4129}4130
4131// Otherwise, if legacy has been specified then we use that to decide on the4132// form4133return legacy ? data : d;4134}
4135
4136
4137/**
4138* Data the data from the server (nuking the old) and redraw the table
4139* @param {object} oSettings dataTables settings object
4140* @param {object} json json data return from the server.
4141* @param {string} json.sEcho Tracking flag for DataTables to match requests
4142* @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4143* @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4144* @param {array} json.aaData The data to display on this page
4145* @param {string} [json.sColumns] Column ordering (sName, comma separated)
4146* @memberof DataTable#oApi
4147*/
4148function _fnAjaxUpdateDraw ( settings, json )4149{
4150// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.4151// Support both4152var compat = function ( old, modern ) {4153return json[old] !== undefined ? json[old] : json[modern];4154};4155
4156var data = _fnAjaxDataSrc( settings, json );4157var draw = compat( 'sEcho', 'draw' );4158var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );4159var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );4160
4161if ( draw !== undefined ) {4162// Protect against out of sequence returns4163if ( draw*1 < settings.iDraw ) {4164return;4165}4166settings.iDraw = draw * 1;4167}4168
4169// No data in returned object, so rather than an array, we show an empty table4170if ( ! data ) {4171data = [];4172}4173
4174_fnClearTable( settings );4175settings._iRecordsTotal = parseInt(recordsTotal, 10);4176settings._iRecordsDisplay = parseInt(recordsFiltered, 10);4177
4178for ( var i=0, ien=data.length ; i<ien ; i++ ) {4179_fnAddData( settings, data[i] );4180}4181settings.aiDisplay = settings.aiDisplayMaster.slice();4182
4183_fnDraw( settings, true );4184
4185if ( ! settings._bInitComplete ) {4186_fnInitComplete( settings, json );4187}4188
4189_fnProcessingDisplay( settings, false );4190}
4191
4192
4193/**
4194* Get the data from the JSON data source to use for drawing a table. Using
4195* `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4196* source object, or from a processing function.
4197* @param {object} oSettings dataTables settings object
4198* @param {object} json Data source object / array from the server
4199* @return {array} Array of data to use
4200*/
4201function _fnAjaxDataSrc ( oSettings, json, write )4202{4203var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?4204oSettings.ajax.dataSrc :4205oSettings.sAjaxDataProp; // Compatibility with 1.9-.4206
4207if ( ! write ) {4208if ( dataSrc === 'data' ) {4209// If the default, then we still want to support the old style, and safely ignore4210// it if possible4211return json.aaData || json[dataSrc];4212}4213
4214return dataSrc !== "" ?4215_fnGetObjectDataFn( dataSrc )( json ) :4216json;4217}4218
4219// set4220_fnSetObjectDataFn( dataSrc )( json, write );4221}
4222
4223/**
4224* Generate the node required for filtering text
4225* @returns {node} Filter control element
4226* @param {object} oSettings dataTables settings object
4227* @memberof DataTable#oApi
4228*/
4229function _fnFeatureHtmlFilter ( settings )4230{
4231var classes = settings.oClasses;4232var tableId = settings.sTableId;4233var language = settings.oLanguage;4234var previousSearch = settings.oPreviousSearch;4235var features = settings.aanFeatures;4236var input = '<input type="search" class="'+classes.sFilterInput+'"/>';4237
4238var str = language.sSearch;4239str = str.match(/_INPUT_/) ?4240str.replace('_INPUT_', input) :4241str+input;4242
4243var filter = $('<div/>', {4244'id': ! features.f ? tableId+'_filter' : null,4245'class': classes.sFilter4246} )4247.append( $('<label/>' ).append( str ) );4248
4249var searchFn = function(event) {4250/* Update all other filter input elements for the new display */4251var n = features.f;4252var val = !this.value ? "" : this.value; // mental IE8 fix :-(4253if(previousSearch.return && event.key !== "Enter") {4254return;4255}4256/* Now do the filter */4257if ( val != previousSearch.sSearch ) {4258_fnFilterComplete( settings, {4259"sSearch": val,4260"bRegex": previousSearch.bRegex,4261"bSmart": previousSearch.bSmart ,4262"bCaseInsensitive": previousSearch.bCaseInsensitive,4263"return": previousSearch.return4264} );4265
4266// Need to redraw, without resorting4267settings._iDisplayStart = 0;4268_fnDraw( settings );4269}4270};4271
4272var searchDelay = settings.searchDelay !== null ?4273settings.searchDelay :4274_fnDataSource( settings ) === 'ssp' ?4275400 :42760;4277
4278var jqFilter = $('input', filter)4279.val( previousSearch.sSearch )4280.attr( 'placeholder', language.sSearchPlaceholder )4281.on(4282'keyup.DT search.DT input.DT paste.DT cut.DT',4283searchDelay ?4284_fnThrottle( searchFn, searchDelay ) :4285searchFn
4286)4287.on( 'mouseup.DT', function(e) {4288// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking4289// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`4290// checks the value to see if it has changed. In other browsers it won't have.4291setTimeout( function () {4292searchFn.call(jqFilter[0], e);4293}, 10);4294} )4295.on( 'keypress.DT', function(e) {4296/* Prevent form submission */4297if ( e.keyCode == 13 ) {4298return false;4299}4300} )4301.attr('aria-controls', tableId);4302
4303// Update the input elements whenever the table is filtered4304$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {4305if ( settings === s ) {4306// IE9 throws an 'unknown error' if document.activeElement is used4307// inside an iframe or frame...4308try {4309if ( jqFilter[0] !== document.activeElement ) {4310jqFilter.val( previousSearch.sSearch );4311}4312}4313catch ( e ) {}4314}4315} );4316
4317return filter[0];4318}
4319
4320
4321/**
4322* Filter the table using both the global filter and column based filtering
4323* @param {object} oSettings dataTables settings object
4324* @param {object} oSearch search information
4325* @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4326* @memberof DataTable#oApi
4327*/
4328function _fnFilterComplete ( oSettings, oInput, iForce )4329{
4330var oPrevSearch = oSettings.oPreviousSearch;4331var aoPrevSearch = oSettings.aoPreSearchCols;4332var fnSaveFilter = function ( oFilter ) {4333/* Save the filtering values */4334oPrevSearch.sSearch = oFilter.sSearch;4335oPrevSearch.bRegex = oFilter.bRegex;4336oPrevSearch.bSmart = oFilter.bSmart;4337oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;4338oPrevSearch.return = oFilter.return;4339};4340var fnRegex = function ( o ) {4341// Backwards compatibility with the bEscapeRegex option4342return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;4343};4344
4345// Resolve any column types that are unknown due to addition or invalidation4346// @todo As per sort - can this be moved into an event handler?4347_fnColumnTypes( oSettings );4348
4349/* In server-side processing all filtering is done by the server, so no point hanging around here */4350if ( _fnDataSource( oSettings ) != 'ssp' )4351{4352/* Global filter */4353_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );4354fnSaveFilter( oInput );4355
4356/* Now do the individual column filter */4357for ( var i=0 ; i<aoPrevSearch.length ; i++ )4358{4359_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),4360aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );4361}4362
4363/* Custom filtering */4364_fnFilterCustom( oSettings );4365}4366else4367{4368fnSaveFilter( oInput );4369}4370
4371/* Tell the draw function we have been filtering */4372oSettings.bFiltered = true;4373_fnCallbackFire( oSettings, null, 'search', [oSettings] );4374}
4375
4376
4377/**
4378* Apply custom filtering functions
4379* @param {object} oSettings dataTables settings object
4380* @memberof DataTable#oApi
4381*/
4382function _fnFilterCustom( settings )4383{
4384var filters = DataTable.ext.search;4385var displayRows = settings.aiDisplay;4386var row, rowIdx;4387
4388for ( var i=0, ien=filters.length ; i<ien ; i++ ) {4389var rows = [];4390
4391// Loop over each row and see if it should be included4392for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {4393rowIdx = displayRows[ j ];4394row = settings.aoData[ rowIdx ];4395
4396if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {4397rows.push( rowIdx );4398}4399}4400
4401// So the array reference doesn't break set the results into the4402// existing array4403displayRows.length = 0;4404$.merge( displayRows, rows );4405}4406}
4407
4408
4409/**
4410* Filter the table on a per-column basis
4411* @param {object} oSettings dataTables settings object
4412* @param {string} sInput string to filter on
4413* @param {int} iColumn column to filter
4414* @param {bool} bRegex treat search string as a regular expression or not
4415* @param {bool} bSmart use smart filtering or not
4416* @param {bool} bCaseInsensitive Do case insensitive matching or not
4417* @memberof DataTable#oApi
4418*/
4419function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )4420{
4421if ( searchStr === '' ) {4422return;4423}4424
4425var data;4426var out = [];4427var display = settings.aiDisplay;4428var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );4429
4430for ( var i=0 ; i<display.length ; i++ ) {4431data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];4432
4433if ( rpSearch.test( data ) ) {4434out.push( display[i] );4435}4436}4437
4438settings.aiDisplay = out;4439}
4440
4441
4442/**
4443* Filter the data table based on user input and draw the table
4444* @param {object} settings dataTables settings object
4445* @param {string} input string to filter on
4446* @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4447* @param {bool} regex treat as a regular expression or not
4448* @param {bool} smart perform smart filtering or not
4449* @param {bool} caseInsensitive Do case insensitive matching or not
4450* @memberof DataTable#oApi
4451*/
4452function _fnFilter( settings, input, force, regex, smart, caseInsensitive )4453{
4454var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );4455var prevSearch = settings.oPreviousSearch.sSearch;4456var displayMaster = settings.aiDisplayMaster;4457var display, invalidated, i;4458var filtered = [];4459
4460// Need to take account of custom filtering functions - always filter4461if ( DataTable.ext.search.length !== 0 ) {4462force = true;4463}4464
4465// Check if any of the rows were invalidated4466invalidated = _fnFilterData( settings );4467
4468// If the input is blank - we just want the full data set4469if ( input.length <= 0 ) {4470settings.aiDisplay = displayMaster.slice();4471}4472else {4473// New search - start from the master array4474if ( invalidated ||4475force ||4476regex ||4477prevSearch.length > input.length ||4478input.indexOf(prevSearch) !== 0 ||4479settings.bSorted // On resort, the display master needs to be4480// re-filtered since indexes will have changed4481) {4482settings.aiDisplay = displayMaster.slice();4483}4484
4485// Search the display array4486display = settings.aiDisplay;4487
4488for ( i=0 ; i<display.length ; i++ ) {4489if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {4490filtered.push( display[i] );4491}4492}4493
4494settings.aiDisplay = filtered;4495}4496}
4497
4498
4499/**
4500* Build a regular expression object suitable for searching a table
4501* @param {string} sSearch string to search for
4502* @param {bool} bRegex treat as a regular expression or not
4503* @param {bool} bSmart perform smart filtering or not
4504* @param {bool} bCaseInsensitive Do case insensitive matching or not
4505* @returns {RegExp} constructed object
4506* @memberof DataTable#oApi
4507*/
4508function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )4509{
4510search = regex ?4511search :4512_fnEscapeRegex( search );4513
4514if ( smart ) {4515/* For smart filtering we want to allow the search to work regardless of4516* word order. We also want double quoted text to be preserved, so word
4517* order is important - a la google. So this is what we want to
4518* generate:
4519*
4520* ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4521*/
4522var a = $.map( search.match( /["\u201C][^"\u201D]+["\u201D]|[^ ]+/g ) || [''], function ( word ) {4523if ( word.charAt(0) === '"' ) {4524var m = word.match( /^"(.*)"$/ );4525word = m ? m[1] : word;4526}4527else if ( word.charAt(0) === '\u201C' ) {4528var m = word.match( /^\u201C(.*)\u201D$/ );4529word = m ? m[1] : word;4530}4531
4532return word.replace('"', '');4533} );4534
4535search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';4536}4537
4538return new RegExp( search, caseInsensitive ? 'i' : '' );4539}
4540
4541
4542/**
4543* Escape a string such that it can be used in a regular expression
4544* @param {string} sVal string to escape
4545* @returns {string} escaped string
4546* @memberof DataTable#oApi
4547*/
4548var _fnEscapeRegex = DataTable.util.escapeRegex;4549
4550var __filter_div = $('<div>')[0];4551var __filter_div_textContent = __filter_div.textContent !== undefined;4552
4553// Update the filtering data for each row if needed (by invalidation or first run)
4554function _fnFilterData ( settings )4555{
4556var columns = settings.aoColumns;4557var column;4558var i, j, ien, jen, filterData, cellData, row;4559var wasInvalidated = false;4560
4561for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {4562row = settings.aoData[i];4563
4564if ( ! row._aFilterData ) {4565filterData = [];4566
4567for ( j=0, jen=columns.length ; j<jen ; j++ ) {4568column = columns[j];4569
4570if ( column.bSearchable ) {4571cellData = _fnGetCellData( settings, i, j, 'filter' );4572
4573// Search in DataTables 1.10 is string based. In 1.11 this4574// should be altered to also allow strict type checking.4575if ( cellData === null ) {4576cellData = '';4577}4578
4579if ( typeof cellData !== 'string' && cellData.toString ) {4580cellData = cellData.toString();4581}4582}4583else {4584cellData = '';4585}4586
4587// If it looks like there is an HTML entity in the string,4588// attempt to decode it so sorting works as expected. Note that4589// we could use a single line of jQuery to do this, but the DOM4590// method used here is much faster http://jsperf.com/html-decode4591if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {4592__filter_div.innerHTML = cellData;4593cellData = __filter_div_textContent ?4594__filter_div.textContent :4595__filter_div.innerText;4596}4597
4598if ( cellData.replace ) {4599cellData = cellData.replace(/[\r\n\u2028]/g, '');4600}4601
4602filterData.push( cellData );4603}4604
4605row._aFilterData = filterData;4606row._sFilterRow = filterData.join(' ');4607wasInvalidated = true;4608}4609}4610
4611return wasInvalidated;4612}
4613
4614
4615/**
4616* Convert from the internal Hungarian notation to camelCase for external
4617* interaction
4618* @param {object} obj Object to convert
4619* @returns {object} Inverted object
4620* @memberof DataTable#oApi
4621*/
4622function _fnSearchToCamel ( obj )4623{
4624return {4625search: obj.sSearch,4626smart: obj.bSmart,4627regex: obj.bRegex,4628caseInsensitive: obj.bCaseInsensitive4629};4630}
4631
4632
4633
4634/**
4635* Convert from camelCase notation to the internal Hungarian. We could use the
4636* Hungarian convert function here, but this is cleaner
4637* @param {object} obj Object to convert
4638* @returns {object} Inverted object
4639* @memberof DataTable#oApi
4640*/
4641function _fnSearchToHung ( obj )4642{
4643return {4644sSearch: obj.search,4645bSmart: obj.smart,4646bRegex: obj.regex,4647bCaseInsensitive: obj.caseInsensitive4648};4649}
4650
4651/**
4652* Generate the node required for the info display
4653* @param {object} oSettings dataTables settings object
4654* @returns {node} Information element
4655* @memberof DataTable#oApi
4656*/
4657function _fnFeatureHtmlInfo ( settings )4658{
4659var4660tid = settings.sTableId,4661nodes = settings.aanFeatures.i,4662n = $('<div/>', {4663'class': settings.oClasses.sInfo,4664'id': ! nodes ? tid+'_info' : null4665} );4666
4667if ( ! nodes ) {4668// Update display on each draw4669settings.aoDrawCallback.push( {4670"fn": _fnUpdateInfo,4671"sName": "information"4672} );4673
4674n
4675.attr( 'role', 'status' )4676.attr( 'aria-live', 'polite' );4677
4678// Table is described by our info div4679$(settings.nTable).attr( 'aria-describedby', tid+'_info' );4680}4681
4682return n[0];4683}
4684
4685
4686/**
4687* Update the information elements in the display
4688* @param {object} settings dataTables settings object
4689* @memberof DataTable#oApi
4690*/
4691function _fnUpdateInfo ( settings )4692{
4693/* Show information about the table */4694var nodes = settings.aanFeatures.i;4695if ( nodes.length === 0 ) {4696return;4697}4698
4699var4700lang = settings.oLanguage,4701start = settings._iDisplayStart+1,4702end = settings.fnDisplayEnd(),4703max = settings.fnRecordsTotal(),4704total = settings.fnRecordsDisplay(),4705out = total ?4706lang.sInfo :4707lang.sInfoEmpty;4708
4709if ( total !== max ) {4710/* Record set after filtering */4711out += ' ' + lang.sInfoFiltered;4712}4713
4714// Convert the macros4715out += lang.sInfoPostFix;4716out = _fnInfoMacros( settings, out );4717
4718var callback = lang.fnInfoCallback;4719if ( callback !== null ) {4720out = callback.call( settings.oInstance,4721settings, start, end, max, total, out4722);4723}4724
4725$(nodes).html( out );4726}
4727
4728
4729function _fnInfoMacros ( settings, str )4730{
4731// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only4732// internally4733var4734formatter = settings.fnFormatNumber,4735start = settings._iDisplayStart+1,4736len = settings._iDisplayLength,4737vis = settings.fnRecordsDisplay(),4738all = len === -1;4739
4740return str.4741replace(/_START_/g, formatter.call( settings, start ) ).4742replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ).4743replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ).4744replace(/_TOTAL_/g, formatter.call( settings, vis ) ).4745replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).4746replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );4747}
4748
4749
4750
4751/**
4752* Draw the table for the first time, adding all required features
4753* @param {object} settings dataTables settings object
4754* @memberof DataTable#oApi
4755*/
4756function _fnInitialise ( settings )4757{
4758var i, iLen, iAjaxStart=settings.iInitDisplayStart;4759var columns = settings.aoColumns, column;4760var features = settings.oFeatures;4761var deferLoading = settings.bDeferLoading; // value modified by the draw4762
4763/* Ensure that the table data is fully initialised */4764if ( ! settings.bInitialised ) {4765setTimeout( function(){ _fnInitialise( settings ); }, 200 );4766return;4767}4768
4769/* Show the display HTML options */4770_fnAddOptionsHtml( settings );4771
4772/* Build and draw the header / footer for the table */4773_fnBuildHead( settings );4774_fnDrawHead( settings, settings.aoHeader );4775_fnDrawHead( settings, settings.aoFooter );4776
4777/* Okay to show that something is going on now */4778_fnProcessingDisplay( settings, true );4779
4780/* Calculate sizes for columns */4781if ( features.bAutoWidth ) {4782_fnCalculateColumnWidths( settings );4783}4784
4785for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {4786column = columns[i];4787
4788if ( column.sWidth ) {4789column.nTh.style.width = _fnStringToCss( column.sWidth );4790}4791}4792
4793_fnCallbackFire( settings, null, 'preInit', [settings] );4794
4795// If there is default sorting required - let's do it. The sort function4796// will do the drawing for us. Otherwise we draw the table regardless of the4797// Ajax source - this allows the table to look initialised for Ajax sourcing4798// data (show 'loading' message possibly)4799_fnReDraw( settings );4800
4801// Server-side processing init complete is done by _fnAjaxUpdateDraw4802var dataSrc = _fnDataSource( settings );4803if ( dataSrc != 'ssp' || deferLoading ) {4804// if there is an ajax source load the data4805if ( dataSrc == 'ajax' ) {4806_fnBuildAjax( settings, [], function(json) {4807var aData = _fnAjaxDataSrc( settings, json );4808
4809// Got the data - add it to the table4810for ( i=0 ; i<aData.length ; i++ ) {4811_fnAddData( settings, aData[i] );4812}4813
4814// Reset the init display for cookie saving. We've already done4815// a filter, and therefore cleared it before. So we need to make4816// it appear 'fresh'4817settings.iInitDisplayStart = iAjaxStart;4818
4819_fnReDraw( settings );4820
4821_fnProcessingDisplay( settings, false );4822_fnInitComplete( settings, json );4823}, settings );4824}4825else {4826_fnProcessingDisplay( settings, false );4827_fnInitComplete( settings );4828}4829}4830}
4831
4832
4833/**
4834* Draw the table for the first time, adding all required features
4835* @param {object} oSettings dataTables settings object
4836* @param {object} [json] JSON from the server that completed the table, if using Ajax source
4837* with client-side processing (optional)
4838* @memberof DataTable#oApi
4839*/
4840function _fnInitComplete ( settings, json )4841{
4842settings._bInitComplete = true;4843
4844// When data was added after the initialisation (data or Ajax) we need to4845// calculate the column sizing4846if ( json || settings.oInit.aaData ) {4847_fnAdjustColumnSizing( settings );4848}4849
4850_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );4851_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );4852}
4853
4854
4855function _fnLengthChange ( settings, val )4856{
4857var len = parseInt( val, 10 );4858settings._iDisplayLength = len;4859
4860_fnLengthOverflow( settings );4861
4862// Fire length change event4863_fnCallbackFire( settings, null, 'length', [settings, len] );4864}
4865
4866
4867/**
4868* Generate the node required for user display length changing
4869* @param {object} settings dataTables settings object
4870* @returns {node} Display length feature node
4871* @memberof DataTable#oApi
4872*/
4873function _fnFeatureHtmlLength ( settings )4874{
4875var4876classes = settings.oClasses,4877tableId = settings.sTableId,4878menu = settings.aLengthMenu,4879d2 = Array.isArray( menu[0] ),4880lengths = d2 ? menu[0] : menu,4881language = d2 ? menu[1] : menu;4882
4883var select = $('<select/>', {4884'name': tableId+'_length',4885'aria-controls': tableId,4886'class': classes.sLengthSelect4887} );4888
4889for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {4890select[0][ i ] = new Option(4891typeof language[i] === 'number' ?4892settings.fnFormatNumber( language[i] ) :4893language[i],4894lengths[i]4895);4896}4897
4898var div = $('<div><label/></div>').addClass( classes.sLength );4899if ( ! settings.aanFeatures.l ) {4900div[0].id = tableId+'_length';4901}4902
4903div.children().append(4904settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )4905);4906
4907// Can't use `select` variable as user might provide their own and the4908// reference is broken by the use of outerHTML4909$('select', div)4910.val( settings._iDisplayLength )4911.on( 'change.DT', function(e) {4912_fnLengthChange( settings, $(this).val() );4913_fnDraw( settings );4914} );4915
4916// Update node value whenever anything changes the table's length4917$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {4918if ( settings === s ) {4919$('select', div).val( len );4920}4921} );4922
4923return div[0];4924}
4925
4926
4927
4928/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4929* Note that most of the paging logic is done in
4930* DataTable.ext.pager
4931*/
4932
4933/**
4934* Generate the node required for default pagination
4935* @param {object} oSettings dataTables settings object
4936* @returns {node} Pagination feature node
4937* @memberof DataTable#oApi
4938*/
4939function _fnFeatureHtmlPaginate ( settings )4940{
4941var4942type = settings.sPaginationType,4943plugin = DataTable.ext.pager[ type ],4944modern = typeof plugin === 'function',4945redraw = function( settings ) {4946_fnDraw( settings );4947},4948node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],4949features = settings.aanFeatures;4950
4951if ( ! modern ) {4952plugin.fnInit( settings, node, redraw );4953}4954
4955/* Add a draw callback for the pagination on first instance, to update the paging display */4956if ( ! features.p )4957{4958node.id = settings.sTableId+'_paginate';4959
4960settings.aoDrawCallback.push( {4961"fn": function( settings ) {4962if ( modern ) {4963var4964start = settings._iDisplayStart,4965len = settings._iDisplayLength,4966visRecords = settings.fnRecordsDisplay(),4967all = len === -1,4968page = all ? 0 : Math.ceil( start / len ),4969pages = all ? 1 : Math.ceil( visRecords / len ),4970buttons = plugin(page, pages),4971i, ien;4972
4973for ( i=0, ien=features.p.length ; i<ien ; i++ ) {4974_fnRenderer( settings, 'pageButton' )(4975settings, features.p[i], i, buttons, page, pages4976);4977}4978}4979else {4980plugin.fnUpdate( settings, redraw );4981}4982},4983"sName": "pagination"4984} );4985}4986
4987return node;4988}
4989
4990
4991/**
4992* Alter the display settings to change the page
4993* @param {object} settings DataTables settings object
4994* @param {string|int} action Paging action to take: "first", "previous",
4995* "next" or "last" or page number to jump to (integer)
4996* @param [bool] redraw Automatically draw the update or not
4997* @returns {bool} true page has changed, false - no change
4998* @memberof DataTable#oApi
4999*/
5000function _fnPageChange ( settings, action, redraw )5001{
5002var5003start = settings._iDisplayStart,5004len = settings._iDisplayLength,5005records = settings.fnRecordsDisplay();5006
5007if ( records === 0 || len === -1 )5008{5009start = 0;5010}5011else if ( typeof action === "number" )5012{5013start = action * len;5014
5015if ( start > records )5016{5017start = 0;5018}5019}5020else if ( action == "first" )5021{5022start = 0;5023}5024else if ( action == "previous" )5025{5026start = len >= 0 ?5027start - len :50280;5029
5030if ( start < 0 )5031{5032start = 0;5033}5034}5035else if ( action == "next" )5036{5037if ( start + len < records )5038{5039start += len;5040}5041}5042else if ( action == "last" )5043{5044start = Math.floor( (records-1) / len) * len;5045}5046else5047{5048_fnLog( settings, 0, "Unknown paging action: "+action, 5 );5049}5050
5051var changed = settings._iDisplayStart !== start;5052settings._iDisplayStart = start;5053
5054if ( changed ) {5055_fnCallbackFire( settings, null, 'page', [settings] );5056
5057if ( redraw ) {5058_fnDraw( settings );5059}5060}5061else {5062// No change event - paging was called, but no change5063_fnCallbackFire( settings, null, 'page-nc', [settings] );5064}5065
5066return changed;5067}
5068
5069
5070
5071/**
5072* Generate the node required for the processing node
5073* @param {object} settings dataTables settings object
5074* @returns {node} Processing element
5075* @memberof DataTable#oApi
5076*/
5077function _fnFeatureHtmlProcessing ( settings )5078{
5079return $('<div/>', {5080'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,5081'class': settings.oClasses.sProcessing,5082'role': 'status'5083} )5084.html( settings.oLanguage.sProcessing )5085.append('<div><div></div><div></div><div></div><div></div></div>')5086.insertBefore( settings.nTable )[0];5087}
5088
5089
5090/**
5091* Display or hide the processing indicator
5092* @param {object} settings dataTables settings object
5093* @param {bool} show Show the processing indicator (true) or not (false)
5094* @memberof DataTable#oApi
5095*/
5096function _fnProcessingDisplay ( settings, show )5097{
5098if ( settings.oFeatures.bProcessing ) {5099$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );5100}5101
5102_fnCallbackFire( settings, null, 'processing', [settings, show] );5103}
5104
5105/**
5106* Add any control elements for the table - specifically scrolling
5107* @param {object} settings dataTables settings object
5108* @returns {node} Node to add to the DOM
5109* @memberof DataTable#oApi
5110*/
5111function _fnFeatureHtmlTable ( settings )5112{
5113var table = $(settings.nTable);5114
5115// Scrolling from here on in5116var scroll = settings.oScroll;5117
5118if ( scroll.sX === '' && scroll.sY === '' ) {5119return settings.nTable;5120}5121
5122var scrollX = scroll.sX;5123var scrollY = scroll.sY;5124var classes = settings.oClasses;5125var caption = table.children('caption');5126var captionSide = caption.length ? caption[0]._captionSide : null;5127var headerClone = $( table[0].cloneNode(false) );5128var footerClone = $( table[0].cloneNode(false) );5129var footer = table.children('tfoot');5130var _div = '<div/>';5131var size = function ( s ) {5132return !s ? null : _fnStringToCss( s );5133};5134
5135if ( ! footer.length ) {5136footer = null;5137}5138
5139/*5140* The HTML structure that we want to generate in this function is:
5141* div - scroller
5142* div - scroll head
5143* div - scroll head inner
5144* table - scroll head table
5145* thead - thead
5146* div - scroll body
5147* table - table (master table)
5148* thead - thead clone for sizing
5149* tbody - tbody
5150* div - scroll foot
5151* div - scroll foot inner
5152* table - scroll foot table
5153* tfoot - tfoot
5154*/
5155var scroller = $( _div, { 'class': classes.sScrollWrapper } )5156.append(5157$(_div, { 'class': classes.sScrollHead } )5158.css( {5159overflow: 'hidden',5160position: 'relative',5161border: 0,5162width: scrollX ? size(scrollX) : '100%'5163} )5164.append(5165$(_div, { 'class': classes.sScrollHeadInner } )5166.css( {5167'box-sizing': 'content-box',5168width: scroll.sXInner || '100%'5169} )5170.append(5171headerClone
5172.removeAttr('id')5173.css( 'margin-left', 0 )5174.append( captionSide === 'top' ? caption : null )5175.append(5176table.children('thead')5177)5178)5179)5180)5181.append(5182$(_div, { 'class': classes.sScrollBody } )5183.css( {5184position: 'relative',5185overflow: 'auto',5186width: size( scrollX )5187} )5188.append( table )5189);5190
5191if ( footer ) {5192scroller.append(5193$(_div, { 'class': classes.sScrollFoot } )5194.css( {5195overflow: 'hidden',5196border: 0,5197width: scrollX ? size(scrollX) : '100%'5198} )5199.append(5200$(_div, { 'class': classes.sScrollFootInner } )5201.append(5202footerClone
5203.removeAttr('id')5204.css( 'margin-left', 0 )5205.append( captionSide === 'bottom' ? caption : null )5206.append(5207table.children('tfoot')5208)5209)5210)5211);5212}5213
5214var children = scroller.children();5215var scrollHead = children[0];5216var scrollBody = children[1];5217var scrollFoot = footer ? children[2] : null;5218
5219// When the body is scrolled, then we also want to scroll the headers5220if ( scrollX ) {5221$(scrollBody).on( 'scroll.DT', function (e) {5222var scrollLeft = this.scrollLeft;5223
5224scrollHead.scrollLeft = scrollLeft;5225
5226if ( footer ) {5227scrollFoot.scrollLeft = scrollLeft;5228}5229} );5230}5231
5232$(scrollBody).css('max-height', scrollY);5233if (! scroll.bCollapse) {5234$(scrollBody).css('height', scrollY);5235}5236
5237settings.nScrollHead = scrollHead;5238settings.nScrollBody = scrollBody;5239settings.nScrollFoot = scrollFoot;5240
5241// On redraw - align columns5242settings.aoDrawCallback.push( {5243"fn": _fnScrollDraw,5244"sName": "scrolling"5245} );5246
5247return scroller[0];5248}
5249
5250
5251
5252/**
5253* Update the header, footer and body tables for resizing - i.e. column
5254* alignment.
5255*
5256* Welcome to the most horrible function DataTables. The process that this
5257* function follows is basically:
5258* 1. Re-create the table inside the scrolling div
5259* 2. Take live measurements from the DOM
5260* 3. Apply the measurements to align the columns
5261* 4. Clean up
5262*
5263* @param {object} settings dataTables settings object
5264* @memberof DataTable#oApi
5265*/
5266function _fnScrollDraw ( settings )5267{
5268// Given that this is such a monster function, a lot of variables are use5269// to try and keep the minimised size as small as possible5270var5271scroll = settings.oScroll,5272scrollX = scroll.sX,5273scrollXInner = scroll.sXInner,5274scrollY = scroll.sY,5275barWidth = scroll.iBarWidth,5276divHeader = $(settings.nScrollHead),5277divHeaderStyle = divHeader[0].style,5278divHeaderInner = divHeader.children('div'),5279divHeaderInnerStyle = divHeaderInner[0].style,5280divHeaderTable = divHeaderInner.children('table'),5281divBodyEl = settings.nScrollBody,5282divBody = $(divBodyEl),5283divBodyStyle = divBodyEl.style,5284divFooter = $(settings.nScrollFoot),5285divFooterInner = divFooter.children('div'),5286divFooterTable = divFooterInner.children('table'),5287header = $(settings.nTHead),5288table = $(settings.nTable),5289tableEl = table[0],5290tableStyle = tableEl.style,5291footer = settings.nTFoot ? $(settings.nTFoot) : null,5292browser = settings.oBrowser,5293ie67 = browser.bScrollOversize,5294dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ),5295headerTrgEls, footerTrgEls,5296headerSrcEls, footerSrcEls,5297headerCopy, footerCopy,5298headerWidths=[], footerWidths=[],5299headerContent=[], footerContent=[],5300idx, correction, sanityWidth,5301zeroOut = function(nSizer) {5302var style = nSizer.style;5303style.paddingTop = "0";5304style.paddingBottom = "0";5305style.borderTopWidth = "0";5306style.borderBottomWidth = "0";5307style.height = 0;5308};5309
5310// If the scrollbar visibility has changed from the last draw, we need to5311// adjust the column sizes as the table width will have changed to account5312// for the scrollbar5313var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;5314
5315if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {5316settings.scrollBarVis = scrollBarVis;5317_fnAdjustColumnSizing( settings );5318return; // adjust column sizing will call this function again5319}5320else {5321settings.scrollBarVis = scrollBarVis;5322}5323
5324/*5325* 1. Re-create the table inside the scrolling div
5326*/
5327
5328// Remove the old minimised thead and tfoot elements in the inner table5329table.children('thead, tfoot').remove();5330
5331if ( footer ) {5332footerCopy = footer.clone().prependTo( table );5333footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized5334footerSrcEls = footerCopy.find('tr');5335footerCopy.find('[id]').removeAttr('id');5336}5337
5338// Clone the current header and footer elements and then place it into the inner table5339headerCopy = header.clone().prependTo( table );5340headerTrgEls = header.find('tr'); // original header is in its own table5341headerSrcEls = headerCopy.find('tr');5342headerCopy.find('th, td').removeAttr('tabindex');5343headerCopy.find('[id]').removeAttr('id');5344
5345
5346/*5347* 2. Take live measurements from the DOM - do not alter the DOM itself!
5348*/
5349
5350// Remove old sizing and apply the calculated column widths5351// Get the unique column headers in the newly created (cloned) header. We want to apply the5352// calculated sizes to this header5353if ( ! scrollX )5354{5355divBodyStyle.width = '100%';5356divHeader[0].style.width = '100%';5357}5358
5359$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {5360idx = _fnVisibleToColumnIndex( settings, i );5361el.style.width = settings.aoColumns[idx].sWidth;5362} );5363
5364if ( footer ) {5365_fnApplyToChildren( function(n) {5366n.style.width = "";5367}, footerSrcEls );5368}5369
5370// Size the table as a whole5371sanityWidth = table.outerWidth();5372if ( scrollX === "" ) {5373// No x scrolling5374tableStyle.width = "100%";5375
5376// IE7 will make the width of the table when 100% include the scrollbar5377// - which is shouldn't. When there is a scrollbar we need to take this5378// into account.5379if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||5380divBody.css('overflow-y') == "scroll")5381) {5382tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);5383}5384
5385// Recalculate the sanity width5386sanityWidth = table.outerWidth();5387}5388else if ( scrollXInner !== "" ) {5389// legacy x scroll inner has been given - use it5390tableStyle.width = _fnStringToCss(scrollXInner);5391
5392// Recalculate the sanity width5393sanityWidth = table.outerWidth();5394}5395
5396// Hidden header should have zero height, so remove padding and borders. Then5397// set the width based on the real headers5398
5399// Apply all styles in one pass5400_fnApplyToChildren( zeroOut, headerSrcEls );5401
5402// Read all widths in next pass5403_fnApplyToChildren( function(nSizer) {5404var style = window.getComputedStyle ?5405window.getComputedStyle(nSizer).width :5406_fnStringToCss( $(nSizer).width() );5407
5408headerContent.push( nSizer.innerHTML );5409headerWidths.push( style );5410}, headerSrcEls );5411
5412// Apply all widths in final pass5413_fnApplyToChildren( function(nToSize, i) {5414nToSize.style.width = headerWidths[i];5415}, headerTrgEls );5416
5417$(headerSrcEls).css('height', 0);5418
5419/* Same again with the footer if we have one */5420if ( footer )5421{5422_fnApplyToChildren( zeroOut, footerSrcEls );5423
5424_fnApplyToChildren( function(nSizer) {5425footerContent.push( nSizer.innerHTML );5426footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );5427}, footerSrcEls );5428
5429_fnApplyToChildren( function(nToSize, i) {5430nToSize.style.width = footerWidths[i];5431}, footerTrgEls );5432
5433$(footerSrcEls).height(0);5434}5435
5436
5437/*5438* 3. Apply the measurements
5439*/
5440
5441// "Hide" the header and footer that we used for the sizing. We need to keep5442// the content of the cell so that the width applied to the header and body5443// both match, but we want to hide it completely. We want to also fix their5444// width to what they currently are5445_fnApplyToChildren( function(nSizer, i) {5446nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';5447nSizer.childNodes[0].style.height = "0";5448nSizer.childNodes[0].style.overflow = "hidden";5449nSizer.style.width = headerWidths[i];5450}, headerSrcEls );5451
5452if ( footer )5453{5454_fnApplyToChildren( function(nSizer, i) {5455nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';5456nSizer.childNodes[0].style.height = "0";5457nSizer.childNodes[0].style.overflow = "hidden";5458nSizer.style.width = footerWidths[i];5459}, footerSrcEls );5460}5461
5462// Sanity check that the table is of a sensible width. If not then we are going to get5463// misalignment - try to prevent this by not allowing the table to shrink below its min width5464if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )5465{5466// The min width depends upon if we have a vertical scrollbar visible or not */5467correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||5468divBody.css('overflow-y') == "scroll")) ?5469sanityWidth+barWidth :5470sanityWidth;5471
5472// IE6/7 are a law unto themselves...5473if ( ie67 && (divBodyEl.scrollHeight >5474divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")5475) {5476tableStyle.width = _fnStringToCss( correction-barWidth );5477}5478
5479// And give the user a warning that we've stopped the table getting too small5480if ( scrollX === "" || scrollXInner !== "" ) {5481_fnLog( settings, 1, 'Possible column misalignment', 6 );5482}5483}5484else5485{5486correction = '100%';5487}5488
5489// Apply to the container elements5490divBodyStyle.width = _fnStringToCss( correction );5491divHeaderStyle.width = _fnStringToCss( correction );5492
5493if ( footer ) {5494settings.nScrollFoot.style.width = _fnStringToCss( correction );5495}5496
5497
5498/*5499* 4. Clean up
5500*/
5501if ( ! scrollY ) {5502/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting5503* the scrollbar height from the visible display, rather than adding it on. We need to
5504* set the height in order to sort this. Don't want to do it in any other browsers.
5505*/
5506if ( ie67 ) {5507divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );5508}5509}5510
5511/* Finally set the width's of the header and footer tables */5512var iOuterWidth = table.outerWidth();5513divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );5514divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );5515
5516// Figure out if there are scrollbar present - if so then we need a the header and footer to5517// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)5518var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";5519var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );5520divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";5521
5522if ( footer ) {5523divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );5524divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );5525divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";5526}5527
5528// Correct DOM ordering for colgroup - comes before the thead5529table.children('colgroup').insertBefore( table.children('thead') );5530
5531/* Adjust the position of the header in case we loose the y-scrollbar */5532divBody.trigger('scroll');5533
5534// If sorting or filtering has occurred, jump the scrolling back to the top5535// only if we aren't holding the position5536if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {5537divBodyEl.scrollTop = 0;5538}5539}
5540
5541
5542
5543/**
5544* Apply a given function to the display child nodes of an element array (typically
5545* TD children of TR rows
5546* @param {function} fn Method to apply to the objects
5547* @param array {nodes} an1 List of elements to look through for display children
5548* @param array {nodes} an2 Another list (identical structure to the first) - optional
5549* @memberof DataTable#oApi
5550*/
5551function _fnApplyToChildren( fn, an1, an2 )5552{
5553var index=0, i=0, iLen=an1.length;5554var nNode1, nNode2;5555
5556while ( i < iLen ) {5557nNode1 = an1[i].firstChild;5558nNode2 = an2 ? an2[i].firstChild : null;5559
5560while ( nNode1 ) {5561if ( nNode1.nodeType === 1 ) {5562if ( an2 ) {5563fn( nNode1, nNode2, index );5564}5565else {5566fn( nNode1, index );5567}5568
5569index++;5570}5571
5572nNode1 = nNode1.nextSibling;5573nNode2 = an2 ? nNode2.nextSibling : null;5574}5575
5576i++;5577}5578}
5579
5580
5581
5582var __re_html_remove = /<.*?>/g;5583
5584
5585/**
5586* Calculate the width of columns for the table
5587* @param {object} oSettings dataTables settings object
5588* @memberof DataTable#oApi
5589*/
5590function _fnCalculateColumnWidths ( oSettings )5591{
5592var5593table = oSettings.nTable,5594columns = oSettings.aoColumns,5595scroll = oSettings.oScroll,5596scrollY = scroll.sY,5597scrollX = scroll.sX,5598scrollXInner = scroll.sXInner,5599columnCount = columns.length,5600visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),5601headerCells = $('th', oSettings.nTHead),5602tableWidthAttr = table.getAttribute('width'), // from DOM element5603tableContainer = table.parentNode,5604userInputs = false,5605i, column, columnIdx, width, outerWidth,5606browser = oSettings.oBrowser,5607ie67 = browser.bScrollOversize;5608
5609var styleWidth = table.style.width;5610if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {5611tableWidthAttr = styleWidth;5612}5613
5614/* Convert any user input sizes into pixel sizes */5615for ( i=0 ; i<visibleColumns.length ; i++ ) {5616column = columns[ visibleColumns[i] ];5617
5618if ( column.sWidth !== null ) {5619column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );5620
5621userInputs = true;5622}5623}5624
5625/* If the number of columns in the DOM equals the number that we have to5626* process in DataTables, then we can use the offsets that are created by
5627* the web- browser. No custom sizes can be set in order for this to happen,
5628* nor scrolling used
5629*/
5630if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&5631columnCount == _fnVisbleColumns( oSettings ) &&5632columnCount == headerCells.length5633) {5634for ( i=0 ; i<columnCount ; i++ ) {5635var colIdx = _fnVisibleToColumnIndex( oSettings, i );5636
5637if ( colIdx !== null ) {5638columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );5639}5640}5641}5642else5643{5644// Otherwise construct a single row, worst case, table with the widest5645// node in the data, assign any user defined widths, then insert it into5646// the DOM and allow the browser to do all the hard work of calculating5647// table widths5648var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table5649.css( 'visibility', 'hidden' )5650.removeAttr( 'id' );5651
5652// Clean up the table body5653tmpTable.find('tbody tr').remove();5654var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );5655
5656// Clone the table header and footer - we can't use the header / footer5657// from the cloned table, since if scrolling is active, the table's5658// real header and footer are contained in different table tags5659tmpTable.find('thead, tfoot').remove();5660tmpTable
5661.append( $(oSettings.nTHead).clone() )5662.append( $(oSettings.nTFoot).clone() );5663
5664// Remove any assigned widths from the footer (from scrolling)5665tmpTable.find('tfoot th, tfoot td').css('width', '');5666
5667// Apply custom sizing to the cloned header5668headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );5669
5670for ( i=0 ; i<visibleColumns.length ; i++ ) {5671column = columns[ visibleColumns[i] ];5672
5673headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?5674_fnStringToCss( column.sWidthOrig ) :5675'';5676
5677// For scrollX we need to force the column width otherwise the5678// browser will collapse it. If this width is smaller than the5679// width the column requires, then it will have no effect5680if ( column.sWidthOrig && scrollX ) {5681$( headerCells[i] ).append( $('<div/>').css( {5682width: column.sWidthOrig,5683margin: 0,5684padding: 0,5685border: 0,5686height: 15687} ) );5688}5689}5690
5691// Find the widest cell for each column and put it into the table5692if ( oSettings.aoData.length ) {5693for ( i=0 ; i<visibleColumns.length ; i++ ) {5694columnIdx = visibleColumns[i];5695column = columns[ columnIdx ];5696
5697$( _fnGetWidestNode( oSettings, columnIdx ) )5698.clone( false )5699.append( column.sContentPadding )5700.appendTo( tr );5701}5702}5703
5704// Tidy the temporary table - remove name attributes so there aren't5705// duplicated in the dom (radio elements for example)5706$('[name]', tmpTable).removeAttr('name');5707
5708// Table has been built, attach to the document so we can work with it.5709// A holding element is used, positioned at the top of the container5710// with minimal height, so it has no effect on if the container scrolls5711// or not. Otherwise it might trigger scrolling when it actually isn't5712// needed5713var holder = $('<div/>').css( scrollX || scrollY ?5714{5715position: 'absolute',5716top: 0,5717left: 0,5718height: 1,5719right: 0,5720overflow: 'hidden'5721} :5722{}5723)5724.append( tmpTable )5725.appendTo( tableContainer );5726
5727// When scrolling (X or Y) we want to set the width of the table as5728// appropriate. However, when not scrolling leave the table width as it5729// is. This results in slightly different, but I think correct behaviour5730if ( scrollX && scrollXInner ) {5731tmpTable.width( scrollXInner );5732}5733else if ( scrollX ) {5734tmpTable.css( 'width', 'auto' );5735tmpTable.removeAttr('width');5736
5737// If there is no width attribute or style, then allow the table to5738// collapse5739if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {5740tmpTable.width( tableContainer.clientWidth );5741}5742}5743else if ( scrollY ) {5744tmpTable.width( tableContainer.clientWidth );5745}5746else if ( tableWidthAttr ) {5747tmpTable.width( tableWidthAttr );5748}5749
5750// Get the width of each column in the constructed table - we need to5751// know the inner width (so it can be assigned to the other table's5752// cells) and the outer width so we can calculate the full width of the5753// table. This is safe since DataTables requires a unique cell for each5754// column, but if ever a header can span multiple columns, this will5755// need to be modified.5756var total = 0;5757for ( i=0 ; i<visibleColumns.length ; i++ ) {5758var cell = $(headerCells[i]);5759var border = cell.outerWidth() - cell.width();5760
5761// Use getBounding... where possible (not IE8-) because it can give5762// sub-pixel accuracy, which we then want to round up!5763var bounding = browser.bBounding ?5764Math.ceil( headerCells[i].getBoundingClientRect().width ) :5765cell.outerWidth();5766
5767// Total is tracked to remove any sub-pixel errors as the outerWidth5768// of the table might not equal the total given here (IE!).5769total += bounding;5770
5771// Width for each column to use5772columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );5773}5774
5775table.style.width = _fnStringToCss( total );5776
5777// Finished with the table - ditch it5778holder.remove();5779}5780
5781// If there is a width attr, we want to attach an event listener which5782// allows the table sizing to automatically adjust when the window is5783// resized. Use the width attr rather than CSS, since we can't know if the5784// CSS is a relative value or absolute - DOM read is always px.5785if ( tableWidthAttr ) {5786table.style.width = _fnStringToCss( tableWidthAttr );5787}5788
5789if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {5790var bindResize = function () {5791$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {5792_fnAdjustColumnSizing( oSettings );5793} ) );5794};5795
5796// IE6/7 will crash if we bind a resize event handler on page load.5797// To be removed in 1.11 which drops IE6/7 support5798if ( ie67 ) {5799setTimeout( bindResize, 1000 );5800}5801else {5802bindResize();5803}5804
5805oSettings._reszEvt = true;5806}5807}
5808
5809
5810/**
5811* Throttle the calls to a function. Arguments and context are maintained for
5812* the throttled function
5813* @param {function} fn Function to be called
5814* @param {int} [freq=200] call frequency in mS
5815* @returns {function} wrapped function
5816* @memberof DataTable#oApi
5817*/
5818var _fnThrottle = DataTable.util.throttle;5819
5820
5821/**
5822* Convert a CSS unit width to pixels (e.g. 2em)
5823* @param {string} width width to be converted
5824* @param {node} parent parent to get the with for (required for relative widths) - optional
5825* @returns {int} width in pixels
5826* @memberof DataTable#oApi
5827*/
5828function _fnConvertToWidth ( width, parent )5829{
5830if ( ! width ) {5831return 0;5832}5833
5834var n = $('<div/>')5835.css( 'width', _fnStringToCss( width ) )5836.appendTo( parent || document.body );5837
5838var val = n[0].offsetWidth;5839n.remove();5840
5841return val;5842}
5843
5844
5845/**
5846* Get the widest node
5847* @param {object} settings dataTables settings object
5848* @param {int} colIdx column of interest
5849* @returns {node} widest table node
5850* @memberof DataTable#oApi
5851*/
5852function _fnGetWidestNode( settings, colIdx )5853{
5854var idx = _fnGetMaxLenString( settings, colIdx );5855if ( idx < 0 ) {5856return null;5857}5858
5859var data = settings.aoData[ idx ];5860return ! data.nTr ? // Might not have been created when deferred rendering5861$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :5862data.anCells[ colIdx ];5863}
5864
5865
5866/**
5867* Get the maximum strlen for each data column
5868* @param {object} settings dataTables settings object
5869* @param {int} colIdx column of interest
5870* @returns {string} max string length for each column
5871* @memberof DataTable#oApi
5872*/
5873function _fnGetMaxLenString( settings, colIdx )5874{
5875var s, max=-1, maxIdx = -1;5876
5877for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {5878s = _fnGetCellData( settings, i, colIdx, 'display' )+'';5879s = s.replace( __re_html_remove, '' );5880s = s.replace( / /g, ' ' );5881
5882if ( s.length > max ) {5883max = s.length;5884maxIdx = i;5885}5886}5887
5888return maxIdx;5889}
5890
5891
5892/**
5893* Append a CSS unit (only if required) to a string
5894* @param {string} value to css-ify
5895* @returns {string} value with css unit
5896* @memberof DataTable#oApi
5897*/
5898function _fnStringToCss( s )5899{
5900if ( s === null ) {5901return '0px';5902}5903
5904if ( typeof s == 'number' ) {5905return s < 0 ?5906'0px' :5907s+'px';5908}5909
5910// Check it has a unit character already5911return s.match(/\d$/) ?5912s+'px' :5913s;5914}
5915
5916
5917
5918function _fnSortFlatten ( settings )5919{
5920var5921i, iLen, k, kLen,5922aSort = [],5923aiOrig = [],5924aoColumns = settings.aoColumns,5925aDataSort, iCol, sType, srcCol,5926fixed = settings.aaSortingFixed,5927fixedObj = $.isPlainObject( fixed ),5928nestedSort = [],5929add = function ( a ) {5930if ( a.length && ! Array.isArray( a[0] ) ) {5931// 1D array5932nestedSort.push( a );5933}5934else {5935// 2D array5936$.merge( nestedSort, a );5937}5938};5939
5940// Build the sort array, with pre-fix and post-fix options if they have been5941// specified5942if ( Array.isArray( fixed ) ) {5943add( fixed );5944}5945
5946if ( fixedObj && fixed.pre ) {5947add( fixed.pre );5948}5949
5950add( settings.aaSorting );5951
5952if (fixedObj && fixed.post ) {5953add( fixed.post );5954}5955
5956for ( i=0 ; i<nestedSort.length ; i++ )5957{5958srcCol = nestedSort[i][0];5959aDataSort = aoColumns[ srcCol ].aDataSort;5960
5961for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )5962{5963iCol = aDataSort[k];5964sType = aoColumns[ iCol ].sType || 'string';5965
5966if ( nestedSort[i]._idx === undefined ) {5967nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );5968}5969
5970aSort.push( {5971src: srcCol,5972col: iCol,5973dir: nestedSort[i][1],5974index: nestedSort[i]._idx,5975type: sType,5976formatter: DataTable.ext.type.order[ sType+"-pre" ]5977} );5978}5979}5980
5981return aSort;5982}
5983
5984/**
5985* Change the order of the table
5986* @param {object} oSettings dataTables settings object
5987* @memberof DataTable#oApi
5988* @todo This really needs split up!
5989*/
5990function _fnSort ( oSettings )5991{
5992var5993i, ien, iLen, j, jLen, k, kLen,5994sDataType, nTh,5995aiOrig = [],5996oExtSort = DataTable.ext.type.order,5997aoData = oSettings.aoData,5998aoColumns = oSettings.aoColumns,5999aDataSort, data, iCol, sType, oSort,6000formatters = 0,6001sortCol,6002displayMaster = oSettings.aiDisplayMaster,6003aSort;6004
6005// Resolve any column types that are unknown due to addition or invalidation6006// @todo Can this be moved into a 'data-ready' handler which is called when6007// data is going to be used in the table?6008_fnColumnTypes( oSettings );6009
6010aSort = _fnSortFlatten( oSettings );6011
6012for ( i=0, ien=aSort.length ; i<ien ; i++ ) {6013sortCol = aSort[i];6014
6015// Track if we can use the fast sort algorithm6016if ( sortCol.formatter ) {6017formatters++;6018}6019
6020// Load the data needed for the sort, for each cell6021_fnSortData( oSettings, sortCol.col );6022}6023
6024/* No sorting required if server-side or no sorting array */6025if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )6026{6027// Create a value - key array of the current row positions such that we can use their6028// current position during the sort, if values match, in order to perform stable sorting6029for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {6030aiOrig[ displayMaster[i] ] = i;6031}6032
6033/* Do the sort - here we want multi-column sorting based on a given data source (column)6034* and sorting function (from oSort) in a certain direction. It's reasonably complex to
6035* follow on it's own, but this is what we want (example two column sorting):
6036* fnLocalSorting = function(a,b){
6037* var iTest;
6038* iTest = oSort['string-asc']('data11', 'data12');
6039* if (iTest !== 0)
6040* return iTest;
6041* iTest = oSort['numeric-desc']('data21', 'data22');
6042* if (iTest !== 0)
6043* return iTest;
6044* return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6045* }
6046* Basically we have a test for each sorting column, if the data in that column is equal,
6047* test the next column. If all columns match, then we use a numeric sort on the row
6048* positions in the original data array to provide a stable sort.
6049*
6050* Note - I know it seems excessive to have two sorting methods, but the first is around
6051* 15% faster, so the second is only maintained for backwards compatibility with sorting
6052* methods which do not have a pre-sort formatting function.
6053*/
6054if ( formatters === aSort.length ) {6055// All sort types have formatting functions6056displayMaster.sort( function ( a, b ) {6057var6058x, y, k, test, sort,6059len=aSort.length,6060dataA = aoData[a]._aSortData,6061dataB = aoData[b]._aSortData;6062
6063for ( k=0 ; k<len ; k++ ) {6064sort = aSort[k];6065
6066x = dataA[ sort.col ];6067y = dataB[ sort.col ];6068
6069test = x<y ? -1 : x>y ? 1 : 0;6070if ( test !== 0 ) {6071return sort.dir === 'asc' ? test : -test;6072}6073}6074
6075x = aiOrig[a];6076y = aiOrig[b];6077return x<y ? -1 : x>y ? 1 : 0;6078} );6079}6080else {6081// Depreciated - remove in 1.11 (providing a plug-in option)6082// Not all sort types have formatting methods, so we have to call their sorting6083// methods.6084displayMaster.sort( function ( a, b ) {6085var6086x, y, k, l, test, sort, fn,6087len=aSort.length,6088dataA = aoData[a]._aSortData,6089dataB = aoData[b]._aSortData;6090
6091for ( k=0 ; k<len ; k++ ) {6092sort = aSort[k];6093
6094x = dataA[ sort.col ];6095y = dataB[ sort.col ];6096
6097fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];6098test = fn( x, y );6099if ( test !== 0 ) {6100return test;6101}6102}6103
6104x = aiOrig[a];6105y = aiOrig[b];6106return x<y ? -1 : x>y ? 1 : 0;6107} );6108}6109}6110
6111/* Tell the draw function that we have sorted the data */6112oSettings.bSorted = true;6113}
6114
6115
6116function _fnSortAria ( settings )6117{
6118var label;6119var nextSort;6120var columns = settings.aoColumns;6121var aSort = _fnSortFlatten( settings );6122var oAria = settings.oLanguage.oAria;6123
6124// ARIA attributes - need to loop all columns, to update all (removing old6125// attributes as needed)6126for ( var i=0, iLen=columns.length ; i<iLen ; i++ )6127{6128var col = columns[i];6129var asSorting = col.asSorting;6130var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );6131var th = col.nTh;6132
6133// IE7 is throwing an error when setting these properties with jQuery's6134// attr() and removeAttr() methods...6135th.removeAttribute('aria-sort');6136
6137/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */6138if ( col.bSortable ) {6139if ( aSort.length > 0 && aSort[0].col == i ) {6140th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );6141nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];6142}6143else {6144nextSort = asSorting[0];6145}6146
6147label = sTitle + ( nextSort === "asc" ?6148oAria.sSortAscending :6149oAria.sSortDescending6150);6151}6152else {6153label = sTitle;6154}6155
6156th.setAttribute('aria-label', label);6157}6158}
6159
6160
6161/**
6162* Function to run on user sort request
6163* @param {object} settings dataTables settings object
6164* @param {node} attachTo node to attach the handler to
6165* @param {int} colIdx column sorting index
6166* @param {boolean} [append=false] Append the requested sort to the existing
6167* sort if true (i.e. multi-column sort)
6168* @param {function} [callback] callback function
6169* @memberof DataTable#oApi
6170*/
6171function _fnSortListener ( settings, colIdx, append, callback )6172{
6173var col = settings.aoColumns[ colIdx ];6174var sorting = settings.aaSorting;6175var asSorting = col.asSorting;6176var nextSortIdx;6177var next = function ( a, overflow ) {6178var idx = a._idx;6179if ( idx === undefined ) {6180idx = $.inArray( a[1], asSorting );6181}6182
6183return idx+1 < asSorting.length ?6184idx+1 :6185overflow ?6186null :61870;6188};6189
6190// Convert to 2D array if needed6191if ( typeof sorting[0] === 'number' ) {6192sorting = settings.aaSorting = [ sorting ];6193}6194
6195// If appending the sort then we are multi-column sorting6196if ( append && settings.oFeatures.bSortMulti ) {6197// Are we already doing some kind of sort on this column?6198var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );6199
6200if ( sortIdx !== -1 ) {6201// Yes, modify the sort6202nextSortIdx = next( sorting[sortIdx], true );6203
6204if ( nextSortIdx === null && sorting.length === 1 ) {6205nextSortIdx = 0; // can't remove sorting completely6206}6207
6208if ( nextSortIdx === null ) {6209sorting.splice( sortIdx, 1 );6210}6211else {6212sorting[sortIdx][1] = asSorting[ nextSortIdx ];6213sorting[sortIdx]._idx = nextSortIdx;6214}6215}6216else {6217// No sort on this column yet6218sorting.push( [ colIdx, asSorting[0], 0 ] );6219sorting[sorting.length-1]._idx = 0;6220}6221}6222else if ( sorting.length && sorting[0][0] == colIdx ) {6223// Single column - already sorting on this column, modify the sort6224nextSortIdx = next( sorting[0] );6225
6226sorting.length = 1;6227sorting[0][1] = asSorting[ nextSortIdx ];6228sorting[0]._idx = nextSortIdx;6229}6230else {6231// Single column - sort only on this column6232sorting.length = 0;6233sorting.push( [ colIdx, asSorting[0] ] );6234sorting[0]._idx = 0;6235}6236
6237// Run the sort by calling a full redraw6238_fnReDraw( settings );6239
6240// callback used for async user interaction6241if ( typeof callback == 'function' ) {6242callback( settings );6243}6244}
6245
6246
6247/**
6248* Attach a sort handler (click) to a node
6249* @param {object} settings dataTables settings object
6250* @param {node} attachTo node to attach the handler to
6251* @param {int} colIdx column sorting index
6252* @param {function} [callback] callback function
6253* @memberof DataTable#oApi
6254*/
6255function _fnSortAttachListener ( settings, attachTo, colIdx, callback )6256{
6257var col = settings.aoColumns[ colIdx ];6258
6259_fnBindAction( attachTo, {}, function (e) {6260/* If the column is not sortable - don't to anything */6261if ( col.bSortable === false ) {6262return;6263}6264
6265// If processing is enabled use a timeout to allow the processing6266// display to be shown - otherwise to it synchronously6267if ( settings.oFeatures.bProcessing ) {6268_fnProcessingDisplay( settings, true );6269
6270setTimeout( function() {6271_fnSortListener( settings, colIdx, e.shiftKey, callback );6272
6273// In server-side processing, the draw callback will remove the6274// processing display6275if ( _fnDataSource( settings ) !== 'ssp' ) {6276_fnProcessingDisplay( settings, false );6277}6278}, 0 );6279}6280else {6281_fnSortListener( settings, colIdx, e.shiftKey, callback );6282}6283} );6284}
6285
6286
6287/**
6288* Set the sorting classes on table's body, Note: it is safe to call this function
6289* when bSort and bSortClasses are false
6290* @param {object} oSettings dataTables settings object
6291* @memberof DataTable#oApi
6292*/
6293function _fnSortingClasses( settings )6294{
6295var oldSort = settings.aLastSort;6296var sortClass = settings.oClasses.sSortColumn;6297var sort = _fnSortFlatten( settings );6298var features = settings.oFeatures;6299var i, ien, colIdx;6300
6301if ( features.bSort && features.bSortClasses ) {6302// Remove old sorting classes6303for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {6304colIdx = oldSort[i].src;6305
6306// Remove column sorting6307$( _pluck( settings.aoData, 'anCells', colIdx ) )6308.removeClass( sortClass + (i<2 ? i+1 : 3) );6309}6310
6311// Add new column sorting6312for ( i=0, ien=sort.length ; i<ien ; i++ ) {6313colIdx = sort[i].src;6314
6315$( _pluck( settings.aoData, 'anCells', colIdx ) )6316.addClass( sortClass + (i<2 ? i+1 : 3) );6317}6318}6319
6320settings.aLastSort = sort;6321}
6322
6323
6324// Get the data to sort a column, be it from cache, fresh (populating the
6325// cache), or from a sort formatter
6326function _fnSortData( settings, idx )6327{
6328// Custom sorting function - provided by the sort data type6329var column = settings.aoColumns[ idx ];6330var customSort = DataTable.ext.order[ column.sSortDataType ];6331var customData;6332
6333if ( customSort ) {6334customData = customSort.call( settings.oInstance, settings, idx,6335_fnColumnIndexToVisible( settings, idx )6336);6337}6338
6339// Use / populate cache6340var row, cellData;6341var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];6342
6343for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {6344row = settings.aoData[i];6345
6346if ( ! row._aSortData ) {6347row._aSortData = [];6348}6349
6350if ( ! row._aSortData[idx] || customSort ) {6351cellData = customSort ?6352customData[i] : // If there was a custom sort function, use data from there6353_fnGetCellData( settings, i, idx, 'sort' );6354
6355row._aSortData[ idx ] = formatter ?6356formatter( cellData ) :6357cellData;6358}6359}6360}
6361
6362
6363
6364/**
6365* Save the state of a table
6366* @param {object} oSettings dataTables settings object
6367* @memberof DataTable#oApi
6368*/
6369function _fnSaveState ( settings )6370{
6371if (settings._bLoadingState) {6372return;6373}6374
6375/* Store the interesting variables */6376var state = {6377time: +new Date(),6378start: settings._iDisplayStart,6379length: settings._iDisplayLength,6380order: $.extend( true, [], settings.aaSorting ),6381search: _fnSearchToCamel( settings.oPreviousSearch ),6382columns: $.map( settings.aoColumns, function ( col, i ) {6383return {6384visible: col.bVisible,6385search: _fnSearchToCamel( settings.aoPreSearchCols[i] )6386};6387} )6388};6389
6390settings.oSavedState = state;6391_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );6392
6393if ( settings.oFeatures.bStateSave && !settings.bDestroying )6394{6395settings.fnStateSaveCallback.call( settings.oInstance, settings, state );6396}6397}
6398
6399
6400/**
6401* Attempt to load a saved table state
6402* @param {object} oSettings dataTables settings object
6403* @param {object} oInit DataTables init object so we can override settings
6404* @param {function} callback Callback to execute when the state has been loaded
6405* @memberof DataTable#oApi
6406*/
6407function _fnLoadState ( settings, oInit, callback )6408{
6409if ( ! settings.oFeatures.bStateSave ) {6410callback();6411return;6412}6413
6414var loaded = function(state) {6415_fnImplementState(settings, state, callback);6416}6417
6418var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );6419
6420if ( state !== undefined ) {6421_fnImplementState( settings, state, callback );6422}6423// otherwise, wait for the loaded callback to be executed6424
6425return true;6426}
6427
6428function _fnImplementState ( settings, s, callback) {6429var i, ien;6430var columns = settings.aoColumns;6431settings._bLoadingState = true;6432
6433// When StateRestore was introduced the state could now be implemented at any time6434// Not just initialisation. To do this an api instance is required in some places6435var api = settings._bInitComplete ? new DataTable.Api(settings) : null;6436
6437if ( ! s || ! s.time ) {6438settings._bLoadingState = false;6439callback();6440return;6441}6442
6443// Allow custom and plug-in manipulation functions to alter the saved data set and6444// cancelling of loading by returning false6445var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );6446if ( $.inArray( false, abStateLoad ) !== -1 ) {6447settings._bLoadingState = false;6448callback();6449return;6450}6451
6452// Reject old data6453var duration = settings.iStateDuration;6454if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {6455settings._bLoadingState = false;6456callback();6457return;6458}6459
6460// Number of columns have changed - all bets are off, no restore of settings6461if ( s.columns && columns.length !== s.columns.length ) {6462settings._bLoadingState = false;6463callback();6464return;6465}6466
6467// Store the saved state so it might be accessed at any time6468settings.oLoadedState = $.extend( true, {}, s );6469
6470// Page Length6471if ( s.length !== undefined ) {6472// If already initialised just set the value directly so that the select element is also updated6473if (api) {6474api.page.len(s.length)6475}6476else {6477settings._iDisplayLength = s.length;6478}6479}6480
6481// Restore key features - todo - for 1.11 this needs to be done by6482// subscribed events6483if ( s.start !== undefined ) {6484if(api === null) {6485settings._iDisplayStart = s.start;6486settings.iInitDisplayStart = s.start;6487}6488else {6489_fnPageChange(settings, s.start/settings._iDisplayLength);6490}6491}6492
6493// Order6494if ( s.order !== undefined ) {6495settings.aaSorting = [];6496$.each( s.order, function ( i, col ) {6497settings.aaSorting.push( col[0] >= columns.length ?6498[ 0, col[1] ] :6499col
6500);6501} );6502}6503
6504// Search6505if ( s.search !== undefined ) {6506$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );6507}6508
6509// Columns6510if ( s.columns ) {6511for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {6512var col = s.columns[i];6513
6514// Visibility6515if ( col.visible !== undefined ) {6516// If the api is defined, the table has been initialised so we need to use it rather than internal settings6517if (api) {6518// Don't redraw the columns on every iteration of this loop, we will do this at the end instead6519api.column(i).visible(col.visible, false);6520}6521else {6522columns[i].bVisible = col.visible;6523}6524}6525
6526// Search6527if ( col.search !== undefined ) {6528$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );6529}6530}6531
6532// If the api is defined then we need to adjust the columns once the visibility has been changed6533if (api) {6534api.columns.adjust();6535}6536}6537
6538settings._bLoadingState = false;6539_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );6540callback();6541};6542
6543
6544/**
6545* Return the settings object for a particular table
6546* @param {node} table table we are using as a dataTable
6547* @returns {object} Settings object - or null if not found
6548* @memberof DataTable#oApi
6549*/
6550function _fnSettingsFromNode ( table )6551{
6552var settings = DataTable.settings;6553var idx = $.inArray( table, _pluck( settings, 'nTable' ) );6554
6555return idx !== -1 ?6556settings[ idx ] :6557null;6558}
6559
6560
6561/**
6562* Log an error message
6563* @param {object} settings dataTables settings object
6564* @param {int} level log error messages, or display them to the user
6565* @param {string} msg error message
6566* @param {int} tn Technical note id to get more information about the error.
6567* @memberof DataTable#oApi
6568*/
6569function _fnLog( settings, level, msg, tn )6570{
6571msg = 'DataTables warning: '+6572(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;6573
6574if ( tn ) {6575msg += '. For more information about this error, please see '+6576'http://datatables.net/tn/'+tn;6577}6578
6579if ( ! level ) {6580// Backwards compatibility pre 1.106581var ext = DataTable.ext;6582var type = ext.sErrMode || ext.errMode;6583
6584if ( settings ) {6585_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );6586}6587
6588if ( type == 'alert' ) {6589alert( msg );6590}6591else if ( type == 'throw' ) {6592throw new Error(msg);6593}6594else if ( typeof type == 'function' ) {6595type( settings, tn, msg );6596}6597}6598else if ( window.console && console.log ) {6599console.log( msg );6600}6601}
6602
6603
6604/**
6605* See if a property is defined on one object, if so assign it to the other object
6606* @param {object} ret target object
6607* @param {object} src source object
6608* @param {string} name property
6609* @param {string} [mappedName] name to map too - optional, name used if not given
6610* @memberof DataTable#oApi
6611*/
6612function _fnMap( ret, src, name, mappedName )6613{
6614if ( Array.isArray( name ) ) {6615$.each( name, function (i, val) {6616if ( Array.isArray( val ) ) {6617_fnMap( ret, src, val[0], val[1] );6618}6619else {6620_fnMap( ret, src, val );6621}6622} );6623
6624return;6625}6626
6627if ( mappedName === undefined ) {6628mappedName = name;6629}6630
6631if ( src[name] !== undefined ) {6632ret[mappedName] = src[name];6633}6634}
6635
6636
6637/**
6638* Extend objects - very similar to jQuery.extend, but deep copy objects, and
6639* shallow copy arrays. The reason we need to do this, is that we don't want to
6640* deep copy array init values (such as aaSorting) since the dev wouldn't be
6641* able to override them, but we do want to deep copy arrays.
6642* @param {object} out Object to extend
6643* @param {object} extender Object from which the properties will be applied to
6644* out
6645* @param {boolean} breakRefs If true, then arrays will be sliced to take an
6646* independent copy with the exception of the `data` or `aaData` parameters
6647* if they are present. This is so you can pass in a collection to
6648* DataTables and have that used as your data source without breaking the
6649* references
6650* @returns {object} out Reference, just for convenience - out === the return.
6651* @memberof DataTable#oApi
6652* @todo This doesn't take account of arrays inside the deep copied objects.
6653*/
6654function _fnExtend( out, extender, breakRefs )6655{
6656var val;6657
6658for ( var prop in extender ) {6659if ( extender.hasOwnProperty(prop) ) {6660val = extender[prop];6661
6662if ( $.isPlainObject( val ) ) {6663if ( ! $.isPlainObject( out[prop] ) ) {6664out[prop] = {};6665}6666$.extend( true, out[prop], val );6667}6668else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {6669out[prop] = val.slice();6670}6671else {6672out[prop] = val;6673}6674}6675}6676
6677return out;6678}
6679
6680
6681/**
6682* Bind an event handers to allow a click or return key to activate the callback.
6683* This is good for accessibility since a return on the keyboard will have the
6684* same effect as a click, if the element has focus.
6685* @param {element} n Element to bind the action to
6686* @param {object} oData Data object to pass to the triggered function
6687* @param {function} fn Callback function for when the event is triggered
6688* @memberof DataTable#oApi
6689*/
6690function _fnBindAction( n, oData, fn )6691{
6692$(n)6693.on( 'click.DT', oData, function (e) {6694$(n).trigger('blur'); // Remove focus outline for mouse users6695fn(e);6696} )6697.on( 'keypress.DT', oData, function (e){6698if ( e.which === 13 ) {6699e.preventDefault();6700fn(e);6701}6702} )6703.on( 'selectstart.DT', function () {6704/* Take the brutal approach to cancelling text selection */6705return false;6706} );6707}
6708
6709
6710/**
6711* Register a callback function. Easily allows a callback function to be added to
6712* an array store of callback functions that can then all be called together.
6713* @param {object} oSettings dataTables settings object
6714* @param {string} sStore Name of the array storage for the callbacks in oSettings
6715* @param {function} fn Function to be called back
6716* @param {string} sName Identifying name for the callback (i.e. a label)
6717* @memberof DataTable#oApi
6718*/
6719function _fnCallbackReg( oSettings, sStore, fn, sName )6720{
6721if ( fn )6722{6723oSettings[sStore].push( {6724"fn": fn,6725"sName": sName6726} );6727}6728}
6729
6730
6731/**
6732* Fire callback functions and trigger events. Note that the loop over the
6733* callback array store is done backwards! Further note that you do not want to
6734* fire off triggers in time sensitive applications (for example cell creation)
6735* as its slow.
6736* @param {object} settings dataTables settings object
6737* @param {string} callbackArr Name of the array storage for the callbacks in
6738* oSettings
6739* @param {string} eventName Name of the jQuery custom event to trigger. If
6740* null no trigger is fired
6741* @param {array} args Array of arguments to pass to the callback function /
6742* trigger
6743* @memberof DataTable#oApi
6744*/
6745function _fnCallbackFire( settings, callbackArr, eventName, args )6746{
6747var ret = [];6748
6749if ( callbackArr ) {6750ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {6751return val.fn.apply( settings.oInstance, args );6752} );6753}6754
6755if ( eventName !== null ) {6756var e = $.Event( eventName+'.dt' );6757var table = $(settings.nTable);6758
6759table.trigger( e, args );6760
6761// If not yet attached to the document, trigger the event6762// on the body directly to sort of simulate the bubble6763if (table.parents('body').length === 0) {6764$('body').trigger( e, args );6765}6766
6767ret.push( e.result );6768}6769
6770return ret;6771}
6772
6773
6774function _fnLengthOverflow ( settings )6775{
6776var6777start = settings._iDisplayStart,6778end = settings.fnDisplayEnd(),6779len = settings._iDisplayLength;6780
6781/* If we have space to show extra rows (backing up from the end point - then do so */6782if ( start >= end )6783{6784start = end - len;6785}6786
6787// Keep the start record on the current page6788start -= (start % len);6789
6790if ( len === -1 || start < 0 )6791{6792start = 0;6793}6794
6795settings._iDisplayStart = start;6796}
6797
6798
6799function _fnRenderer( settings, type )6800{
6801var renderer = settings.renderer;6802var host = DataTable.ext.renderer[type];6803
6804if ( $.isPlainObject( renderer ) && renderer[type] ) {6805// Specific renderer for this type. If available use it, otherwise use6806// the default.6807return host[renderer[type]] || host._;6808}6809else if ( typeof renderer === 'string' ) {6810// Common renderer - if there is one available for this type use it,6811// otherwise use the default6812return host[renderer] || host._;6813}6814
6815// Use the default6816return host._;6817}
6818
6819
6820/**
6821* Detect the data source being used for the table. Used to simplify the code
6822* a little (ajax) and to make it compress a little smaller.
6823*
6824* @param {object} settings dataTables settings object
6825* @returns {string} Data source
6826* @memberof DataTable#oApi
6827*/
6828function _fnDataSource ( settings )6829{
6830if ( settings.oFeatures.bServerSide ) {6831return 'ssp';6832}6833else if ( settings.ajax || settings.sAjaxSource ) {6834return 'ajax';6835}6836return 'dom';6837}
6838
6839
6840
6841
6842/**
6843* Computed structure of the DataTables API, defined by the options passed to
6844* `DataTable.Api.register()` when building the API.
6845*
6846* The structure is built in order to speed creation and extension of the Api
6847* objects since the extensions are effectively pre-parsed.
6848*
6849* The array is an array of objects with the following structure, where this
6850* base array represents the Api prototype base:
6851*
6852* [
6853* {
6854* name: 'data' -- string - Property name
6855* val: function () {}, -- function - Api method (or undefined if just an object
6856* methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
6857* propExt: [ ... ] -- array - Array of Api object definitions to extend the property
6858* },
6859* {
6860* name: 'row'
6861* val: {},
6862* methodExt: [ ... ],
6863* propExt: [
6864* {
6865* name: 'data'
6866* val: function () {},
6867* methodExt: [ ... ],
6868* propExt: [ ... ]
6869* },
6870* ...
6871* ]
6872* }
6873* ]
6874*
6875* @type {Array}
6876* @ignore
6877*/
6878var __apiStruct = [];6879
6880
6881/**
6882* `Array.prototype` reference.
6883*
6884* @type object
6885* @ignore
6886*/
6887var __arrayProto = Array.prototype;6888
6889
6890/**
6891* Abstraction for `context` parameter of the `Api` constructor to allow it to
6892* take several different forms for ease of use.
6893*
6894* Each of the input parameter types will be converted to a DataTables settings
6895* object where possible.
6896*
6897* @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
6898* of:
6899*
6900* * `string` - jQuery selector. Any DataTables' matching the given selector
6901* with be found and used.
6902* * `node` - `TABLE` node which has already been formed into a DataTable.
6903* * `jQuery` - A jQuery object of `TABLE` nodes.
6904* * `object` - DataTables settings object
6905* * `DataTables.Api` - API instance
6906* @return {array|null} Matching DataTables settings objects. `null` or
6907* `undefined` is returned if no matching DataTable is found.
6908* @ignore
6909*/
6910var _toSettings = function ( mixed )6911{
6912var idx, jq;6913var settings = DataTable.settings;6914var tables = $.map( settings, function (el, i) {6915return el.nTable;6916} );6917
6918if ( ! mixed ) {6919return [];6920}6921else if ( mixed.nTable && mixed.oApi ) {6922// DataTables settings object6923return [ mixed ];6924}6925else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {6926// Table node6927idx = $.inArray( mixed, tables );6928return idx !== -1 ? [ settings[idx] ] : null;6929}6930else if ( mixed && typeof mixed.settings === 'function' ) {6931return mixed.settings().toArray();6932}6933else if ( typeof mixed === 'string' ) {6934// jQuery selector6935jq = $(mixed);6936}6937else if ( mixed instanceof $ ) {6938// jQuery object (also DataTables instance)6939jq = mixed;6940}6941
6942if ( jq ) {6943return jq.map( function(i) {6944idx = $.inArray( this, tables );6945return idx !== -1 ? settings[idx] : null;6946} ).toArray();6947}6948};6949
6950
6951/**
6952* DataTables API class - used to control and interface with one or more
6953* DataTables enhanced tables.
6954*
6955* The API class is heavily based on jQuery, presenting a chainable interface
6956* that you can use to interact with tables. Each instance of the API class has
6957* a "context" - i.e. the tables that it will operate on. This could be a single
6958* table, all tables on a page or a sub-set thereof.
6959*
6960* Additionally the API is designed to allow you to easily work with the data in
6961* the tables, retrieving and manipulating it as required. This is done by
6962* presenting the API class as an array like interface. The contents of the
6963* array depend upon the actions requested by each method (for example
6964* `rows().nodes()` will return an array of nodes, while `rows().data()` will
6965* return an array of objects or arrays depending upon your table's
6966* configuration). The API object has a number of array like methods (`push`,
6967* `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6968* `unique` etc) to assist your working with the data held in a table.
6969*
6970* Most methods (those which return an Api instance) are chainable, which means
6971* the return from a method call also has all of the methods available that the
6972* top level object had. For example, these two calls are equivalent:
6973*
6974* // Not chained
6975* api.row.add( {...} );
6976* api.draw();
6977*
6978* // Chained
6979* api.row.add( {...} ).draw();
6980*
6981* @class DataTable.Api
6982* @param {array|object|string|jQuery} context DataTable identifier. This is
6983* used to define which DataTables enhanced tables this API will operate on.
6984* Can be one of:
6985*
6986* * `string` - jQuery selector. Any DataTables' matching the given selector
6987* with be found and used.
6988* * `node` - `TABLE` node which has already been formed into a DataTable.
6989* * `jQuery` - A jQuery object of `TABLE` nodes.
6990* * `object` - DataTables settings object
6991* @param {array} [data] Data to initialise the Api instance with.
6992*
6993* @example
6994* // Direct initialisation during DataTables construction
6995* var api = $('#example').DataTable();
6996*
6997* @example
6998* // Initialisation using a DataTables jQuery object
6999* var api = $('#example').dataTable().api();
7000*
7001* @example
7002* // Initialisation as a constructor
7003* var api = new $.fn.DataTable.Api( 'table.dataTable' );
7004*/
7005_Api = function ( context, data )7006{
7007if ( ! (this instanceof _Api) ) {7008return new _Api( context, data );7009}7010
7011var settings = [];7012var ctxSettings = function ( o ) {7013var a = _toSettings( o );7014if ( a ) {7015settings.push.apply( settings, a );7016}7017};7018
7019if ( Array.isArray( context ) ) {7020for ( var i=0, ien=context.length ; i<ien ; i++ ) {7021ctxSettings( context[i] );7022}7023}7024else {7025ctxSettings( context );7026}7027
7028// Remove duplicates7029this.context = _unique( settings );7030
7031// Initial data7032if ( data ) {7033$.merge( this, data );7034}7035
7036// selector7037this.selector = {7038rows: null,7039cols: null,7040opts: null7041};7042
7043_Api.extend( this, this, __apiStruct );7044};7045
7046DataTable.Api = _Api;7047
7048// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
7049// isPlainObject.
7050$.extend( _Api.prototype, {7051any: function ()7052{7053return this.count() !== 0;7054},7055
7056
7057concat: __arrayProto.concat,7058
7059
7060context: [], // array of table settings objects7061
7062
7063count: function ()7064{7065return this.flatten().length;7066},7067
7068
7069each: function ( fn )7070{7071for ( var i=0, ien=this.length ; i<ien; i++ ) {7072fn.call( this, this[i], i, this );7073}7074
7075return this;7076},7077
7078
7079eq: function ( idx )7080{7081var ctx = this.context;7082
7083return ctx.length > idx ?7084new _Api( ctx[idx], this[idx] ) :7085null;7086},7087
7088
7089filter: function ( fn )7090{7091var a = [];7092
7093if ( __arrayProto.filter ) {7094a = __arrayProto.filter.call( this, fn, this );7095}7096else {7097// Compatibility for browsers without EMCA-252-5 (JS 1.6)7098for ( var i=0, ien=this.length ; i<ien ; i++ ) {7099if ( fn.call( this, this[i], i, this ) ) {7100a.push( this[i] );7101}7102}7103}7104
7105return new _Api( this.context, a );7106},7107
7108
7109flatten: function ()7110{7111var a = [];7112return new _Api( this.context, a.concat.apply( a, this.toArray() ) );7113},7114
7115
7116join: __arrayProto.join,7117
7118
7119indexOf: __arrayProto.indexOf || function (obj, start)7120{7121for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {7122if ( this[i] === obj ) {7123return i;7124}7125}7126return -1;7127},7128
7129iterator: function ( flatten, type, fn, alwaysNew ) {7130var7131a = [], ret,7132i, ien, j, jen,7133context = this.context,7134rows, items, item,7135selector = this.selector;7136
7137// Argument shifting7138if ( typeof flatten === 'string' ) {7139alwaysNew = fn;7140fn = type;7141type = flatten;7142flatten = false;7143}7144
7145for ( i=0, ien=context.length ; i<ien ; i++ ) {7146var apiInst = new _Api( context[i] );7147
7148if ( type === 'table' ) {7149ret = fn.call( apiInst, context[i], i );7150
7151if ( ret !== undefined ) {7152a.push( ret );7153}7154}7155else if ( type === 'columns' || type === 'rows' ) {7156// this has same length as context - one entry for each table7157ret = fn.call( apiInst, context[i], this[i], i );7158
7159if ( ret !== undefined ) {7160a.push( ret );7161}7162}7163else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {7164// columns and rows share the same structure.7165// 'this' is an array of column indexes for each context7166items = this[i];7167
7168if ( type === 'column-rows' ) {7169rows = _selector_row_indexes( context[i], selector.opts );7170}7171
7172for ( j=0, jen=items.length ; j<jen ; j++ ) {7173item = items[j];7174
7175if ( type === 'cell' ) {7176ret = fn.call( apiInst, context[i], item.row, item.column, i, j );7177}7178else {7179ret = fn.call( apiInst, context[i], item, i, j, rows );7180}7181
7182if ( ret !== undefined ) {7183a.push( ret );7184}7185}7186}7187}7188
7189if ( a.length || alwaysNew ) {7190var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );7191var apiSelector = api.selector;7192apiSelector.rows = selector.rows;7193apiSelector.cols = selector.cols;7194apiSelector.opts = selector.opts;7195return api;7196}7197return this;7198},7199
7200
7201lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)7202{7203// Bit cheeky...7204return this.indexOf.apply( this.toArray.reverse(), arguments );7205},7206
7207
7208length: 0,7209
7210
7211map: function ( fn )7212{7213var a = [];7214
7215if ( __arrayProto.map ) {7216a = __arrayProto.map.call( this, fn, this );7217}7218else {7219// Compatibility for browsers without EMCA-252-5 (JS 1.6)7220for ( var i=0, ien=this.length ; i<ien ; i++ ) {7221a.push( fn.call( this, this[i], i ) );7222}7223}7224
7225return new _Api( this.context, a );7226},7227
7228
7229pluck: function ( prop )7230{7231var fn = DataTable.util.get(prop);7232
7233return this.map( function ( el ) {7234return fn(el);7235} );7236},7237
7238pop: __arrayProto.pop,7239
7240
7241push: __arrayProto.push,7242
7243
7244// Does not return an API instance7245reduce: __arrayProto.reduce || function ( fn, init )7246{7247return _fnReduce( this, fn, init, 0, this.length, 1 );7248},7249
7250
7251reduceRight: __arrayProto.reduceRight || function ( fn, init )7252{7253return _fnReduce( this, fn, init, this.length-1, -1, -1 );7254},7255
7256
7257reverse: __arrayProto.reverse,7258
7259
7260// Object with rows, columns and opts7261selector: null,7262
7263
7264shift: __arrayProto.shift,7265
7266
7267slice: function () {7268return new _Api( this.context, this );7269},7270
7271
7272sort: __arrayProto.sort, // ? name - order?7273
7274
7275splice: __arrayProto.splice,7276
7277
7278toArray: function ()7279{7280return __arrayProto.slice.call( this );7281},7282
7283
7284to$: function ()7285{7286return $( this );7287},7288
7289
7290toJQuery: function ()7291{7292return $( this );7293},7294
7295
7296unique: function ()7297{7298return new _Api( this.context, _unique(this) );7299},7300
7301
7302unshift: __arrayProto.unshift7303} );7304
7305
7306_Api.extend = function ( scope, obj, ext )7307{
7308// Only extend API instances and static properties of the API7309if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {7310return;7311}7312
7313var7314i, ien,7315struct,7316methodScoping = function ( scope, fn, struc ) {7317return function () {7318var ret = fn.apply( scope, arguments );7319
7320// Method extension7321_Api.extend( ret, ret, struc.methodExt );7322return ret;7323};7324};7325
7326for ( i=0, ien=ext.length ; i<ien ; i++ ) {7327struct = ext[i];7328
7329// Value7330obj[ struct.name ] = struct.type === 'function' ?7331methodScoping( scope, struct.val, struct ) :7332struct.type === 'object' ?7333{} :7334struct.val;7335
7336obj[ struct.name ].__dt_wrapper = true;7337
7338// Property extension7339_Api.extend( scope, obj[ struct.name ], struct.propExt );7340}7341};7342
7343
7344// @todo - Is there need for an augment function?
7345// _Api.augment = function ( inst, name )
7346// {
7347// // Find src object in the structure from the name
7348// var parts = name.split('.');
7349
7350// _Api.extend( inst, obj );
7351// };
7352
7353
7354// [
7355// {
7356// name: 'data' -- string - Property name
7357// val: function () {}, -- function - Api method (or undefined if just an object
7358// methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
7359// propExt: [ ... ] -- array - Array of Api object definitions to extend the property
7360// },
7361// {
7362// name: 'row'
7363// val: {},
7364// methodExt: [ ... ],
7365// propExt: [
7366// {
7367// name: 'data'
7368// val: function () {},
7369// methodExt: [ ... ],
7370// propExt: [ ... ]
7371// },
7372// ...
7373// ]
7374// }
7375// ]
7376
7377_Api.register = _api_register = function ( name, val )7378{
7379if ( Array.isArray( name ) ) {7380for ( var j=0, jen=name.length ; j<jen ; j++ ) {7381_Api.register( name[j], val );7382}7383return;7384}7385
7386var7387i, ien,7388heir = name.split('.'),7389struct = __apiStruct,7390key, method;7391
7392var find = function ( src, name ) {7393for ( var i=0, ien=src.length ; i<ien ; i++ ) {7394if ( src[i].name === name ) {7395return src[i];7396}7397}7398return null;7399};7400
7401for ( i=0, ien=heir.length ; i<ien ; i++ ) {7402method = heir[i].indexOf('()') !== -1;7403key = method ?7404heir[i].replace('()', '') :7405heir[i];7406
7407var src = find( struct, key );7408if ( ! src ) {7409src = {7410name: key,7411val: {},7412methodExt: [],7413propExt: [],7414type: 'object'7415};7416struct.push( src );7417}7418
7419if ( i === ien-1 ) {7420src.val = val;7421src.type = typeof val === 'function' ?7422'function' :7423$.isPlainObject( val ) ?7424'object' :7425'other';7426}7427else {7428struct = method ?7429src.methodExt :7430src.propExt;7431}7432}7433};7434
7435_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {7436_Api.register( pluralName, val );7437
7438_Api.register( singularName, function () {7439var ret = val.apply( this, arguments );7440
7441if ( ret === this ) {7442// Returned item is the API instance that was passed in, return it7443return this;7444}7445else if ( ret instanceof _Api ) {7446// New API instance returned, want the value from the first item7447// in the returned array for the singular result.7448return ret.length ?7449Array.isArray( ret[0] ) ?7450new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'7451ret[0] :7452undefined;7453}7454
7455// Non-API return - just fire it back7456return ret;7457} );7458};7459
7460
7461/**
7462* Selector for HTML tables. Apply the given selector to the give array of
7463* DataTables settings objects.
7464*
7465* @param {string|integer} [selector] jQuery selector string or integer
7466* @param {array} Array of DataTables settings objects to be filtered
7467* @return {array}
7468* @ignore
7469*/
7470var __table_selector = function ( selector, a )7471{
7472if ( Array.isArray(selector) ) {7473return $.map( selector, function (item) {7474return __table_selector(item, a);7475} );7476}7477
7478// Integer is used to pick out a table by index7479if ( typeof selector === 'number' ) {7480return [ a[ selector ] ];7481}7482
7483// Perform a jQuery selector on the table nodes7484var nodes = $.map( a, function (el, i) {7485return el.nTable;7486} );7487
7488return $(nodes)7489.filter( selector )7490.map( function (i) {7491// Need to translate back from the table node to the settings7492var idx = $.inArray( this, nodes );7493return a[ idx ];7494} )7495.toArray();7496};7497
7498
7499
7500/**
7501* Context selector for the API's context (i.e. the tables the API instance
7502* refers to.
7503*
7504* @name DataTable.Api#tables
7505* @param {string|integer} [selector] Selector to pick which tables the iterator
7506* should operate on. If not given, all tables in the current context are
7507* used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7508* select multiple tables or as an integer to select a single table.
7509* @returns {DataTable.Api} Returns a new API instance if a selector is given.
7510*/
7511_api_register( 'tables()', function ( selector ) {7512// A new instance is created if there was a selector specified7513return selector !== undefined && selector !== null ?7514new _Api( __table_selector( selector, this.context ) ) :7515this;7516} );7517
7518
7519_api_register( 'table()', function ( selector ) {7520var tables = this.tables( selector );7521var ctx = tables.context;7522
7523// Truncate to the first matched table7524return ctx.length ?7525new _Api( ctx[0] ) :7526tables;7527} );7528
7529
7530_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {7531return this.iterator( 'table', function ( ctx ) {7532return ctx.nTable;7533}, 1 );7534} );7535
7536
7537_api_registerPlural( 'tables().body()', 'table().body()' , function () {7538return this.iterator( 'table', function ( ctx ) {7539return ctx.nTBody;7540}, 1 );7541} );7542
7543
7544_api_registerPlural( 'tables().header()', 'table().header()' , function () {7545return this.iterator( 'table', function ( ctx ) {7546return ctx.nTHead;7547}, 1 );7548} );7549
7550
7551_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {7552return this.iterator( 'table', function ( ctx ) {7553return ctx.nTFoot;7554}, 1 );7555} );7556
7557
7558_api_registerPlural( 'tables().containers()', 'table().container()' , function () {7559return this.iterator( 'table', function ( ctx ) {7560return ctx.nTableWrapper;7561}, 1 );7562} );7563
7564
7565
7566/**
7567* Redraw the tables in the current context.
7568*/
7569_api_register( 'draw()', function ( paging ) {7570return this.iterator( 'table', function ( settings ) {7571if ( paging === 'page' ) {7572_fnDraw( settings );7573}7574else {7575if ( typeof paging === 'string' ) {7576paging = paging === 'full-hold' ?7577false :7578true;7579}7580
7581_fnReDraw( settings, paging===false );7582}7583} );7584} );7585
7586
7587
7588/**
7589* Get the current page index.
7590*
7591* @return {integer} Current page index (zero based)
7592*//**7593* Set the current page.7594*7595* Note that if you attempt to show a page which does not exist, DataTables will7596* not throw an error, but rather reset the paging.7597*7598* @param {integer|string} action The paging action to take. This can be one of:7599* * `integer` - The page index to jump to7600* * `string` - An action to take:7601* * `first` - Jump to first page.7602* * `next` - Jump to the next page7603* * `previous` - Jump to previous page7604* * `last` - Jump to the last page.7605* @returns {DataTables.Api} this7606*/7607_api_register( 'page()', function ( action ) {7608if ( action === undefined ) {7609return this.page.info().page; // not an expensive call7610}7611
7612// else, have an action to take on all tables7613return this.iterator( 'table', function ( settings ) {7614_fnPageChange( settings, action );7615} );7616} );7617
7618
7619/**
7620* Paging information for the first table in the current context.
7621*
7622* If you require paging information for another table, use the `table()` method
7623* with a suitable selector.
7624*
7625* @return {object} Object with the following properties set:
7626* * `page` - Current page index (zero based - i.e. the first page is `0`)
7627* * `pages` - Total number of pages
7628* * `start` - Display index for the first record shown on the current page
7629* * `end` - Display index for the last record shown on the current page
7630* * `length` - Display length (number of records). Note that generally `start
7631* + length = end`, but this is not always true, for example if there are
7632* only 2 records to show on the final page, with a length of 10.
7633* * `recordsTotal` - Full data set length
7634* * `recordsDisplay` - Data set length once the current filtering criterion
7635* are applied.
7636*/
7637_api_register( 'page.info()', function ( action ) {7638if ( this.context.length === 0 ) {7639return undefined;7640}7641
7642var7643settings = this.context[0],7644start = settings._iDisplayStart,7645len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,7646visRecords = settings.fnRecordsDisplay(),7647all = len === -1;7648
7649return {7650"page": all ? 0 : Math.floor( start / len ),7651"pages": all ? 1 : Math.ceil( visRecords / len ),7652"start": start,7653"end": settings.fnDisplayEnd(),7654"length": len,7655"recordsTotal": settings.fnRecordsTotal(),7656"recordsDisplay": visRecords,7657"serverSide": _fnDataSource( settings ) === 'ssp'7658};7659} );7660
7661
7662/**
7663* Get the current page length.
7664*
7665* @return {integer} Current page length. Note `-1` indicates that all records
7666* are to be shown.
7667*//**7668* Set the current page length.7669*7670* @param {integer} Page length to set. Use `-1` to show all records.7671* @returns {DataTables.Api} this7672*/7673_api_register( 'page.len()', function ( len ) {7674// Note that we can't call this function 'length()' because `length`7675// is a Javascript property of functions which defines how many arguments7676// the function expects.7677if ( len === undefined ) {7678return this.context.length !== 0 ?7679this.context[0]._iDisplayLength :7680undefined;7681}7682
7683// else, set the page length7684return this.iterator( 'table', function ( settings ) {7685_fnLengthChange( settings, len );7686} );7687} );7688
7689
7690
7691var __reload = function ( settings, holdPosition, callback ) {7692// Use the draw event to trigger a callback7693if ( callback ) {7694var api = new _Api( settings );7695
7696api.one( 'draw', function () {7697callback( api.ajax.json() );7698} );7699}7700
7701if ( _fnDataSource( settings ) == 'ssp' ) {7702_fnReDraw( settings, holdPosition );7703}7704else {7705_fnProcessingDisplay( settings, true );7706
7707// Cancel an existing request7708var xhr = settings.jqXHR;7709if ( xhr && xhr.readyState !== 4 ) {7710xhr.abort();7711}7712
7713// Trigger xhr7714_fnBuildAjax( settings, [], function( json ) {7715_fnClearTable( settings );7716
7717var data = _fnAjaxDataSrc( settings, json );7718for ( var i=0, ien=data.length ; i<ien ; i++ ) {7719_fnAddData( settings, data[i] );7720}7721
7722_fnReDraw( settings, holdPosition );7723_fnProcessingDisplay( settings, false );7724} );7725}7726};7727
7728
7729/**
7730* Get the JSON response from the last Ajax request that DataTables made to the
7731* server. Note that this returns the JSON from the first table in the current
7732* context.
7733*
7734* @return {object} JSON received from the server.
7735*/
7736_api_register( 'ajax.json()', function () {7737var ctx = this.context;7738
7739if ( ctx.length > 0 ) {7740return ctx[0].json;7741}7742
7743// else return undefined;7744} );7745
7746
7747/**
7748* Get the data submitted in the last Ajax request
7749*/
7750_api_register( 'ajax.params()', function () {7751var ctx = this.context;7752
7753if ( ctx.length > 0 ) {7754return ctx[0].oAjaxData;7755}7756
7757// else return undefined;7758} );7759
7760
7761/**
7762* Reload tables from the Ajax data source. Note that this function will
7763* automatically re-draw the table when the remote data has been loaded.
7764*
7765* @param {boolean} [reset=true] Reset (default) or hold the current paging
7766* position. A full re-sort and re-filter is performed when this method is
7767* called, which is why the pagination reset is the default action.
7768* @returns {DataTables.Api} this
7769*/
7770_api_register( 'ajax.reload()', function ( callback, resetPaging ) {7771return this.iterator( 'table', function (settings) {7772__reload( settings, resetPaging===false, callback );7773} );7774} );7775
7776
7777/**
7778* Get the current Ajax URL. Note that this returns the URL from the first
7779* table in the current context.
7780*
7781* @return {string} Current Ajax source URL
7782*//**7783* Set the Ajax URL. Note that this will set the URL for all tables in the7784* current context.7785*7786* @param {string} url URL to set.7787* @returns {DataTables.Api} this7788*/7789_api_register( 'ajax.url()', function ( url ) {7790var ctx = this.context;7791
7792if ( url === undefined ) {7793// get7794if ( ctx.length === 0 ) {7795return undefined;7796}7797ctx = ctx[0];7798
7799return ctx.ajax ?7800$.isPlainObject( ctx.ajax ) ?7801ctx.ajax.url :7802ctx.ajax :7803ctx.sAjaxSource;7804}7805
7806// set7807return this.iterator( 'table', function ( settings ) {7808if ( $.isPlainObject( settings.ajax ) ) {7809settings.ajax.url = url;7810}7811else {7812settings.ajax = url;7813}7814// No need to consider sAjaxSource here since DataTables gives priority7815// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any7816// value of `sAjaxSource` redundant.7817} );7818} );7819
7820
7821/**
7822* Load data from the newly set Ajax URL. Note that this method is only
7823* available when `ajax.url()` is used to set a URL. Additionally, this method
7824* has the same effect as calling `ajax.reload()` but is provided for
7825* convenience when setting a new URL. Like `ajax.reload()` it will
7826* automatically redraw the table once the remote data has been loaded.
7827*
7828* @returns {DataTables.Api} this
7829*/
7830_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {7831// Same as a reload, but makes sense to present it for easy access after a7832// url change7833return this.iterator( 'table', function ( ctx ) {7834__reload( ctx, resetPaging===false, callback );7835} );7836} );7837
7838
7839
7840
7841var _selector_run = function ( type, selector, selectFn, settings, opts )7842{
7843var7844out = [], res,7845a, i, ien, j, jen,7846selectorType = typeof selector;7847
7848// Can't just check for isArray here, as an API or jQuery instance might be7849// given with their array like look7850if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {7851selector = [ selector ];7852}7853
7854for ( i=0, ien=selector.length ; i<ien ; i++ ) {7855// Only split on simple strings - complex expressions will be jQuery selectors7856a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?7857selector[i].split(',') :7858[ selector[i] ];7859
7860for ( j=0, jen=a.length ; j<jen ; j++ ) {7861res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );7862
7863if ( res && res.length ) {7864out = out.concat( res );7865}7866}7867}7868
7869// selector extensions7870var ext = _ext.selector[ type ];7871if ( ext.length ) {7872for ( i=0, ien=ext.length ; i<ien ; i++ ) {7873out = ext[i]( settings, opts, out );7874}7875}7876
7877return _unique( out );7878};7879
7880
7881var _selector_opts = function ( opts )7882{
7883if ( ! opts ) {7884opts = {};7885}7886
7887// Backwards compatibility for 1.9- which used the terminology filter rather7888// than search7889if ( opts.filter && opts.search === undefined ) {7890opts.search = opts.filter;7891}7892
7893return $.extend( {7894search: 'none',7895order: 'current',7896page: 'all'7897}, opts );7898};7899
7900
7901var _selector_first = function ( inst )7902{
7903// Reduce the API instance to the first item found7904for ( var i=0, ien=inst.length ; i<ien ; i++ ) {7905if ( inst[i].length > 0 ) {7906// Assign the first element to the first item in the instance7907// and truncate the instance and context7908inst[0] = inst[i];7909inst[0].length = 1;7910inst.length = 1;7911inst.context = [ inst.context[i] ];7912
7913return inst;7914}7915}7916
7917// Not found - return an empty instance7918inst.length = 0;7919return inst;7920};7921
7922
7923var _selector_row_indexes = function ( settings, opts )7924{
7925var7926i, ien, tmp, a=[],7927displayFiltered = settings.aiDisplay,7928displayMaster = settings.aiDisplayMaster;7929
7930var7931search = opts.search, // none, applied, removed7932order = opts.order, // applied, current, index (original - compatibility with 1.9)7933page = opts.page; // all, current7934
7935if ( _fnDataSource( settings ) == 'ssp' ) {7936// In server-side processing mode, most options are irrelevant since7937// rows not shown don't exist and the index order is the applied order7938// Removed is a special case - for consistency just return an empty7939// array7940return search === 'removed' ?7941[] :7942_range( 0, displayMaster.length );7943}7944else if ( page == 'current' ) {7945// Current page implies that order=current and filter=applied, since it is7946// fairly senseless otherwise, regardless of what order and search actually7947// are7948for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {7949a.push( displayFiltered[i] );7950}7951}7952else if ( order == 'current' || order == 'applied' ) {7953if ( search == 'none') {7954a = displayMaster.slice();7955}7956else if ( search == 'applied' ) {7957a = displayFiltered.slice();7958}7959else if ( search == 'removed' ) {7960// O(n+m) solution by creating a hash map7961var displayFilteredMap = {};7962
7963for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {7964displayFilteredMap[displayFiltered[i]] = null;7965}7966
7967a = $.map( displayMaster, function (el) {7968return ! displayFilteredMap.hasOwnProperty(el) ?7969el :7970null;7971} );7972}7973}7974else if ( order == 'index' || order == 'original' ) {7975for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {7976if ( search == 'none' ) {7977a.push( i );7978}7979else { // applied | removed7980tmp = $.inArray( i, displayFiltered );7981
7982if ((tmp === -1 && search == 'removed') ||7983(tmp >= 0 && search == 'applied') )7984{7985a.push( i );7986}7987}7988}7989}7990
7991return a;7992};7993
7994
7995/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7996* Rows
7997*
7998* {} - no selector - use all available rows
7999* {integer} - row aoData index
8000* {node} - TR node
8001* {string} - jQuery selector to apply to the TR elements
8002* {array} - jQuery array of nodes, or simply an array of TR nodes
8003*
8004*/
8005var __row_selector = function ( settings, selector, opts )8006{
8007var rows;8008var run = function ( sel ) {8009var selInt = _intVal( sel );8010var i, ien;8011var aoData = settings.aoData;8012
8013// Short cut - selector is a number and no options provided (default is8014// all records, so no need to check if the index is in there, since it8015// must be - dev error if the index doesn't exist).8016if ( selInt !== null && ! opts ) {8017return [ selInt ];8018}8019
8020if ( ! rows ) {8021rows = _selector_row_indexes( settings, opts );8022}8023
8024if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {8025// Selector - integer8026return [ selInt ];8027}8028else if ( sel === null || sel === undefined || sel === '' ) {8029// Selector - none8030return rows;8031}8032
8033// Selector - function8034if ( typeof sel === 'function' ) {8035return $.map( rows, function (idx) {8036var row = aoData[ idx ];8037return sel( idx, row._aData, row.nTr ) ? idx : null;8038} );8039}8040
8041// Selector - node8042if ( sel.nodeName ) {8043var rowIdx = sel._DT_RowIndex; // Property added by DT for fast lookup8044var cellIdx = sel._DT_CellIndex;8045
8046if ( rowIdx !== undefined ) {8047// Make sure that the row is actually still present in the table8048return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?8049[ rowIdx ] :8050[];8051}8052else if ( cellIdx ) {8053return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?8054[ cellIdx.row ] :8055[];8056}8057else {8058var host = $(sel).closest('*[data-dt-row]');8059return host.length ?8060[ host.data('dt-row') ] :8061[];8062}8063}8064
8065// ID selector. Want to always be able to select rows by id, regardless8066// of if the tr element has been created or not, so can't rely upon8067// jQuery here - hence a custom implementation. This does not match8068// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,8069// but to select it using a CSS selector engine (like Sizzle or8070// querySelect) it would need to need to be escaped for some characters.8071// DataTables simplifies this for row selectors since you can select8072// only a row. A # indicates an id any anything that follows is the id -8073// unescaped.8074if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {8075// get row index from id8076var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];8077if ( rowObj !== undefined ) {8078return [ rowObj.idx ];8079}8080
8081// need to fall through to jQuery in case there is DOM id that8082// matches8083}8084
8085// Get nodes in the order from the `rows` array with null values removed8086var nodes = _removeEmpty(8087_pluck_order( settings.aoData, rows, 'nTr' )8088);8089
8090// Selector - jQuery selector string, array of nodes or jQuery object/8091// As jQuery's .filter() allows jQuery objects to be passed in filter,8092// it also allows arrays, so this will cope with all three options8093return $(nodes)8094.filter( sel )8095.map( function () {8096return this._DT_RowIndex;8097} )8098.toArray();8099};8100
8101return _selector_run( 'row', selector, run, settings, opts );8102};8103
8104
8105_api_register( 'rows()', function ( selector, opts ) {8106// argument shifting8107if ( selector === undefined ) {8108selector = '';8109}8110else if ( $.isPlainObject( selector ) ) {8111opts = selector;8112selector = '';8113}8114
8115opts = _selector_opts( opts );8116
8117var inst = this.iterator( 'table', function ( settings ) {8118return __row_selector( settings, selector, opts );8119}, 1 );8120
8121// Want argument shifting here and in __row_selector?8122inst.selector.rows = selector;8123inst.selector.opts = opts;8124
8125return inst;8126} );8127
8128_api_register( 'rows().nodes()', function () {8129return this.iterator( 'row', function ( settings, row ) {8130return settings.aoData[ row ].nTr || undefined;8131}, 1 );8132} );8133
8134_api_register( 'rows().data()', function () {8135return this.iterator( true, 'rows', function ( settings, rows ) {8136return _pluck_order( settings.aoData, rows, '_aData' );8137}, 1 );8138} );8139
8140_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {8141return this.iterator( 'row', function ( settings, row ) {8142var r = settings.aoData[ row ];8143return type === 'search' ? r._aFilterData : r._aSortData;8144}, 1 );8145} );8146
8147_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {8148return this.iterator( 'row', function ( settings, row ) {8149_fnInvalidate( settings, row, src );8150} );8151} );8152
8153_api_registerPlural( 'rows().indexes()', 'row().index()', function () {8154return this.iterator( 'row', function ( settings, row ) {8155return row;8156}, 1 );8157} );8158
8159_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {8160var a = [];8161var context = this.context;8162
8163// `iterator` will drop undefined values, but in this case we want them8164for ( var i=0, ien=context.length ; i<ien ; i++ ) {8165for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {8166var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );8167a.push( (hash === true ? '#' : '' )+ id );8168}8169}8170
8171return new _Api( context, a );8172} );8173
8174_api_registerPlural( 'rows().remove()', 'row().remove()', function () {8175var that = this;8176
8177this.iterator( 'row', function ( settings, row, thatIdx ) {8178var data = settings.aoData;8179var rowData = data[ row ];8180var i, ien, j, jen;8181var loopRow, loopCells;8182
8183data.splice( row, 1 );8184
8185// Update the cached indexes8186for ( i=0, ien=data.length ; i<ien ; i++ ) {8187loopRow = data[i];8188loopCells = loopRow.anCells;8189
8190// Rows8191if ( loopRow.nTr !== null ) {8192loopRow.nTr._DT_RowIndex = i;8193}8194
8195// Cells8196if ( loopCells !== null ) {8197for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {8198loopCells[j]._DT_CellIndex.row = i;8199}8200}8201}8202
8203// Delete from the display arrays8204_fnDeleteIndex( settings.aiDisplayMaster, row );8205_fnDeleteIndex( settings.aiDisplay, row );8206_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes8207
8208// For server-side processing tables - subtract the deleted row from the count8209if ( settings._iRecordsDisplay > 0 ) {8210settings._iRecordsDisplay--;8211}8212
8213// Check for an 'overflow' they case for displaying the table8214_fnLengthOverflow( settings );8215
8216// Remove the row's ID reference if there is one8217var id = settings.rowIdFn( rowData._aData );8218if ( id !== undefined ) {8219delete settings.aIds[ id ];8220}8221} );8222
8223this.iterator( 'table', function ( settings ) {8224for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {8225settings.aoData[i].idx = i;8226}8227} );8228
8229return this;8230} );8231
8232
8233_api_register( 'rows.add()', function ( rows ) {8234var newRows = this.iterator( 'table', function ( settings ) {8235var row, i, ien;8236var out = [];8237
8238for ( i=0, ien=rows.length ; i<ien ; i++ ) {8239row = rows[i];8240
8241if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {8242out.push( _fnAddTr( settings, row )[0] );8243}8244else {8245out.push( _fnAddData( settings, row ) );8246}8247}8248
8249return out;8250}, 1 );8251
8252// Return an Api.rows() extended instance, so rows().nodes() etc can be used8253var modRows = this.rows( -1 );8254modRows.pop();8255$.merge( modRows, newRows );8256
8257return modRows;8258} );8259
8260
8261
8262
8263
8264/**
8265*
8266*/
8267_api_register( 'row()', function ( selector, opts ) {8268return _selector_first( this.rows( selector, opts ) );8269} );8270
8271
8272_api_register( 'row().data()', function ( data ) {8273var ctx = this.context;8274
8275if ( data === undefined ) {8276// Get8277return ctx.length && this.length ?8278ctx[0].aoData[ this[0] ]._aData :8279undefined;8280}8281
8282// Set8283var row = ctx[0].aoData[ this[0] ];8284row._aData = data;8285
8286// If the DOM has an id, and the data source is an array8287if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {8288_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );8289}8290
8291// Automatically invalidate8292_fnInvalidate( ctx[0], this[0], 'data' );8293
8294return this;8295} );8296
8297
8298_api_register( 'row().node()', function () {8299var ctx = this.context;8300
8301return ctx.length && this.length ?8302ctx[0].aoData[ this[0] ].nTr || null :8303null;8304} );8305
8306
8307_api_register( 'row.add()', function ( row ) {8308// Allow a jQuery object to be passed in - only a single row is added from8309// it though - the first element in the set8310if ( row instanceof $ && row.length ) {8311row = row[0];8312}8313
8314var rows = this.iterator( 'table', function ( settings ) {8315if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {8316return _fnAddTr( settings, row )[0];8317}8318return _fnAddData( settings, row );8319} );8320
8321// Return an Api.rows() extended instance, with the newly added row selected8322return this.row( rows[0] );8323} );8324
8325
8326$(document).on('plugin-init.dt', function (e, context) {8327var api = new _Api( context );8328var namespace = 'on-plugin-init';8329var stateSaveParamsEvent = 'stateSaveParams.' + namespace;8330var destroyEvent = 'destroy. ' + namespace;8331
8332api.on( stateSaveParamsEvent, function ( e, settings, d ) {8333// This could be more compact with the API, but it is a lot faster as a simple8334// internal loop8335var idFn = settings.rowIdFn;8336var data = settings.aoData;8337var ids = [];8338
8339for (var i=0 ; i<data.length ; i++) {8340if (data[i]._detailsShow) {8341ids.push( '#' + idFn(data[i]._aData) );8342}8343}8344
8345d.childRows = ids;8346});8347
8348api.on( destroyEvent, function () {8349api.off(stateSaveParamsEvent + ' ' + destroyEvent);8350});8351
8352var loaded = api.state.loaded();8353
8354if ( loaded && loaded.childRows ) {8355api
8356.rows( $.map(loaded.childRows, function (id){8357return id.replace(/:/g, '\\:')8358}) )8359.every( function () {8360_fnCallbackFire( context, null, 'requestChild', [ this ] )8361});8362}8363});8364
8365var __details_add = function ( ctx, row, data, klass )8366{
8367// Convert to array of TR elements8368var rows = [];8369var addRow = function ( r, k ) {8370// Recursion to allow for arrays of jQuery objects8371if ( Array.isArray( r ) || r instanceof $ ) {8372for ( var i=0, ien=r.length ; i<ien ; i++ ) {8373addRow( r[i], k );8374}8375return;8376}8377
8378// If we get a TR element, then just add it directly - up to the dev8379// to add the correct number of columns etc8380if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {8381rows.push( r );8382}8383else {8384// Otherwise create a row with a wrapper8385var created = $('<tr><td></td></tr>').addClass( k );8386$('td', created)8387.addClass( k )8388.html( r )8389[0].colSpan = _fnVisbleColumns( ctx );8390
8391rows.push( created[0] );8392}8393};8394
8395addRow( data, klass );8396
8397if ( row._details ) {8398row._details.detach();8399}8400
8401row._details = $(rows);8402
8403// If the children were already shown, that state should be retained8404if ( row._detailsShow ) {8405row._details.insertAfter( row.nTr );8406}8407};8408
8409
8410// Make state saving of child row details async to allow them to be batch processed
8411var __details_state = DataTable.util.throttle(8412function (ctx) {8413_fnSaveState( ctx[0] )8414},84155008416);8417
8418
8419var __details_remove = function ( api, idx )8420{
8421var ctx = api.context;8422
8423if ( ctx.length ) {8424var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];8425
8426if ( row && row._details ) {8427row._details.remove();8428
8429row._detailsShow = undefined;8430row._details = undefined;8431$( row.nTr ).removeClass( 'dt-hasChild' );8432__details_state( ctx );8433}8434}8435};8436
8437
8438var __details_display = function ( api, show ) {8439var ctx = api.context;8440
8441if ( ctx.length && api.length ) {8442var row = ctx[0].aoData[ api[0] ];8443
8444if ( row._details ) {8445row._detailsShow = show;8446
8447if ( show ) {8448row._details.insertAfter( row.nTr );8449$( row.nTr ).addClass( 'dt-hasChild' );8450}8451else {8452row._details.detach();8453$( row.nTr ).removeClass( 'dt-hasChild' );8454}8455
8456_fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )8457
8458__details_events( ctx[0] );8459__details_state( ctx );8460}8461}8462};8463
8464
8465var __details_events = function ( settings )8466{
8467var api = new _Api( settings );8468var namespace = '.dt.DT_details';8469var drawEvent = 'draw'+namespace;8470var colvisEvent = 'column-sizing'+namespace;8471var destroyEvent = 'destroy'+namespace;8472var data = settings.aoData;8473
8474api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );8475
8476if ( _pluck( data, '_details' ).length > 0 ) {8477// On each draw, insert the required elements into the document8478api.on( drawEvent, function ( e, ctx ) {8479if ( settings !== ctx ) {8480return;8481}8482
8483api.rows( {page:'current'} ).eq(0).each( function (idx) {8484// Internal data grab8485var row = data[ idx ];8486
8487if ( row._detailsShow ) {8488row._details.insertAfter( row.nTr );8489}8490} );8491} );8492
8493// Column visibility change - update the colspan8494api.on( colvisEvent, function ( e, ctx, idx, vis ) {8495if ( settings !== ctx ) {8496return;8497}8498
8499// Update the colspan for the details rows (note, only if it already has8500// a colspan)8501var row, visible = _fnVisbleColumns( ctx );8502
8503for ( var i=0, ien=data.length ; i<ien ; i++ ) {8504row = data[i];8505
8506if ( row._details ) {8507row._details.children('td[colspan]').attr('colspan', visible );8508}8509}8510} );8511
8512// Table destroyed - nuke any child rows8513api.on( destroyEvent, function ( e, ctx ) {8514if ( settings !== ctx ) {8515return;8516}8517
8518for ( var i=0, ien=data.length ; i<ien ; i++ ) {8519if ( data[i]._details ) {8520__details_remove( api, i );8521}8522}8523} );8524}8525};8526
8527// Strings for the method names to help minification
8528var _emp = '';8529var _child_obj = _emp+'row().child';8530var _child_mth = _child_obj+'()';8531
8532// data can be:
8533// tr
8534// string
8535// jQuery or array of any of the above
8536_api_register( _child_mth, function ( data, klass ) {8537var ctx = this.context;8538
8539if ( data === undefined ) {8540// get8541return ctx.length && this.length ?8542ctx[0].aoData[ this[0] ]._details :8543undefined;8544}8545else if ( data === true ) {8546// show8547this.child.show();8548}8549else if ( data === false ) {8550// remove8551__details_remove( this );8552}8553else if ( ctx.length && this.length ) {8554// set8555__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );8556}8557
8558return this;8559} );8560
8561
8562_api_register( [8563_child_obj+'.show()',8564_child_mth+'.show()' // only when `child()` was called with parameters (without8565], function ( show ) { // it returns an object and this method is not executed)8566__details_display( this, true );8567return this;8568} );8569
8570
8571_api_register( [8572_child_obj+'.hide()',8573_child_mth+'.hide()' // only when `child()` was called with parameters (without8574], function () { // it returns an object and this method is not executed)8575__details_display( this, false );8576return this;8577} );8578
8579
8580_api_register( [8581_child_obj+'.remove()',8582_child_mth+'.remove()' // only when `child()` was called with parameters (without8583], function () { // it returns an object and this method is not executed)8584__details_remove( this );8585return this;8586} );8587
8588
8589_api_register( _child_obj+'.isShown()', function () {8590var ctx = this.context;8591
8592if ( ctx.length && this.length ) {8593// _detailsShown as false or undefined will fall through to return false8594return ctx[0].aoData[ this[0] ]._detailsShow || false;8595}8596return false;8597} );8598
8599
8600
8601/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8602* Columns
8603*
8604* {integer} - column index (>=0 count from left, <0 count from right)
8605* "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
8606* "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
8607* "{string}:name" - column name
8608* "{string}" - jQuery selector on column header nodes
8609*
8610*/
8611
8612// can be an array of these items, comma separated list, or an array of comma
8613// separated lists
8614
8615var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;8616
8617
8618// r1 and r2 are redundant - but it means that the parameters match for the
8619// iterator callback in columns().data()
8620var __columnData = function ( settings, column, r1, r2, rows ) {8621var a = [];8622for ( var row=0, ien=rows.length ; row<ien ; row++ ) {8623a.push( _fnGetCellData( settings, rows[row], column ) );8624}8625return a;8626};8627
8628
8629var __column_selector = function ( settings, selector, opts )8630{
8631var8632columns = settings.aoColumns,8633names = _pluck( columns, 'sName' ),8634nodes = _pluck( columns, 'nTh' );8635
8636var run = function ( s ) {8637var selInt = _intVal( s );8638
8639// Selector - all8640if ( s === '' ) {8641return _range( columns.length );8642}8643
8644// Selector - index8645if ( selInt !== null ) {8646return [ selInt >= 0 ?8647selInt : // Count from left8648columns.length + selInt // Count from right (+ because its a negative value)8649];8650}8651
8652// Selector = function8653if ( typeof s === 'function' ) {8654var rows = _selector_row_indexes( settings, opts );8655
8656return $.map( columns, function (col, idx) {8657return s(8658idx,8659__columnData( settings, idx, 0, 0, rows ),8660nodes[ idx ]8661) ? idx : null;8662} );8663}8664
8665// jQuery or string selector8666var match = typeof s === 'string' ?8667s.match( __re_column_selector ) :8668'';8669
8670if ( match ) {8671switch( match[2] ) {8672case 'visIdx':8673case 'visible':8674var idx = parseInt( match[1], 10 );8675// Visible index given, convert to column index8676if ( idx < 0 ) {8677// Counting from the right8678var visColumns = $.map( columns, function (col,i) {8679return col.bVisible ? i : null;8680} );8681return [ visColumns[ visColumns.length + idx ] ];8682}8683// Counting from the left8684return [ _fnVisibleToColumnIndex( settings, idx ) ];8685
8686case 'name':8687// match by name. `names` is column index complete and in order8688return $.map( names, function (name, i) {8689return name === match[1] ? i : null;8690} );8691
8692default:8693return [];8694}8695}8696
8697// Cell in the table body8698if ( s.nodeName && s._DT_CellIndex ) {8699return [ s._DT_CellIndex.column ];8700}8701
8702// jQuery selector on the TH elements for the columns8703var jqResult = $( nodes )8704.filter( s )8705.map( function () {8706return $.inArray( this, nodes ); // `nodes` is column index complete and in order8707} )8708.toArray();8709
8710if ( jqResult.length || ! s.nodeName ) {8711return jqResult;8712}8713
8714// Otherwise a node which might have a `dt-column` data attribute, or be8715// a child or such an element8716var host = $(s).closest('*[data-dt-column]');8717return host.length ?8718[ host.data('dt-column') ] :8719[];8720};8721
8722return _selector_run( 'column', selector, run, settings, opts );8723};8724
8725
8726var __setColumnVis = function ( settings, column, vis ) {8727var8728cols = settings.aoColumns,8729col = cols[ column ],8730data = settings.aoData,8731row, cells, i, ien, tr;8732
8733// Get8734if ( vis === undefined ) {8735return col.bVisible;8736}8737
8738// Set8739// No change8740if ( col.bVisible === vis ) {8741return;8742}8743
8744if ( vis ) {8745// Insert column8746// Need to decide if we should use appendChild or insertBefore8747var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );8748
8749for ( i=0, ien=data.length ; i<ien ; i++ ) {8750tr = data[i].nTr;8751cells = data[i].anCells;8752
8753if ( tr ) {8754// insertBefore can act like appendChild if 2nd arg is null8755tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );8756}8757}8758}8759else {8760// Remove column8761$( _pluck( settings.aoData, 'anCells', column ) ).detach();8762}8763
8764// Common actions8765col.bVisible = vis;8766};8767
8768
8769_api_register( 'columns()', function ( selector, opts ) {8770// argument shifting8771if ( selector === undefined ) {8772selector = '';8773}8774else if ( $.isPlainObject( selector ) ) {8775opts = selector;8776selector = '';8777}8778
8779opts = _selector_opts( opts );8780
8781var inst = this.iterator( 'table', function ( settings ) {8782return __column_selector( settings, selector, opts );8783}, 1 );8784
8785// Want argument shifting here and in _row_selector?8786inst.selector.cols = selector;8787inst.selector.opts = opts;8788
8789return inst;8790} );8791
8792_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {8793return this.iterator( 'column', function ( settings, column ) {8794return settings.aoColumns[column].nTh;8795}, 1 );8796} );8797
8798_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {8799return this.iterator( 'column', function ( settings, column ) {8800return settings.aoColumns[column].nTf;8801}, 1 );8802} );8803
8804_api_registerPlural( 'columns().data()', 'column().data()', function () {8805return this.iterator( 'column-rows', __columnData, 1 );8806} );8807
8808_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {8809return this.iterator( 'column', function ( settings, column ) {8810return settings.aoColumns[column].mData;8811}, 1 );8812} );8813
8814_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {8815return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {8816return _pluck_order( settings.aoData, rows,8817type === 'search' ? '_aFilterData' : '_aSortData', column8818);8819}, 1 );8820} );8821
8822_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {8823return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {8824return _pluck_order( settings.aoData, rows, 'anCells', column ) ;8825}, 1 );8826} );8827
8828_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {8829var that = this;8830var ret = this.iterator( 'column', function ( settings, column ) {8831if ( vis === undefined ) {8832return settings.aoColumns[ column ].bVisible;8833} // else8834__setColumnVis( settings, column, vis );8835} );8836
8837// Group the column visibility changes8838if ( vis !== undefined ) {8839this.iterator( 'table', function ( settings ) {8840// Redraw the header after changes8841_fnDrawHead( settings, settings.aoHeader );8842_fnDrawHead( settings, settings.aoFooter );8843
8844// Update colspan for no records display. Child rows and extensions will use their own8845// listeners to do this - only need to update the empty table item here8846if ( ! settings.aiDisplay.length ) {8847$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));8848}8849
8850_fnSaveState( settings );8851
8852// Second loop once the first is done for events8853that.iterator( 'column', function ( settings, column ) {8854_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );8855} );8856
8857if ( calc === undefined || calc ) {8858that.columns.adjust();8859}8860});8861}8862
8863return ret;8864} );8865
8866_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {8867return this.iterator( 'column', function ( settings, column ) {8868return type === 'visible' ?8869_fnColumnIndexToVisible( settings, column ) :8870column;8871}, 1 );8872} );8873
8874_api_register( 'columns.adjust()', function () {8875return this.iterator( 'table', function ( settings ) {8876_fnAdjustColumnSizing( settings );8877}, 1 );8878} );8879
8880_api_register( 'column.index()', function ( type, idx ) {8881if ( this.context.length !== 0 ) {8882var ctx = this.context[0];8883
8884if ( type === 'fromVisible' || type === 'toData' ) {8885return _fnVisibleToColumnIndex( ctx, idx );8886}8887else if ( type === 'fromData' || type === 'toVisible' ) {8888return _fnColumnIndexToVisible( ctx, idx );8889}8890}8891} );8892
8893_api_register( 'column()', function ( selector, opts ) {8894return _selector_first( this.columns( selector, opts ) );8895} );8896
8897var __cell_selector = function ( settings, selector, opts )8898{
8899var data = settings.aoData;8900var rows = _selector_row_indexes( settings, opts );8901var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );8902var allCells = $(_flatten( [], cells ));8903var row;8904var columns = settings.aoColumns.length;8905var a, i, ien, j, o, host;8906
8907var run = function ( s ) {8908var fnSelector = typeof s === 'function';8909
8910if ( s === null || s === undefined || fnSelector ) {8911// All cells and function selectors8912a = [];8913
8914for ( i=0, ien=rows.length ; i<ien ; i++ ) {8915row = rows[i];8916
8917for ( j=0 ; j<columns ; j++ ) {8918o = {8919row: row,8920column: j8921};8922
8923if ( fnSelector ) {8924// Selector - function8925host = data[ row ];8926
8927if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {8928a.push( o );8929}8930}8931else {8932// Selector - all8933a.push( o );8934}8935}8936}8937
8938return a;8939}8940
8941// Selector - index8942if ( $.isPlainObject( s ) ) {8943// Valid cell index and its in the array of selectable rows8944return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?8945[s] :8946[];8947}8948
8949// Selector - jQuery filtered cells8950var jqResult = allCells8951.filter( s )8952.map( function (i, el) {8953return { // use a new object, in case someone changes the values8954row: el._DT_CellIndex.row,8955column: el._DT_CellIndex.column8956};8957} )8958.toArray();8959
8960if ( jqResult.length || ! s.nodeName ) {8961return jqResult;8962}8963
8964// Otherwise the selector is a node, and there is one last option - the8965// element might be a child of an element which has dt-row and dt-column8966// data attributes8967host = $(s).closest('*[data-dt-row]');8968return host.length ?8969[ {8970row: host.data('dt-row'),8971column: host.data('dt-column')8972} ] :8973[];8974};8975
8976return _selector_run( 'cell', selector, run, settings, opts );8977};8978
8979
8980
8981
8982_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {8983// Argument shifting8984if ( $.isPlainObject( rowSelector ) ) {8985// Indexes8986if ( rowSelector.row === undefined ) {8987// Selector options in first parameter8988opts = rowSelector;8989rowSelector = null;8990}8991else {8992// Cell index objects in first parameter8993opts = columnSelector;8994columnSelector = null;8995}8996}8997if ( $.isPlainObject( columnSelector ) ) {8998opts = columnSelector;8999columnSelector = null;9000}9001
9002// Cell selector9003if ( columnSelector === null || columnSelector === undefined ) {9004return this.iterator( 'table', function ( settings ) {9005return __cell_selector( settings, rowSelector, _selector_opts( opts ) );9006} );9007}9008
9009// The default built in options need to apply to row and columns9010var internalOpts = opts ? {9011page: opts.page,9012order: opts.order,9013search: opts.search9014} : {};9015
9016// Row + column selector9017var columns = this.columns( columnSelector, internalOpts );9018var rows = this.rows( rowSelector, internalOpts );9019var i, ien, j, jen;9020
9021var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {9022var a = [];9023
9024for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {9025for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {9026a.push( {9027row: rows[idx][i],9028column: columns[idx][j]9029} );9030}9031}9032
9033return a;9034}, 1 );9035
9036// There is currently only one extension which uses a cell selector extension9037// It is a _major_ performance drag to run this if it isn't needed, so this is9038// an extension specific check at the moment9039var cells = opts && opts.selected ?9040this.cells( cellsNoOpts, opts ) :9041cellsNoOpts;9042
9043$.extend( cells.selector, {9044cols: columnSelector,9045rows: rowSelector,9046opts: opts9047} );9048
9049return cells;9050} );9051
9052
9053_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {9054return this.iterator( 'cell', function ( settings, row, column ) {9055var data = settings.aoData[ row ];9056
9057return data && data.anCells ?9058data.anCells[ column ] :9059undefined;9060}, 1 );9061} );9062
9063
9064_api_register( 'cells().data()', function () {9065return this.iterator( 'cell', function ( settings, row, column ) {9066return _fnGetCellData( settings, row, column );9067}, 1 );9068} );9069
9070
9071_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {9072type = type === 'search' ? '_aFilterData' : '_aSortData';9073
9074return this.iterator( 'cell', function ( settings, row, column ) {9075return settings.aoData[ row ][ type ][ column ];9076}, 1 );9077} );9078
9079
9080_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {9081return this.iterator( 'cell', function ( settings, row, column ) {9082return _fnGetCellData( settings, row, column, type );9083}, 1 );9084} );9085
9086
9087_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {9088return this.iterator( 'cell', function ( settings, row, column ) {9089return {9090row: row,9091column: column,9092columnVisible: _fnColumnIndexToVisible( settings, column )9093};9094}, 1 );9095} );9096
9097
9098_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {9099return this.iterator( 'cell', function ( settings, row, column ) {9100_fnInvalidate( settings, row, src, column );9101} );9102} );9103
9104
9105
9106_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {9107return _selector_first( this.cells( rowSelector, columnSelector, opts ) );9108} );9109
9110
9111_api_register( 'cell().data()', function ( data ) {9112var ctx = this.context;9113var cell = this[0];9114
9115if ( data === undefined ) {9116// Get9117return ctx.length && cell.length ?9118_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :9119undefined;9120}9121
9122// Set9123_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );9124_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );9125
9126return this;9127} );9128
9129
9130
9131/**
9132* Get current ordering (sorting) that has been applied to the table.
9133*
9134* @returns {array} 2D array containing the sorting information for the first
9135* table in the current context. Each element in the parent array represents
9136* a column being sorted upon (i.e. multi-sorting with two columns would have
9137* 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
9138* the column index that the sorting condition applies to, the second is the
9139* direction of the sort (`desc` or `asc`) and, optionally, the third is the
9140* index of the sorting order from the `column.sorting` initialisation array.
9141*//**9142* Set the ordering for the table.9143*9144* @param {integer} order Column index to sort upon.9145* @param {string} direction Direction of the sort to be applied (`asc` or `desc`)9146* @returns {DataTables.Api} this9147*//**9148* Set the ordering for the table.9149*9150* @param {array} order 1D array of sorting information to be applied.9151* @param {array} [...] Optional additional sorting conditions9152* @returns {DataTables.Api} this9153*//**9154* Set the ordering for the table.9155*9156* @param {array} order 2D array of sorting information to be applied.9157* @returns {DataTables.Api} this9158*/9159_api_register( 'order()', function ( order, dir ) {9160var ctx = this.context;9161
9162if ( order === undefined ) {9163// get9164return ctx.length !== 0 ?9165ctx[0].aaSorting :9166undefined;9167}9168
9169// set9170if ( typeof order === 'number' ) {9171// Simple column / direction passed in9172order = [ [ order, dir ] ];9173}9174else if ( order.length && ! Array.isArray( order[0] ) ) {9175// Arguments passed in (list of 1D arrays)9176order = Array.prototype.slice.call( arguments );9177}9178// otherwise a 2D array was passed in9179
9180return this.iterator( 'table', function ( settings ) {9181settings.aaSorting = order.slice();9182} );9183} );9184
9185
9186/**
9187* Attach a sort listener to an element for a given column
9188*
9189* @param {node|jQuery|string} node Identifier for the element(s) to attach the
9190* listener to. This can take the form of a single DOM node, a jQuery
9191* collection of nodes or a jQuery selector which will identify the node(s).
9192* @param {integer} column the column that a click on this node will sort on
9193* @param {function} [callback] callback function when sort is run
9194* @returns {DataTables.Api} this
9195*/
9196_api_register( 'order.listener()', function ( node, column, callback ) {9197return this.iterator( 'table', function ( settings ) {9198_fnSortAttachListener( settings, node, column, callback );9199} );9200} );9201
9202
9203_api_register( 'order.fixed()', function ( set ) {9204if ( ! set ) {9205var ctx = this.context;9206var fixed = ctx.length ?9207ctx[0].aaSortingFixed :9208undefined;9209
9210return Array.isArray( fixed ) ?9211{ pre: fixed } :9212fixed;9213}9214
9215return this.iterator( 'table', function ( settings ) {9216settings.aaSortingFixed = $.extend( true, {}, set );9217} );9218} );9219
9220
9221// Order by the selected column(s)
9222_api_register( [9223'columns().order()',9224'column().order()'9225], function ( dir ) {9226var that = this;9227
9228return this.iterator( 'table', function ( settings, i ) {9229var sort = [];9230
9231$.each( that[i], function (j, col) {9232sort.push( [ col, dir ] );9233} );9234
9235settings.aaSorting = sort;9236} );9237} );9238
9239
9240
9241_api_register( 'search()', function ( input, regex, smart, caseInsen ) {9242var ctx = this.context;9243
9244if ( input === undefined ) {9245// get9246return ctx.length !== 0 ?9247ctx[0].oPreviousSearch.sSearch :9248undefined;9249}9250
9251// set9252return this.iterator( 'table', function ( settings ) {9253if ( ! settings.oFeatures.bFilter ) {9254return;9255}9256
9257_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {9258"sSearch": input+"",9259"bRegex": regex === null ? false : regex,9260"bSmart": smart === null ? true : smart,9261"bCaseInsensitive": caseInsen === null ? true : caseInsen9262} ), 1 );9263} );9264} );9265
9266
9267_api_registerPlural(9268'columns().search()',9269'column().search()',9270function ( input, regex, smart, caseInsen ) {9271return this.iterator( 'column', function ( settings, column ) {9272var preSearch = settings.aoPreSearchCols;9273
9274if ( input === undefined ) {9275// get9276return preSearch[ column ].sSearch;9277}9278
9279// set9280if ( ! settings.oFeatures.bFilter ) {9281return;9282}9283
9284$.extend( preSearch[ column ], {9285"sSearch": input+"",9286"bRegex": regex === null ? false : regex,9287"bSmart": smart === null ? true : smart,9288"bCaseInsensitive": caseInsen === null ? true : caseInsen9289} );9290
9291_fnFilterComplete( settings, settings.oPreviousSearch, 1 );9292} );9293}9294);9295
9296/*
9297* State API methods
9298*/
9299
9300_api_register( 'state()', function () {9301return this.context.length ?9302this.context[0].oSavedState :9303null;9304} );9305
9306
9307_api_register( 'state.clear()', function () {9308return this.iterator( 'table', function ( settings ) {9309// Save an empty object9310settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );9311} );9312} );9313
9314
9315_api_register( 'state.loaded()', function () {9316return this.context.length ?9317this.context[0].oLoadedState :9318null;9319} );9320
9321
9322_api_register( 'state.save()', function () {9323return this.iterator( 'table', function ( settings ) {9324_fnSaveState( settings );9325} );9326} );9327
9328
9329
9330/**
9331* Set the jQuery or window object to be used by DataTables
9332*
9333* @param {*} module Library / container object
9334* @param {string} [type] Library or container type `lib`, `win` or `datetime`.
9335* If not provided, automatic detection is attempted.
9336*/
9337DataTable.use = function (module, type) {9338if (type === 'lib' || module.fn) {9339$ = module;9340}9341else if (type == 'win' || module.document) {9342window = module;9343document = module.document;9344}9345else if (type === 'datetime' || module.type === 'DateTime') {9346DataTable.DateTime = module;9347}9348}
9349
9350/**
9351* CommonJS factory function pass through. This will check if the arguments
9352* given are a window object or a jQuery object. If so they are set
9353* accordingly.
9354* @param {*} root Window
9355* @param {*} jq jQUery
9356* @returns {boolean} Indicator
9357*/
9358DataTable.factory = function (root, jq) {9359var is = false;9360
9361// Test if the first parameter is a window object9362if (root && root.document) {9363window = root;9364document = root.document;9365}9366
9367// Test if the second parameter is a jQuery object9368if (jq && jq.fn && jq.fn.jquery) {9369$ = jq;9370is = true;9371}9372
9373return is;9374}
9375
9376/**
9377* Provide a common method for plug-ins to check the version of DataTables being
9378* used, in order to ensure compatibility.
9379*
9380* @param {string} version Version string to check for, in the format "X.Y.Z".
9381* Note that the formats "X" and "X.Y" are also acceptable.
9382* @returns {boolean} true if this version of DataTables is greater or equal to
9383* the required version, or false if this version of DataTales is not
9384* suitable
9385* @static
9386* @dtopt API-Static
9387*
9388* @example
9389* alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9390*/
9391DataTable.versionCheck = DataTable.fnVersionCheck = function( version )9392{
9393var aThis = DataTable.version.split('.');9394var aThat = version.split('.');9395var iThis, iThat;9396
9397for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {9398iThis = parseInt( aThis[i], 10 ) || 0;9399iThat = parseInt( aThat[i], 10 ) || 0;9400
9401// Parts are the same, keep comparing9402if (iThis === iThat) {9403continue;9404}9405
9406// Parts are different, return immediately9407return iThis > iThat;9408}9409
9410return true;9411};9412
9413
9414/**
9415* Check if a `<table>` node is a DataTable table already or not.
9416*
9417* @param {node|jquery|string} table Table node, jQuery object or jQuery
9418* selector for the table to test. Note that if more than more than one
9419* table is passed on, only the first will be checked
9420* @returns {boolean} true the table given is a DataTable, or false otherwise
9421* @static
9422* @dtopt API-Static
9423*
9424* @example
9425* if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9426* $('#example').dataTable();
9427* }
9428*/
9429DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )9430{
9431var t = $(table).get(0);9432var is = false;9433
9434if ( table instanceof DataTable.Api ) {9435return true;9436}9437
9438$.each( DataTable.settings, function (i, o) {9439var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;9440var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;9441
9442if ( o.nTable === t || head === t || foot === t ) {9443is = true;9444}9445} );9446
9447return is;9448};9449
9450
9451/**
9452* Get all DataTable tables that have been initialised - optionally you can
9453* select to get only currently visible tables.
9454*
9455* @param {boolean} [visible=false] Flag to indicate if you want all (default)
9456* or visible tables only.
9457* @returns {array} Array of `table` nodes (not DataTable instances) which are
9458* DataTables
9459* @static
9460* @dtopt API-Static
9461*
9462* @example
9463* $.each( $.fn.dataTable.tables(true), function () {
9464* $(table).DataTable().columns.adjust();
9465* } );
9466*/
9467DataTable.tables = DataTable.fnTables = function ( visible )9468{
9469var api = false;9470
9471if ( $.isPlainObject( visible ) ) {9472api = visible.api;9473visible = visible.visible;9474}9475
9476var a = $.map( DataTable.settings, function (o) {9477if ( !visible || (visible && $(o.nTable).is(':visible')) ) {9478return o.nTable;9479}9480} );9481
9482return api ?9483new _Api( a ) :9484a;9485};9486
9487
9488/**
9489* Convert from camel case parameters to Hungarian notation. This is made public
9490* for the extensions to provide the same ability as DataTables core to accept
9491* either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9492* parameters.
9493*
9494* @param {object} src The model object which holds all parameters that can be
9495* mapped.
9496* @param {object} user The object to convert from camel case to Hungarian.
9497* @param {boolean} force When set to `true`, properties which already have a
9498* Hungarian value in the `user` object will be overwritten. Otherwise they
9499* won't be.
9500*/
9501DataTable.camelToHungarian = _fnCamelToHungarian;9502
9503
9504
9505/**
9506*
9507*/
9508_api_register( '$()', function ( selector, opts ) {9509var9510rows = this.rows( opts ).nodes(), // Get all rows9511jqRows = $(rows);9512
9513return $( [].concat(9514jqRows.filter( selector ).toArray(),9515jqRows.find( selector ).toArray()9516) );9517} );9518
9519
9520// jQuery functions to operate on the tables
9521$.each( [ 'on', 'one', 'off' ], function (i, key) {9522_api_register( key+'()', function ( /* event, handler */ ) {9523var args = Array.prototype.slice.call(arguments);9524
9525// Add the `dt` namespace automatically if it isn't already present9526args[0] = $.map( args[0].split( /\s/ ), function ( e ) {9527return ! e.match(/\.dt\b/) ?9528e+'.dt' :9529e;9530} ).join( ' ' );9531
9532var inst = $( this.tables().nodes() );9533inst[key].apply( inst, args );9534return this;9535} );9536} );9537
9538
9539_api_register( 'clear()', function () {9540return this.iterator( 'table', function ( settings ) {9541_fnClearTable( settings );9542} );9543} );9544
9545
9546_api_register( 'settings()', function () {9547return new _Api( this.context, this.context );9548} );9549
9550
9551_api_register( 'init()', function () {9552var ctx = this.context;9553return ctx.length ? ctx[0].oInit : null;9554} );9555
9556
9557_api_register( 'data()', function () {9558return this.iterator( 'table', function ( settings ) {9559return _pluck( settings.aoData, '_aData' );9560} ).flatten();9561} );9562
9563
9564_api_register( 'destroy()', function ( remove ) {9565remove = remove || false;9566
9567return this.iterator( 'table', function ( settings ) {9568var classes = settings.oClasses;9569var table = settings.nTable;9570var tbody = settings.nTBody;9571var thead = settings.nTHead;9572var tfoot = settings.nTFoot;9573var jqTable = $(table);9574var jqTbody = $(tbody);9575var jqWrapper = $(settings.nTableWrapper);9576var rows = $.map( settings.aoData, function (r) { return r.nTr; } );9577var i, ien;9578
9579// Flag to note that the table is currently being destroyed - no action9580// should be taken9581settings.bDestroying = true;9582
9583// Fire off the destroy callbacks for plug-ins etc9584_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );9585
9586// If not being removed from the document, make all columns visible9587if ( ! remove ) {9588new _Api( settings ).columns().visible( true );9589}9590
9591// Blitz all `DT` namespaced events (these are internal events, the9592// lowercase, `dt` events are user subscribed and they are responsible9593// for removing them9594jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');9595$(window).off('.DT-'+settings.sInstance);9596
9597// When scrolling we had to break the table up - restore it9598if ( table != thead.parentNode ) {9599jqTable.children('thead').detach();9600jqTable.append( thead );9601}9602
9603if ( tfoot && table != tfoot.parentNode ) {9604jqTable.children('tfoot').detach();9605jqTable.append( tfoot );9606}9607
9608settings.aaSorting = [];9609settings.aaSortingFixed = [];9610_fnSortingClasses( settings );9611
9612$( rows ).removeClass( settings.asStripeClasses.join(' ') );9613
9614$('th, td', thead).removeClass( classes.sSortable+' '+9615classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone9616);9617
9618// Add the TR elements back into the table in their original order9619jqTbody.children().detach();9620jqTbody.append( rows );9621
9622var orig = settings.nTableWrapper.parentNode;9623
9624// Remove the DataTables generated nodes, events and classes9625var removedMethod = remove ? 'remove' : 'detach';9626jqTable[ removedMethod ]();9627jqWrapper[ removedMethod ]();9628
9629// If we need to reattach the table to the document9630if ( ! remove && orig ) {9631// insertBefore acts like appendChild if !arg[1]9632orig.insertBefore( table, settings.nTableReinsertBefore );9633
9634// Restore the width of the original table - was read from the style property,9635// so we can restore directly to that9636jqTable
9637.css( 'width', settings.sDestroyWidth )9638.removeClass( classes.sTable );9639
9640// If the were originally stripe classes - then we add them back here.9641// Note this is not fool proof (for example if not all rows had stripe9642// classes - but it's a good effort without getting carried away9643ien = settings.asDestroyStripes.length;9644
9645if ( ien ) {9646jqTbody.children().each( function (i) {9647$(this).addClass( settings.asDestroyStripes[i % ien] );9648} );9649}9650}9651
9652/* Remove the settings object from the settings array */9653var idx = $.inArray( settings, DataTable.settings );9654if ( idx !== -1 ) {9655DataTable.settings.splice( idx, 1 );9656}9657} );9658} );9659
9660
9661// Add the `every()` method for rows, columns and cells in a compact form
9662$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {9663_api_register( type+'s().every()', function ( fn ) {9664var opts = this.selector.opts;9665var api = this;9666
9667return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {9668// Rows and columns:9669// arg1 - index9670// arg2 - table counter9671// arg3 - loop counter9672// arg4 - undefined9673// Cells:9674// arg1 - row index9675// arg2 - column index9676// arg3 - table counter9677// arg4 - loop counter9678fn.call(9679api[ type ](9680arg1,9681type==='cell' ? arg2 : opts,9682type==='cell' ? opts : undefined9683),9684arg1, arg2, arg3, arg49685);9686} );9687} );9688} );9689
9690
9691// i18n method for extensions to be able to use the language object from the
9692// DataTable
9693_api_register( 'i18n()', function ( token, def, plural ) {9694var ctx = this.context[0];9695var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );9696
9697if ( resolved === undefined ) {9698resolved = def;9699}9700
9701if ( plural !== undefined && $.isPlainObject( resolved ) ) {9702resolved = resolved[ plural ] !== undefined ?9703resolved[ plural ] :9704resolved._;9705}9706
9707return typeof resolved === 'string'9708? resolved.replace( '%d', plural ) // nb: plural might be undefined,9709: resolved;9710} );9711/**
9712* Version string for plug-ins to check compatibility. Allowed format is
9713* `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9714* only for non-release builds. See http://semver.org/ for more information.
9715* @member
9716* @type string
9717* @default Version number
9718*/
9719DataTable.version = "1.13.5";9720
9721/**
9722* Private data store, containing all of the settings objects that are
9723* created for the tables on a given page.
9724*
9725* Note that the `DataTable.settings` object is aliased to
9726* `jQuery.fn.dataTableExt` through which it may be accessed and
9727* manipulated, or `jQuery.fn.dataTable.settings`.
9728* @member
9729* @type array
9730* @default []
9731* @private
9732*/
9733DataTable.settings = [];9734
9735/**
9736* Object models container, for the various models that DataTables has
9737* available to it. These models define the objects that are used to hold
9738* the active state and configuration of the table.
9739* @namespace
9740*/
9741DataTable.models = {};9742
9743
9744
9745/**
9746* Template object for the way in which DataTables holds information about
9747* search information for the global filter and individual column filters.
9748* @namespace
9749*/
9750DataTable.models.oSearch = {9751/**9752* Flag to indicate if the filtering should be case insensitive or not
9753* @type boolean
9754* @default true
9755*/
9756"bCaseInsensitive": true,9757
9758/**9759* Applied search term
9760* @type string
9761* @default <i>Empty string</i>
9762*/
9763"sSearch": "",9764
9765/**9766* Flag to indicate if the search term should be interpreted as a
9767* regular expression (true) or not (false) and therefore and special
9768* regex characters escaped.
9769* @type boolean
9770* @default false
9771*/
9772"bRegex": false,9773
9774/**9775* Flag to indicate if DataTables is to use its smart filtering or not.
9776* @type boolean
9777* @default true
9778*/
9779"bSmart": true,9780
9781/**9782* Flag to indicate if DataTables should only trigger a search when
9783* the return key is pressed.
9784* @type boolean
9785* @default false
9786*/
9787"return": false9788};9789
9790
9791
9792
9793/**
9794* Template object for the way in which DataTables holds information about
9795* each individual row. This is the object format used for the settings
9796* aoData array.
9797* @namespace
9798*/
9799DataTable.models.oRow = {9800/**9801* TR element for the row
9802* @type node
9803* @default null
9804*/
9805"nTr": null,9806
9807/**9808* Array of TD elements for each row. This is null until the row has been
9809* created.
9810* @type array nodes
9811* @default []
9812*/
9813"anCells": null,9814
9815/**9816* Data object from the original data source for the row. This is either
9817* an array if using the traditional form of DataTables, or an object if
9818* using mData options. The exact type will depend on the passed in
9819* data from the data source, or will be an array if using DOM a data
9820* source.
9821* @type array|object
9822* @default []
9823*/
9824"_aData": [],9825
9826/**9827* Sorting data cache - this array is ostensibly the same length as the
9828* number of columns (although each index is generated only as it is
9829* needed), and holds the data that is used for sorting each column in the
9830* row. We do this cache generation at the start of the sort in order that
9831* the formatting of the sort data need be done only once for each cell
9832* per sort. This array should not be read from or written to by anything
9833* other than the master sorting methods.
9834* @type array
9835* @default null
9836* @private
9837*/
9838"_aSortData": null,9839
9840/**9841* Per cell filtering data cache. As per the sort data cache, used to
9842* increase the performance of the filtering in DataTables
9843* @type array
9844* @default null
9845* @private
9846*/
9847"_aFilterData": null,9848
9849/**9850* Filtering data cache. This is the same as the cell filtering cache, but
9851* in this case a string rather than an array. This is easily computed with
9852* a join on `_aFilterData`, but is provided as a cache so the join isn't
9853* needed on every search (memory traded for performance)
9854* @type array
9855* @default null
9856* @private
9857*/
9858"_sFilterRow": null,9859
9860/**9861* Cache of the class name that DataTables has applied to the row, so we
9862* can quickly look at this variable rather than needing to do a DOM check
9863* on className for the nTr property.
9864* @type string
9865* @default <i>Empty string</i>
9866* @private
9867*/
9868"_sRowStripe": "",9869
9870/**9871* Denote if the original data source was from the DOM, or the data source
9872* object. This is used for invalidating data, so DataTables can
9873* automatically read data from the original source, unless uninstructed
9874* otherwise.
9875* @type string
9876* @default null
9877* @private
9878*/
9879"src": null,9880
9881/**9882* Index in the aoData array. This saves an indexOf lookup when we have the
9883* object, but want to know the index
9884* @type integer
9885* @default -1
9886* @private
9887*/
9888"idx": -19889};9890
9891
9892/**
9893* Template object for the column information object in DataTables. This object
9894* is held in the settings aoColumns array and contains all the information that
9895* DataTables needs about each individual column.
9896*
9897* Note that this object is related to {@link DataTable.defaults.column}
9898* but this one is the internal data store for DataTables's cache of columns.
9899* It should NOT be manipulated outside of DataTables. Any configuration should
9900* be done through the initialisation options.
9901* @namespace
9902*/
9903DataTable.models.oColumn = {9904/**9905* Column index. This could be worked out on-the-fly with $.inArray, but it
9906* is faster to just hold it as a variable
9907* @type integer
9908* @default null
9909*/
9910"idx": null,9911
9912/**9913* A list of the columns that sorting should occur on when this column
9914* is sorted. That this property is an array allows multi-column sorting
9915* to be defined for a column (for example first name / last name columns
9916* would benefit from this). The values are integers pointing to the
9917* columns to be sorted on (typically it will be a single integer pointing
9918* at itself, but that doesn't need to be the case).
9919* @type array
9920*/
9921"aDataSort": null,9922
9923/**9924* Define the sorting directions that are applied to the column, in sequence
9925* as the column is repeatedly sorted upon - i.e. the first value is used
9926* as the sorting direction when the column if first sorted (clicked on).
9927* Sort it again (click again) and it will move on to the next index.
9928* Repeat until loop.
9929* @type array
9930*/
9931"asSorting": null,9932
9933/**9934* Flag to indicate if the column is searchable, and thus should be included
9935* in the filtering or not.
9936* @type boolean
9937*/
9938"bSearchable": null,9939
9940/**9941* Flag to indicate if the column is sortable or not.
9942* @type boolean
9943*/
9944"bSortable": null,9945
9946/**9947* Flag to indicate if the column is currently visible in the table or not
9948* @type boolean
9949*/
9950"bVisible": null,9951
9952/**9953* Store for manual type assignment using the `column.type` option. This
9954* is held in store so we can manipulate the column's `sType` property.
9955* @type string
9956* @default null
9957* @private
9958*/
9959"_sManualType": null,9960
9961/**9962* Flag to indicate if HTML5 data attributes should be used as the data
9963* source for filtering or sorting. True is either are.
9964* @type boolean
9965* @default false
9966* @private
9967*/
9968"_bAttrSrc": false,9969
9970/**9971* Developer definable function that is called whenever a cell is created (Ajax source,
9972* etc) or processed for input (DOM source). This can be used as a compliment to mRender
9973* allowing you to modify the DOM element (add background colour for example) when the
9974* element is available.
9975* @type function
9976* @param {element} nTd The TD node that has been created
9977* @param {*} sData The Data for the cell
9978* @param {array|object} oData The data for the whole row
9979* @param {int} iRow The row index for the aoData data store
9980* @default null
9981*/
9982"fnCreatedCell": null,9983
9984/**9985* Function to get data from a cell in a column. You should <b>never</b>
9986* access data directly through _aData internally in DataTables - always use
9987* the method attached to this property. It allows mData to function as
9988* required. This function is automatically assigned by the column
9989* initialisation method
9990* @type function
9991* @param {array|object} oData The data array/object for the array
9992* (i.e. aoData[]._aData)
9993* @param {string} sSpecific The specific data type you want to get -
9994* 'display', 'type' 'filter' 'sort'
9995* @returns {*} The data for the cell from the given row's data
9996* @default null
9997*/
9998"fnGetData": null,9999
10000/**10001* Function to set data for a cell in the column. You should <b>never</b>
10002* set the data directly to _aData internally in DataTables - always use
10003* this method. It allows mData to function as required. This function
10004* is automatically assigned by the column initialisation method
10005* @type function
10006* @param {array|object} oData The data array/object for the array
10007* (i.e. aoData[]._aData)
10008* @param {*} sValue Value to set
10009* @default null
10010*/
10011"fnSetData": null,10012
10013/**10014* Property to read the value for the cells in the column from the data
10015* source array / object. If null, then the default content is used, if a
10016* function is given then the return from the function is used.
10017* @type function|int|string|null
10018* @default null
10019*/
10020"mData": null,10021
10022/**10023* Partner property to mData which is used (only when defined) to get
10024* the data - i.e. it is basically the same as mData, but without the
10025* 'set' option, and also the data fed to it is the result from mData.
10026* This is the rendering method to match the data method of mData.
10027* @type function|int|string|null
10028* @default null
10029*/
10030"mRender": null,10031
10032/**10033* Unique header TH/TD element for this column - this is what the sorting
10034* listener is attached to (if sorting is enabled.)
10035* @type node
10036* @default null
10037*/
10038"nTh": null,10039
10040/**10041* Unique footer TH/TD element for this column (if there is one). Not used
10042* in DataTables as such, but can be used for plug-ins to reference the
10043* footer for each column.
10044* @type node
10045* @default null
10046*/
10047"nTf": null,10048
10049/**10050* The class to apply to all TD elements in the table's TBODY for the column
10051* @type string
10052* @default null
10053*/
10054"sClass": null,10055
10056/**10057* When DataTables calculates the column widths to assign to each column,
10058* it finds the longest string in each column and then constructs a
10059* temporary table and reads the widths from that. The problem with this
10060* is that "mmm" is much wider then "iiii", but the latter is a longer
10061* string - thus the calculation can go wrong (doing it properly and putting
10062* it into an DOM object and measuring that is horribly(!) slow). Thus as
10063* a "work around" we provide this option. It will append its value to the
10064* text that is found to be the longest string for the column - i.e. padding.
10065* @type string
10066*/
10067"sContentPadding": null,10068
10069/**10070* Allows a default value to be given for a column's data, and will be used
10071* whenever a null data source is encountered (this can be because mData
10072* is set to null, or because the data source itself is null).
10073* @type string
10074* @default null
10075*/
10076"sDefaultContent": null,10077
10078/**10079* Name for the column, allowing reference to the column by name as well as
10080* by index (needs a lookup to work by name).
10081* @type string
10082*/
10083"sName": null,10084
10085/**10086* Custom sorting data type - defines which of the available plug-ins in
10087* afnSortData the custom sorting will use - if any is defined.
10088* @type string
10089* @default std
10090*/
10091"sSortDataType": 'std',10092
10093/**10094* Class to be applied to the header element when sorting on this column
10095* @type string
10096* @default null
10097*/
10098"sSortingClass": null,10099
10100/**10101* Class to be applied to the header element when sorting on this column -
10102* when jQuery UI theming is used.
10103* @type string
10104* @default null
10105*/
10106"sSortingClassJUI": null,10107
10108/**10109* Title of the column - what is seen in the TH element (nTh).
10110* @type string
10111*/
10112"sTitle": null,10113
10114/**10115* Column sorting and filtering type
10116* @type string
10117* @default null
10118*/
10119"sType": null,10120
10121/**10122* Width of the column
10123* @type string
10124* @default null
10125*/
10126"sWidth": null,10127
10128/**10129* Width of the column when it was first "encountered"
10130* @type string
10131* @default null
10132*/
10133"sWidthOrig": null10134};10135
10136
10137/*
10138* Developer note: The properties of the object below are given in Hungarian
10139* notation, that was used as the interface for DataTables prior to v1.10, however
10140* from v1.10 onwards the primary interface is camel case. In order to avoid
10141* breaking backwards compatibility utterly with this change, the Hungarian
10142* version is still, internally the primary interface, but is is not documented
10143* - hence the @name tags in each doc comment. This allows a Javascript function
10144* to create a map from Hungarian notation to camel case (going the other direction
10145* would require each property to be listed, which would add around 3K to the size
10146* of DataTables, while this method is about a 0.5K hit).
10147*
10148* Ultimately this does pave the way for Hungarian notation to be dropped
10149* completely, but that is a massive amount of work and will break current
10150* installs (therefore is on-hold until v2).
10151*/
10152
10153/**
10154* Initialisation options that can be given to DataTables at initialisation
10155* time.
10156* @namespace
10157*/
10158DataTable.defaults = {10159/**10160* An array of data to use for the table, passed in at initialisation which
10161* will be used in preference to any data which is already in the DOM. This is
10162* particularly useful for constructing tables purely in Javascript, for
10163* example with a custom Ajax call.
10164* @type array
10165* @default null
10166*
10167* @dtopt Option
10168* @name DataTable.defaults.data
10169*
10170* @example
10171* // Using a 2D array data source
10172* $(document).ready( function () {
10173* $('#example').dataTable( {
10174* "data": [
10175* ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
10176* ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
10177* ],
10178* "columns": [
10179* { "title": "Engine" },
10180* { "title": "Browser" },
10181* { "title": "Platform" },
10182* { "title": "Version" },
10183* { "title": "Grade" }
10184* ]
10185* } );
10186* } );
10187*
10188* @example
10189* // Using an array of objects as a data source (`data`)
10190* $(document).ready( function () {
10191* $('#example').dataTable( {
10192* "data": [
10193* {
10194* "engine": "Trident",
10195* "browser": "Internet Explorer 4.0",
10196* "platform": "Win 95+",
10197* "version": 4,
10198* "grade": "X"
10199* },
10200* {
10201* "engine": "Trident",
10202* "browser": "Internet Explorer 5.0",
10203* "platform": "Win 95+",
10204* "version": 5,
10205* "grade": "C"
10206* }
10207* ],
10208* "columns": [
10209* { "title": "Engine", "data": "engine" },
10210* { "title": "Browser", "data": "browser" },
10211* { "title": "Platform", "data": "platform" },
10212* { "title": "Version", "data": "version" },
10213* { "title": "Grade", "data": "grade" }
10214* ]
10215* } );
10216* } );
10217*/
10218"aaData": null,10219
10220
10221/**10222* If ordering is enabled, then DataTables will perform a first pass sort on
10223* initialisation. You can define which column(s) the sort is performed
10224* upon, and the sorting direction, with this variable. The `sorting` array
10225* should contain an array for each column to be sorted initially containing
10226* the column's index and a direction string ('asc' or 'desc').
10227* @type array
10228* @default [[0,'asc']]
10229*
10230* @dtopt Option
10231* @name DataTable.defaults.order
10232*
10233* @example
10234* // Sort by 3rd column first, and then 4th column
10235* $(document).ready( function() {
10236* $('#example').dataTable( {
10237* "order": [[2,'asc'], [3,'desc']]
10238* } );
10239* } );
10240*
10241* // No initial sorting
10242* $(document).ready( function() {
10243* $('#example').dataTable( {
10244* "order": []
10245* } );
10246* } );
10247*/
10248"aaSorting": [[0,'asc']],10249
10250
10251/**10252* This parameter is basically identical to the `sorting` parameter, but
10253* cannot be overridden by user interaction with the table. What this means
10254* is that you could have a column (visible or hidden) which the sorting
10255* will always be forced on first - any sorting after that (from the user)
10256* will then be performed as required. This can be useful for grouping rows
10257* together.
10258* @type array
10259* @default null
10260*
10261* @dtopt Option
10262* @name DataTable.defaults.orderFixed
10263*
10264* @example
10265* $(document).ready( function() {
10266* $('#example').dataTable( {
10267* "orderFixed": [[0,'asc']]
10268* } );
10269* } )
10270*/
10271"aaSortingFixed": [],10272
10273
10274/**10275* DataTables can be instructed to load data to display in the table from a
10276* Ajax source. This option defines how that Ajax call is made and where to.
10277*
10278* The `ajax` property has three different modes of operation, depending on
10279* how it is defined. These are:
10280*
10281* * `string` - Set the URL from where the data should be loaded from.
10282* * `object` - Define properties for `jQuery.ajax`.
10283* * `function` - Custom data get function
10284*
10285* `string`
10286* --------
10287*
10288* As a string, the `ajax` property simply defines the URL from which
10289* DataTables will load data.
10290*
10291* `object`
10292* --------
10293*
10294* As an object, the parameters in the object are passed to
10295* [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10296* of the Ajax request. DataTables has a number of default parameters which
10297* you can override using this option. Please refer to the jQuery
10298* documentation for a full description of the options available, although
10299* the following parameters provide additional options in DataTables or
10300* require special consideration:
10301*
10302* * `data` - As with jQuery, `data` can be provided as an object, but it
10303* can also be used as a function to manipulate the data DataTables sends
10304* to the server. The function takes a single parameter, an object of
10305* parameters with the values that DataTables has readied for sending. An
10306* object may be returned which will be merged into the DataTables
10307* defaults, or you can add the items to the object that was passed in and
10308* not return anything from the function. This supersedes `fnServerParams`
10309* from DataTables 1.9-.
10310*
10311* * `dataSrc` - By default DataTables will look for the property `data` (or
10312* `aaData` for compatibility with DataTables 1.9-) when obtaining data
10313* from an Ajax source or for server-side processing - this parameter
10314* allows that property to be changed. You can use Javascript dotted
10315* object notation to get a data source for multiple levels of nesting, or
10316* it my be used as a function. As a function it takes a single parameter,
10317* the JSON returned from the server, which can be manipulated as
10318* required, with the returned value being that used by DataTables as the
10319* data source for the table. This supersedes `sAjaxDataProp` from
10320* DataTables 1.9-.
10321*
10322* * `success` - Should not be overridden it is used internally in
10323* DataTables. To manipulate / transform the data returned by the server
10324* use `ajax.dataSrc`, or use `ajax` as a function (see below).
10325*
10326* `function`
10327* ----------
10328*
10329* As a function, making the Ajax call is left up to yourself allowing
10330* complete control of the Ajax request. Indeed, if desired, a method other
10331* than Ajax could be used to obtain the required data, such as Web storage
10332* or an AIR database.
10333*
10334* The function is given four parameters and no return is required. The
10335* parameters are:
10336*
10337* 1. _object_ - Data to send to the server
10338* 2. _function_ - Callback function that must be executed when the required
10339* data has been obtained. That data should be passed into the callback
10340* as the only parameter
10341* 3. _object_ - DataTables settings object for the table
10342*
10343* Note that this supersedes `fnServerData` from DataTables 1.9-.
10344*
10345* @type string|object|function
10346* @default null
10347*
10348* @dtopt Option
10349* @name DataTable.defaults.ajax
10350* @since 1.10.0
10351*
10352* @example
10353* // Get JSON data from a file via Ajax.
10354* // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10355* $('#example').dataTable( {
10356* "ajax": "data.json"
10357* } );
10358*
10359* @example
10360* // Get JSON data from a file via Ajax, using `dataSrc` to change
10361* // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10362* $('#example').dataTable( {
10363* "ajax": {
10364* "url": "data.json",
10365* "dataSrc": "tableData"
10366* }
10367* } );
10368*
10369* @example
10370* // Get JSON data from a file via Ajax, using `dataSrc` to read data
10371* // from a plain array rather than an array in an object
10372* $('#example').dataTable( {
10373* "ajax": {
10374* "url": "data.json",
10375* "dataSrc": ""
10376* }
10377* } );
10378*
10379* @example
10380* // Manipulate the data returned from the server - add a link to data
10381* // (note this can, should, be done using `render` for the column - this
10382* // is just a simple example of how the data can be manipulated).
10383* $('#example').dataTable( {
10384* "ajax": {
10385* "url": "data.json",
10386* "dataSrc": function ( json ) {
10387* for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10388* json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10389* }
10390* return json;
10391* }
10392* }
10393* } );
10394*
10395* @example
10396* // Add data to the request
10397* $('#example').dataTable( {
10398* "ajax": {
10399* "url": "data.json",
10400* "data": function ( d ) {
10401* return {
10402* "extra_search": $('#extra').val()
10403* };
10404* }
10405* }
10406* } );
10407*
10408* @example
10409* // Send request as POST
10410* $('#example').dataTable( {
10411* "ajax": {
10412* "url": "data.json",
10413* "type": "POST"
10414* }
10415* } );
10416*
10417* @example
10418* // Get the data from localStorage (could interface with a form for
10419* // adding, editing and removing rows).
10420* $('#example').dataTable( {
10421* "ajax": function (data, callback, settings) {
10422* callback(
10423* JSON.parse( localStorage.getItem('dataTablesData') )
10424* );
10425* }
10426* } );
10427*/
10428"ajax": null,10429
10430
10431/**10432* This parameter allows you to readily specify the entries in the length drop
10433* down menu that DataTables shows when pagination is enabled. It can be
10434* either a 1D array of options which will be used for both the displayed
10435* option and the value, or a 2D array which will use the array in the first
10436* position as the value, and the array in the second position as the
10437* displayed options (useful for language strings such as 'All').
10438*
10439* Note that the `pageLength` property will be automatically set to the
10440* first value given in this array, unless `pageLength` is also provided.
10441* @type array
10442* @default [ 10, 25, 50, 100 ]
10443*
10444* @dtopt Option
10445* @name DataTable.defaults.lengthMenu
10446*
10447* @example
10448* $(document).ready( function() {
10449* $('#example').dataTable( {
10450* "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10451* } );
10452* } );
10453*/
10454"aLengthMenu": [ 10, 25, 50, 100 ],10455
10456
10457/**10458* The `columns` option in the initialisation parameter allows you to define
10459* details about the way individual columns behave. For a full list of
10460* column options that can be set, please see
10461* {@link DataTable.defaults.column}. Note that if you use `columns` to
10462* define your columns, you must have an entry in the array for every single
10463* column that you have in your table (these can be null if you don't which
10464* to specify any options).
10465* @member
10466*
10467* @name DataTable.defaults.column
10468*/
10469"aoColumns": null,10470
10471/**10472* Very similar to `columns`, `columnDefs` allows you to target a specific
10473* column, multiple columns, or all columns, using the `targets` property of
10474* each object in the array. This allows great flexibility when creating
10475* tables, as the `columnDefs` arrays can be of any length, targeting the
10476* columns you specifically want. `columnDefs` may use any of the column
10477* options available: {@link DataTable.defaults.column}, but it _must_
10478* have `targets` defined in each object in the array. Values in the `targets`
10479* array may be:
10480* <ul>
10481* <li>a string - class name will be matched on the TH for the column</li>
10482* <li>0 or a positive integer - column index counting from the left</li>
10483* <li>a negative integer - column index counting from the right</li>
10484* <li>the string "_all" - all columns (i.e. assign a default)</li>
10485* </ul>
10486* @member
10487*
10488* @name DataTable.defaults.columnDefs
10489*/
10490"aoColumnDefs": null,10491
10492
10493/**10494* Basically the same as `search`, this parameter defines the individual column
10495* filtering state at initialisation time. The array must be of the same size
10496* as the number of columns, and each element be an object with the parameters
10497* `search` and `escapeRegex` (the latter is optional). 'null' is also
10498* accepted and the default will be used.
10499* @type array
10500* @default []
10501*
10502* @dtopt Option
10503* @name DataTable.defaults.searchCols
10504*
10505* @example
10506* $(document).ready( function() {
10507* $('#example').dataTable( {
10508* "searchCols": [
10509* null,
10510* { "search": "My filter" },
10511* null,
10512* { "search": "^[0-9]", "escapeRegex": false }
10513* ]
10514* } );
10515* } )
10516*/
10517"aoSearchCols": [],10518
10519
10520/**10521* An array of CSS classes that should be applied to displayed rows. This
10522* array may be of any length, and DataTables will apply each class
10523* sequentially, looping when required.
10524* @type array
10525* @default null <i>Will take the values determined by the `oClasses.stripe*`
10526* options</i>
10527*
10528* @dtopt Option
10529* @name DataTable.defaults.stripeClasses
10530*
10531* @example
10532* $(document).ready( function() {
10533* $('#example').dataTable( {
10534* "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10535* } );
10536* } )
10537*/
10538"asStripeClasses": null,10539
10540
10541/**10542* Enable or disable automatic column width calculation. This can be disabled
10543* as an optimisation (it takes some time to calculate the widths) if the
10544* tables widths are passed in using `columns`.
10545* @type boolean
10546* @default true
10547*
10548* @dtopt Features
10549* @name DataTable.defaults.autoWidth
10550*
10551* @example
10552* $(document).ready( function () {
10553* $('#example').dataTable( {
10554* "autoWidth": false
10555* } );
10556* } );
10557*/
10558"bAutoWidth": true,10559
10560
10561/**10562* Deferred rendering can provide DataTables with a huge speed boost when you
10563* are using an Ajax or JS data source for the table. This option, when set to
10564* true, will cause DataTables to defer the creation of the table elements for
10565* each row until they are needed for a draw - saving a significant amount of
10566* time.
10567* @type boolean
10568* @default false
10569*
10570* @dtopt Features
10571* @name DataTable.defaults.deferRender
10572*
10573* @example
10574* $(document).ready( function() {
10575* $('#example').dataTable( {
10576* "ajax": "sources/arrays.txt",
10577* "deferRender": true
10578* } );
10579* } );
10580*/
10581"bDeferRender": false,10582
10583
10584/**10585* Replace a DataTable which matches the given selector and replace it with
10586* one which has the properties of the new initialisation object passed. If no
10587* table matches the selector, then the new DataTable will be constructed as
10588* per normal.
10589* @type boolean
10590* @default false
10591*
10592* @dtopt Options
10593* @name DataTable.defaults.destroy
10594*
10595* @example
10596* $(document).ready( function() {
10597* $('#example').dataTable( {
10598* "srollY": "200px",
10599* "paginate": false
10600* } );
10601*
10602* // Some time later....
10603* $('#example').dataTable( {
10604* "filter": false,
10605* "destroy": true
10606* } );
10607* } );
10608*/
10609"bDestroy": false,10610
10611
10612/**10613* Enable or disable filtering of data. Filtering in DataTables is "smart" in
10614* that it allows the end user to input multiple words (space separated) and
10615* will match a row containing those words, even if not in the order that was
10616* specified (this allow matching across multiple columns). Note that if you
10617* wish to use filtering in DataTables this must remain 'true' - to remove the
10618* default filtering input box and retain filtering abilities, please use
10619* {@link DataTable.defaults.dom}.
10620* @type boolean
10621* @default true
10622*
10623* @dtopt Features
10624* @name DataTable.defaults.searching
10625*
10626* @example
10627* $(document).ready( function () {
10628* $('#example').dataTable( {
10629* "searching": false
10630* } );
10631* } );
10632*/
10633"bFilter": true,10634
10635
10636/**10637* Enable or disable the table information display. This shows information
10638* about the data that is currently visible on the page, including information
10639* about filtered data if that action is being performed.
10640* @type boolean
10641* @default true
10642*
10643* @dtopt Features
10644* @name DataTable.defaults.info
10645*
10646* @example
10647* $(document).ready( function () {
10648* $('#example').dataTable( {
10649* "info": false
10650* } );
10651* } );
10652*/
10653"bInfo": true,10654
10655
10656/**10657* Allows the end user to select the size of a formatted page from a select
10658* menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10659* @type boolean
10660* @default true
10661*
10662* @dtopt Features
10663* @name DataTable.defaults.lengthChange
10664*
10665* @example
10666* $(document).ready( function () {
10667* $('#example').dataTable( {
10668* "lengthChange": false
10669* } );
10670* } );
10671*/
10672"bLengthChange": true,10673
10674
10675/**10676* Enable or disable pagination.
10677* @type boolean
10678* @default true
10679*
10680* @dtopt Features
10681* @name DataTable.defaults.paging
10682*
10683* @example
10684* $(document).ready( function () {
10685* $('#example').dataTable( {
10686* "paging": false
10687* } );
10688* } );
10689*/
10690"bPaginate": true,10691
10692
10693/**10694* Enable or disable the display of a 'processing' indicator when the table is
10695* being processed (e.g. a sort). This is particularly useful for tables with
10696* large amounts of data where it can take a noticeable amount of time to sort
10697* the entries.
10698* @type boolean
10699* @default false
10700*
10701* @dtopt Features
10702* @name DataTable.defaults.processing
10703*
10704* @example
10705* $(document).ready( function () {
10706* $('#example').dataTable( {
10707* "processing": true
10708* } );
10709* } );
10710*/
10711"bProcessing": false,10712
10713
10714/**10715* Retrieve the DataTables object for the given selector. Note that if the
10716* table has already been initialised, this parameter will cause DataTables
10717* to simply return the object that has already been set up - it will not take
10718* account of any changes you might have made to the initialisation object
10719* passed to DataTables (setting this parameter to true is an acknowledgement
10720* that you understand this). `destroy` can be used to reinitialise a table if
10721* you need.
10722* @type boolean
10723* @default false
10724*
10725* @dtopt Options
10726* @name DataTable.defaults.retrieve
10727*
10728* @example
10729* $(document).ready( function() {
10730* initTable();
10731* tableActions();
10732* } );
10733*
10734* function initTable ()
10735* {
10736* return $('#example').dataTable( {
10737* "scrollY": "200px",
10738* "paginate": false,
10739* "retrieve": true
10740* } );
10741* }
10742*
10743* function tableActions ()
10744* {
10745* var table = initTable();
10746* // perform API operations with oTable
10747* }
10748*/
10749"bRetrieve": false,10750
10751
10752/**10753* When vertical (y) scrolling is enabled, DataTables will force the height of
10754* the table's viewport to the given height at all times (useful for layout).
10755* However, this can look odd when filtering data down to a small data set,
10756* and the footer is left "floating" further down. This parameter (when
10757* enabled) will cause DataTables to collapse the table's viewport down when
10758* the result set will fit within the given Y height.
10759* @type boolean
10760* @default false
10761*
10762* @dtopt Options
10763* @name DataTable.defaults.scrollCollapse
10764*
10765* @example
10766* $(document).ready( function() {
10767* $('#example').dataTable( {
10768* "scrollY": "200",
10769* "scrollCollapse": true
10770* } );
10771* } );
10772*/
10773"bScrollCollapse": false,10774
10775
10776/**10777* Configure DataTables to use server-side processing. Note that the
10778* `ajax` parameter must also be given in order to give DataTables a
10779* source to obtain the required data for each draw.
10780* @type boolean
10781* @default false
10782*
10783* @dtopt Features
10784* @dtopt Server-side
10785* @name DataTable.defaults.serverSide
10786*
10787* @example
10788* $(document).ready( function () {
10789* $('#example').dataTable( {
10790* "serverSide": true,
10791* "ajax": "xhr.php"
10792* } );
10793* } );
10794*/
10795"bServerSide": false,10796
10797
10798/**10799* Enable or disable sorting of columns. Sorting of individual columns can be
10800* disabled by the `sortable` option for each column.
10801* @type boolean
10802* @default true
10803*
10804* @dtopt Features
10805* @name DataTable.defaults.ordering
10806*
10807* @example
10808* $(document).ready( function () {
10809* $('#example').dataTable( {
10810* "ordering": false
10811* } );
10812* } );
10813*/
10814"bSort": true,10815
10816
10817/**10818* Enable or display DataTables' ability to sort multiple columns at the
10819* same time (activated by shift-click by the user).
10820* @type boolean
10821* @default true
10822*
10823* @dtopt Options
10824* @name DataTable.defaults.orderMulti
10825*
10826* @example
10827* // Disable multiple column sorting ability
10828* $(document).ready( function () {
10829* $('#example').dataTable( {
10830* "orderMulti": false
10831* } );
10832* } );
10833*/
10834"bSortMulti": true,10835
10836
10837/**10838* Allows control over whether DataTables should use the top (true) unique
10839* cell that is found for a single column, or the bottom (false - default).
10840* This is useful when using complex headers.
10841* @type boolean
10842* @default false
10843*
10844* @dtopt Options
10845* @name DataTable.defaults.orderCellsTop
10846*
10847* @example
10848* $(document).ready( function() {
10849* $('#example').dataTable( {
10850* "orderCellsTop": true
10851* } );
10852* } );
10853*/
10854"bSortCellsTop": false,10855
10856
10857/**10858* Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10859* `sorting\_3` to the columns which are currently being sorted on. This is
10860* presented as a feature switch as it can increase processing time (while
10861* classes are removed and added) so for large data sets you might want to
10862* turn this off.
10863* @type boolean
10864* @default true
10865*
10866* @dtopt Features
10867* @name DataTable.defaults.orderClasses
10868*
10869* @example
10870* $(document).ready( function () {
10871* $('#example').dataTable( {
10872* "orderClasses": false
10873* } );
10874* } );
10875*/
10876"bSortClasses": true,10877
10878
10879/**10880* Enable or disable state saving. When enabled HTML5 `localStorage` will be
10881* used to save table display information such as pagination information,
10882* display length, filtering and sorting. As such when the end user reloads
10883* the page the display display will match what thy had previously set up.
10884*
10885* Due to the use of `localStorage` the default state saving is not supported
10886* in IE6 or 7. If state saving is required in those browsers, use
10887* `stateSaveCallback` to provide a storage solution such as cookies.
10888* @type boolean
10889* @default false
10890*
10891* @dtopt Features
10892* @name DataTable.defaults.stateSave
10893*
10894* @example
10895* $(document).ready( function () {
10896* $('#example').dataTable( {
10897* "stateSave": true
10898* } );
10899* } );
10900*/
10901"bStateSave": false,10902
10903
10904/**10905* This function is called when a TR element is created (and all TD child
10906* elements have been inserted), or registered if using a DOM source, allowing
10907* manipulation of the TR element (adding classes etc).
10908* @type function
10909* @param {node} row "TR" element for the current row
10910* @param {array} data Raw data array for this row
10911* @param {int} dataIndex The index of this row in the internal aoData array
10912*
10913* @dtopt Callbacks
10914* @name DataTable.defaults.createdRow
10915*
10916* @example
10917* $(document).ready( function() {
10918* $('#example').dataTable( {
10919* "createdRow": function( row, data, dataIndex ) {
10920* // Bold the grade for all 'A' grade browsers
10921* if ( data[4] == "A" )
10922* {
10923* $('td:eq(4)', row).html( '<b>A</b>' );
10924* }
10925* }
10926* } );
10927* } );
10928*/
10929"fnCreatedRow": null,10930
10931
10932/**10933* This function is called on every 'draw' event, and allows you to
10934* dynamically modify any aspect you want about the created DOM.
10935* @type function
10936* @param {object} settings DataTables settings object
10937*
10938* @dtopt Callbacks
10939* @name DataTable.defaults.drawCallback
10940*
10941* @example
10942* $(document).ready( function() {
10943* $('#example').dataTable( {
10944* "drawCallback": function( settings ) {
10945* alert( 'DataTables has redrawn the table' );
10946* }
10947* } );
10948* } );
10949*/
10950"fnDrawCallback": null,10951
10952
10953/**10954* Identical to fnHeaderCallback() but for the table footer this function
10955* allows you to modify the table footer on every 'draw' event.
10956* @type function
10957* @param {node} foot "TR" element for the footer
10958* @param {array} data Full table data (as derived from the original HTML)
10959* @param {int} start Index for the current display starting point in the
10960* display array
10961* @param {int} end Index for the current display ending point in the
10962* display array
10963* @param {array int} display Index array to translate the visual position
10964* to the full data array
10965*
10966* @dtopt Callbacks
10967* @name DataTable.defaults.footerCallback
10968*
10969* @example
10970* $(document).ready( function() {
10971* $('#example').dataTable( {
10972* "footerCallback": function( tfoot, data, start, end, display ) {
10973* tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10974* }
10975* } );
10976* } )
10977*/
10978"fnFooterCallback": null,10979
10980
10981/**10982* When rendering large numbers in the information element for the table
10983* (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10984* to have a comma separator for the 'thousands' units (e.g. 1 million is
10985* rendered as "1,000,000") to help readability for the end user. This
10986* function will override the default method DataTables uses.
10987* @type function
10988* @member
10989* @param {int} toFormat number to be formatted
10990* @returns {string} formatted string for DataTables to show the number
10991*
10992* @dtopt Callbacks
10993* @name DataTable.defaults.formatNumber
10994*
10995* @example
10996* // Format a number using a single quote for the separator (note that
10997* // this can also be done with the language.thousands option)
10998* $(document).ready( function() {
10999* $('#example').dataTable( {
11000* "formatNumber": function ( toFormat ) {
11001* return toFormat.toString().replace(
11002* /\B(?=(\d{3})+(?!\d))/g, "'"
11003* );
11004* };
11005* } );
11006* } );
11007*/
11008"fnFormatNumber": function ( toFormat ) {11009return toFormat.toString().replace(11010/\B(?=(\d{3})+(?!\d))/g,11011this.oLanguage.sThousands11012);11013},11014
11015
11016/**11017* This function is called on every 'draw' event, and allows you to
11018* dynamically modify the header row. This can be used to calculate and
11019* display useful information about the table.
11020* @type function
11021* @param {node} head "TR" element for the header
11022* @param {array} data Full table data (as derived from the original HTML)
11023* @param {int} start Index for the current display starting point in the
11024* display array
11025* @param {int} end Index for the current display ending point in the
11026* display array
11027* @param {array int} display Index array to translate the visual position
11028* to the full data array
11029*
11030* @dtopt Callbacks
11031* @name DataTable.defaults.headerCallback
11032*
11033* @example
11034* $(document).ready( function() {
11035* $('#example').dataTable( {
11036* "fheaderCallback": function( head, data, start, end, display ) {
11037* head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
11038* }
11039* } );
11040* } )
11041*/
11042"fnHeaderCallback": null,11043
11044
11045/**11046* The information element can be used to convey information about the current
11047* state of the table. Although the internationalisation options presented by
11048* DataTables are quite capable of dealing with most customisations, there may
11049* be times where you wish to customise the string further. This callback
11050* allows you to do exactly that.
11051* @type function
11052* @param {object} oSettings DataTables settings object
11053* @param {int} start Starting position in data for the draw
11054* @param {int} end End position in data for the draw
11055* @param {int} max Total number of rows in the table (regardless of
11056* filtering)
11057* @param {int} total Total number of rows in the data set, after filtering
11058* @param {string} pre The string that DataTables has formatted using it's
11059* own rules
11060* @returns {string} The string to be displayed in the information element.
11061*
11062* @dtopt Callbacks
11063* @name DataTable.defaults.infoCallback
11064*
11065* @example
11066* $('#example').dataTable( {
11067* "infoCallback": function( settings, start, end, max, total, pre ) {
11068* return start +" to "+ end;
11069* }
11070* } );
11071*/
11072"fnInfoCallback": null,11073
11074
11075/**11076* Called when the table has been initialised. Normally DataTables will
11077* initialise sequentially and there will be no need for this function,
11078* however, this does not hold true when using external language information
11079* since that is obtained using an async XHR call.
11080* @type function
11081* @param {object} settings DataTables settings object
11082* @param {object} json The JSON object request from the server - only
11083* present if client-side Ajax sourced data is used
11084*
11085* @dtopt Callbacks
11086* @name DataTable.defaults.initComplete
11087*
11088* @example
11089* $(document).ready( function() {
11090* $('#example').dataTable( {
11091* "initComplete": function(settings, json) {
11092* alert( 'DataTables has finished its initialisation.' );
11093* }
11094* } );
11095* } )
11096*/
11097"fnInitComplete": null,11098
11099
11100/**11101* Called at the very start of each table draw and can be used to cancel the
11102* draw by returning false, any other return (including undefined) results in
11103* the full draw occurring).
11104* @type function
11105* @param {object} settings DataTables settings object
11106* @returns {boolean} False will cancel the draw, anything else (including no
11107* return) will allow it to complete.
11108*
11109* @dtopt Callbacks
11110* @name DataTable.defaults.preDrawCallback
11111*
11112* @example
11113* $(document).ready( function() {
11114* $('#example').dataTable( {
11115* "preDrawCallback": function( settings ) {
11116* if ( $('#test').val() == 1 ) {
11117* return false;
11118* }
11119* }
11120* } );
11121* } );
11122*/
11123"fnPreDrawCallback": null,11124
11125
11126/**11127* This function allows you to 'post process' each row after it have been
11128* generated for each table draw, but before it is rendered on screen. This
11129* function might be used for setting the row class name etc.
11130* @type function
11131* @param {node} row "TR" element for the current row
11132* @param {array} data Raw data array for this row
11133* @param {int} displayIndex The display index for the current table draw
11134* @param {int} displayIndexFull The index of the data in the full list of
11135* rows (after filtering)
11136*
11137* @dtopt Callbacks
11138* @name DataTable.defaults.rowCallback
11139*
11140* @example
11141* $(document).ready( function() {
11142* $('#example').dataTable( {
11143* "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
11144* // Bold the grade for all 'A' grade browsers
11145* if ( data[4] == "A" ) {
11146* $('td:eq(4)', row).html( '<b>A</b>' );
11147* }
11148* }
11149* } );
11150* } );
11151*/
11152"fnRowCallback": null,11153
11154
11155/**11156* __Deprecated__ The functionality provided by this parameter has now been
11157* superseded by that provided through `ajax`, which should be used instead.
11158*
11159* This parameter allows you to override the default function which obtains
11160* the data from the server so something more suitable for your application.
11161* For example you could use POST data, or pull information from a Gears or
11162* AIR database.
11163* @type function
11164* @member
11165* @param {string} source HTTP source to obtain the data from (`ajax`)
11166* @param {array} data A key/value pair object containing the data to send
11167* to the server
11168* @param {function} callback to be called on completion of the data get
11169* process that will draw the data on the page.
11170* @param {object} settings DataTables settings object
11171*
11172* @dtopt Callbacks
11173* @dtopt Server-side
11174* @name DataTable.defaults.serverData
11175*
11176* @deprecated 1.10. Please use `ajax` for this functionality now.
11177*/
11178"fnServerData": null,11179
11180
11181/**11182* __Deprecated__ The functionality provided by this parameter has now been
11183* superseded by that provided through `ajax`, which should be used instead.
11184*
11185* It is often useful to send extra data to the server when making an Ajax
11186* request - for example custom filtering information, and this callback
11187* function makes it trivial to send extra information to the server. The
11188* passed in parameter is the data set that has been constructed by
11189* DataTables, and you can add to this or modify it as you require.
11190* @type function
11191* @param {array} data Data array (array of objects which are name/value
11192* pairs) that has been constructed by DataTables and will be sent to the
11193* server. In the case of Ajax sourced data with server-side processing
11194* this will be an empty array, for server-side processing there will be a
11195* significant number of parameters!
11196* @returns {undefined} Ensure that you modify the data array passed in,
11197* as this is passed by reference.
11198*
11199* @dtopt Callbacks
11200* @dtopt Server-side
11201* @name DataTable.defaults.serverParams
11202*
11203* @deprecated 1.10. Please use `ajax` for this functionality now.
11204*/
11205"fnServerParams": null,11206
11207
11208/**11209* Load the table state. With this function you can define from where, and how, the
11210* state of a table is loaded. By default DataTables will load from `localStorage`
11211* but you might wish to use a server-side database or cookies.
11212* @type function
11213* @member
11214* @param {object} settings DataTables settings object
11215* @param {object} callback Callback that can be executed when done. It
11216* should be passed the loaded state object.
11217* @return {object} The DataTables state object to be loaded
11218*
11219* @dtopt Callbacks
11220* @name DataTable.defaults.stateLoadCallback
11221*
11222* @example
11223* $(document).ready( function() {
11224* $('#example').dataTable( {
11225* "stateSave": true,
11226* "stateLoadCallback": function (settings, callback) {
11227* $.ajax( {
11228* "url": "/state_load",
11229* "dataType": "json",
11230* "success": function (json) {
11231* callback( json );
11232* }
11233* } );
11234* }
11235* } );
11236* } );
11237*/
11238"fnStateLoadCallback": function ( settings ) {11239try {11240return JSON.parse(11241(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(11242'DataTables_'+settings.sInstance+'_'+location.pathname11243)11244);11245} catch (e) {11246return {};11247}11248},11249
11250
11251/**11252* Callback which allows modification of the saved state prior to loading that state.
11253* This callback is called when the table is loading state from the stored data, but
11254* prior to the settings object being modified by the saved state. Note that for
11255* plug-in authors, you should use the `stateLoadParams` event to load parameters for
11256* a plug-in.
11257* @type function
11258* @param {object} settings DataTables settings object
11259* @param {object} data The state object that is to be loaded
11260*
11261* @dtopt Callbacks
11262* @name DataTable.defaults.stateLoadParams
11263*
11264* @example
11265* // Remove a saved filter, so filtering is never loaded
11266* $(document).ready( function() {
11267* $('#example').dataTable( {
11268* "stateSave": true,
11269* "stateLoadParams": function (settings, data) {
11270* data.oSearch.sSearch = "";
11271* }
11272* } );
11273* } );
11274*
11275* @example
11276* // Disallow state loading by returning false
11277* $(document).ready( function() {
11278* $('#example').dataTable( {
11279* "stateSave": true,
11280* "stateLoadParams": function (settings, data) {
11281* return false;
11282* }
11283* } );
11284* } );
11285*/
11286"fnStateLoadParams": null,11287
11288
11289/**11290* Callback that is called when the state has been loaded from the state saving method
11291* and the DataTables settings object has been modified as a result of the loaded state.
11292* @type function
11293* @param {object} settings DataTables settings object
11294* @param {object} data The state object that was loaded
11295*
11296* @dtopt Callbacks
11297* @name DataTable.defaults.stateLoaded
11298*
11299* @example
11300* // Show an alert with the filtering value that was saved
11301* $(document).ready( function() {
11302* $('#example').dataTable( {
11303* "stateSave": true,
11304* "stateLoaded": function (settings, data) {
11305* alert( 'Saved filter was: '+data.oSearch.sSearch );
11306* }
11307* } );
11308* } );
11309*/
11310"fnStateLoaded": null,11311
11312
11313/**11314* Save the table state. This function allows you to define where and how the state
11315* information for the table is stored By default DataTables will use `localStorage`
11316* but you might wish to use a server-side database or cookies.
11317* @type function
11318* @member
11319* @param {object} settings DataTables settings object
11320* @param {object} data The state object to be saved
11321*
11322* @dtopt Callbacks
11323* @name DataTable.defaults.stateSaveCallback
11324*
11325* @example
11326* $(document).ready( function() {
11327* $('#example').dataTable( {
11328* "stateSave": true,
11329* "stateSaveCallback": function (settings, data) {
11330* // Send an Ajax request to the server with the state object
11331* $.ajax( {
11332* "url": "/state_save",
11333* "data": data,
11334* "dataType": "json",
11335* "method": "POST"
11336* "success": function () {}
11337* } );
11338* }
11339* } );
11340* } );
11341*/
11342"fnStateSaveCallback": function ( settings, data ) {11343try {11344(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(11345'DataTables_'+settings.sInstance+'_'+location.pathname,11346JSON.stringify( data )11347);11348} catch (e) {}11349},11350
11351
11352/**11353* Callback which allows modification of the state to be saved. Called when the table
11354* has changed state a new state save is required. This method allows modification of
11355* the state saving object prior to actually doing the save, including addition or
11356* other state properties or modification. Note that for plug-in authors, you should
11357* use the `stateSaveParams` event to save parameters for a plug-in.
11358* @type function
11359* @param {object} settings DataTables settings object
11360* @param {object} data The state object to be saved
11361*
11362* @dtopt Callbacks
11363* @name DataTable.defaults.stateSaveParams
11364*
11365* @example
11366* // Remove a saved filter, so filtering is never saved
11367* $(document).ready( function() {
11368* $('#example').dataTable( {
11369* "stateSave": true,
11370* "stateSaveParams": function (settings, data) {
11371* data.oSearch.sSearch = "";
11372* }
11373* } );
11374* } );
11375*/
11376"fnStateSaveParams": null,11377
11378
11379/**11380* Duration for which the saved state information is considered valid. After this period
11381* has elapsed the state will be returned to the default.
11382* Value is given in seconds.
11383* @type int
11384* @default 7200 <i>(2 hours)</i>
11385*
11386* @dtopt Options
11387* @name DataTable.defaults.stateDuration
11388*
11389* @example
11390* $(document).ready( function() {
11391* $('#example').dataTable( {
11392* "stateDuration": 60*60*24; // 1 day
11393* } );
11394* } )
11395*/
11396"iStateDuration": 7200,11397
11398
11399/**11400* When enabled DataTables will not make a request to the server for the first
11401* page draw - rather it will use the data already on the page (no sorting etc
11402* will be applied to it), thus saving on an XHR at load time. `deferLoading`
11403* is used to indicate that deferred loading is required, but it is also used
11404* to tell DataTables how many records there are in the full table (allowing
11405* the information element and pagination to be displayed correctly). In the case
11406* where a filtering is applied to the table on initial load, this can be
11407* indicated by giving the parameter as an array, where the first element is
11408* the number of records available after filtering and the second element is the
11409* number of records without filtering (allowing the table information element
11410* to be shown correctly).
11411* @type int | array
11412* @default null
11413*
11414* @dtopt Options
11415* @name DataTable.defaults.deferLoading
11416*
11417* @example
11418* // 57 records available in the table, no filtering applied
11419* $(document).ready( function() {
11420* $('#example').dataTable( {
11421* "serverSide": true,
11422* "ajax": "scripts/server_processing.php",
11423* "deferLoading": 57
11424* } );
11425* } );
11426*
11427* @example
11428* // 57 records after filtering, 100 without filtering (an initial filter applied)
11429* $(document).ready( function() {
11430* $('#example').dataTable( {
11431* "serverSide": true,
11432* "ajax": "scripts/server_processing.php",
11433* "deferLoading": [ 57, 100 ],
11434* "search": {
11435* "search": "my_filter"
11436* }
11437* } );
11438* } );
11439*/
11440"iDeferLoading": null,11441
11442
11443/**11444* Number of rows to display on a single page when using pagination. If
11445* feature enabled (`lengthChange`) then the end user will be able to override
11446* this to a custom setting using a pop-up menu.
11447* @type int
11448* @default 10
11449*
11450* @dtopt Options
11451* @name DataTable.defaults.pageLength
11452*
11453* @example
11454* $(document).ready( function() {
11455* $('#example').dataTable( {
11456* "pageLength": 50
11457* } );
11458* } )
11459*/
11460"iDisplayLength": 10,11461
11462
11463/**11464* Define the starting point for data display when using DataTables with
11465* pagination. Note that this parameter is the number of records, rather than
11466* the page number, so if you have 10 records per page and want to start on
11467* the third page, it should be "20".
11468* @type int
11469* @default 0
11470*
11471* @dtopt Options
11472* @name DataTable.defaults.displayStart
11473*
11474* @example
11475* $(document).ready( function() {
11476* $('#example').dataTable( {
11477* "displayStart": 20
11478* } );
11479* } )
11480*/
11481"iDisplayStart": 0,11482
11483
11484/**11485* By default DataTables allows keyboard navigation of the table (sorting, paging,
11486* and filtering) by adding a `tabindex` attribute to the required elements. This
11487* allows you to tab through the controls and press the enter key to activate them.
11488* The tabindex is default 0, meaning that the tab follows the flow of the document.
11489* You can overrule this using this parameter if you wish. Use a value of -1 to
11490* disable built-in keyboard navigation.
11491* @type int
11492* @default 0
11493*
11494* @dtopt Options
11495* @name DataTable.defaults.tabIndex
11496*
11497* @example
11498* $(document).ready( function() {
11499* $('#example').dataTable( {
11500* "tabIndex": 1
11501* } );
11502* } );
11503*/
11504"iTabIndex": 0,11505
11506
11507/**11508* Classes that DataTables assigns to the various components and features
11509* that it adds to the HTML table. This allows classes to be configured
11510* during initialisation in addition to through the static
11511* {@link DataTable.ext.oStdClasses} object).
11512* @namespace
11513* @name DataTable.defaults.classes
11514*/
11515"oClasses": {},11516
11517
11518/**11519* All strings that DataTables uses in the user interface that it creates
11520* are defined in this object, allowing you to modified them individually or
11521* completely replace them all as required.
11522* @namespace
11523* @name DataTable.defaults.language
11524*/
11525"oLanguage": {11526/**11527* Strings that are used for WAI-ARIA labels and controls only (these are not
11528* actually visible on the page, but will be read by screenreaders, and thus
11529* must be internationalised as well).
11530* @namespace
11531* @name DataTable.defaults.language.aria
11532*/
11533"oAria": {11534/**11535* ARIA label that is added to the table headers when the column may be
11536* sorted ascending by activing the column (click or return when focused).
11537* Note that the column header is prefixed to this string.
11538* @type string
11539* @default : activate to sort column ascending
11540*
11541* @dtopt Language
11542* @name DataTable.defaults.language.aria.sortAscending
11543*
11544* @example
11545* $(document).ready( function() {
11546* $('#example').dataTable( {
11547* "language": {
11548* "aria": {
11549* "sortAscending": " - click/return to sort ascending"
11550* }
11551* }
11552* } );
11553* } );
11554*/
11555"sSortAscending": ": activate to sort column ascending",11556
11557/**11558* ARIA label that is added to the table headers when the column may be
11559* sorted descending by activing the column (click or return when focused).
11560* Note that the column header is prefixed to this string.
11561* @type string
11562* @default : activate to sort column ascending
11563*
11564* @dtopt Language
11565* @name DataTable.defaults.language.aria.sortDescending
11566*
11567* @example
11568* $(document).ready( function() {
11569* $('#example').dataTable( {
11570* "language": {
11571* "aria": {
11572* "sortDescending": " - click/return to sort descending"
11573* }
11574* }
11575* } );
11576* } );
11577*/
11578"sSortDescending": ": activate to sort column descending"11579},11580
11581/**11582* Pagination string used by DataTables for the built-in pagination
11583* control types.
11584* @namespace
11585* @name DataTable.defaults.language.paginate
11586*/
11587"oPaginate": {11588/**11589* Text to use when using the 'full_numbers' type of pagination for the
11590* button to take the user to the first page.
11591* @type string
11592* @default First
11593*
11594* @dtopt Language
11595* @name DataTable.defaults.language.paginate.first
11596*
11597* @example
11598* $(document).ready( function() {
11599* $('#example').dataTable( {
11600* "language": {
11601* "paginate": {
11602* "first": "First page"
11603* }
11604* }
11605* } );
11606* } );
11607*/
11608"sFirst": "First",11609
11610
11611/**11612* Text to use when using the 'full_numbers' type of pagination for the
11613* button to take the user to the last page.
11614* @type string
11615* @default Last
11616*
11617* @dtopt Language
11618* @name DataTable.defaults.language.paginate.last
11619*
11620* @example
11621* $(document).ready( function() {
11622* $('#example').dataTable( {
11623* "language": {
11624* "paginate": {
11625* "last": "Last page"
11626* }
11627* }
11628* } );
11629* } );
11630*/
11631"sLast": "Last",11632
11633
11634/**11635* Text to use for the 'next' pagination button (to take the user to the
11636* next page).
11637* @type string
11638* @default Next
11639*
11640* @dtopt Language
11641* @name DataTable.defaults.language.paginate.next
11642*
11643* @example
11644* $(document).ready( function() {
11645* $('#example').dataTable( {
11646* "language": {
11647* "paginate": {
11648* "next": "Next page"
11649* }
11650* }
11651* } );
11652* } );
11653*/
11654"sNext": "Next",11655
11656
11657/**11658* Text to use for the 'previous' pagination button (to take the user to
11659* the previous page).
11660* @type string
11661* @default Previous
11662*
11663* @dtopt Language
11664* @name DataTable.defaults.language.paginate.previous
11665*
11666* @example
11667* $(document).ready( function() {
11668* $('#example').dataTable( {
11669* "language": {
11670* "paginate": {
11671* "previous": "Previous page"
11672* }
11673* }
11674* } );
11675* } );
11676*/
11677"sPrevious": "Previous"11678},11679
11680/**11681* This string is shown in preference to `zeroRecords` when the table is
11682* empty of data (regardless of filtering). Note that this is an optional
11683* parameter - if it is not given, the value of `zeroRecords` will be used
11684* instead (either the default or given value).
11685* @type string
11686* @default No data available in table
11687*
11688* @dtopt Language
11689* @name DataTable.defaults.language.emptyTable
11690*
11691* @example
11692* $(document).ready( function() {
11693* $('#example').dataTable( {
11694* "language": {
11695* "emptyTable": "No data available in table"
11696* }
11697* } );
11698* } );
11699*/
11700"sEmptyTable": "No data available in table",11701
11702
11703/**11704* This string gives information to the end user about the information
11705* that is current on display on the page. The following tokens can be
11706* used in the string and will be dynamically replaced as the table
11707* display updates. This tokens can be placed anywhere in the string, or
11708* removed as needed by the language requires:
11709*
11710* * `\_START\_` - Display index of the first record on the current page
11711* * `\_END\_` - Display index of the last record on the current page
11712* * `\_TOTAL\_` - Number of records in the table after filtering
11713* * `\_MAX\_` - Number of records in the table without filtering
11714* * `\_PAGE\_` - Current page number
11715* * `\_PAGES\_` - Total number of pages of data in the table
11716*
11717* @type string
11718* @default Showing _START_ to _END_ of _TOTAL_ entries
11719*
11720* @dtopt Language
11721* @name DataTable.defaults.language.info
11722*
11723* @example
11724* $(document).ready( function() {
11725* $('#example').dataTable( {
11726* "language": {
11727* "info": "Showing page _PAGE_ of _PAGES_"
11728* }
11729* } );
11730* } );
11731*/
11732"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",11733
11734
11735/**11736* Display information string for when the table is empty. Typically the
11737* format of this string should match `info`.
11738* @type string
11739* @default Showing 0 to 0 of 0 entries
11740*
11741* @dtopt Language
11742* @name DataTable.defaults.language.infoEmpty
11743*
11744* @example
11745* $(document).ready( function() {
11746* $('#example').dataTable( {
11747* "language": {
11748* "infoEmpty": "No entries to show"
11749* }
11750* } );
11751* } );
11752*/
11753"sInfoEmpty": "Showing 0 to 0 of 0 entries",11754
11755
11756/**11757* When a user filters the information in a table, this string is appended
11758* to the information (`info`) to give an idea of how strong the filtering
11759* is. The variable _MAX_ is dynamically updated.
11760* @type string
11761* @default (filtered from _MAX_ total entries)
11762*
11763* @dtopt Language
11764* @name DataTable.defaults.language.infoFiltered
11765*
11766* @example
11767* $(document).ready( function() {
11768* $('#example').dataTable( {
11769* "language": {
11770* "infoFiltered": " - filtering from _MAX_ records"
11771* }
11772* } );
11773* } );
11774*/
11775"sInfoFiltered": "(filtered from _MAX_ total entries)",11776
11777
11778/**11779* If can be useful to append extra information to the info string at times,
11780* and this variable does exactly that. This information will be appended to
11781* the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11782* being used) at all times.
11783* @type string
11784* @default <i>Empty string</i>
11785*
11786* @dtopt Language
11787* @name DataTable.defaults.language.infoPostFix
11788*
11789* @example
11790* $(document).ready( function() {
11791* $('#example').dataTable( {
11792* "language": {
11793* "infoPostFix": "All records shown are derived from real information."
11794* }
11795* } );
11796* } );
11797*/
11798"sInfoPostFix": "",11799
11800
11801/**11802* This decimal place operator is a little different from the other
11803* language options since DataTables doesn't output floating point
11804* numbers, so it won't ever use this for display of a number. Rather,
11805* what this parameter does is modify the sort methods of the table so
11806* that numbers which are in a format which has a character other than
11807* a period (`.`) as a decimal place will be sorted numerically.
11808*
11809* Note that numbers with different decimal places cannot be shown in
11810* the same table and still be sortable, the table must be consistent.
11811* However, multiple different tables on the page can use different
11812* decimal place characters.
11813* @type string
11814* @default
11815*
11816* @dtopt Language
11817* @name DataTable.defaults.language.decimal
11818*
11819* @example
11820* $(document).ready( function() {
11821* $('#example').dataTable( {
11822* "language": {
11823* "decimal": ","
11824* "thousands": "."
11825* }
11826* } );
11827* } );
11828*/
11829"sDecimal": "",11830
11831
11832/**11833* DataTables has a build in number formatter (`formatNumber`) which is
11834* used to format large numbers that are used in the table information.
11835* By default a comma is used, but this can be trivially changed to any
11836* character you wish with this parameter.
11837* @type string
11838* @default ,
11839*
11840* @dtopt Language
11841* @name DataTable.defaults.language.thousands
11842*
11843* @example
11844* $(document).ready( function() {
11845* $('#example').dataTable( {
11846* "language": {
11847* "thousands": "'"
11848* }
11849* } );
11850* } );
11851*/
11852"sThousands": ",",11853
11854
11855/**11856* Detail the action that will be taken when the drop down menu for the
11857* pagination length option is changed. The '_MENU_' variable is replaced
11858* with a default select list of 10, 25, 50 and 100, and can be replaced
11859* with a custom select box if required.
11860* @type string
11861* @default Show _MENU_ entries
11862*
11863* @dtopt Language
11864* @name DataTable.defaults.language.lengthMenu
11865*
11866* @example
11867* // Language change only
11868* $(document).ready( function() {
11869* $('#example').dataTable( {
11870* "language": {
11871* "lengthMenu": "Display _MENU_ records"
11872* }
11873* } );
11874* } );
11875*
11876* @example
11877* // Language and options change
11878* $(document).ready( function() {
11879* $('#example').dataTable( {
11880* "language": {
11881* "lengthMenu": 'Display <select>'+
11882* '<option value="10">10</option>'+
11883* '<option value="20">20</option>'+
11884* '<option value="30">30</option>'+
11885* '<option value="40">40</option>'+
11886* '<option value="50">50</option>'+
11887* '<option value="-1">All</option>'+
11888* '</select> records'
11889* }
11890* } );
11891* } );
11892*/
11893"sLengthMenu": "Show _MENU_ entries",11894
11895
11896/**11897* When using Ajax sourced data and during the first draw when DataTables is
11898* gathering the data, this message is shown in an empty row in the table to
11899* indicate to the end user the the data is being loaded. Note that this
11900* parameter is not used when loading data by server-side processing, just
11901* Ajax sourced data with client-side processing.
11902* @type string
11903* @default Loading...
11904*
11905* @dtopt Language
11906* @name DataTable.defaults.language.loadingRecords
11907*
11908* @example
11909* $(document).ready( function() {
11910* $('#example').dataTable( {
11911* "language": {
11912* "loadingRecords": "Please wait - loading..."
11913* }
11914* } );
11915* } );
11916*/
11917"sLoadingRecords": "Loading...",11918
11919
11920/**11921* Text which is displayed when the table is processing a user action
11922* (usually a sort command or similar).
11923* @type string
11924*
11925* @dtopt Language
11926* @name DataTable.defaults.language.processing
11927*
11928* @example
11929* $(document).ready( function() {
11930* $('#example').dataTable( {
11931* "language": {
11932* "processing": "DataTables is currently busy"
11933* }
11934* } );
11935* } );
11936*/
11937"sProcessing": "",11938
11939
11940/**11941* Details the actions that will be taken when the user types into the
11942* filtering input text box. The variable "_INPUT_", if used in the string,
11943* is replaced with the HTML text box for the filtering input allowing
11944* control over where it appears in the string. If "_INPUT_" is not given
11945* then the input box is appended to the string automatically.
11946* @type string
11947* @default Search:
11948*
11949* @dtopt Language
11950* @name DataTable.defaults.language.search
11951*
11952* @example
11953* // Input text box will be appended at the end automatically
11954* $(document).ready( function() {
11955* $('#example').dataTable( {
11956* "language": {
11957* "search": "Filter records:"
11958* }
11959* } );
11960* } );
11961*
11962* @example
11963* // Specify where the filter should appear
11964* $(document).ready( function() {
11965* $('#example').dataTable( {
11966* "language": {
11967* "search": "Apply filter _INPUT_ to table"
11968* }
11969* } );
11970* } );
11971*/
11972"sSearch": "Search:",11973
11974
11975/**11976* Assign a `placeholder` attribute to the search `input` element
11977* @type string
11978* @default
11979*
11980* @dtopt Language
11981* @name DataTable.defaults.language.searchPlaceholder
11982*/
11983"sSearchPlaceholder": "",11984
11985
11986/**11987* All of the language information can be stored in a file on the
11988* server-side, which DataTables will look up if this parameter is passed.
11989* It must store the URL of the language file, which is in a JSON format,
11990* and the object has the same properties as the oLanguage object in the
11991* initialiser object (i.e. the above parameters). Please refer to one of
11992* the example language files to see how this works in action.
11993* @type string
11994* @default <i>Empty string - i.e. disabled</i>
11995*
11996* @dtopt Language
11997* @name DataTable.defaults.language.url
11998*
11999* @example
12000* $(document).ready( function() {
12001* $('#example').dataTable( {
12002* "language": {
12003* "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
12004* }
12005* } );
12006* } );
12007*/
12008"sUrl": "",12009
12010
12011/**12012* Text shown inside the table records when the is no information to be
12013* displayed after filtering. `emptyTable` is shown when there is simply no
12014* information in the table at all (regardless of filtering).
12015* @type string
12016* @default No matching records found
12017*
12018* @dtopt Language
12019* @name DataTable.defaults.language.zeroRecords
12020*
12021* @example
12022* $(document).ready( function() {
12023* $('#example').dataTable( {
12024* "language": {
12025* "zeroRecords": "No records to display"
12026* }
12027* } );
12028* } );
12029*/
12030"sZeroRecords": "No matching records found"12031},12032
12033
12034/**12035* This parameter allows you to have define the global filtering state at
12036* initialisation time. As an object the `search` parameter must be
12037* defined, but all other parameters are optional. When `regex` is true,
12038* the search string will be treated as a regular expression, when false
12039* (default) it will be treated as a straight string. When `smart`
12040* DataTables will use it's smart filtering methods (to word match at
12041* any point in the data), when false this will not be done.
12042* @namespace
12043* @extends DataTable.models.oSearch
12044*
12045* @dtopt Options
12046* @name DataTable.defaults.search
12047*
12048* @example
12049* $(document).ready( function() {
12050* $('#example').dataTable( {
12051* "search": {"search": "Initial search"}
12052* } );
12053* } )
12054*/
12055"oSearch": $.extend( {}, DataTable.models.oSearch ),12056
12057
12058/**12059* __Deprecated__ The functionality provided by this parameter has now been
12060* superseded by that provided through `ajax`, which should be used instead.
12061*
12062* By default DataTables will look for the property `data` (or `aaData` for
12063* compatibility with DataTables 1.9-) when obtaining data from an Ajax
12064* source or for server-side processing - this parameter allows that
12065* property to be changed. You can use Javascript dotted object notation to
12066* get a data source for multiple levels of nesting.
12067* @type string
12068* @default data
12069*
12070* @dtopt Options
12071* @dtopt Server-side
12072* @name DataTable.defaults.ajaxDataProp
12073*
12074* @deprecated 1.10. Please use `ajax` for this functionality now.
12075*/
12076"sAjaxDataProp": "data",12077
12078
12079/**12080* __Deprecated__ The functionality provided by this parameter has now been
12081* superseded by that provided through `ajax`, which should be used instead.
12082*
12083* You can instruct DataTables to load data from an external
12084* source using this parameter (use aData if you want to pass data in you
12085* already have). Simply provide a url a JSON object can be obtained from.
12086* @type string
12087* @default null
12088*
12089* @dtopt Options
12090* @dtopt Server-side
12091* @name DataTable.defaults.ajaxSource
12092*
12093* @deprecated 1.10. Please use `ajax` for this functionality now.
12094*/
12095"sAjaxSource": null,12096
12097
12098/**12099* This initialisation variable allows you to specify exactly where in the
12100* DOM you want DataTables to inject the various controls it adds to the page
12101* (for example you might want the pagination controls at the top of the
12102* table). DIV elements (with or without a custom class) can also be added to
12103* aid styling. The follow syntax is used:
12104* <ul>
12105* <li>The following options are allowed:
12106* <ul>
12107* <li>'l' - Length changing</li>
12108* <li>'f' - Filtering input</li>
12109* <li>'t' - The table!</li>
12110* <li>'i' - Information</li>
12111* <li>'p' - Pagination</li>
12112* <li>'r' - pRocessing</li>
12113* </ul>
12114* </li>
12115* <li>The following constants are allowed:
12116* <ul>
12117* <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
12118* <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
12119* </ul>
12120* </li>
12121* <li>The following syntax is expected:
12122* <ul>
12123* <li>'<' and '>' - div elements</li>
12124* <li>'<"class" and '>' - div with a class</li>
12125* <li>'<"#id" and '>' - div with an ID</li>
12126* </ul>
12127* </li>
12128* <li>Examples:
12129* <ul>
12130* <li>'<"wrapper"flipt>'</li>
12131* <li>'<lf<t>ip>'</li>
12132* </ul>
12133* </li>
12134* </ul>
12135* @type string
12136* @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
12137* <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
12138*
12139* @dtopt Options
12140* @name DataTable.defaults.dom
12141*
12142* @example
12143* $(document).ready( function() {
12144* $('#example').dataTable( {
12145* "dom": '<"top"i>rt<"bottom"flp><"clear">'
12146* } );
12147* } );
12148*/
12149"sDom": "lfrtip",12150
12151
12152/**12153* Search delay option. This will throttle full table searches that use the
12154* DataTables provided search input element (it does not effect calls to
12155* `dt-api search()`, providing a delay before the search is made.
12156* @type integer
12157* @default 0
12158*
12159* @dtopt Options
12160* @name DataTable.defaults.searchDelay
12161*
12162* @example
12163* $(document).ready( function() {
12164* $('#example').dataTable( {
12165* "searchDelay": 200
12166* } );
12167* } )
12168*/
12169"searchDelay": null,12170
12171
12172/**12173* DataTables features six different built-in options for the buttons to
12174* display for pagination control:
12175*
12176* * `numbers` - Page number buttons only
12177* * `simple` - 'Previous' and 'Next' buttons only
12178* * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
12179* * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
12180* * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
12181* * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
12182*
12183* Further methods can be added using {@link DataTable.ext.oPagination}.
12184* @type string
12185* @default simple_numbers
12186*
12187* @dtopt Options
12188* @name DataTable.defaults.pagingType
12189*
12190* @example
12191* $(document).ready( function() {
12192* $('#example').dataTable( {
12193* "pagingType": "full_numbers"
12194* } );
12195* } )
12196*/
12197"sPaginationType": "simple_numbers",12198
12199
12200/**12201* Enable horizontal scrolling. When a table is too wide to fit into a
12202* certain layout, or you have a large number of columns in the table, you
12203* can enable x-scrolling to show the table in a viewport, which can be
12204* scrolled. This property can be `true` which will allow the table to
12205* scroll horizontally when needed, or any CSS unit, or a number (in which
12206* case it will be treated as a pixel measurement). Setting as simply `true`
12207* is recommended.
12208* @type boolean|string
12209* @default <i>blank string - i.e. disabled</i>
12210*
12211* @dtopt Features
12212* @name DataTable.defaults.scrollX
12213*
12214* @example
12215* $(document).ready( function() {
12216* $('#example').dataTable( {
12217* "scrollX": true,
12218* "scrollCollapse": true
12219* } );
12220* } );
12221*/
12222"sScrollX": "",12223
12224
12225/**12226* This property can be used to force a DataTable to use more width than it
12227* might otherwise do when x-scrolling is enabled. For example if you have a
12228* table which requires to be well spaced, this parameter is useful for
12229* "over-sizing" the table, and thus forcing scrolling. This property can by
12230* any CSS unit, or a number (in which case it will be treated as a pixel
12231* measurement).
12232* @type string
12233* @default <i>blank string - i.e. disabled</i>
12234*
12235* @dtopt Options
12236* @name DataTable.defaults.scrollXInner
12237*
12238* @example
12239* $(document).ready( function() {
12240* $('#example').dataTable( {
12241* "scrollX": "100%",
12242* "scrollXInner": "110%"
12243* } );
12244* } );
12245*/
12246"sScrollXInner": "",12247
12248
12249/**12250* Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12251* to the given height, and enable scrolling for any data which overflows the
12252* current viewport. This can be used as an alternative to paging to display
12253* a lot of data in a small area (although paging and scrolling can both be
12254* enabled at the same time). This property can be any CSS unit, or a number
12255* (in which case it will be treated as a pixel measurement).
12256* @type string
12257* @default <i>blank string - i.e. disabled</i>
12258*
12259* @dtopt Features
12260* @name DataTable.defaults.scrollY
12261*
12262* @example
12263* $(document).ready( function() {
12264* $('#example').dataTable( {
12265* "scrollY": "200px",
12266* "paginate": false
12267* } );
12268* } );
12269*/
12270"sScrollY": "",12271
12272
12273/**12274* __Deprecated__ The functionality provided by this parameter has now been
12275* superseded by that provided through `ajax`, which should be used instead.
12276*
12277* Set the HTTP method that is used to make the Ajax call for server-side
12278* processing or Ajax sourced data.
12279* @type string
12280* @default GET
12281*
12282* @dtopt Options
12283* @dtopt Server-side
12284* @name DataTable.defaults.serverMethod
12285*
12286* @deprecated 1.10. Please use `ajax` for this functionality now.
12287*/
12288"sServerMethod": "GET",12289
12290
12291/**12292* DataTables makes use of renderers when displaying HTML elements for
12293* a table. These renderers can be added or modified by plug-ins to
12294* generate suitable mark-up for a site. For example the Bootstrap
12295* integration plug-in for DataTables uses a paging button renderer to
12296* display pagination buttons in the mark-up required by Bootstrap.
12297*
12298* For further information about the renderers available see
12299* DataTable.ext.renderer
12300* @type string|object
12301* @default null
12302*
12303* @name DataTable.defaults.renderer
12304*
12305*/
12306"renderer": null,12307
12308
12309/**12310* Set the data property name that DataTables should use to get a row's id
12311* to set as the `id` property in the node.
12312* @type string
12313* @default DT_RowId
12314*
12315* @name DataTable.defaults.rowId
12316*/
12317"rowId": "DT_RowId"12318};12319
12320_fnHungarianMap( DataTable.defaults );12321
12322
12323
12324/*
12325* Developer note - See note in model.defaults.js about the use of Hungarian
12326* notation and camel case.
12327*/
12328
12329/**
12330* Column options that can be given to DataTables at initialisation time.
12331* @namespace
12332*/
12333DataTable.defaults.column = {12334/**12335* Define which column(s) an order will occur on for this column. This
12336* allows a column's ordering to take multiple columns into account when
12337* doing a sort or use the data from a different column. For example first
12338* name / last name columns make sense to do a multi-column sort over the
12339* two columns.
12340* @type array|int
12341* @default null <i>Takes the value of the column index automatically</i>
12342*
12343* @name DataTable.defaults.column.orderData
12344* @dtopt Columns
12345*
12346* @example
12347* // Using `columnDefs`
12348* $(document).ready( function() {
12349* $('#example').dataTable( {
12350* "columnDefs": [
12351* { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12352* { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12353* { "orderData": 2, "targets": [ 2 ] }
12354* ]
12355* } );
12356* } );
12357*
12358* @example
12359* // Using `columns`
12360* $(document).ready( function() {
12361* $('#example').dataTable( {
12362* "columns": [
12363* { "orderData": [ 0, 1 ] },
12364* { "orderData": [ 1, 0 ] },
12365* { "orderData": 2 },
12366* null,
12367* null
12368* ]
12369* } );
12370* } );
12371*/
12372"aDataSort": null,12373"iDataSort": -1,12374
12375
12376/**12377* You can control the default ordering direction, and even alter the
12378* behaviour of the sort handler (i.e. only allow ascending ordering etc)
12379* using this parameter.
12380* @type array
12381* @default [ 'asc', 'desc' ]
12382*
12383* @name DataTable.defaults.column.orderSequence
12384* @dtopt Columns
12385*
12386* @example
12387* // Using `columnDefs`
12388* $(document).ready( function() {
12389* $('#example').dataTable( {
12390* "columnDefs": [
12391* { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12392* { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12393* { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12394* ]
12395* } );
12396* } );
12397*
12398* @example
12399* // Using `columns`
12400* $(document).ready( function() {
12401* $('#example').dataTable( {
12402* "columns": [
12403* null,
12404* { "orderSequence": [ "asc" ] },
12405* { "orderSequence": [ "desc", "asc", "asc" ] },
12406* { "orderSequence": [ "desc" ] },
12407* null
12408* ]
12409* } );
12410* } );
12411*/
12412"asSorting": [ 'asc', 'desc' ],12413
12414
12415/**12416* Enable or disable filtering on the data in this column.
12417* @type boolean
12418* @default true
12419*
12420* @name DataTable.defaults.column.searchable
12421* @dtopt Columns
12422*
12423* @example
12424* // Using `columnDefs`
12425* $(document).ready( function() {
12426* $('#example').dataTable( {
12427* "columnDefs": [
12428* { "searchable": false, "targets": [ 0 ] }
12429* ] } );
12430* } );
12431*
12432* @example
12433* // Using `columns`
12434* $(document).ready( function() {
12435* $('#example').dataTable( {
12436* "columns": [
12437* { "searchable": false },
12438* null,
12439* null,
12440* null,
12441* null
12442* ] } );
12443* } );
12444*/
12445"bSearchable": true,12446
12447
12448/**12449* Enable or disable ordering on this column.
12450* @type boolean
12451* @default true
12452*
12453* @name DataTable.defaults.column.orderable
12454* @dtopt Columns
12455*
12456* @example
12457* // Using `columnDefs`
12458* $(document).ready( function() {
12459* $('#example').dataTable( {
12460* "columnDefs": [
12461* { "orderable": false, "targets": [ 0 ] }
12462* ] } );
12463* } );
12464*
12465* @example
12466* // Using `columns`
12467* $(document).ready( function() {
12468* $('#example').dataTable( {
12469* "columns": [
12470* { "orderable": false },
12471* null,
12472* null,
12473* null,
12474* null
12475* ] } );
12476* } );
12477*/
12478"bSortable": true,12479
12480
12481/**12482* Enable or disable the display of this column.
12483* @type boolean
12484* @default true
12485*
12486* @name DataTable.defaults.column.visible
12487* @dtopt Columns
12488*
12489* @example
12490* // Using `columnDefs`
12491* $(document).ready( function() {
12492* $('#example').dataTable( {
12493* "columnDefs": [
12494* { "visible": false, "targets": [ 0 ] }
12495* ] } );
12496* } );
12497*
12498* @example
12499* // Using `columns`
12500* $(document).ready( function() {
12501* $('#example').dataTable( {
12502* "columns": [
12503* { "visible": false },
12504* null,
12505* null,
12506* null,
12507* null
12508* ] } );
12509* } );
12510*/
12511"bVisible": true,12512
12513
12514/**12515* Developer definable function that is called whenever a cell is created (Ajax source,
12516* etc) or processed for input (DOM source). This can be used as a compliment to mRender
12517* allowing you to modify the DOM element (add background colour for example) when the
12518* element is available.
12519* @type function
12520* @param {element} td The TD node that has been created
12521* @param {*} cellData The Data for the cell
12522* @param {array|object} rowData The data for the whole row
12523* @param {int} row The row index for the aoData data store
12524* @param {int} col The column index for aoColumns
12525*
12526* @name DataTable.defaults.column.createdCell
12527* @dtopt Columns
12528*
12529* @example
12530* $(document).ready( function() {
12531* $('#example').dataTable( {
12532* "columnDefs": [ {
12533* "targets": [3],
12534* "createdCell": function (td, cellData, rowData, row, col) {
12535* if ( cellData == "1.7" ) {
12536* $(td).css('color', 'blue')
12537* }
12538* }
12539* } ]
12540* });
12541* } );
12542*/
12543"fnCreatedCell": null,12544
12545
12546/**12547* This parameter has been replaced by `data` in DataTables to ensure naming
12548* consistency. `dataProp` can still be used, as there is backwards
12549* compatibility in DataTables for this option, but it is strongly
12550* recommended that you use `data` in preference to `dataProp`.
12551* @name DataTable.defaults.column.dataProp
12552*/
12553
12554
12555/**12556* This property can be used to read data from any data source property,
12557* including deeply nested objects / properties. `data` can be given in a
12558* number of different ways which effect its behaviour:
12559*
12560* * `integer` - treated as an array index for the data source. This is the
12561* default that DataTables uses (incrementally increased for each column).
12562* * `string` - read an object property from the data source. There are
12563* three 'special' options that can be used in the string to alter how
12564* DataTables reads the data from the source object:
12565* * `.` - Dotted Javascript notation. Just as you use a `.` in
12566* Javascript to read from nested objects, so to can the options
12567* specified in `data`. For example: `browser.version` or
12568* `browser.name`. If your object parameter name contains a period, use
12569* `\\` to escape it - i.e. `first\\.name`.
12570* * `[]` - Array notation. DataTables can automatically combine data
12571* from and array source, joining the data with the characters provided
12572* between the two brackets. For example: `name[, ]` would provide a
12573* comma-space separated list from the source array. If no characters
12574* are provided between the brackets, the original array source is
12575* returned.
12576* * `()` - Function notation. Adding `()` to the end of a parameter will
12577* execute a function of the name given. For example: `browser()` for a
12578* simple function on the data source, `browser.version()` for a
12579* function in a nested property or even `browser().version` to get an
12580* object property if the function called returns an object. Note that
12581* function notation is recommended for use in `render` rather than
12582* `data` as it is much simpler to use as a renderer.
12583* * `null` - use the original data source for the row rather than plucking
12584* data directly from it. This action has effects on two other
12585* initialisation options:
12586* * `defaultContent` - When null is given as the `data` option and
12587* `defaultContent` is specified for the column, the value defined by
12588* `defaultContent` will be used for the cell.
12589* * `render` - When null is used for the `data` option and the `render`
12590* option is specified for the column, the whole data source for the
12591* row is used for the renderer.
12592* * `function` - the function given will be executed whenever DataTables
12593* needs to set or get the data for a cell in the column. The function
12594* takes three parameters:
12595* * Parameters:
12596* * `{array|object}` The data source for the row
12597* * `{string}` The type call data requested - this will be 'set' when
12598* setting data or 'filter', 'display', 'type', 'sort' or undefined
12599* when gathering data. Note that when `undefined` is given for the
12600* type DataTables expects to get the raw data for the object back<
12601* * `{*}` Data to set when the second parameter is 'set'.
12602* * Return:
12603* * The return value from the function is not required when 'set' is
12604* the type of call, but otherwise the return is what will be used
12605* for the data requested.
12606*
12607* Note that `data` is a getter and setter option. If you just require
12608* formatting of data for output, you will likely want to use `render` which
12609* is simply a getter and thus simpler to use.
12610*
12611* Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12612* name change reflects the flexibility of this property and is consistent
12613* with the naming of mRender. If 'mDataProp' is given, then it will still
12614* be used by DataTables, as it automatically maps the old name to the new
12615* if required.
12616*
12617* @type string|int|function|null
12618* @default null <i>Use automatically calculated column index</i>
12619*
12620* @name DataTable.defaults.column.data
12621* @dtopt Columns
12622*
12623* @example
12624* // Read table data from objects
12625* // JSON structure for each row:
12626* // {
12627* // "engine": {value},
12628* // "browser": {value},
12629* // "platform": {value},
12630* // "version": {value},
12631* // "grade": {value}
12632* // }
12633* $(document).ready( function() {
12634* $('#example').dataTable( {
12635* "ajaxSource": "sources/objects.txt",
12636* "columns": [
12637* { "data": "engine" },
12638* { "data": "browser" },
12639* { "data": "platform" },
12640* { "data": "version" },
12641* { "data": "grade" }
12642* ]
12643* } );
12644* } );
12645*
12646* @example
12647* // Read information from deeply nested objects
12648* // JSON structure for each row:
12649* // {
12650* // "engine": {value},
12651* // "browser": {value},
12652* // "platform": {
12653* // "inner": {value}
12654* // },
12655* // "details": [
12656* // {value}, {value}
12657* // ]
12658* // }
12659* $(document).ready( function() {
12660* $('#example').dataTable( {
12661* "ajaxSource": "sources/deep.txt",
12662* "columns": [
12663* { "data": "engine" },
12664* { "data": "browser" },
12665* { "data": "platform.inner" },
12666* { "data": "details.0" },
12667* { "data": "details.1" }
12668* ]
12669* } );
12670* } );
12671*
12672* @example
12673* // Using `data` as a function to provide different information for
12674* // sorting, filtering and display. In this case, currency (price)
12675* $(document).ready( function() {
12676* $('#example').dataTable( {
12677* "columnDefs": [ {
12678* "targets": [ 0 ],
12679* "data": function ( source, type, val ) {
12680* if (type === 'set') {
12681* source.price = val;
12682* // Store the computed display and filter values for efficiency
12683* source.price_display = val=="" ? "" : "$"+numberFormat(val);
12684* source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12685* return;
12686* }
12687* else if (type === 'display') {
12688* return source.price_display;
12689* }
12690* else if (type === 'filter') {
12691* return source.price_filter;
12692* }
12693* // 'sort', 'type' and undefined all just use the integer
12694* return source.price;
12695* }
12696* } ]
12697* } );
12698* } );
12699*
12700* @example
12701* // Using default content
12702* $(document).ready( function() {
12703* $('#example').dataTable( {
12704* "columnDefs": [ {
12705* "targets": [ 0 ],
12706* "data": null,
12707* "defaultContent": "Click to edit"
12708* } ]
12709* } );
12710* } );
12711*
12712* @example
12713* // Using array notation - outputting a list from an array
12714* $(document).ready( function() {
12715* $('#example').dataTable( {
12716* "columnDefs": [ {
12717* "targets": [ 0 ],
12718* "data": "name[, ]"
12719* } ]
12720* } );
12721* } );
12722*
12723*/
12724"mData": null,12725
12726
12727/**12728* This property is the rendering partner to `data` and it is suggested that
12729* when you want to manipulate data for display (including filtering,
12730* sorting etc) without altering the underlying data for the table, use this
12731* property. `render` can be considered to be the the read only companion to
12732* `data` which is read / write (then as such more complex). Like `data`
12733* this option can be given in a number of different ways to effect its
12734* behaviour:
12735*
12736* * `integer` - treated as an array index for the data source. This is the
12737* default that DataTables uses (incrementally increased for each column).
12738* * `string` - read an object property from the data source. There are
12739* three 'special' options that can be used in the string to alter how
12740* DataTables reads the data from the source object:
12741* * `.` - Dotted Javascript notation. Just as you use a `.` in
12742* Javascript to read from nested objects, so to can the options
12743* specified in `data`. For example: `browser.version` or
12744* `browser.name`. If your object parameter name contains a period, use
12745* `\\` to escape it - i.e. `first\\.name`.
12746* * `[]` - Array notation. DataTables can automatically combine data
12747* from and array source, joining the data with the characters provided
12748* between the two brackets. For example: `name[, ]` would provide a
12749* comma-space separated list from the source array. If no characters
12750* are provided between the brackets, the original array source is
12751* returned.
12752* * `()` - Function notation. Adding `()` to the end of a parameter will
12753* execute a function of the name given. For example: `browser()` for a
12754* simple function on the data source, `browser.version()` for a
12755* function in a nested property or even `browser().version` to get an
12756* object property if the function called returns an object.
12757* * `object` - use different data for the different data types requested by
12758* DataTables ('filter', 'display', 'type' or 'sort'). The property names
12759* of the object is the data type the property refers to and the value can
12760* defined using an integer, string or function using the same rules as
12761* `render` normally does. Note that an `_` option _must_ be specified.
12762* This is the default value to use if you haven't specified a value for
12763* the data type requested by DataTables.
12764* * `function` - the function given will be executed whenever DataTables
12765* needs to set or get the data for a cell in the column. The function
12766* takes three parameters:
12767* * Parameters:
12768* * {array|object} The data source for the row (based on `data`)
12769* * {string} The type call data requested - this will be 'filter',
12770* 'display', 'type' or 'sort'.
12771* * {array|object} The full data source for the row (not based on
12772* `data`)
12773* * Return:
12774* * The return value from the function is what will be used for the
12775* data requested.
12776*
12777* @type string|int|function|object|null
12778* @default null Use the data source value.
12779*
12780* @name DataTable.defaults.column.render
12781* @dtopt Columns
12782*
12783* @example
12784* // Create a comma separated list from an array of objects
12785* $(document).ready( function() {
12786* $('#example').dataTable( {
12787* "ajaxSource": "sources/deep.txt",
12788* "columns": [
12789* { "data": "engine" },
12790* { "data": "browser" },
12791* {
12792* "data": "platform",
12793* "render": "[, ].name"
12794* }
12795* ]
12796* } );
12797* } );
12798*
12799* @example
12800* // Execute a function to obtain data
12801* $(document).ready( function() {
12802* $('#example').dataTable( {
12803* "columnDefs": [ {
12804* "targets": [ 0 ],
12805* "data": null, // Use the full data source object for the renderer's source
12806* "render": "browserName()"
12807* } ]
12808* } );
12809* } );
12810*
12811* @example
12812* // As an object, extracting different data for the different types
12813* // This would be used with a data source such as:
12814* // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12815* // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12816* // (which has both forms) is used for filtering for if a user inputs either format, while
12817* // the formatted phone number is the one that is shown in the table.
12818* $(document).ready( function() {
12819* $('#example').dataTable( {
12820* "columnDefs": [ {
12821* "targets": [ 0 ],
12822* "data": null, // Use the full data source object for the renderer's source
12823* "render": {
12824* "_": "phone",
12825* "filter": "phone_filter",
12826* "display": "phone_display"
12827* }
12828* } ]
12829* } );
12830* } );
12831*
12832* @example
12833* // Use as a function to create a link from the data source
12834* $(document).ready( function() {
12835* $('#example').dataTable( {
12836* "columnDefs": [ {
12837* "targets": [ 0 ],
12838* "data": "download_link",
12839* "render": function ( data, type, full ) {
12840* return '<a href="'+data+'">Download</a>';
12841* }
12842* } ]
12843* } );
12844* } );
12845*/
12846"mRender": null,12847
12848
12849/**12850* Change the cell type created for the column - either TD cells or TH cells. This
12851* can be useful as TH cells have semantic meaning in the table body, allowing them
12852* to act as a header for a row (you may wish to add scope='row' to the TH elements).
12853* @type string
12854* @default td
12855*
12856* @name DataTable.defaults.column.cellType
12857* @dtopt Columns
12858*
12859* @example
12860* // Make the first column use TH cells
12861* $(document).ready( function() {
12862* $('#example').dataTable( {
12863* "columnDefs": [ {
12864* "targets": [ 0 ],
12865* "cellType": "th"
12866* } ]
12867* } );
12868* } );
12869*/
12870"sCellType": "td",12871
12872
12873/**12874* Class to give to each cell in this column.
12875* @type string
12876* @default <i>Empty string</i>
12877*
12878* @name DataTable.defaults.column.class
12879* @dtopt Columns
12880*
12881* @example
12882* // Using `columnDefs`
12883* $(document).ready( function() {
12884* $('#example').dataTable( {
12885* "columnDefs": [
12886* { "class": "my_class", "targets": [ 0 ] }
12887* ]
12888* } );
12889* } );
12890*
12891* @example
12892* // Using `columns`
12893* $(document).ready( function() {
12894* $('#example').dataTable( {
12895* "columns": [
12896* { "class": "my_class" },
12897* null,
12898* null,
12899* null,
12900* null
12901* ]
12902* } );
12903* } );
12904*/
12905"sClass": "",12906
12907/**12908* When DataTables calculates the column widths to assign to each column,
12909* it finds the longest string in each column and then constructs a
12910* temporary table and reads the widths from that. The problem with this
12911* is that "mmm" is much wider then "iiii", but the latter is a longer
12912* string - thus the calculation can go wrong (doing it properly and putting
12913* it into an DOM object and measuring that is horribly(!) slow). Thus as
12914* a "work around" we provide this option. It will append its value to the
12915* text that is found to be the longest string for the column - i.e. padding.
12916* Generally you shouldn't need this!
12917* @type string
12918* @default <i>Empty string<i>
12919*
12920* @name DataTable.defaults.column.contentPadding
12921* @dtopt Columns
12922*
12923* @example
12924* // Using `columns`
12925* $(document).ready( function() {
12926* $('#example').dataTable( {
12927* "columns": [
12928* null,
12929* null,
12930* null,
12931* {
12932* "contentPadding": "mmm"
12933* }
12934* ]
12935* } );
12936* } );
12937*/
12938"sContentPadding": "",12939
12940
12941/**12942* Allows a default value to be given for a column's data, and will be used
12943* whenever a null data source is encountered (this can be because `data`
12944* is set to null, or because the data source itself is null).
12945* @type string
12946* @default null
12947*
12948* @name DataTable.defaults.column.defaultContent
12949* @dtopt Columns
12950*
12951* @example
12952* // Using `columnDefs`
12953* $(document).ready( function() {
12954* $('#example').dataTable( {
12955* "columnDefs": [
12956* {
12957* "data": null,
12958* "defaultContent": "Edit",
12959* "targets": [ -1 ]
12960* }
12961* ]
12962* } );
12963* } );
12964*
12965* @example
12966* // Using `columns`
12967* $(document).ready( function() {
12968* $('#example').dataTable( {
12969* "columns": [
12970* null,
12971* null,
12972* null,
12973* {
12974* "data": null,
12975* "defaultContent": "Edit"
12976* }
12977* ]
12978* } );
12979* } );
12980*/
12981"sDefaultContent": null,12982
12983
12984/**12985* This parameter is only used in DataTables' server-side processing. It can
12986* be exceptionally useful to know what columns are being displayed on the
12987* client side, and to map these to database fields. When defined, the names
12988* also allow DataTables to reorder information from the server if it comes
12989* back in an unexpected order (i.e. if you switch your columns around on the
12990* client-side, your server-side code does not also need updating).
12991* @type string
12992* @default <i>Empty string</i>
12993*
12994* @name DataTable.defaults.column.name
12995* @dtopt Columns
12996*
12997* @example
12998* // Using `columnDefs`
12999* $(document).ready( function() {
13000* $('#example').dataTable( {
13001* "columnDefs": [
13002* { "name": "engine", "targets": [ 0 ] },
13003* { "name": "browser", "targets": [ 1 ] },
13004* { "name": "platform", "targets": [ 2 ] },
13005* { "name": "version", "targets": [ 3 ] },
13006* { "name": "grade", "targets": [ 4 ] }
13007* ]
13008* } );
13009* } );
13010*
13011* @example
13012* // Using `columns`
13013* $(document).ready( function() {
13014* $('#example').dataTable( {
13015* "columns": [
13016* { "name": "engine" },
13017* { "name": "browser" },
13018* { "name": "platform" },
13019* { "name": "version" },
13020* { "name": "grade" }
13021* ]
13022* } );
13023* } );
13024*/
13025"sName": "",13026
13027
13028/**13029* Defines a data source type for the ordering which can be used to read
13030* real-time information from the table (updating the internally cached
13031* version) prior to ordering. This allows ordering to occur on user
13032* editable elements such as form inputs.
13033* @type string
13034* @default std
13035*
13036* @name DataTable.defaults.column.orderDataType
13037* @dtopt Columns
13038*
13039* @example
13040* // Using `columnDefs`
13041* $(document).ready( function() {
13042* $('#example').dataTable( {
13043* "columnDefs": [
13044* { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
13045* { "type": "numeric", "targets": [ 3 ] },
13046* { "orderDataType": "dom-select", "targets": [ 4 ] },
13047* { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
13048* ]
13049* } );
13050* } );
13051*
13052* @example
13053* // Using `columns`
13054* $(document).ready( function() {
13055* $('#example').dataTable( {
13056* "columns": [
13057* null,
13058* null,
13059* { "orderDataType": "dom-text" },
13060* { "orderDataType": "dom-text", "type": "numeric" },
13061* { "orderDataType": "dom-select" },
13062* { "orderDataType": "dom-checkbox" }
13063* ]
13064* } );
13065* } );
13066*/
13067"sSortDataType": "std",13068
13069
13070/**13071* The title of this column.
13072* @type string
13073* @default null <i>Derived from the 'TH' value for this column in the
13074* original HTML table.</i>
13075*
13076* @name DataTable.defaults.column.title
13077* @dtopt Columns
13078*
13079* @example
13080* // Using `columnDefs`
13081* $(document).ready( function() {
13082* $('#example').dataTable( {
13083* "columnDefs": [
13084* { "title": "My column title", "targets": [ 0 ] }
13085* ]
13086* } );
13087* } );
13088*
13089* @example
13090* // Using `columns`
13091* $(document).ready( function() {
13092* $('#example').dataTable( {
13093* "columns": [
13094* { "title": "My column title" },
13095* null,
13096* null,
13097* null,
13098* null
13099* ]
13100* } );
13101* } );
13102*/
13103"sTitle": null,13104
13105
13106/**13107* The type allows you to specify how the data for this column will be
13108* ordered. Four types (string, numeric, date and html (which will strip
13109* HTML tags before ordering)) are currently available. Note that only date
13110* formats understood by Javascript's Date() object will be accepted as type
13111* date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
13112* 'numeric', 'date' or 'html' (by default). Further types can be adding
13113* through plug-ins.
13114* @type string
13115* @default null <i>Auto-detected from raw data</i>
13116*
13117* @name DataTable.defaults.column.type
13118* @dtopt Columns
13119*
13120* @example
13121* // Using `columnDefs`
13122* $(document).ready( function() {
13123* $('#example').dataTable( {
13124* "columnDefs": [
13125* { "type": "html", "targets": [ 0 ] }
13126* ]
13127* } );
13128* } );
13129*
13130* @example
13131* // Using `columns`
13132* $(document).ready( function() {
13133* $('#example').dataTable( {
13134* "columns": [
13135* { "type": "html" },
13136* null,
13137* null,
13138* null,
13139* null
13140* ]
13141* } );
13142* } );
13143*/
13144"sType": null,13145
13146
13147/**13148* Defining the width of the column, this parameter may take any CSS value
13149* (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
13150* been given a specific width through this interface ensuring that the table
13151* remains readable.
13152* @type string
13153* @default null <i>Automatic</i>
13154*
13155* @name DataTable.defaults.column.width
13156* @dtopt Columns
13157*
13158* @example
13159* // Using `columnDefs`
13160* $(document).ready( function() {
13161* $('#example').dataTable( {
13162* "columnDefs": [
13163* { "width": "20%", "targets": [ 0 ] }
13164* ]
13165* } );
13166* } );
13167*
13168* @example
13169* // Using `columns`
13170* $(document).ready( function() {
13171* $('#example').dataTable( {
13172* "columns": [
13173* { "width": "20%" },
13174* null,
13175* null,
13176* null,
13177* null
13178* ]
13179* } );
13180* } );
13181*/
13182"sWidth": null13183};13184
13185_fnHungarianMap( DataTable.defaults.column );13186
13187
13188
13189/**
13190* DataTables settings object - this holds all the information needed for a
13191* given table, including configuration, data and current application of the
13192* table options. DataTables does not have a single instance for each DataTable
13193* with the settings attached to that instance, but rather instances of the
13194* DataTable "class" are created on-the-fly as needed (typically by a
13195* $().dataTable() call) and the settings object is then applied to that
13196* instance.
13197*
13198* Note that this object is related to {@link DataTable.defaults} but this
13199* one is the internal data store for DataTables's cache of columns. It should
13200* NOT be manipulated outside of DataTables. Any configuration should be done
13201* through the initialisation options.
13202* @namespace
13203* @todo Really should attach the settings object to individual instances so we
13204* don't need to create new instances on each $().dataTable() call (if the
13205* table already exists). It would also save passing oSettings around and
13206* into every single function. However, this is a very significant
13207* architecture change for DataTables and will almost certainly break
13208* backwards compatibility with older installations. This is something that
13209* will be done in 2.0.
13210*/
13211DataTable.models.oSettings = {13212/**13213* Primary features of DataTables and their enablement state.
13214* @namespace
13215*/
13216"oFeatures": {13217
13218/**13219* Flag to say if DataTables should automatically try to calculate the
13220* optimum table and columns widths (true) or not (false).
13221* Note that this parameter will be set by the initialisation routine. To
13222* set a default use {@link DataTable.defaults}.
13223* @type boolean
13224*/
13225"bAutoWidth": null,13226
13227/**13228* Delay the creation of TR and TD elements until they are actually
13229* needed by a driven page draw. This can give a significant speed
13230* increase for Ajax source and Javascript source data, but makes no
13231* difference at all for DOM and server-side processing tables.
13232* Note that this parameter will be set by the initialisation routine. To
13233* set a default use {@link DataTable.defaults}.
13234* @type boolean
13235*/
13236"bDeferRender": null,13237
13238/**13239* Enable filtering on the table or not. Note that if this is disabled
13240* then there is no filtering at all on the table, including fnFilter.
13241* To just remove the filtering input use sDom and remove the 'f' option.
13242* Note that this parameter will be set by the initialisation routine. To
13243* set a default use {@link DataTable.defaults}.
13244* @type boolean
13245*/
13246"bFilter": null,13247
13248/**13249* Table information element (the 'Showing x of y records' div) enable
13250* flag.
13251* Note that this parameter will be set by the initialisation routine. To
13252* set a default use {@link DataTable.defaults}.
13253* @type boolean
13254*/
13255"bInfo": null,13256
13257/**13258* Present a user control allowing the end user to change the page size
13259* when pagination is enabled.
13260* Note that this parameter will be set by the initialisation routine. To
13261* set a default use {@link DataTable.defaults}.
13262* @type boolean
13263*/
13264"bLengthChange": null,13265
13266/**13267* Pagination enabled or not. Note that if this is disabled then length
13268* changing must also be disabled.
13269* Note that this parameter will be set by the initialisation routine. To
13270* set a default use {@link DataTable.defaults}.
13271* @type boolean
13272*/
13273"bPaginate": null,13274
13275/**13276* Processing indicator enable flag whenever DataTables is enacting a
13277* user request - typically an Ajax request for server-side processing.
13278* Note that this parameter will be set by the initialisation routine. To
13279* set a default use {@link DataTable.defaults}.
13280* @type boolean
13281*/
13282"bProcessing": null,13283
13284/**13285* Server-side processing enabled flag - when enabled DataTables will
13286* get all data from the server for every draw - there is no filtering,
13287* sorting or paging done on the client-side.
13288* Note that this parameter will be set by the initialisation routine. To
13289* set a default use {@link DataTable.defaults}.
13290* @type boolean
13291*/
13292"bServerSide": null,13293
13294/**13295* Sorting enablement flag.
13296* Note that this parameter will be set by the initialisation routine. To
13297* set a default use {@link DataTable.defaults}.
13298* @type boolean
13299*/
13300"bSort": null,13301
13302/**13303* Multi-column sorting
13304* Note that this parameter will be set by the initialisation routine. To
13305* set a default use {@link DataTable.defaults}.
13306* @type boolean
13307*/
13308"bSortMulti": null,13309
13310/**13311* Apply a class to the columns which are being sorted to provide a
13312* visual highlight or not. This can slow things down when enabled since
13313* there is a lot of DOM interaction.
13314* Note that this parameter will be set by the initialisation routine. To
13315* set a default use {@link DataTable.defaults}.
13316* @type boolean
13317*/
13318"bSortClasses": null,13319
13320/**13321* State saving enablement flag.
13322* Note that this parameter will be set by the initialisation routine. To
13323* set a default use {@link DataTable.defaults}.
13324* @type boolean
13325*/
13326"bStateSave": null13327},13328
13329
13330/**13331* Scrolling settings for a table.
13332* @namespace
13333*/
13334"oScroll": {13335/**13336* When the table is shorter in height than sScrollY, collapse the
13337* table container down to the height of the table (when true).
13338* Note that this parameter will be set by the initialisation routine. To
13339* set a default use {@link DataTable.defaults}.
13340* @type boolean
13341*/
13342"bCollapse": null,13343
13344/**13345* Width of the scrollbar for the web-browser's platform. Calculated
13346* during table initialisation.
13347* @type int
13348* @default 0
13349*/
13350"iBarWidth": 0,13351
13352/**13353* Viewport width for horizontal scrolling. Horizontal scrolling is
13354* disabled if an empty string.
13355* Note that this parameter will be set by the initialisation routine. To
13356* set a default use {@link DataTable.defaults}.
13357* @type string
13358*/
13359"sX": null,13360
13361/**13362* Width to expand the table to when using x-scrolling. Typically you
13363* should not need to use this.
13364* Note that this parameter will be set by the initialisation routine. To
13365* set a default use {@link DataTable.defaults}.
13366* @type string
13367* @deprecated
13368*/
13369"sXInner": null,13370
13371/**13372* Viewport height for vertical scrolling. Vertical scrolling is disabled
13373* if an empty string.
13374* Note that this parameter will be set by the initialisation routine. To
13375* set a default use {@link DataTable.defaults}.
13376* @type string
13377*/
13378"sY": null13379},13380
13381/**13382* Language information for the table.
13383* @namespace
13384* @extends DataTable.defaults.oLanguage
13385*/
13386"oLanguage": {13387/**13388* Information callback function. See
13389* {@link DataTable.defaults.fnInfoCallback}
13390* @type function
13391* @default null
13392*/
13393"fnInfoCallback": null13394},13395
13396/**13397* Browser support parameters
13398* @namespace
13399*/
13400"oBrowser": {13401/**13402* Indicate if the browser incorrectly calculates width:100% inside a
13403* scrolling element (IE6/7)
13404* @type boolean
13405* @default false
13406*/
13407"bScrollOversize": false,13408
13409/**13410* Determine if the vertical scrollbar is on the right or left of the
13411* scrolling container - needed for rtl language layout, although not
13412* all browsers move the scrollbar (Safari).
13413* @type boolean
13414* @default false
13415*/
13416"bScrollbarLeft": false,13417
13418/**13419* Flag for if `getBoundingClientRect` is fully supported or not
13420* @type boolean
13421* @default false
13422*/
13423"bBounding": false,13424
13425/**13426* Browser scrollbar width
13427* @type integer
13428* @default 0
13429*/
13430"barWidth": 013431},13432
13433
13434"ajax": null,13435
13436
13437/**13438* Array referencing the nodes which are used for the features. The
13439* parameters of this object match what is allowed by sDom - i.e.
13440* <ul>
13441* <li>'l' - Length changing</li>
13442* <li>'f' - Filtering input</li>
13443* <li>'t' - The table!</li>
13444* <li>'i' - Information</li>
13445* <li>'p' - Pagination</li>
13446* <li>'r' - pRocessing</li>
13447* </ul>
13448* @type array
13449* @default []
13450*/
13451"aanFeatures": [],13452
13453/**13454* Store data information - see {@link DataTable.models.oRow} for detailed
13455* information.
13456* @type array
13457* @default []
13458*/
13459"aoData": [],13460
13461/**13462* Array of indexes which are in the current display (after filtering etc)
13463* @type array
13464* @default []
13465*/
13466"aiDisplay": [],13467
13468/**13469* Array of indexes for display - no filtering
13470* @type array
13471* @default []
13472*/
13473"aiDisplayMaster": [],13474
13475/**13476* Map of row ids to data indexes
13477* @type object
13478* @default {}
13479*/
13480"aIds": {},13481
13482/**13483* Store information about each column that is in use
13484* @type array
13485* @default []
13486*/
13487"aoColumns": [],13488
13489/**13490* Store information about the table's header
13491* @type array
13492* @default []
13493*/
13494"aoHeader": [],13495
13496/**13497* Store information about the table's footer
13498* @type array
13499* @default []
13500*/
13501"aoFooter": [],13502
13503/**13504* Store the applied global search information in case we want to force a
13505* research or compare the old search to a new one.
13506* Note that this parameter will be set by the initialisation routine. To
13507* set a default use {@link DataTable.defaults}.
13508* @namespace
13509* @extends DataTable.models.oSearch
13510*/
13511"oPreviousSearch": {},13512
13513/**13514* Store the applied search for each column - see
13515* {@link DataTable.models.oSearch} for the format that is used for the
13516* filtering information for each column.
13517* @type array
13518* @default []
13519*/
13520"aoPreSearchCols": [],13521
13522/**13523* Sorting that is applied to the table. Note that the inner arrays are
13524* used in the following manner:
13525* <ul>
13526* <li>Index 0 - column number</li>
13527* <li>Index 1 - current sorting direction</li>
13528* </ul>
13529* Note that this parameter will be set by the initialisation routine. To
13530* set a default use {@link DataTable.defaults}.
13531* @type array
13532* @todo These inner arrays should really be objects
13533*/
13534"aaSorting": null,13535
13536/**13537* Sorting that is always applied to the table (i.e. prefixed in front of
13538* aaSorting).
13539* Note that this parameter will be set by the initialisation routine. To
13540* set a default use {@link DataTable.defaults}.
13541* @type array
13542* @default []
13543*/
13544"aaSortingFixed": [],13545
13546/**13547* Classes to use for the striping of a table.
13548* Note that this parameter will be set by the initialisation routine. To
13549* set a default use {@link DataTable.defaults}.
13550* @type array
13551* @default []
13552*/
13553"asStripeClasses": null,13554
13555/**13556* If restoring a table - we should restore its striping classes as well
13557* @type array
13558* @default []
13559*/
13560"asDestroyStripes": [],13561
13562/**13563* If restoring a table - we should restore its width
13564* @type int
13565* @default 0
13566*/
13567"sDestroyWidth": 0,13568
13569/**13570* Callback functions array for every time a row is inserted (i.e. on a draw).
13571* @type array
13572* @default []
13573*/
13574"aoRowCallback": [],13575
13576/**13577* Callback functions for the header on each draw.
13578* @type array
13579* @default []
13580*/
13581"aoHeaderCallback": [],13582
13583/**13584* Callback function for the footer on each draw.
13585* @type array
13586* @default []
13587*/
13588"aoFooterCallback": [],13589
13590/**13591* Array of callback functions for draw callback functions
13592* @type array
13593* @default []
13594*/
13595"aoDrawCallback": [],13596
13597/**13598* Array of callback functions for row created function
13599* @type array
13600* @default []
13601*/
13602"aoRowCreatedCallback": [],13603
13604/**13605* Callback functions for just before the table is redrawn. A return of
13606* false will be used to cancel the draw.
13607* @type array
13608* @default []
13609*/
13610"aoPreDrawCallback": [],13611
13612/**13613* Callback functions for when the table has been initialised.
13614* @type array
13615* @default []
13616*/
13617"aoInitComplete": [],13618
13619
13620/**13621* Callbacks for modifying the settings to be stored for state saving, prior to
13622* saving state.
13623* @type array
13624* @default []
13625*/
13626"aoStateSaveParams": [],13627
13628/**13629* Callbacks for modifying the settings that have been stored for state saving
13630* prior to using the stored values to restore the state.
13631* @type array
13632* @default []
13633*/
13634"aoStateLoadParams": [],13635
13636/**13637* Callbacks for operating on the settings object once the saved state has been
13638* loaded
13639* @type array
13640* @default []
13641*/
13642"aoStateLoaded": [],13643
13644/**13645* Cache the table ID for quick access
13646* @type string
13647* @default <i>Empty string</i>
13648*/
13649"sTableId": "",13650
13651/**13652* The TABLE node for the main table
13653* @type node
13654* @default null
13655*/
13656"nTable": null,13657
13658/**13659* Permanent ref to the thead element
13660* @type node
13661* @default null
13662*/
13663"nTHead": null,13664
13665/**13666* Permanent ref to the tfoot element - if it exists
13667* @type node
13668* @default null
13669*/
13670"nTFoot": null,13671
13672/**13673* Permanent ref to the tbody element
13674* @type node
13675* @default null
13676*/
13677"nTBody": null,13678
13679/**13680* Cache the wrapper node (contains all DataTables controlled elements)
13681* @type node
13682* @default null
13683*/
13684"nTableWrapper": null,13685
13686/**13687* Indicate if when using server-side processing the loading of data
13688* should be deferred until the second draw.
13689* Note that this parameter will be set by the initialisation routine. To
13690* set a default use {@link DataTable.defaults}.
13691* @type boolean
13692* @default false
13693*/
13694"bDeferLoading": false,13695
13696/**13697* Indicate if all required information has been read in
13698* @type boolean
13699* @default false
13700*/
13701"bInitialised": false,13702
13703/**13704* Information about open rows. Each object in the array has the parameters
13705* 'nTr' and 'nParent'
13706* @type array
13707* @default []
13708*/
13709"aoOpenRows": [],13710
13711/**13712* Dictate the positioning of DataTables' control elements - see
13713* {@link DataTable.model.oInit.sDom}.
13714* Note that this parameter will be set by the initialisation routine. To
13715* set a default use {@link DataTable.defaults}.
13716* @type string
13717* @default null
13718*/
13719"sDom": null,13720
13721/**13722* Search delay (in mS)
13723* @type integer
13724* @default null
13725*/
13726"searchDelay": null,13727
13728/**13729* Which type of pagination should be used.
13730* Note that this parameter will be set by the initialisation routine. To
13731* set a default use {@link DataTable.defaults}.
13732* @type string
13733* @default two_button
13734*/
13735"sPaginationType": "two_button",13736
13737/**13738* The state duration (for `stateSave`) in seconds.
13739* Note that this parameter will be set by the initialisation routine. To
13740* set a default use {@link DataTable.defaults}.
13741* @type int
13742* @default 0
13743*/
13744"iStateDuration": 0,13745
13746/**13747* Array of callback functions for state saving. Each array element is an
13748* object with the following parameters:
13749* <ul>
13750* <li>function:fn - function to call. Takes two parameters, oSettings
13751* and the JSON string to save that has been thus far created. Returns
13752* a JSON string to be inserted into a json object
13753* (i.e. '"param": [ 0, 1, 2]')</li>
13754* <li>string:sName - name of callback</li>
13755* </ul>
13756* @type array
13757* @default []
13758*/
13759"aoStateSave": [],13760
13761/**13762* Array of callback functions for state loading. Each array element is an
13763* object with the following parameters:
13764* <ul>
13765* <li>function:fn - function to call. Takes two parameters, oSettings
13766* and the object stored. May return false to cancel state loading</li>
13767* <li>string:sName - name of callback</li>
13768* </ul>
13769* @type array
13770* @default []
13771*/
13772"aoStateLoad": [],13773
13774/**13775* State that was saved. Useful for back reference
13776* @type object
13777* @default null
13778*/
13779"oSavedState": null,13780
13781/**13782* State that was loaded. Useful for back reference
13783* @type object
13784* @default null
13785*/
13786"oLoadedState": null,13787
13788/**13789* Source url for AJAX data for the table.
13790* Note that this parameter will be set by the initialisation routine. To
13791* set a default use {@link DataTable.defaults}.
13792* @type string
13793* @default null
13794*/
13795"sAjaxSource": null,13796
13797/**13798* Property from a given object from which to read the table data from. This
13799* can be an empty string (when not server-side processing), in which case
13800* it is assumed an an array is given directly.
13801* Note that this parameter will be set by the initialisation routine. To
13802* set a default use {@link DataTable.defaults}.
13803* @type string
13804*/
13805"sAjaxDataProp": null,13806
13807/**13808* The last jQuery XHR object that was used for server-side data gathering.
13809* This can be used for working with the XHR information in one of the
13810* callbacks
13811* @type object
13812* @default null
13813*/
13814"jqXHR": null,13815
13816/**13817* JSON returned from the server in the last Ajax request
13818* @type object
13819* @default undefined
13820*/
13821"json": undefined,13822
13823/**13824* Data submitted as part of the last Ajax request
13825* @type object
13826* @default undefined
13827*/
13828"oAjaxData": undefined,13829
13830/**13831* Function to get the server-side data.
13832* Note that this parameter will be set by the initialisation routine. To
13833* set a default use {@link DataTable.defaults}.
13834* @type function
13835*/
13836"fnServerData": null,13837
13838/**13839* Functions which are called prior to sending an Ajax request so extra
13840* parameters can easily be sent to the server
13841* @type array
13842* @default []
13843*/
13844"aoServerParams": [],13845
13846/**13847* Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13848* required).
13849* Note that this parameter will be set by the initialisation routine. To
13850* set a default use {@link DataTable.defaults}.
13851* @type string
13852*/
13853"sServerMethod": null,13854
13855/**13856* Format numbers for display.
13857* Note that this parameter will be set by the initialisation routine. To
13858* set a default use {@link DataTable.defaults}.
13859* @type function
13860*/
13861"fnFormatNumber": null,13862
13863/**13864* List of options that can be used for the user selectable length menu.
13865* Note that this parameter will be set by the initialisation routine. To
13866* set a default use {@link DataTable.defaults}.
13867* @type array
13868* @default []
13869*/
13870"aLengthMenu": null,13871
13872/**13873* Counter for the draws that the table does. Also used as a tracker for
13874* server-side processing
13875* @type int
13876* @default 0
13877*/
13878"iDraw": 0,13879
13880/**13881* Indicate if a redraw is being done - useful for Ajax
13882* @type boolean
13883* @default false
13884*/
13885"bDrawing": false,13886
13887/**13888* Draw index (iDraw) of the last error when parsing the returned data
13889* @type int
13890* @default -1
13891*/
13892"iDrawError": -1,13893
13894/**13895* Paging display length
13896* @type int
13897* @default 10
13898*/
13899"_iDisplayLength": 10,13900
13901/**13902* Paging start point - aiDisplay index
13903* @type int
13904* @default 0
13905*/
13906"_iDisplayStart": 0,13907
13908/**13909* Server-side processing - number of records in the result set
13910* (i.e. before filtering), Use fnRecordsTotal rather than
13911* this property to get the value of the number of records, regardless of
13912* the server-side processing setting.
13913* @type int
13914* @default 0
13915* @private
13916*/
13917"_iRecordsTotal": 0,13918
13919/**13920* Server-side processing - number of records in the current display set
13921* (i.e. after filtering). Use fnRecordsDisplay rather than
13922* this property to get the value of the number of records, regardless of
13923* the server-side processing setting.
13924* @type boolean
13925* @default 0
13926* @private
13927*/
13928"_iRecordsDisplay": 0,13929
13930/**13931* The classes to use for the table
13932* @type object
13933* @default {}
13934*/
13935"oClasses": {},13936
13937/**13938* Flag attached to the settings object so you can check in the draw
13939* callback if filtering has been done in the draw. Deprecated in favour of
13940* events.
13941* @type boolean
13942* @default false
13943* @deprecated
13944*/
13945"bFiltered": false,13946
13947/**13948* Flag attached to the settings object so you can check in the draw
13949* callback if sorting has been done in the draw. Deprecated in favour of
13950* events.
13951* @type boolean
13952* @default false
13953* @deprecated
13954*/
13955"bSorted": false,13956
13957/**13958* Indicate that if multiple rows are in the header and there is more than
13959* one unique cell per column, if the top one (true) or bottom one (false)
13960* should be used for sorting / title by DataTables.
13961* Note that this parameter will be set by the initialisation routine. To
13962* set a default use {@link DataTable.defaults}.
13963* @type boolean
13964*/
13965"bSortCellsTop": null,13966
13967/**13968* Initialisation object that is used for the table
13969* @type object
13970* @default null
13971*/
13972"oInit": null,13973
13974/**13975* Destroy callback functions - for plug-ins to attach themselves to the
13976* destroy so they can clean up markup and events.
13977* @type array
13978* @default []
13979*/
13980"aoDestroyCallback": [],13981
13982
13983/**13984* Get the number of records in the current record set, before filtering
13985* @type function
13986*/
13987"fnRecordsTotal": function ()13988{13989return _fnDataSource( this ) == 'ssp' ?13990this._iRecordsTotal * 1 :13991this.aiDisplayMaster.length;13992},13993
13994/**13995* Get the number of records in the current record set, after filtering
13996* @type function
13997*/
13998"fnRecordsDisplay": function ()13999{14000return _fnDataSource( this ) == 'ssp' ?14001this._iRecordsDisplay * 1 :14002this.aiDisplay.length;14003},14004
14005/**14006* Get the display end point - aiDisplay index
14007* @type function
14008*/
14009"fnDisplayEnd": function ()14010{14011var14012len = this._iDisplayLength,14013start = this._iDisplayStart,14014calc = start + len,14015records = this.aiDisplay.length,14016features = this.oFeatures,14017paginate = features.bPaginate;14018
14019if ( features.bServerSide ) {14020return paginate === false || len === -1 ?14021start + records :14022Math.min( start+len, this._iRecordsDisplay );14023}14024else {14025return ! paginate || calc>records || len===-1 ?14026records :14027calc;14028}14029},14030
14031/**14032* The DataTables object for this table
14033* @type object
14034* @default null
14035*/
14036"oInstance": null,14037
14038/**14039* Unique identifier for each instance of the DataTables object. If there
14040* is an ID on the table node, then it takes that value, otherwise an
14041* incrementing internal counter is used.
14042* @type string
14043* @default null
14044*/
14045"sInstance": null,14046
14047/**14048* tabindex attribute value that is added to DataTables control elements, allowing
14049* keyboard navigation of the table and its controls.
14050*/
14051"iTabIndex": 0,14052
14053/**14054* DIV container for the footer scrolling table if scrolling
14055*/
14056"nScrollHead": null,14057
14058/**14059* DIV container for the footer scrolling table if scrolling
14060*/
14061"nScrollFoot": null,14062
14063/**14064* Last applied sort
14065* @type array
14066* @default []
14067*/
14068"aLastSort": [],14069
14070/**14071* Stored plug-in instances
14072* @type object
14073* @default {}
14074*/
14075"oPlugins": {},14076
14077/**14078* Function used to get a row's id from the row's data
14079* @type function
14080* @default null
14081*/
14082"rowIdFn": null,14083
14084/**14085* Data location where to store a row's id
14086* @type string
14087* @default null
14088*/
14089"rowId": null14090};14091
14092/**
14093* Extension object for DataTables that is used to provide all extension
14094* options.
14095*
14096* Note that the `DataTable.ext` object is available through
14097* `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
14098* also aliased to `jQuery.fn.dataTableExt` for historic reasons.
14099* @namespace
14100* @extends DataTable.models.ext
14101*/
14102
14103
14104/**
14105* DataTables extensions
14106*
14107* This namespace acts as a collection area for plug-ins that can be used to
14108* extend DataTables capabilities. Indeed many of the build in methods
14109* use this method to provide their own capabilities (sorting methods for
14110* example).
14111*
14112* Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
14113* reasons
14114*
14115* @namespace
14116*/
14117DataTable.ext = _ext = {14118/**14119* Buttons. For use with the Buttons extension for DataTables. This is
14120* defined here so other extensions can define buttons regardless of load
14121* order. It is _not_ used by DataTables core.
14122*
14123* @type object
14124* @default {}
14125*/
14126buttons: {},14127
14128
14129/**14130* Element class names
14131*
14132* @type object
14133* @default {}
14134*/
14135classes: {},14136
14137
14138/**14139* DataTables build type (expanded by the download builder)
14140*
14141* @type string
14142*/
14143builder: "-source-",14144
14145
14146/**14147* Error reporting.
14148*
14149* How should DataTables report an error. Can take the value 'alert',
14150* 'throw', 'none' or a function.
14151*
14152* @type string|function
14153* @default alert
14154*/
14155errMode: "alert",14156
14157
14158/**14159* Feature plug-ins.
14160*
14161* This is an array of objects which describe the feature plug-ins that are
14162* available to DataTables. These feature plug-ins are then available for
14163* use through the `dom` initialisation option.
14164*
14165* Each feature plug-in is described by an object which must have the
14166* following properties:
14167*
14168* * `fnInit` - function that is used to initialise the plug-in,
14169* * `cFeature` - a character so the feature can be enabled by the `dom`
14170* instillation option. This is case sensitive.
14171*
14172* The `fnInit` function has the following input parameters:
14173*
14174* 1. `{object}` DataTables settings object: see
14175* {@link DataTable.models.oSettings}
14176*
14177* And the following return is expected:
14178*
14179* * {node|null} The element which contains your feature. Note that the
14180* return may also be void if your plug-in does not require to inject any
14181* DOM elements into DataTables control (`dom`) - for example this might
14182* be useful when developing a plug-in which allows table control via
14183* keyboard entry
14184*
14185* @type array
14186*
14187* @example
14188* $.fn.dataTable.ext.features.push( {
14189* "fnInit": function( oSettings ) {
14190* return new TableTools( { "oDTSettings": oSettings } );
14191* },
14192* "cFeature": "T"
14193* } );
14194*/
14195feature: [],14196
14197
14198/**14199* Row searching.
14200*
14201* This method of searching is complimentary to the default type based
14202* searching, and a lot more comprehensive as it allows you complete control
14203* over the searching logic. Each element in this array is a function
14204* (parameters described below) that is called for every row in the table,
14205* and your logic decides if it should be included in the searching data set
14206* or not.
14207*
14208* Searching functions have the following input parameters:
14209*
14210* 1. `{object}` DataTables settings object: see
14211* {@link DataTable.models.oSettings}
14212* 2. `{array|object}` Data for the row to be processed (same as the
14213* original format that was passed in as the data source, or an array
14214* from a DOM data source
14215* 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14216* can be useful to retrieve the `TR` element if you need DOM interaction.
14217*
14218* And the following return is expected:
14219*
14220* * {boolean} Include the row in the searched result set (true) or not
14221* (false)
14222*
14223* Note that as with the main search ability in DataTables, technically this
14224* is "filtering", since it is subtractive. However, for consistency in
14225* naming we call it searching here.
14226*
14227* @type array
14228* @default []
14229*
14230* @example
14231* // The following example shows custom search being applied to the
14232* // fourth column (i.e. the data[3] index) based on two input values
14233* // from the end-user, matching the data in a certain range.
14234* $.fn.dataTable.ext.search.push(
14235* function( settings, data, dataIndex ) {
14236* var min = document.getElementById('min').value * 1;
14237* var max = document.getElementById('max').value * 1;
14238* var version = data[3] == "-" ? 0 : data[3]*1;
14239*
14240* if ( min == "" && max == "" ) {
14241* return true;
14242* }
14243* else if ( min == "" && version < max ) {
14244* return true;
14245* }
14246* else if ( min < version && "" == max ) {
14247* return true;
14248* }
14249* else if ( min < version && version < max ) {
14250* return true;
14251* }
14252* return false;
14253* }
14254* );
14255*/
14256search: [],14257
14258
14259/**14260* Selector extensions
14261*
14262* The `selector` option can be used to extend the options available for the
14263* selector modifier options (`selector-modifier` object data type) that
14264* each of the three built in selector types offer (row, column and cell +
14265* their plural counterparts). For example the Select extension uses this
14266* mechanism to provide an option to select only rows, columns and cells
14267* that have been marked as selected by the end user (`{selected: true}`),
14268* which can be used in conjunction with the existing built in selector
14269* options.
14270*
14271* Each property is an array to which functions can be pushed. The functions
14272* take three attributes:
14273*
14274* * Settings object for the host table
14275* * Options object (`selector-modifier` object type)
14276* * Array of selected item indexes
14277*
14278* The return is an array of the resulting item indexes after the custom
14279* selector has been applied.
14280*
14281* @type object
14282*/
14283selector: {14284cell: [],14285column: [],14286row: []14287},14288
14289
14290/**14291* Internal functions, exposed for used in plug-ins.
14292*
14293* Please note that you should not need to use the internal methods for
14294* anything other than a plug-in (and even then, try to avoid if possible).
14295* The internal function may change between releases.
14296*
14297* @type object
14298* @default {}
14299*/
14300internal: {},14301
14302
14303/**14304* Legacy configuration options. Enable and disable legacy options that
14305* are available in DataTables.
14306*
14307* @type object
14308*/
14309legacy: {14310/**14311* Enable / disable DataTables 1.9 compatible server-side processing
14312* requests
14313*
14314* @type boolean
14315* @default null
14316*/
14317ajax: null14318},14319
14320
14321/**14322* Pagination plug-in methods.
14323*
14324* Each entry in this object is a function and defines which buttons should
14325* be shown by the pagination rendering method that is used for the table:
14326* {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14327* buttons are displayed in the document, while the functions here tell it
14328* what buttons to display. This is done by returning an array of button
14329* descriptions (what each button will do).
14330*
14331* Pagination types (the four built in options and any additional plug-in
14332* options defined here) can be used through the `paginationType`
14333* initialisation parameter.
14334*
14335* The functions defined take two parameters:
14336*
14337* 1. `{int} page` The current page index
14338* 2. `{int} pages` The number of pages in the table
14339*
14340* Each function is expected to return an array where each element of the
14341* array can be one of:
14342*
14343* * `first` - Jump to first page when activated
14344* * `last` - Jump to last page when activated
14345* * `previous` - Show previous page when activated
14346* * `next` - Show next page when activated
14347* * `{int}` - Show page of the index given
14348* * `{array}` - A nested array containing the above elements to add a
14349* containing 'DIV' element (might be useful for styling).
14350*
14351* Note that DataTables v1.9- used this object slightly differently whereby
14352* an object with two functions would be defined for each plug-in. That
14353* ability is still supported by DataTables 1.10+ to provide backwards
14354* compatibility, but this option of use is now decremented and no longer
14355* documented in DataTables 1.10+.
14356*
14357* @type object
14358* @default {}
14359*
14360* @example
14361* // Show previous, next and current page buttons only
14362* $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14363* return [ 'previous', page, 'next' ];
14364* };
14365*/
14366pager: {},14367
14368
14369renderer: {14370pageButton: {},14371header: {}14372},14373
14374
14375/**14376* Ordering plug-ins - custom data source
14377*
14378* The extension options for ordering of data available here is complimentary
14379* to the default type based ordering that DataTables typically uses. It
14380* allows much greater control over the the data that is being used to
14381* order a column, but is necessarily therefore more complex.
14382*
14383* This type of ordering is useful if you want to do ordering based on data
14384* live from the DOM (for example the contents of an 'input' element) rather
14385* than just the static string that DataTables knows of.
14386*
14387* The way these plug-ins work is that you create an array of the values you
14388* wish to be ordering for the column in question and then return that
14389* array. The data in the array much be in the index order of the rows in
14390* the table (not the currently ordering order!). Which order data gathering
14391* function is run here depends on the `dt-init columns.orderDataType`
14392* parameter that is used for the column (if any).
14393*
14394* The functions defined take two parameters:
14395*
14396* 1. `{object}` DataTables settings object: see
14397* {@link DataTable.models.oSettings}
14398* 2. `{int}` Target column index
14399*
14400* Each function is expected to return an array:
14401*
14402* * `{array}` Data for the column to be ordering upon
14403*
14404* @type array
14405*
14406* @example
14407* // Ordering using `input` node values
14408* $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
14409* {
14410* return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14411* return $('input', td).val();
14412* } );
14413* }
14414*/
14415order: {},14416
14417
14418/**14419* Type based plug-ins.
14420*
14421* Each column in DataTables has a type assigned to it, either by automatic
14422* detection or by direct assignment using the `type` option for the column.
14423* The type of a column will effect how it is ordering and search (plug-ins
14424* can also make use of the column type if required).
14425*
14426* @namespace
14427*/
14428type: {14429/**14430* Type detection functions.
14431*
14432* The functions defined in this object are used to automatically detect
14433* a column's type, making initialisation of DataTables super easy, even
14434* when complex data is in the table.
14435*
14436* The functions defined take two parameters:
14437*
14438* 1. `{*}` Data from the column cell to be analysed
14439* 2. `{settings}` DataTables settings object. This can be used to
14440* perform context specific type detection - for example detection
14441* based on language settings such as using a comma for a decimal
14442* place. Generally speaking the options from the settings will not
14443* be required
14444*
14445* Each function is expected to return:
14446*
14447* * `{string|null}` Data type detected, or null if unknown (and thus
14448* pass it on to the other type detection functions.
14449*
14450* @type array
14451*
14452* @example
14453* // Currency type detection plug-in:
14454* $.fn.dataTable.ext.type.detect.push(
14455* function ( data, settings ) {
14456* // Check the numeric part
14457* if ( ! data.substring(1).match(/[0-9]/) ) {
14458* return null;
14459* }
14460*
14461* // Check prefixed by currency
14462* if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) {
14463* return 'currency';
14464* }
14465* return null;
14466* }
14467* );
14468*/
14469detect: [],14470
14471
14472/**14473* Type based search formatting.
14474*
14475* The type based searching functions can be used to pre-format the
14476* data to be search on. For example, it can be used to strip HTML
14477* tags or to de-format telephone numbers for numeric only searching.
14478*
14479* Note that is a search is not defined for a column of a given type,
14480* no search formatting will be performed.
14481*
14482* Pre-processing of searching data plug-ins - When you assign the sType
14483* for a column (or have it automatically detected for you by DataTables
14484* or a type detection plug-in), you will typically be using this for
14485* custom sorting, but it can also be used to provide custom searching
14486* by allowing you to pre-processing the data and returning the data in
14487* the format that should be searched upon. This is done by adding
14488* functions this object with a parameter name which matches the sType
14489* for that target column. This is the corollary of <i>afnSortData</i>
14490* for searching data.
14491*
14492* The functions defined take a single parameter:
14493*
14494* 1. `{*}` Data from the column cell to be prepared for searching
14495*
14496* Each function is expected to return:
14497*
14498* * `{string|null}` Formatted string that will be used for the searching.
14499*
14500* @type object
14501* @default {}
14502*
14503* @example
14504* $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14505* return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14506* }
14507*/
14508search: {},14509
14510
14511/**14512* Type based ordering.
14513*
14514* The column type tells DataTables what ordering to apply to the table
14515* when a column is sorted upon. The order for each type that is defined,
14516* is defined by the functions available in this object.
14517*
14518* Each ordering option can be described by three properties added to
14519* this object:
14520*
14521* * `{type}-pre` - Pre-formatting function
14522* * `{type}-asc` - Ascending order function
14523* * `{type}-desc` - Descending order function
14524*
14525* All three can be used together, only `{type}-pre` or only
14526* `{type}-asc` and `{type}-desc` together. It is generally recommended
14527* that only `{type}-pre` is used, as this provides the optimal
14528* implementation in terms of speed, although the others are provided
14529* for compatibility with existing Javascript sort functions.
14530*
14531* `{type}-pre`: Functions defined take a single parameter:
14532*
14533* 1. `{*}` Data from the column cell to be prepared for ordering
14534*
14535* And return:
14536*
14537* * `{*}` Data to be sorted upon
14538*
14539* `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14540* functions, taking two parameters:
14541*
14542* 1. `{*}` Data to compare to the second parameter
14543* 2. `{*}` Data to compare to the first parameter
14544*
14545* And returning:
14546*
14547* * `{*}` Ordering match: <0 if first parameter should be sorted lower
14548* than the second parameter, ===0 if the two parameters are equal and
14549* >0 if the first parameter should be sorted height than the second
14550* parameter.
14551*
14552* @type object
14553* @default {}
14554*
14555* @example
14556* // Numeric ordering of formatted numbers with a pre-formatter
14557* $.extend( $.fn.dataTable.ext.type.order, {
14558* "string-pre": function(x) {
14559* a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14560* return parseFloat( a );
14561* }
14562* } );
14563*
14564* @example
14565* // Case-sensitive string ordering, with no pre-formatting method
14566* $.extend( $.fn.dataTable.ext.order, {
14567* "string-case-asc": function(x,y) {
14568* return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14569* },
14570* "string-case-desc": function(x,y) {
14571* return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14572* }
14573* } );
14574*/
14575order: {}14576},14577
14578/**14579* Unique DataTables instance counter
14580*
14581* @type int
14582* @private
14583*/
14584_unique: 0,14585
14586
14587//14588// Depreciated14589// The following properties are retained for backwards compatibility only.14590// The should not be used in new projects and will be removed in a future14591// version14592//14593
14594/**14595* Version check function.
14596* @type function
14597* @depreciated Since 1.10
14598*/
14599fnVersionCheck: DataTable.fnVersionCheck,14600
14601
14602/**14603* Index for what 'this' index API functions should use
14604* @type int
14605* @deprecated Since v1.10
14606*/
14607iApiIndex: 0,14608
14609
14610/**14611* jQuery UI class container
14612* @type object
14613* @deprecated Since v1.10
14614*/
14615oJUIClasses: {},14616
14617
14618/**14619* Software version
14620* @type string
14621* @deprecated Since v1.10
14622*/
14623sVersion: DataTable.version14624};14625
14626
14627//
14628// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14629//
14630$.extend( _ext, {14631afnFiltering: _ext.search,14632aTypes: _ext.type.detect,14633ofnSearch: _ext.type.search,14634oSort: _ext.type.order,14635afnSortData: _ext.order,14636aoFeatures: _ext.feature,14637oApi: _ext.internal,14638oStdClasses: _ext.classes,14639oPagination: _ext.pager14640} );14641
14642
14643$.extend( DataTable.ext.classes, {14644"sTable": "dataTable",14645"sNoFooter": "no-footer",14646
14647/* Paging buttons */14648"sPageButton": "paginate_button",14649"sPageButtonActive": "current",14650"sPageButtonDisabled": "disabled",14651
14652/* Striping classes */14653"sStripeOdd": "odd",14654"sStripeEven": "even",14655
14656/* Empty row */14657"sRowEmpty": "dataTables_empty",14658
14659/* Features */14660"sWrapper": "dataTables_wrapper",14661"sFilter": "dataTables_filter",14662"sInfo": "dataTables_info",14663"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */14664"sLength": "dataTables_length",14665"sProcessing": "dataTables_processing",14666
14667/* Sorting */14668"sSortAsc": "sorting_asc",14669"sSortDesc": "sorting_desc",14670"sSortable": "sorting", /* Sortable in both directions */14671"sSortableAsc": "sorting_desc_disabled",14672"sSortableDesc": "sorting_asc_disabled",14673"sSortableNone": "sorting_disabled",14674"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */14675
14676/* Filtering */14677"sFilterInput": "",14678
14679/* Page length */14680"sLengthSelect": "",14681
14682/* Scrolling */14683"sScrollWrapper": "dataTables_scroll",14684"sScrollHead": "dataTables_scrollHead",14685"sScrollHeadInner": "dataTables_scrollHeadInner",14686"sScrollBody": "dataTables_scrollBody",14687"sScrollFoot": "dataTables_scrollFoot",14688"sScrollFootInner": "dataTables_scrollFootInner",14689
14690/* Misc */14691"sHeaderTH": "",14692"sFooterTH": "",14693
14694// Deprecated14695"sSortJUIAsc": "",14696"sSortJUIDesc": "",14697"sSortJUI": "",14698"sSortJUIAscAllowed": "",14699"sSortJUIDescAllowed": "",14700"sSortJUIWrapper": "",14701"sSortIcon": "",14702"sJUIHeader": "",14703"sJUIFooter": ""14704} );14705
14706
14707var extPagination = DataTable.ext.pager;14708
14709function _numbers ( page, pages ) {14710var14711numbers = [],14712buttons = extPagination.numbers_length,14713half = Math.floor( buttons / 2 ),14714i = 1;14715
14716if ( pages <= buttons ) {14717numbers = _range( 0, pages );14718}14719else if ( page <= half ) {14720numbers = _range( 0, buttons-2 );14721numbers.push( 'ellipsis' );14722numbers.push( pages-1 );14723}14724else if ( page >= pages - 1 - half ) {14725numbers = _range( pages-(buttons-2), pages );14726numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie614727numbers.splice( 0, 0, 0 );14728}14729else {14730numbers = _range( page-half+2, page+half-1 );14731numbers.push( 'ellipsis' );14732numbers.push( pages-1 );14733numbers.splice( 0, 0, 'ellipsis' );14734numbers.splice( 0, 0, 0 );14735}14736
14737numbers.DT_el = 'span';14738return numbers;14739}
14740
14741
14742$.extend( extPagination, {14743simple: function ( page, pages ) {14744return [ 'previous', 'next' ];14745},14746
14747full: function ( page, pages ) {14748return [ 'first', 'previous', 'next', 'last' ];14749},14750
14751numbers: function ( page, pages ) {14752return [ _numbers(page, pages) ];14753},14754
14755simple_numbers: function ( page, pages ) {14756return [ 'previous', _numbers(page, pages), 'next' ];14757},14758
14759full_numbers: function ( page, pages ) {14760return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];14761},14762
14763first_last_numbers: function (page, pages) {14764return ['first', _numbers(page, pages), 'last'];14765},14766
14767// For testing and plug-ins to use14768_numbers: _numbers,14769
14770// Number of number buttons (including ellipsis) to show. _Must be odd!_14771numbers_length: 714772} );14773
14774
14775$.extend( true, DataTable.ext.renderer, {14776pageButton: {14777_: function ( settings, host, idx, buttons, page, pages ) {14778var classes = settings.oClasses;14779var lang = settings.oLanguage.oPaginate;14780var aria = settings.oLanguage.oAria.paginate || {};14781var btnDisplay, btnClass;14782
14783var attach = function( container, buttons ) {14784var i, ien, node, button, tabIndex;14785var disabledClass = classes.sPageButtonDisabled;14786var clickHandler = function ( e ) {14787_fnPageChange( settings, e.data.action, true );14788};14789
14790for ( i=0, ien=buttons.length ; i<ien ; i++ ) {14791button = buttons[i];14792
14793if ( Array.isArray( button ) ) {14794var inner = $( '<'+(button.DT_el || 'div')+'/>' )14795.appendTo( container );14796attach( inner, button );14797}14798else {14799btnDisplay = null;14800btnClass = button;14801tabIndex = settings.iTabIndex;14802
14803switch ( button ) {14804case 'ellipsis':14805container.append('<span class="ellipsis">…</span>');14806break;14807
14808case 'first':14809btnDisplay = lang.sFirst;14810
14811if ( page === 0 ) {14812tabIndex = -1;14813btnClass += ' ' + disabledClass;14814}14815break;14816
14817case 'previous':14818btnDisplay = lang.sPrevious;14819
14820if ( page === 0 ) {14821tabIndex = -1;14822btnClass += ' ' + disabledClass;14823}14824break;14825
14826case 'next':14827btnDisplay = lang.sNext;14828
14829if ( pages === 0 || page === pages-1 ) {14830tabIndex = -1;14831btnClass += ' ' + disabledClass;14832}14833break;14834
14835case 'last':14836btnDisplay = lang.sLast;14837
14838if ( pages === 0 || page === pages-1 ) {14839tabIndex = -1;14840btnClass += ' ' + disabledClass;14841}14842break;14843
14844default:14845btnDisplay = settings.fnFormatNumber( button + 1 );14846btnClass = page === button ?14847classes.sPageButtonActive : '';14848break;14849}14850
14851if ( btnDisplay !== null ) {14852var tag = settings.oInit.pagingTag || 'a';14853var disabled = btnClass.indexOf(disabledClass) !== -1;14854
14855
14856node = $('<'+tag+'>', {14857'class': classes.sPageButton+' '+btnClass,14858'aria-controls': settings.sTableId,14859'aria-disabled': disabled ? 'true' : null,14860'aria-label': aria[ button ],14861'role': 'link',14862'aria-current': btnClass === classes.sPageButtonActive ? 'page' : null,14863'data-dt-idx': button,14864'tabindex': tabIndex,14865'id': idx === 0 && typeof button === 'string' ?14866settings.sTableId +'_'+ button :14867null14868} )14869.html( btnDisplay )14870.appendTo( container );14871
14872_fnBindAction(14873node, {action: button}, clickHandler14874);14875}14876}14877}14878};14879
14880// IE9 throws an 'unknown error' if document.activeElement is used14881// inside an iframe or frame. Try / catch the error. Not good for14882// accessibility, but neither are frames.14883var activeEl;14884
14885try {14886// Because this approach is destroying and recreating the paging14887// elements, focus is lost on the select button which is bad for14888// accessibility. So we want to restore focus once the draw has14889// completed14890activeEl = $(host).find(document.activeElement).data('dt-idx');14891}14892catch (e) {}14893
14894attach( $(host).empty(), buttons );14895
14896if ( activeEl !== undefined ) {14897$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');14898}14899}14900}14901} );14902
14903
14904
14905// Built in type detection. See model.ext.aTypes for information about
14906// what is required from this methods.
14907$.extend( DataTable.ext.type.detect, [14908// Plain numbers - first since V8 detects some plain numbers as dates14909// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).14910function ( d, settings )14911{14912var decimal = settings.oLanguage.sDecimal;14913return _isNumber( d, decimal ) ? 'num'+decimal : null;14914},14915
14916// Dates (only those recognised by the browser's Date.parse)14917function ( d, settings )14918{14919// V8 tries _very_ hard to make a string passed into `Date.parse()`14920// valid, so we need to use a regex to restrict date formats. Use a14921// plug-in for anything other than ISO8601 style strings14922if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {14923return null;14924}14925var parsed = Date.parse(d);14926return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;14927},14928
14929// Formatted numbers14930function ( d, settings )14931{14932var decimal = settings.oLanguage.sDecimal;14933return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;14934},14935
14936// HTML numeric14937function ( d, settings )14938{14939var decimal = settings.oLanguage.sDecimal;14940return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;14941},14942
14943// HTML numeric, formatted14944function ( d, settings )14945{14946var decimal = settings.oLanguage.sDecimal;14947return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;14948},14949
14950// HTML (this is strict checking - there must be html)14951function ( d, settings )14952{14953return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?14954'html' : null;14955}14956] );14957
14958
14959
14960// Filter formatting functions. See model.ext.ofnSearch for information about
14961// what is required from these methods.
14962//
14963// Note that additional search methods are added for the html numbers and
14964// html formatted numbers by `_addNumericSort()` when we know what the decimal
14965// place is
14966
14967
14968$.extend( DataTable.ext.type.search, {14969html: function ( data ) {14970return _empty(data) ?14971data :14972typeof data === 'string' ?14973data
14974.replace( _re_new_lines, " " )14975.replace( _re_html, "" ) :14976'';14977},14978
14979string: function ( data ) {14980return _empty(data) ?14981data :14982typeof data === 'string' ?14983data.replace( _re_new_lines, " " ) :14984data;14985}14986} );14987
14988
14989
14990var __numericReplace = function ( d, decimalPlace, re1, re2 ) {14991if ( d !== 0 && (!d || d === '-') ) {14992return -Infinity;14993}14994
14995var type = typeof d;14996
14997if (type === 'number' || type === 'bigint') {14998return d;14999}15000
15001// If a decimal place other than `.` is used, it needs to be given to the15002// function so we can detect it and replace with a `.` which is the only15003// decimal place Javascript recognises - it is not locale aware.15004if ( decimalPlace ) {15005d = _numToDecimal( d, decimalPlace );15006}15007
15008if ( d.replace ) {15009if ( re1 ) {15010d = d.replace( re1, '' );15011}15012
15013if ( re2 ) {15014d = d.replace( re2, '' );15015}15016}15017
15018return d * 1;15019};15020
15021
15022// Add the numeric 'deformatting' functions for sorting and search. This is done
15023// in a function to provide an easy ability for the language options to add
15024// additional methods if a non-period decimal place is used.
15025function _addNumericSort ( decimalPlace ) {15026$.each(15027{15028// Plain numbers15029"num": function ( d ) {15030return __numericReplace( d, decimalPlace );15031},15032
15033// Formatted numbers15034"num-fmt": function ( d ) {15035return __numericReplace( d, decimalPlace, _re_formatted_numeric );15036},15037
15038// HTML numeric15039"html-num": function ( d ) {15040return __numericReplace( d, decimalPlace, _re_html );15041},15042
15043// HTML numeric, formatted15044"html-num-fmt": function ( d ) {15045return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );15046}15047},15048function ( key, fn ) {15049// Add the ordering method15050_ext.type.order[ key+decimalPlace+'-pre' ] = fn;15051
15052// For HTML types add a search formatter that will strip the HTML15053if ( key.match(/^html\-/) ) {15054_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;15055}15056}15057);15058}
15059
15060
15061// Default sort methods
15062$.extend( _ext.type.order, {15063// Dates15064"date-pre": function ( d ) {15065var ts = Date.parse( d );15066return isNaN(ts) ? -Infinity : ts;15067},15068
15069// html15070"html-pre": function ( a ) {15071return _empty(a) ?15072'' :15073a.replace ?15074a.replace( /<.*?>/g, "" ).toLowerCase() :15075a+'';15076},15077
15078// string15079"string-pre": function ( a ) {15080// This is a little complex, but faster than always calling toString,15081// http://jsperf.com/tostring-v-check15082return _empty(a) ?15083'' :15084typeof a === 'string' ?15085a.toLowerCase() :15086! a.toString ?15087'' :15088a.toString();15089},15090
15091// string-asc and -desc are retained only for compatibility with the old15092// sort methods15093"string-asc": function ( x, y ) {15094return ((x < y) ? -1 : ((x > y) ? 1 : 0));15095},15096
15097"string-desc": function ( x, y ) {15098return ((x < y) ? 1 : ((x > y) ? -1 : 0));15099}15100} );15101
15102
15103// Numeric sorting types - order doesn't matter here
15104_addNumericSort( '' );15105
15106
15107$.extend( true, DataTable.ext.renderer, {15108header: {15109_: function ( settings, cell, column, classes ) {15110// No additional mark-up required15111// Attach a sort listener to update on sort - note that using the15112// `DT` namespace will allow the event to be removed automatically15113// on destroy, while the `dt` namespaced event is the one we are15114// listening for15115$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {15116if ( settings !== ctx ) { // need to check this this is the host15117return; // table, not a nested one15118}15119
15120var colIdx = column.idx;15121
15122cell
15123.removeClass(15124classes.sSortAsc +' '+15125classes.sSortDesc15126)15127.addClass( columns[ colIdx ] == 'asc' ?15128classes.sSortAsc : columns[ colIdx ] == 'desc' ?15129classes.sSortDesc :15130column.sSortingClass15131);15132} );15133},15134
15135jqueryui: function ( settings, cell, column, classes ) {15136$('<div/>')15137.addClass( classes.sSortJUIWrapper )15138.append( cell.contents() )15139.append( $('<span/>')15140.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )15141)15142.appendTo( cell );15143
15144// Attach a sort listener to update on sort15145$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {15146if ( settings !== ctx ) {15147return;15148}15149
15150var colIdx = column.idx;15151
15152cell
15153.removeClass( classes.sSortAsc +" "+classes.sSortDesc )15154.addClass( columns[ colIdx ] == 'asc' ?15155classes.sSortAsc : columns[ colIdx ] == 'desc' ?15156classes.sSortDesc :15157column.sSortingClass15158);15159
15160cell
15161.find( 'span.'+classes.sSortIcon )15162.removeClass(15163classes.sSortJUIAsc +" "+15164classes.sSortJUIDesc +" "+15165classes.sSortJUI +" "+15166classes.sSortJUIAscAllowed +" "+15167classes.sSortJUIDescAllowed15168)15169.addClass( columns[ colIdx ] == 'asc' ?15170classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?15171classes.sSortJUIDesc :15172column.sSortingClassJUI15173);15174} );15175}15176}15177} );15178
15179/*
15180* Public helper functions. These aren't used internally by DataTables, or
15181* called by any of the options passed into DataTables, but they can be used
15182* externally by developers working with DataTables. They are helper functions
15183* to make working with DataTables a little bit easier.
15184*/
15185
15186var __htmlEscapeEntities = function ( d ) {15187if (Array.isArray(d)) {15188d = d.join(',');15189}15190
15191return typeof d === 'string' ?15192d
15193.replace(/&/g, '&')15194.replace(/</g, '<')15195.replace(/>/g, '>')15196.replace(/"/g, '"') :15197d;15198};15199
15200// Common logic for moment, luxon or a date action
15201function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {15202if (window.moment) {15203return dt[momentFn]( arg1 );15204}15205else if (window.luxon) {15206return dt[luxonFn]( arg1 );15207}15208
15209return dateFn ? dt[dateFn]( arg1 ) : dt;15210}
15211
15212
15213var __mlWarning = false;15214function __mldObj (d, format, locale) {15215var dt;15216
15217if (window.moment) {15218dt = window.moment.utc( d, format, locale, true );15219
15220if (! dt.isValid()) {15221return null;15222}15223}15224else if (window.luxon) {15225dt = format && typeof d === 'string'15226? window.luxon.DateTime.fromFormat( d, format )15227: window.luxon.DateTime.fromISO( d );15228
15229if (! dt.isValid) {15230return null;15231}15232
15233dt.setLocale(locale);15234}15235else if (! format) {15236// No format given, must be ISO15237dt = new Date(d);15238}15239else {15240if (! __mlWarning) {15241alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');15242}15243
15244__mlWarning = true;15245}15246
15247return dt;15248}
15249
15250// Wrapper for date, datetime and time which all operate the same way with the exception of
15251// the output string for auto locale support
15252function __mlHelper (localeString) {15253return function ( from, to, locale, def ) {15254// Luxon and Moment support15255// Argument shifting15256if ( arguments.length === 0 ) {15257locale = 'en';15258to = null; // means toLocaleString15259from = null; // means iso860115260}15261else if ( arguments.length === 1 ) {15262locale = 'en';15263to = from;15264from = null;15265}15266else if ( arguments.length === 2 ) {15267locale = to;15268to = from;15269from = null;15270}15271
15272var typeName = 'datetime-' + to;15273
15274// Add type detection and sorting specific to this date format - we need to be able to identify15275// date type columns as such, rather than as numbers in extensions. Hence the need for this.15276if (! DataTable.ext.type.order[typeName]) {15277// The renderer will give the value to type detect as the type!15278DataTable.ext.type.detect.unshift(function (d) {15279return d === typeName ? typeName : false;15280});15281
15282// The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a15283// `valueOf` which gives milliseconds epoch15284DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {15285var x = a.valueOf();15286var y = b.valueOf();15287
15288return x === y15289? 015290: x < y15291? -115292: 1;15293}15294
15295DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {15296var x = a.valueOf();15297var y = b.valueOf();15298
15299return x === y15300? 015301: x > y15302? -115303: 1;15304}15305}15306
15307return function ( d, type ) {15308// Allow for a default value15309if (d === null || d === undefined) {15310if (def === '--now') {15311// We treat everything as UTC further down, so no changes are15312// made, as such need to get the local date / time as if it were15313// UTC15314var local = new Date();15315d = new Date( Date.UTC(15316local.getFullYear(), local.getMonth(), local.getDate(),15317local.getHours(), local.getMinutes(), local.getSeconds()15318) );15319}15320else {15321d = '';15322}15323}15324
15325if (type === 'type') {15326// Typing uses the type name for fast matching15327return typeName;15328}15329
15330if (d === '') {15331return type !== 'sort'15332? ''15333: __mldObj('0000-01-01 00:00:00', null, locale);15334}15335
15336// Shortcut. If `from` and `to` are the same, we are using the renderer to15337// format for ordering, not display - its already in the display format.15338if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {15339return d;15340}15341
15342var dt = __mldObj(d, from, locale);15343
15344if (dt === null) {15345return d;15346}15347
15348if (type === 'sort') {15349return dt;15350}15351
15352var formatted = to === null15353? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()15354: __mld(dt, 'format', 'toFormat', 'toISOString', to);15355
15356// XSS protection15357return type === 'display' ?15358__htmlEscapeEntities( formatted ) :15359formatted;15360};15361}15362}
15363
15364// Based on locale, determine standard number formatting
15365// Fallback for legacy browsers is US English
15366var __thousands = ',';15367var __decimal = '.';15368
15369if (window.Intl !== undefined) {15370try {15371var num = new Intl.NumberFormat().formatToParts(100000.1);15372
15373for (var i=0 ; i<num.length ; i++) {15374if (num[i].type === 'group') {15375__thousands = num[i].value;15376}15377else if (num[i].type === 'decimal') {15378__decimal = num[i].value;15379}15380}15381}15382catch (e) {15383// noop15384}15385}
15386
15387// Formatted date time detection - use by declaring the formats you are going to use
15388DataTable.datetime = function ( format, locale ) {15389var typeName = 'datetime-detect-' + format;15390
15391if (! locale) {15392locale = 'en';15393}15394
15395if (! DataTable.ext.type.order[typeName]) {15396DataTable.ext.type.detect.unshift(function (d) {15397var dt = __mldObj(d, format, locale);15398return d === '' || dt ? typeName : false;15399});15400
15401DataTable.ext.type.order[typeName + '-pre'] = function (d) {15402return __mldObj(d, format, locale) || 0;15403}15404}15405}
15406
15407/**
15408* Helpers for `columns.render`.
15409*
15410* The options defined here can be used with the `columns.render` initialisation
15411* option to provide a display renderer. The following functions are defined:
15412*
15413* * `number` - Will format numeric data (defined by `columns.data`) for
15414* display, retaining the original unformatted data for sorting and filtering.
15415* It takes 5 parameters:
15416* * `string` - Thousands grouping separator
15417* * `string` - Decimal point indicator
15418* * `integer` - Number of decimal points to show
15419* * `string` (optional) - Prefix.
15420* * `string` (optional) - Postfix (/suffix).
15421* * `text` - Escape HTML to help prevent XSS attacks. It has no optional
15422* parameters.
15423*
15424* @example
15425* // Column definition using the number renderer
15426* {
15427* data: "salary",
15428* render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
15429* }
15430*
15431* @namespace
15432*/
15433DataTable.render = {15434date: __mlHelper('toLocaleDateString'),15435datetime: __mlHelper('toLocaleString'),15436time: __mlHelper('toLocaleTimeString'),15437number: function ( thousands, decimal, precision, prefix, postfix ) {15438// Auto locale detection15439if (thousands === null || thousands === undefined) {15440thousands = __thousands;15441}15442
15443if (decimal === null || decimal === undefined) {15444decimal = __decimal;15445}15446
15447return {15448display: function ( d ) {15449if ( typeof d !== 'number' && typeof d !== 'string' ) {15450return d;15451}15452
15453if (d === '' || d === null) {15454return d;15455}15456
15457var negative = d < 0 ? '-' : '';15458var flo = parseFloat( d );15459
15460// If NaN then there isn't much formatting that we can do - just15461// return immediately, escaping any HTML (this was supposed to15462// be a number after all)15463if ( isNaN( flo ) ) {15464return __htmlEscapeEntities( d );15465}15466
15467flo = flo.toFixed( precision );15468d = Math.abs( flo );15469
15470var intPart = parseInt( d, 10 );15471var floatPart = precision ?15472decimal+(d - intPart).toFixed( precision ).substring( 2 ):15473'';15474
15475// If zero, then can't have a negative prefix15476if (intPart === 0 && parseFloat(floatPart) === 0) {15477negative = '';15478}15479
15480return negative + (prefix||'') +15481intPart.toString().replace(15482/\B(?=(\d{3})+(?!\d))/g, thousands15483) +15484floatPart +15485(postfix||'');15486}15487};15488},15489
15490text: function () {15491return {15492display: __htmlEscapeEntities,15493filter: __htmlEscapeEntities15494};15495}15496};15497
15498
15499/*
15500* This is really a good bit rubbish this method of exposing the internal methods
15501* publicly... - To be fixed in 2.0 using methods on the prototype
15502*/
15503
15504
15505/**
15506* Create a wrapper function for exporting an internal functions to an external API.
15507* @param {string} fn API function name
15508* @returns {function} wrapped function
15509* @memberof DataTable#internal
15510*/
15511function _fnExternApiFunc (fn)15512{
15513return function() {15514var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(15515Array.prototype.slice.call(arguments)15516);15517return DataTable.ext.internal[fn].apply( this, args );15518};15519}
15520
15521
15522/**
15523* Reference to internal functions for use by plug-in developers. Note that
15524* these methods are references to internal functions and are considered to be
15525* private. If you use these methods, be aware that they are liable to change
15526* between versions.
15527* @namespace
15528*/
15529$.extend( DataTable.ext.internal, {15530_fnExternApiFunc: _fnExternApiFunc,15531_fnBuildAjax: _fnBuildAjax,15532_fnAjaxUpdate: _fnAjaxUpdate,15533_fnAjaxParameters: _fnAjaxParameters,15534_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,15535_fnAjaxDataSrc: _fnAjaxDataSrc,15536_fnAddColumn: _fnAddColumn,15537_fnColumnOptions: _fnColumnOptions,15538_fnAdjustColumnSizing: _fnAdjustColumnSizing,15539_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,15540_fnColumnIndexToVisible: _fnColumnIndexToVisible,15541_fnVisbleColumns: _fnVisbleColumns,15542_fnGetColumns: _fnGetColumns,15543_fnColumnTypes: _fnColumnTypes,15544_fnApplyColumnDefs: _fnApplyColumnDefs,15545_fnHungarianMap: _fnHungarianMap,15546_fnCamelToHungarian: _fnCamelToHungarian,15547_fnLanguageCompat: _fnLanguageCompat,15548_fnBrowserDetect: _fnBrowserDetect,15549_fnAddData: _fnAddData,15550_fnAddTr: _fnAddTr,15551_fnNodeToDataIndex: _fnNodeToDataIndex,15552_fnNodeToColumnIndex: _fnNodeToColumnIndex,15553_fnGetCellData: _fnGetCellData,15554_fnSetCellData: _fnSetCellData,15555_fnSplitObjNotation: _fnSplitObjNotation,15556_fnGetObjectDataFn: _fnGetObjectDataFn,15557_fnSetObjectDataFn: _fnSetObjectDataFn,15558_fnGetDataMaster: _fnGetDataMaster,15559_fnClearTable: _fnClearTable,15560_fnDeleteIndex: _fnDeleteIndex,15561_fnInvalidate: _fnInvalidate,15562_fnGetRowElements: _fnGetRowElements,15563_fnCreateTr: _fnCreateTr,15564_fnBuildHead: _fnBuildHead,15565_fnDrawHead: _fnDrawHead,15566_fnDraw: _fnDraw,15567_fnReDraw: _fnReDraw,15568_fnAddOptionsHtml: _fnAddOptionsHtml,15569_fnDetectHeader: _fnDetectHeader,15570_fnGetUniqueThs: _fnGetUniqueThs,15571_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,15572_fnFilterComplete: _fnFilterComplete,15573_fnFilterCustom: _fnFilterCustom,15574_fnFilterColumn: _fnFilterColumn,15575_fnFilter: _fnFilter,15576_fnFilterCreateSearch: _fnFilterCreateSearch,15577_fnEscapeRegex: _fnEscapeRegex,15578_fnFilterData: _fnFilterData,15579_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,15580_fnUpdateInfo: _fnUpdateInfo,15581_fnInfoMacros: _fnInfoMacros,15582_fnInitialise: _fnInitialise,15583_fnInitComplete: _fnInitComplete,15584_fnLengthChange: _fnLengthChange,15585_fnFeatureHtmlLength: _fnFeatureHtmlLength,15586_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,15587_fnPageChange: _fnPageChange,15588_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,15589_fnProcessingDisplay: _fnProcessingDisplay,15590_fnFeatureHtmlTable: _fnFeatureHtmlTable,15591_fnScrollDraw: _fnScrollDraw,15592_fnApplyToChildren: _fnApplyToChildren,15593_fnCalculateColumnWidths: _fnCalculateColumnWidths,15594_fnThrottle: _fnThrottle,15595_fnConvertToWidth: _fnConvertToWidth,15596_fnGetWidestNode: _fnGetWidestNode,15597_fnGetMaxLenString: _fnGetMaxLenString,15598_fnStringToCss: _fnStringToCss,15599_fnSortFlatten: _fnSortFlatten,15600_fnSort: _fnSort,15601_fnSortAria: _fnSortAria,15602_fnSortListener: _fnSortListener,15603_fnSortAttachListener: _fnSortAttachListener,15604_fnSortingClasses: _fnSortingClasses,15605_fnSortData: _fnSortData,15606_fnSaveState: _fnSaveState,15607_fnLoadState: _fnLoadState,15608_fnImplementState: _fnImplementState,15609_fnSettingsFromNode: _fnSettingsFromNode,15610_fnLog: _fnLog,15611_fnMap: _fnMap,15612_fnBindAction: _fnBindAction,15613_fnCallbackReg: _fnCallbackReg,15614_fnCallbackFire: _fnCallbackFire,15615_fnLengthOverflow: _fnLengthOverflow,15616_fnRenderer: _fnRenderer,15617_fnDataSource: _fnDataSource,15618_fnRowAttributes: _fnRowAttributes,15619_fnExtend: _fnExtend,15620_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant15621// in 1.10, so this dead-end function is15622// added to prevent errors15623} );15624
15625
15626// jQuery access
15627$.fn.dataTable = DataTable;15628
15629// Provide access to the host jQuery object (circular reference)
15630DataTable.$ = $;15631
15632// Legacy aliases
15633$.fn.dataTableSettings = DataTable.settings;15634$.fn.dataTableExt = DataTable.ext;15635
15636// With a capital `D` we return a DataTables API instance rather than a
15637// jQuery object
15638$.fn.DataTable = function ( opts ) {15639return $(this).dataTable( opts ).api();15640};15641
15642// All properties that are available to $.fn.dataTable should also be
15643// available on $.fn.DataTable
15644$.each( DataTable, function ( prop, val ) {15645$.fn.DataTable[ prop ] = val;15646} );15647
15648export default DataTable;15649