|
4
|
1 /*! DataTables 1.10.9
|
|
|
2 * ©2008-2015 SpryMedia Ltd - datatables.net/license
|
|
|
3 */
|
|
|
4
|
|
|
5 /**
|
|
|
6 * @summary DataTables
|
|
|
7 * @description Paginate, search and order HTML tables
|
|
|
8 * @version 1.10.9
|
|
|
9 * @file jquery.dataTables.js
|
|
|
10 * @author SpryMedia Ltd (www.sprymedia.co.uk)
|
|
|
11 * @contact www.sprymedia.co.uk/contact
|
|
|
12 * @copyright Copyright 2008-2015 SpryMedia Ltd.
|
|
|
13 *
|
|
|
14 * This source file is free software, available under the following license:
|
|
|
15 * MIT license - http://datatables.net/license
|
|
|
16 *
|
|
|
17 * This source file is distributed in the hope that it will be useful, but
|
|
|
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
|
|
20 *
|
|
|
21 * For details please refer to: http://www.datatables.net
|
|
|
22 */
|
|
|
23
|
|
|
24 /*jslint evil: true, undef: true, browser: true */
|
|
|
25 /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
|
|
|
26
|
|
|
27 (/** @lends <global> */function( window, document, undefined ) {
|
|
|
28
|
|
|
29 (function( factory ) {
|
|
|
30 "use strict";
|
|
|
31
|
|
|
32 if ( typeof define === 'function' && define.amd ) {
|
|
|
33 // Define as an AMD module if possible
|
|
|
34 define( 'datatables', ['jquery'], factory );
|
|
|
35 }
|
|
|
36 else if ( typeof exports === 'object' ) {
|
|
|
37 // Node/CommonJS
|
|
|
38 module.exports = factory( require( 'jquery' ) );
|
|
|
39 }
|
|
|
40 else if ( jQuery && !jQuery.fn.dataTable ) {
|
|
|
41 // Define using browser globals otherwise
|
|
|
42 // Prevent multiple instantiations if the script is loaded twice
|
|
|
43 factory( jQuery );
|
|
|
44 }
|
|
|
45 }
|
|
|
46 (/** @lends <global> */function( $ ) {
|
|
|
47 "use strict";
|
|
|
48
|
|
|
49 /**
|
|
|
50 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
|
|
|
51 * flexible tool, based upon the foundations of progressive enhancement,
|
|
|
52 * which will add advanced interaction controls to any HTML table. For a
|
|
|
53 * full list of features please refer to
|
|
|
54 * [DataTables.net](href="http://datatables.net).
|
|
|
55 *
|
|
|
56 * Note that the `DataTable` object is not a global variable but is aliased
|
|
|
57 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
|
|
|
58 * be accessed.
|
|
|
59 *
|
|
|
60 * @class
|
|
|
61 * @param {object} [init={}] Configuration object for DataTables. Options
|
|
|
62 * are defined by {@link DataTable.defaults}
|
|
|
63 * @requires jQuery 1.7+
|
|
|
64 *
|
|
|
65 * @example
|
|
|
66 * // Basic initialisation
|
|
|
67 * $(document).ready( function {
|
|
|
68 * $('#example').dataTable();
|
|
|
69 * } );
|
|
|
70 *
|
|
|
71 * @example
|
|
|
72 * // Initialisation with configuration options - in this case, disable
|
|
|
73 * // pagination and sorting.
|
|
|
74 * $(document).ready( function {
|
|
|
75 * $('#example').dataTable( {
|
|
|
76 * "paginate": false,
|
|
|
77 * "sort": false
|
|
|
78 * } );
|
|
|
79 * } );
|
|
|
80 */
|
|
|
81 var DataTable;
|
|
|
82
|
|
|
83
|
|
|
84 /*
|
|
|
85 * It is useful to have variables which are scoped locally so only the
|
|
|
86 * DataTables functions can access them and they don't leak into global space.
|
|
|
87 * At the same time these functions are often useful over multiple files in the
|
|
|
88 * core and API, so we list, or at least document, all variables which are used
|
|
|
89 * by DataTables as private variables here. This also ensures that there is no
|
|
|
90 * clashing of variable names and that they can easily referenced for reuse.
|
|
|
91 */
|
|
|
92
|
|
|
93
|
|
|
94 // Defined else where
|
|
|
95 // _selector_run
|
|
|
96 // _selector_opts
|
|
|
97 // _selector_first
|
|
|
98 // _selector_row_indexes
|
|
|
99
|
|
|
100 var _ext; // DataTable.ext
|
|
|
101 var _Api; // DataTable.Api
|
|
|
102 var _api_register; // DataTable.Api.register
|
|
|
103 var _api_registerPlural; // DataTable.Api.registerPlural
|
|
|
104
|
|
|
105 var _re_dic = {};
|
|
|
106 var _re_new_lines = /[\r\n]/g;
|
|
|
107 var _re_html = /<.*?>/g;
|
|
|
108 var _re_date_start = /^[\w\+\-]/;
|
|
|
109 var _re_date_end = /[\w\+\-]$/;
|
|
|
110
|
|
|
111 // Escape regular expression special characters
|
|
|
112 var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
|
|
|
113
|
|
|
114 // http://en.wikipedia.org/wiki/Foreign_exchange_market
|
|
|
115 // - \u20BD - Russian ruble.
|
|
|
116 // - \u20a9 - South Korean Won
|
|
|
117 // - \u20BA - Turkish Lira
|
|
|
118 // - \u20B9 - Indian Rupee
|
|
|
119 // - R - Brazil (R$) and South Africa
|
|
|
120 // - fr - Swiss Franc
|
|
|
121 // - kr - Swedish krona, Norwegian krone and Danish krone
|
|
|
122 // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
|
|
|
123 // standards as thousands separators.
|
|
|
124 var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
|
|
|
125
|
|
|
126
|
|
|
127 var _empty = function ( d ) {
|
|
|
128 return !d || d === true || d === '-' ? true : false;
|
|
|
129 };
|
|
|
130
|
|
|
131
|
|
|
132 var _intVal = function ( s ) {
|
|
|
133 var integer = parseInt( s, 10 );
|
|
|
134 return !isNaN(integer) && isFinite(s) ? integer : null;
|
|
|
135 };
|
|
|
136
|
|
|
137 // Convert from a formatted number with characters other than `.` as the
|
|
|
138 // decimal place, to a Javascript number
|
|
|
139 var _numToDecimal = function ( num, decimalPoint ) {
|
|
|
140 // Cache created regular expressions for speed as this function is called often
|
|
|
141 if ( ! _re_dic[ decimalPoint ] ) {
|
|
|
142 _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
|
|
|
143 }
|
|
|
144 return typeof num === 'string' && decimalPoint !== '.' ?
|
|
|
145 num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
|
|
|
146 num;
|
|
|
147 };
|
|
|
148
|
|
|
149
|
|
|
150 var _isNumber = function ( d, decimalPoint, formatted ) {
|
|
|
151 var strType = typeof d === 'string';
|
|
|
152
|
|
|
153 // If empty return immediately so there must be a number if it is a
|
|
|
154 // formatted string (this stops the string "k", or "kr", etc being detected
|
|
|
155 // as a formatted number for currency
|
|
|
156 if ( _empty( d ) ) {
|
|
|
157 return true;
|
|
|
158 }
|
|
|
159
|
|
|
160 if ( decimalPoint && strType ) {
|
|
|
161 d = _numToDecimal( d, decimalPoint );
|
|
|
162 }
|
|
|
163
|
|
|
164 if ( formatted && strType ) {
|
|
|
165 d = d.replace( _re_formatted_numeric, '' );
|
|
|
166 }
|
|
|
167
|
|
|
168 return !isNaN( parseFloat(d) ) && isFinite( d );
|
|
|
169 };
|
|
|
170
|
|
|
171
|
|
|
172 // A string without HTML in it can be considered to be HTML still
|
|
|
173 var _isHtml = function ( d ) {
|
|
|
174 return _empty( d ) || typeof d === 'string';
|
|
|
175 };
|
|
|
176
|
|
|
177
|
|
|
178 var _htmlNumeric = function ( d, decimalPoint, formatted ) {
|
|
|
179 if ( _empty( d ) ) {
|
|
|
180 return true;
|
|
|
181 }
|
|
|
182
|
|
|
183 var html = _isHtml( d );
|
|
|
184 return ! html ?
|
|
|
185 null :
|
|
|
186 _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
|
|
|
187 true :
|
|
|
188 null;
|
|
|
189 };
|
|
|
190
|
|
|
191
|
|
|
192 var _pluck = function ( a, prop, prop2 ) {
|
|
|
193 var out = [];
|
|
|
194 var i=0, ien=a.length;
|
|
|
195
|
|
|
196 // Could have the test in the loop for slightly smaller code, but speed
|
|
|
197 // is essential here
|
|
|
198 if ( prop2 !== undefined ) {
|
|
|
199 for ( ; i<ien ; i++ ) {
|
|
|
200 if ( a[i] && a[i][ prop ] ) {
|
|
|
201 out.push( a[i][ prop ][ prop2 ] );
|
|
|
202 }
|
|
|
203 }
|
|
|
204 }
|
|
|
205 else {
|
|
|
206 for ( ; i<ien ; i++ ) {
|
|
|
207 if ( a[i] ) {
|
|
|
208 out.push( a[i][ prop ] );
|
|
|
209 }
|
|
|
210 }
|
|
|
211 }
|
|
|
212
|
|
|
213 return out;
|
|
|
214 };
|
|
|
215
|
|
|
216
|
|
|
217 // Basically the same as _pluck, but rather than looping over `a` we use `order`
|
|
|
218 // as the indexes to pick from `a`
|
|
|
219 var _pluck_order = function ( a, order, prop, prop2 )
|
|
|
220 {
|
|
|
221 var out = [];
|
|
|
222 var i=0, ien=order.length;
|
|
|
223
|
|
|
224 // Could have the test in the loop for slightly smaller code, but speed
|
|
|
225 // is essential here
|
|
|
226 if ( prop2 !== undefined ) {
|
|
|
227 for ( ; i<ien ; i++ ) {
|
|
|
228 if ( a[ order[i] ][ prop ] ) {
|
|
|
229 out.push( a[ order[i] ][ prop ][ prop2 ] );
|
|
|
230 }
|
|
|
231 }
|
|
|
232 }
|
|
|
233 else {
|
|
|
234 for ( ; i<ien ; i++ ) {
|
|
|
235 out.push( a[ order[i] ][ prop ] );
|
|
|
236 }
|
|
|
237 }
|
|
|
238
|
|
|
239 return out;
|
|
|
240 };
|
|
|
241
|
|
|
242
|
|
|
243 var _range = function ( len, start )
|
|
|
244 {
|
|
|
245 var out = [];
|
|
|
246 var end;
|
|
|
247
|
|
|
248 if ( start === undefined ) {
|
|
|
249 start = 0;
|
|
|
250 end = len;
|
|
|
251 }
|
|
|
252 else {
|
|
|
253 end = start;
|
|
|
254 start = len;
|
|
|
255 }
|
|
|
256
|
|
|
257 for ( var i=start ; i<end ; i++ ) {
|
|
|
258 out.push( i );
|
|
|
259 }
|
|
|
260
|
|
|
261 return out;
|
|
|
262 };
|
|
|
263
|
|
|
264
|
|
|
265 var _removeEmpty = function ( a )
|
|
|
266 {
|
|
|
267 var out = [];
|
|
|
268
|
|
|
269 for ( var i=0, ien=a.length ; i<ien ; i++ ) {
|
|
|
270 if ( a[i] ) { // careful - will remove all falsy values!
|
|
|
271 out.push( a[i] );
|
|
|
272 }
|
|
|
273 }
|
|
|
274
|
|
|
275 return out;
|
|
|
276 };
|
|
|
277
|
|
|
278
|
|
|
279 var _stripHtml = function ( d ) {
|
|
|
280 return d.replace( _re_html, '' );
|
|
|
281 };
|
|
|
282
|
|
|
283
|
|
|
284 /**
|
|
|
285 * Find the unique elements in a source array.
|
|
|
286 *
|
|
|
287 * @param {array} src Source array
|
|
|
288 * @return {array} Array of unique items
|
|
|
289 * @ignore
|
|
|
290 */
|
|
|
291 var _unique = function ( src )
|
|
|
292 {
|
|
|
293 // A faster unique method is to use object keys to identify used values,
|
|
|
294 // but this doesn't work with arrays or objects, which we must also
|
|
|
295 // consider. See jsperf.com/compare-array-unique-versions/4 for more
|
|
|
296 // information.
|
|
|
297 var
|
|
|
298 out = [],
|
|
|
299 val,
|
|
|
300 i, ien=src.length,
|
|
|
301 j, k=0;
|
|
|
302
|
|
|
303 again: for ( i=0 ; i<ien ; i++ ) {
|
|
|
304 val = src[i];
|
|
|
305
|
|
|
306 for ( j=0 ; j<k ; j++ ) {
|
|
|
307 if ( out[j] === val ) {
|
|
|
308 continue again;
|
|
|
309 }
|
|
|
310 }
|
|
|
311
|
|
|
312 out.push( val );
|
|
|
313 k++;
|
|
|
314 }
|
|
|
315
|
|
|
316 return out;
|
|
|
317 };
|
|
|
318
|
|
|
319
|
|
|
320
|
|
|
321 /**
|
|
|
322 * Create a mapping object that allows camel case parameters to be looked up
|
|
|
323 * for their Hungarian counterparts. The mapping is stored in a private
|
|
|
324 * parameter called `_hungarianMap` which can be accessed on the source object.
|
|
|
325 * @param {object} o
|
|
|
326 * @memberof DataTable#oApi
|
|
|
327 */
|
|
|
328 function _fnHungarianMap ( o )
|
|
|
329 {
|
|
|
330 var
|
|
|
331 hungarian = 'a aa ai ao as b fn i m o s ',
|
|
|
332 match,
|
|
|
333 newKey,
|
|
|
334 map = {};
|
|
|
335
|
|
|
336 $.each( o, function (key, val) {
|
|
|
337 match = key.match(/^([^A-Z]+?)([A-Z])/);
|
|
|
338
|
|
|
339 if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
|
|
|
340 {
|
|
|
341 newKey = key.replace( match[0], match[2].toLowerCase() );
|
|
|
342 map[ newKey ] = key;
|
|
|
343
|
|
|
344 if ( match[1] === 'o' )
|
|
|
345 {
|
|
|
346 _fnHungarianMap( o[key] );
|
|
|
347 }
|
|
|
348 }
|
|
|
349 } );
|
|
|
350
|
|
|
351 o._hungarianMap = map;
|
|
|
352 }
|
|
|
353
|
|
|
354
|
|
|
355 /**
|
|
|
356 * Convert from camel case parameters to Hungarian, based on a Hungarian map
|
|
|
357 * created by _fnHungarianMap.
|
|
|
358 * @param {object} src The model object which holds all parameters that can be
|
|
|
359 * mapped.
|
|
|
360 * @param {object} user The object to convert from camel case to Hungarian.
|
|
|
361 * @param {boolean} force When set to `true`, properties which already have a
|
|
|
362 * Hungarian value in the `user` object will be overwritten. Otherwise they
|
|
|
363 * won't be.
|
|
|
364 * @memberof DataTable#oApi
|
|
|
365 */
|
|
|
366 function _fnCamelToHungarian ( src, user, force )
|
|
|
367 {
|
|
|
368 if ( ! src._hungarianMap ) {
|
|
|
369 _fnHungarianMap( src );
|
|
|
370 }
|
|
|
371
|
|
|
372 var hungarianKey;
|
|
|
373
|
|
|
374 $.each( user, function (key, val) {
|
|
|
375 hungarianKey = src._hungarianMap[ key ];
|
|
|
376
|
|
|
377 if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
|
|
|
378 {
|
|
|
379 // For objects, we need to buzz down into the object to copy parameters
|
|
|
380 if ( hungarianKey.charAt(0) === 'o' )
|
|
|
381 {
|
|
|
382 // Copy the camelCase options over to the hungarian
|
|
|
383 if ( ! user[ hungarianKey ] ) {
|
|
|
384 user[ hungarianKey ] = {};
|
|
|
385 }
|
|
|
386 $.extend( true, user[hungarianKey], user[key] );
|
|
|
387
|
|
|
388 _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
|
|
|
389 }
|
|
|
390 else {
|
|
|
391 user[hungarianKey] = user[ key ];
|
|
|
392 }
|
|
|
393 }
|
|
|
394 } );
|
|
|
395 }
|
|
|
396
|
|
|
397
|
|
|
398 /**
|
|
|
399 * Language compatibility - when certain options are given, and others aren't, we
|
|
|
400 * need to duplicate the values over, in order to provide backwards compatibility
|
|
|
401 * with older language files.
|
|
|
402 * @param {object} oSettings dataTables settings object
|
|
|
403 * @memberof DataTable#oApi
|
|
|
404 */
|
|
|
405 function _fnLanguageCompat( lang )
|
|
|
406 {
|
|
|
407 var defaults = DataTable.defaults.oLanguage;
|
|
|
408 var zeroRecords = lang.sZeroRecords;
|
|
|
409
|
|
|
410 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
|
|
|
411 * sZeroRecords - assuming that is given.
|
|
|
412 */
|
|
|
413 if ( ! lang.sEmptyTable && zeroRecords &&
|
|
|
414 defaults.sEmptyTable === "No data available in table" )
|
|
|
415 {
|
|
|
416 _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
|
|
|
417 }
|
|
|
418
|
|
|
419 /* Likewise with loading records */
|
|
|
420 if ( ! lang.sLoadingRecords && zeroRecords &&
|
|
|
421 defaults.sLoadingRecords === "Loading..." )
|
|
|
422 {
|
|
|
423 _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
|
|
|
424 }
|
|
|
425
|
|
|
426 // Old parameter name of the thousands separator mapped onto the new
|
|
|
427 if ( lang.sInfoThousands ) {
|
|
|
428 lang.sThousands = lang.sInfoThousands;
|
|
|
429 }
|
|
|
430
|
|
|
431 var decimal = lang.sDecimal;
|
|
|
432 if ( decimal ) {
|
|
|
433 _addNumericSort( decimal );
|
|
|
434 }
|
|
|
435 }
|
|
|
436
|
|
|
437
|
|
|
438 /**
|
|
|
439 * Map one parameter onto another
|
|
|
440 * @param {object} o Object to map
|
|
|
441 * @param {*} knew The new parameter name
|
|
|
442 * @param {*} old The old parameter name
|
|
|
443 */
|
|
|
444 var _fnCompatMap = function ( o, knew, old ) {
|
|
|
445 if ( o[ knew ] !== undefined ) {
|
|
|
446 o[ old ] = o[ knew ];
|
|
|
447 }
|
|
|
448 };
|
|
|
449
|
|
|
450
|
|
|
451 /**
|
|
|
452 * Provide backwards compatibility for the main DT options. Note that the new
|
|
|
453 * options are mapped onto the old parameters, so this is an external interface
|
|
|
454 * change only.
|
|
|
455 * @param {object} init Object to map
|
|
|
456 */
|
|
|
457 function _fnCompatOpts ( init )
|
|
|
458 {
|
|
|
459 _fnCompatMap( init, 'ordering', 'bSort' );
|
|
|
460 _fnCompatMap( init, 'orderMulti', 'bSortMulti' );
|
|
|
461 _fnCompatMap( init, 'orderClasses', 'bSortClasses' );
|
|
|
462 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
|
|
|
463 _fnCompatMap( init, 'order', 'aaSorting' );
|
|
|
464 _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' );
|
|
|
465 _fnCompatMap( init, 'paging', 'bPaginate' );
|
|
|
466 _fnCompatMap( init, 'pagingType', 'sPaginationType' );
|
|
|
467 _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
|
|
|
468 _fnCompatMap( init, 'searching', 'bFilter' );
|
|
|
469
|
|
|
470 // Boolean initialisation of x-scrolling
|
|
|
471 if ( typeof init.sScrollX === 'boolean' ) {
|
|
|
472 init.sScrollX = init.sScrollX ? '100%' : '';
|
|
|
473 }
|
|
|
474
|
|
|
475 // Column search objects are in an array, so it needs to be converted
|
|
|
476 // element by element
|
|
|
477 var searchCols = init.aoSearchCols;
|
|
|
478
|
|
|
479 if ( searchCols ) {
|
|
|
480 for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
|
|
|
481 if ( searchCols[i] ) {
|
|
|
482 _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
|
|
|
483 }
|
|
|
484 }
|
|
|
485 }
|
|
|
486 }
|
|
|
487
|
|
|
488
|
|
|
489 /**
|
|
|
490 * Provide backwards compatibility for column options. Note that the new options
|
|
|
491 * are mapped onto the old parameters, so this is an external interface change
|
|
|
492 * only.
|
|
|
493 * @param {object} init Object to map
|
|
|
494 */
|
|
|
495 function _fnCompatCols ( init )
|
|
|
496 {
|
|
|
497 _fnCompatMap( init, 'orderable', 'bSortable' );
|
|
|
498 _fnCompatMap( init, 'orderData', 'aDataSort' );
|
|
|
499 _fnCompatMap( init, 'orderSequence', 'asSorting' );
|
|
|
500 _fnCompatMap( init, 'orderDataType', 'sortDataType' );
|
|
|
501
|
|
|
502 // orderData can be given as an integer
|
|
|
503 var dataSort = init.aDataSort;
|
|
|
504 if ( dataSort && ! $.isArray( dataSort ) ) {
|
|
|
505 init.aDataSort = [ dataSort ];
|
|
|
506 }
|
|
|
507 }
|
|
|
508
|
|
|
509
|
|
|
510 /**
|
|
|
511 * Browser feature detection for capabilities, quirks
|
|
|
512 * @param {object} settings dataTables settings object
|
|
|
513 * @memberof DataTable#oApi
|
|
|
514 */
|
|
|
515 function _fnBrowserDetect( settings )
|
|
|
516 {
|
|
|
517 // We don't need to do this every time DataTables is constructed, the values
|
|
|
518 // calculated are specific to the browser and OS configuration which we
|
|
|
519 // don't expect to change between initialisations
|
|
|
520 if ( ! DataTable.__browser ) {
|
|
|
521 var browser = {};
|
|
|
522 DataTable.__browser = browser;
|
|
|
523
|
|
|
524 // Scrolling feature / quirks detection
|
|
|
525 var n = $('<div/>')
|
|
|
526 .css( {
|
|
|
527 position: 'fixed',
|
|
|
528 top: 0,
|
|
|
529 left: 0,
|
|
|
530 height: 1,
|
|
|
531 width: 1,
|
|
|
532 overflow: 'hidden'
|
|
|
533 } )
|
|
|
534 .append(
|
|
|
535 $('<div/>')
|
|
|
536 .css( {
|
|
|
537 position: 'absolute',
|
|
|
538 top: 1,
|
|
|
539 left: 1,
|
|
|
540 width: 100,
|
|
|
541 overflow: 'scroll'
|
|
|
542 } )
|
|
|
543 .append(
|
|
|
544 $('<div/>')
|
|
|
545 .css( {
|
|
|
546 width: '100%',
|
|
|
547 height: 10
|
|
|
548 } )
|
|
|
549 )
|
|
|
550 )
|
|
|
551 .appendTo( 'body' );
|
|
|
552
|
|
|
553 var outer = n.children();
|
|
|
554 var inner = outer.children();
|
|
|
555
|
|
|
556 // Numbers below, in order, are:
|
|
|
557 // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
|
|
|
558 //
|
|
|
559 // IE6 XP: 100 100 100 83
|
|
|
560 // IE7 Vista: 100 100 100 83
|
|
|
561 // IE 8+ Windows: 83 83 100 83
|
|
|
562 // Evergreen Windows: 83 83 100 83
|
|
|
563 // Evergreen Mac with scrollbars: 85 85 100 85
|
|
|
564 // Evergreen Mac without scrollbars: 100 100 100 100
|
|
|
565
|
|
|
566 // Get scrollbar width
|
|
|
567 browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
|
|
|
568
|
|
|
569 // IE6/7 will oversize a width 100% element inside a scrolling element, to
|
|
|
570 // include the width of the scrollbar, while other browsers ensure the inner
|
|
|
571 // element is contained without forcing scrolling
|
|
|
572 //console.log( inner.offsetWidth );
|
|
|
573 browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
|
|
|
574
|
|
|
575 // In rtl text layout, some browsers (most, but not all) will place the
|
|
|
576 // scrollbar on the left, rather than the right.
|
|
|
577 browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
|
|
|
578
|
|
|
579 // IE8- don't provide height and width for getBoundingClientRect
|
|
|
580 browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
|
|
|
581
|
|
|
582 n.remove();
|
|
|
583 }
|
|
|
584
|
|
|
585 $.extend( settings.oBrowser, DataTable.__browser );
|
|
|
586 settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
|
|
|
587 }
|
|
|
588
|
|
|
589
|
|
|
590 /**
|
|
|
591 * Array.prototype reduce[Right] method, used for browsers which don't support
|
|
|
592 * JS 1.6. Done this way to reduce code size, since we iterate either way
|
|
|
593 * @param {object} settings dataTables settings object
|
|
|
594 * @memberof DataTable#oApi
|
|
|
595 */
|
|
|
596 function _fnReduce ( that, fn, init, start, end, inc )
|
|
|
597 {
|
|
|
598 var
|
|
|
599 i = start,
|
|
|
600 value,
|
|
|
601 isSet = false;
|
|
|
602
|
|
|
603 if ( init !== undefined ) {
|
|
|
604 value = init;
|
|
|
605 isSet = true;
|
|
|
606 }
|
|
|
607
|
|
|
608 while ( i !== end ) {
|
|
|
609 if ( ! that.hasOwnProperty(i) ) {
|
|
|
610 continue;
|
|
|
611 }
|
|
|
612
|
|
|
613 value = isSet ?
|
|
|
614 fn( value, that[i], i, that ) :
|
|
|
615 that[i];
|
|
|
616
|
|
|
617 isSet = true;
|
|
|
618 i += inc;
|
|
|
619 }
|
|
|
620
|
|
|
621 return value;
|
|
|
622 }
|
|
|
623
|
|
|
624 /**
|
|
|
625 * Add a column to the list used for the table with default values
|
|
|
626 * @param {object} oSettings dataTables settings object
|
|
|
627 * @param {node} nTh The th element for this column
|
|
|
628 * @memberof DataTable#oApi
|
|
|
629 */
|
|
|
630 function _fnAddColumn( oSettings, nTh )
|
|
|
631 {
|
|
|
632 // Add column to aoColumns array
|
|
|
633 var oDefaults = DataTable.defaults.column;
|
|
|
634 var iCol = oSettings.aoColumns.length;
|
|
|
635 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
|
|
|
636 "nTh": nTh ? nTh : document.createElement('th'),
|
|
|
637 "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
|
|
|
638 "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
|
|
|
639 "mData": oDefaults.mData ? oDefaults.mData : iCol,
|
|
|
640 idx: iCol
|
|
|
641 } );
|
|
|
642 oSettings.aoColumns.push( oCol );
|
|
|
643
|
|
|
644 // Add search object for column specific search. Note that the `searchCols[ iCol ]`
|
|
|
645 // passed into extend can be undefined. This allows the user to give a default
|
|
|
646 // with only some of the parameters defined, and also not give a default
|
|
|
647 var searchCols = oSettings.aoPreSearchCols;
|
|
|
648 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
|
|
|
649
|
|
|
650 // Use the default column options function to initialise classes etc
|
|
|
651 _fnColumnOptions( oSettings, iCol, $(nTh).data() );
|
|
|
652 }
|
|
|
653
|
|
|
654
|
|
|
655 /**
|
|
|
656 * Apply options for a column
|
|
|
657 * @param {object} oSettings dataTables settings object
|
|
|
658 * @param {int} iCol column index to consider
|
|
|
659 * @param {object} oOptions object with sType, bVisible and bSearchable etc
|
|
|
660 * @memberof DataTable#oApi
|
|
|
661 */
|
|
|
662 function _fnColumnOptions( oSettings, iCol, oOptions )
|
|
|
663 {
|
|
|
664 var oCol = oSettings.aoColumns[ iCol ];
|
|
|
665 var oClasses = oSettings.oClasses;
|
|
|
666 var th = $(oCol.nTh);
|
|
|
667
|
|
|
668 // Try to get width information from the DOM. We can't get it from CSS
|
|
|
669 // as we'd need to parse the CSS stylesheet. `width` option can override
|
|
|
670 if ( ! oCol.sWidthOrig ) {
|
|
|
671 // Width attribute
|
|
|
672 oCol.sWidthOrig = th.attr('width') || null;
|
|
|
673
|
|
|
674 // Style attribute
|
|
|
675 var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
|
|
|
676 if ( t ) {
|
|
|
677 oCol.sWidthOrig = t[1];
|
|
|
678 }
|
|
|
679 }
|
|
|
680
|
|
|
681 /* User specified column options */
|
|
|
682 if ( oOptions !== undefined && oOptions !== null )
|
|
|
683 {
|
|
|
684 // Backwards compatibility
|
|
|
685 _fnCompatCols( oOptions );
|
|
|
686
|
|
|
687 // Map camel case parameters to their Hungarian counterparts
|
|
|
688 _fnCamelToHungarian( DataTable.defaults.column, oOptions );
|
|
|
689
|
|
|
690 /* Backwards compatibility for mDataProp */
|
|
|
691 if ( oOptions.mDataProp !== undefined && !oOptions.mData )
|
|
|
692 {
|
|
|
693 oOptions.mData = oOptions.mDataProp;
|
|
|
694 }
|
|
|
695
|
|
|
696 if ( oOptions.sType )
|
|
|
697 {
|
|
|
698 oCol._sManualType = oOptions.sType;
|
|
|
699 }
|
|
|
700
|
|
|
701 // `class` is a reserved word in Javascript, so we need to provide
|
|
|
702 // the ability to use a valid name for the camel case input
|
|
|
703 if ( oOptions.className && ! oOptions.sClass )
|
|
|
704 {
|
|
|
705 oOptions.sClass = oOptions.className;
|
|
|
706 }
|
|
|
707
|
|
|
708 $.extend( oCol, oOptions );
|
|
|
709 _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
|
|
|
710
|
|
|
711 /* iDataSort to be applied (backwards compatibility), but aDataSort will take
|
|
|
712 * priority if defined
|
|
|
713 */
|
|
|
714 if ( oOptions.iDataSort !== undefined )
|
|
|
715 {
|
|
|
716 oCol.aDataSort = [ oOptions.iDataSort ];
|
|
|
717 }
|
|
|
718 _fnMap( oCol, oOptions, "aDataSort" );
|
|
|
719 }
|
|
|
720
|
|
|
721 /* Cache the data get and set functions for speed */
|
|
|
722 var mDataSrc = oCol.mData;
|
|
|
723 var mData = _fnGetObjectDataFn( mDataSrc );
|
|
|
724 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
|
|
|
725
|
|
|
726 var attrTest = function( src ) {
|
|
|
727 return typeof src === 'string' && src.indexOf('@') !== -1;
|
|
|
728 };
|
|
|
729 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
|
|
|
730 attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
|
|
|
731 );
|
|
|
732
|
|
|
733 oCol.fnGetData = function (rowData, type, meta) {
|
|
|
734 var innerData = mData( rowData, type, undefined, meta );
|
|
|
735
|
|
|
736 return mRender && type ?
|
|
|
737 mRender( innerData, type, rowData, meta ) :
|
|
|
738 innerData;
|
|
|
739 };
|
|
|
740 oCol.fnSetData = function ( rowData, val, meta ) {
|
|
|
741 return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
|
|
|
742 };
|
|
|
743
|
|
|
744 // Indicate if DataTables should read DOM data as an object or array
|
|
|
745 // Used in _fnGetRowElements
|
|
|
746 if ( typeof mDataSrc !== 'number' ) {
|
|
|
747 oSettings._rowReadObject = true;
|
|
|
748 }
|
|
|
749
|
|
|
750 /* Feature sorting overrides column specific when off */
|
|
|
751 if ( !oSettings.oFeatures.bSort )
|
|
|
752 {
|
|
|
753 oCol.bSortable = false;
|
|
|
754 th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
|
|
|
755 }
|
|
|
756
|
|
|
757 /* Check that the class assignment is correct for sorting */
|
|
|
758 var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
|
|
|
759 var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
|
|
|
760 if ( !oCol.bSortable || (!bAsc && !bDesc) )
|
|
|
761 {
|
|
|
762 oCol.sSortingClass = oClasses.sSortableNone;
|
|
|
763 oCol.sSortingClassJUI = "";
|
|
|
764 }
|
|
|
765 else if ( bAsc && !bDesc )
|
|
|
766 {
|
|
|
767 oCol.sSortingClass = oClasses.sSortableAsc;
|
|
|
768 oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
|
|
|
769 }
|
|
|
770 else if ( !bAsc && bDesc )
|
|
|
771 {
|
|
|
772 oCol.sSortingClass = oClasses.sSortableDesc;
|
|
|
773 oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
|
|
|
774 }
|
|
|
775 else
|
|
|
776 {
|
|
|
777 oCol.sSortingClass = oClasses.sSortable;
|
|
|
778 oCol.sSortingClassJUI = oClasses.sSortJUI;
|
|
|
779 }
|
|
|
780 }
|
|
|
781
|
|
|
782
|
|
|
783 /**
|
|
|
784 * Adjust the table column widths for new data. Note: you would probably want to
|
|
|
785 * do a redraw after calling this function!
|
|
|
786 * @param {object} settings dataTables settings object
|
|
|
787 * @memberof DataTable#oApi
|
|
|
788 */
|
|
|
789 function _fnAdjustColumnSizing ( settings )
|
|
|
790 {
|
|
|
791 /* Not interested in doing column width calculation if auto-width is disabled */
|
|
|
792 if ( settings.oFeatures.bAutoWidth !== false )
|
|
|
793 {
|
|
|
794 var columns = settings.aoColumns;
|
|
|
795
|
|
|
796 _fnCalculateColumnWidths( settings );
|
|
|
797 for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
|
|
|
798 {
|
|
|
799 columns[i].nTh.style.width = columns[i].sWidth;
|
|
|
800 }
|
|
|
801 }
|
|
|
802
|
|
|
803 var scroll = settings.oScroll;
|
|
|
804 if ( scroll.sY !== '' || scroll.sX !== '')
|
|
|
805 {
|
|
|
806 _fnScrollDraw( settings );
|
|
|
807 }
|
|
|
808
|
|
|
809 _fnCallbackFire( settings, null, 'column-sizing', [settings] );
|
|
|
810 }
|
|
|
811
|
|
|
812
|
|
|
813 /**
|
|
|
814 * Covert the index of a visible column to the index in the data array (take account
|
|
|
815 * of hidden columns)
|
|
|
816 * @param {object} oSettings dataTables settings object
|
|
|
817 * @param {int} iMatch Visible column index to lookup
|
|
|
818 * @returns {int} i the data index
|
|
|
819 * @memberof DataTable#oApi
|
|
|
820 */
|
|
|
821 function _fnVisibleToColumnIndex( oSettings, iMatch )
|
|
|
822 {
|
|
|
823 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
|
|
|
824
|
|
|
825 return typeof aiVis[iMatch] === 'number' ?
|
|
|
826 aiVis[iMatch] :
|
|
|
827 null;
|
|
|
828 }
|
|
|
829
|
|
|
830
|
|
|
831 /**
|
|
|
832 * Covert the index of an index in the data array and convert it to the visible
|
|
|
833 * column index (take account of hidden columns)
|
|
|
834 * @param {int} iMatch Column index to lookup
|
|
|
835 * @param {object} oSettings dataTables settings object
|
|
|
836 * @returns {int} i the data index
|
|
|
837 * @memberof DataTable#oApi
|
|
|
838 */
|
|
|
839 function _fnColumnIndexToVisible( oSettings, iMatch )
|
|
|
840 {
|
|
|
841 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
|
|
|
842 var iPos = $.inArray( iMatch, aiVis );
|
|
|
843
|
|
|
844 return iPos !== -1 ? iPos : null;
|
|
|
845 }
|
|
|
846
|
|
|
847
|
|
|
848 /**
|
|
|
849 * Get the number of visible columns
|
|
|
850 * @param {object} oSettings dataTables settings object
|
|
|
851 * @returns {int} i the number of visible columns
|
|
|
852 * @memberof DataTable#oApi
|
|
|
853 */
|
|
|
854 function _fnVisbleColumns( oSettings )
|
|
|
855 {
|
|
|
856 return _fnGetColumns( oSettings, 'bVisible' ).length;
|
|
|
857 }
|
|
|
858
|
|
|
859
|
|
|
860 /**
|
|
|
861 * Get an array of column indexes that match a given property
|
|
|
862 * @param {object} oSettings dataTables settings object
|
|
|
863 * @param {string} sParam Parameter in aoColumns to look for - typically
|
|
|
864 * bVisible or bSearchable
|
|
|
865 * @returns {array} Array of indexes with matched properties
|
|
|
866 * @memberof DataTable#oApi
|
|
|
867 */
|
|
|
868 function _fnGetColumns( oSettings, sParam )
|
|
|
869 {
|
|
|
870 var a = [];
|
|
|
871
|
|
|
872 $.map( oSettings.aoColumns, function(val, i) {
|
|
|
873 if ( val[sParam] ) {
|
|
|
874 a.push( i );
|
|
|
875 }
|
|
|
876 } );
|
|
|
877
|
|
|
878 return a;
|
|
|
879 }
|
|
|
880
|
|
|
881
|
|
|
882 /**
|
|
|
883 * Calculate the 'type' of a column
|
|
|
884 * @param {object} settings dataTables settings object
|
|
|
885 * @memberof DataTable#oApi
|
|
|
886 */
|
|
|
887 function _fnColumnTypes ( settings )
|
|
|
888 {
|
|
|
889 var columns = settings.aoColumns;
|
|
|
890 var data = settings.aoData;
|
|
|
891 var types = DataTable.ext.type.detect;
|
|
|
892 var i, ien, j, jen, k, ken;
|
|
|
893 var col, cell, detectedType, cache;
|
|
|
894
|
|
|
895 // For each column, spin over the
|
|
|
896 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
|
|
897 col = columns[i];
|
|
|
898 cache = [];
|
|
|
899
|
|
|
900 if ( ! col.sType && col._sManualType ) {
|
|
|
901 col.sType = col._sManualType;
|
|
|
902 }
|
|
|
903 else if ( ! col.sType ) {
|
|
|
904 for ( j=0, jen=types.length ; j<jen ; j++ ) {
|
|
|
905 for ( k=0, ken=data.length ; k<ken ; k++ ) {
|
|
|
906 // Use a cache array so we only need to get the type data
|
|
|
907 // from the formatter once (when using multiple detectors)
|
|
|
908 if ( cache[k] === undefined ) {
|
|
|
909 cache[k] = _fnGetCellData( settings, k, i, 'type' );
|
|
|
910 }
|
|
|
911
|
|
|
912 detectedType = types[j]( cache[k], settings );
|
|
|
913
|
|
|
914 // If null, then this type can't apply to this column, so
|
|
|
915 // rather than testing all cells, break out. There is an
|
|
|
916 // exception for the last type which is `html`. We need to
|
|
|
917 // scan all rows since it is possible to mix string and HTML
|
|
|
918 // types
|
|
|
919 if ( ! detectedType && j !== types.length-1 ) {
|
|
|
920 break;
|
|
|
921 }
|
|
|
922
|
|
|
923 // Only a single match is needed for html type since it is
|
|
|
924 // bottom of the pile and very similar to string
|
|
|
925 if ( detectedType === 'html' ) {
|
|
|
926 break;
|
|
|
927 }
|
|
|
928 }
|
|
|
929
|
|
|
930 // Type is valid for all data points in the column - use this
|
|
|
931 // type
|
|
|
932 if ( detectedType ) {
|
|
|
933 col.sType = detectedType;
|
|
|
934 break;
|
|
|
935 }
|
|
|
936 }
|
|
|
937
|
|
|
938 // Fall back - if no type was detected, always use string
|
|
|
939 if ( ! col.sType ) {
|
|
|
940 col.sType = 'string';
|
|
|
941 }
|
|
|
942 }
|
|
|
943 }
|
|
|
944 }
|
|
|
945
|
|
|
946
|
|
|
947 /**
|
|
|
948 * Take the column definitions and static columns arrays and calculate how
|
|
|
949 * they relate to column indexes. The callback function will then apply the
|
|
|
950 * definition found for a column to a suitable configuration object.
|
|
|
951 * @param {object} oSettings dataTables settings object
|
|
|
952 * @param {array} aoColDefs The aoColumnDefs array that is to be applied
|
|
|
953 * @param {array} aoCols The aoColumns array that defines columns individually
|
|
|
954 * @param {function} fn Callback function - takes two parameters, the calculated
|
|
|
955 * column index and the definition for that column.
|
|
|
956 * @memberof DataTable#oApi
|
|
|
957 */
|
|
|
958 function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
|
|
|
959 {
|
|
|
960 var i, iLen, j, jLen, k, kLen, def;
|
|
|
961 var columns = oSettings.aoColumns;
|
|
|
962
|
|
|
963 // Column definitions with aTargets
|
|
|
964 if ( aoColDefs )
|
|
|
965 {
|
|
|
966 /* Loop over the definitions array - loop in reverse so first instance has priority */
|
|
|
967 for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
|
|
|
968 {
|
|
|
969 def = aoColDefs[i];
|
|
|
970
|
|
|
971 /* Each definition can target multiple columns, as it is an array */
|
|
|
972 var aTargets = def.targets !== undefined ?
|
|
|
973 def.targets :
|
|
|
974 def.aTargets;
|
|
|
975
|
|
|
976 if ( ! $.isArray( aTargets ) )
|
|
|
977 {
|
|
|
978 aTargets = [ aTargets ];
|
|
|
979 }
|
|
|
980
|
|
|
981 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
|
|
|
982 {
|
|
|
983 if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
|
|
|
984 {
|
|
|
985 /* Add columns that we don't yet know about */
|
|
|
986 while( columns.length <= aTargets[j] )
|
|
|
987 {
|
|
|
988 _fnAddColumn( oSettings );
|
|
|
989 }
|
|
|
990
|
|
|
991 /* Integer, basic index */
|
|
|
992 fn( aTargets[j], def );
|
|
|
993 }
|
|
|
994 else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
|
|
|
995 {
|
|
|
996 /* Negative integer, right to left column counting */
|
|
|
997 fn( columns.length+aTargets[j], def );
|
|
|
998 }
|
|
|
999 else if ( typeof aTargets[j] === 'string' )
|
|
|
1000 {
|
|
|
1001 /* Class name matching on TH element */
|
|
|
1002 for ( k=0, kLen=columns.length ; k<kLen ; k++ )
|
|
|
1003 {
|
|
|
1004 if ( aTargets[j] == "_all" ||
|
|
|
1005 $(columns[k].nTh).hasClass( aTargets[j] ) )
|
|
|
1006 {
|
|
|
1007 fn( k, def );
|
|
|
1008 }
|
|
|
1009 }
|
|
|
1010 }
|
|
|
1011 }
|
|
|
1012 }
|
|
|
1013 }
|
|
|
1014
|
|
|
1015 // Statically defined columns array
|
|
|
1016 if ( aoCols )
|
|
|
1017 {
|
|
|
1018 for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
|
|
|
1019 {
|
|
|
1020 fn( i, aoCols[i] );
|
|
|
1021 }
|
|
|
1022 }
|
|
|
1023 }
|
|
|
1024
|
|
|
1025 /**
|
|
|
1026 * Add a data array to the table, creating DOM node etc. This is the parallel to
|
|
|
1027 * _fnGatherData, but for adding rows from a Javascript source, rather than a
|
|
|
1028 * DOM source.
|
|
|
1029 * @param {object} oSettings dataTables settings object
|
|
|
1030 * @param {array} aData data array to be added
|
|
|
1031 * @param {node} [nTr] TR element to add to the table - optional. If not given,
|
|
|
1032 * DataTables will create a row automatically
|
|
|
1033 * @param {array} [anTds] Array of TD|TH elements for the row - must be given
|
|
|
1034 * if nTr is.
|
|
|
1035 * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
|
|
|
1036 * @memberof DataTable#oApi
|
|
|
1037 */
|
|
|
1038 function _fnAddData ( oSettings, aDataIn, nTr, anTds )
|
|
|
1039 {
|
|
|
1040 /* Create the object for storing information about this new row */
|
|
|
1041 var iRow = oSettings.aoData.length;
|
|
|
1042 var oData = $.extend( true, {}, DataTable.models.oRow, {
|
|
|
1043 src: nTr ? 'dom' : 'data',
|
|
|
1044 idx: iRow
|
|
|
1045 } );
|
|
|
1046
|
|
|
1047 oData._aData = aDataIn;
|
|
|
1048 oSettings.aoData.push( oData );
|
|
|
1049
|
|
|
1050 /* Create the cells */
|
|
|
1051 var nTd, sThisType;
|
|
|
1052 var columns = oSettings.aoColumns;
|
|
|
1053
|
|
|
1054 // Invalidate the column types as the new data needs to be revalidated
|
|
|
1055 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
|
|
|
1056 {
|
|
|
1057 columns[i].sType = null;
|
|
|
1058 }
|
|
|
1059
|
|
|
1060 /* Add to the display array */
|
|
|
1061 oSettings.aiDisplayMaster.push( iRow );
|
|
|
1062
|
|
|
1063 var id = oSettings.rowIdFn( aDataIn );
|
|
|
1064 if ( id !== undefined ) {
|
|
|
1065 oSettings.aIds[ id ] = oData;
|
|
|
1066 }
|
|
|
1067
|
|
|
1068 /* Create the DOM information, or register it if already present */
|
|
|
1069 if ( nTr || ! oSettings.oFeatures.bDeferRender )
|
|
|
1070 {
|
|
|
1071 _fnCreateTr( oSettings, iRow, nTr, anTds );
|
|
|
1072 }
|
|
|
1073
|
|
|
1074 return iRow;
|
|
|
1075 }
|
|
|
1076
|
|
|
1077
|
|
|
1078 /**
|
|
|
1079 * Add one or more TR elements to the table. Generally we'd expect to
|
|
|
1080 * use this for reading data from a DOM sourced table, but it could be
|
|
|
1081 * used for an TR element. Note that if a TR is given, it is used (i.e.
|
|
|
1082 * it is not cloned).
|
|
|
1083 * @param {object} settings dataTables settings object
|
|
|
1084 * @param {array|node|jQuery} trs The TR element(s) to add to the table
|
|
|
1085 * @returns {array} Array of indexes for the added rows
|
|
|
1086 * @memberof DataTable#oApi
|
|
|
1087 */
|
|
|
1088 function _fnAddTr( settings, trs )
|
|
|
1089 {
|
|
|
1090 var row;
|
|
|
1091
|
|
|
1092 // Allow an individual node to be passed in
|
|
|
1093 if ( ! (trs instanceof $) ) {
|
|
|
1094 trs = $(trs);
|
|
|
1095 }
|
|
|
1096
|
|
|
1097 return trs.map( function (i, el) {
|
|
|
1098 row = _fnGetRowElements( settings, el );
|
|
|
1099 return _fnAddData( settings, row.data, el, row.cells );
|
|
|
1100 } );
|
|
|
1101 }
|
|
|
1102
|
|
|
1103
|
|
|
1104 /**
|
|
|
1105 * Take a TR element and convert it to an index in aoData
|
|
|
1106 * @param {object} oSettings dataTables settings object
|
|
|
1107 * @param {node} n the TR element to find
|
|
|
1108 * @returns {int} index if the node is found, null if not
|
|
|
1109 * @memberof DataTable#oApi
|
|
|
1110 */
|
|
|
1111 function _fnNodeToDataIndex( oSettings, n )
|
|
|
1112 {
|
|
|
1113 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
|
|
|
1114 }
|
|
|
1115
|
|
|
1116
|
|
|
1117 /**
|
|
|
1118 * Take a TD element and convert it into a column data index (not the visible index)
|
|
|
1119 * @param {object} oSettings dataTables settings object
|
|
|
1120 * @param {int} iRow The row number the TD/TH can be found in
|
|
|
1121 * @param {node} n The TD/TH element to find
|
|
|
1122 * @returns {int} index if the node is found, -1 if not
|
|
|
1123 * @memberof DataTable#oApi
|
|
|
1124 */
|
|
|
1125 function _fnNodeToColumnIndex( oSettings, iRow, n )
|
|
|
1126 {
|
|
|
1127 return $.inArray( n, oSettings.aoData[ iRow ].anCells );
|
|
|
1128 }
|
|
|
1129
|
|
|
1130
|
|
|
1131 /**
|
|
|
1132 * Get the data for a given cell from the internal cache, taking into account data mapping
|
|
|
1133 * @param {object} settings dataTables settings object
|
|
|
1134 * @param {int} rowIdx aoData row id
|
|
|
1135 * @param {int} colIdx Column index
|
|
|
1136 * @param {string} type data get type ('display', 'type' 'filter' 'sort')
|
|
|
1137 * @returns {*} Cell data
|
|
|
1138 * @memberof DataTable#oApi
|
|
|
1139 */
|
|
|
1140 function _fnGetCellData( settings, rowIdx, colIdx, type )
|
|
|
1141 {
|
|
|
1142 var draw = settings.iDraw;
|
|
|
1143 var col = settings.aoColumns[colIdx];
|
|
|
1144 var rowData = settings.aoData[rowIdx]._aData;
|
|
|
1145 var defaultContent = col.sDefaultContent;
|
|
|
1146 var cellData = col.fnGetData( rowData, type, {
|
|
|
1147 settings: settings,
|
|
|
1148 row: rowIdx,
|
|
|
1149 col: colIdx
|
|
|
1150 } );
|
|
|
1151
|
|
|
1152 if ( cellData === undefined ) {
|
|
|
1153 if ( settings.iDrawError != draw && defaultContent === null ) {
|
|
|
1154 _fnLog( settings, 0, "Requested unknown parameter "+
|
|
|
1155 (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
|
|
|
1156 " for row "+rowIdx, 4 );
|
|
|
1157 settings.iDrawError = draw;
|
|
|
1158 }
|
|
|
1159 return defaultContent;
|
|
|
1160 }
|
|
|
1161
|
|
|
1162 /* When the data source is null, we can use default column data */
|
|
|
1163 if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
|
|
|
1164 cellData = defaultContent;
|
|
|
1165 }
|
|
|
1166 else if ( typeof cellData === 'function' ) {
|
|
|
1167 // If the data source is a function, then we run it and use the return,
|
|
|
1168 // executing in the scope of the data object (for instances)
|
|
|
1169 return cellData.call( rowData );
|
|
|
1170 }
|
|
|
1171
|
|
|
1172 if ( cellData === null && type == 'display' ) {
|
|
|
1173 return '';
|
|
|
1174 }
|
|
|
1175 return cellData;
|
|
|
1176 }
|
|
|
1177
|
|
|
1178
|
|
|
1179 /**
|
|
|
1180 * Set the value for a specific cell, into the internal data cache
|
|
|
1181 * @param {object} settings dataTables settings object
|
|
|
1182 * @param {int} rowIdx aoData row id
|
|
|
1183 * @param {int} colIdx Column index
|
|
|
1184 * @param {*} val Value to set
|
|
|
1185 * @memberof DataTable#oApi
|
|
|
1186 */
|
|
|
1187 function _fnSetCellData( settings, rowIdx, colIdx, val )
|
|
|
1188 {
|
|
|
1189 var col = settings.aoColumns[colIdx];
|
|
|
1190 var rowData = settings.aoData[rowIdx]._aData;
|
|
|
1191
|
|
|
1192 col.fnSetData( rowData, val, {
|
|
|
1193 settings: settings,
|
|
|
1194 row: rowIdx,
|
|
|
1195 col: colIdx
|
|
|
1196 } );
|
|
|
1197 }
|
|
|
1198
|
|
|
1199
|
|
|
1200 // Private variable that is used to match action syntax in the data property object
|
|
|
1201 var __reArray = /\[.*?\]$/;
|
|
|
1202 var __reFn = /\(\)$/;
|
|
|
1203
|
|
|
1204 /**
|
|
|
1205 * Split string on periods, taking into account escaped periods
|
|
|
1206 * @param {string} str String to split
|
|
|
1207 * @return {array} Split string
|
|
|
1208 */
|
|
|
1209 function _fnSplitObjNotation( str )
|
|
|
1210 {
|
|
|
1211 return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
|
|
|
1212 return s.replace(/\\./g, '.');
|
|
|
1213 } );
|
|
|
1214 }
|
|
|
1215
|
|
|
1216
|
|
|
1217 /**
|
|
|
1218 * Return a function that can be used to get data from a source object, taking
|
|
|
1219 * into account the ability to use nested objects as a source
|
|
|
1220 * @param {string|int|function} mSource The data source for the object
|
|
|
1221 * @returns {function} Data get function
|
|
|
1222 * @memberof DataTable#oApi
|
|
|
1223 */
|
|
|
1224 function _fnGetObjectDataFn( mSource )
|
|
|
1225 {
|
|
|
1226 if ( $.isPlainObject( mSource ) )
|
|
|
1227 {
|
|
|
1228 /* Build an object of get functions, and wrap them in a single call */
|
|
|
1229 var o = {};
|
|
|
1230 $.each( mSource, function (key, val) {
|
|
|
1231 if ( val ) {
|
|
|
1232 o[key] = _fnGetObjectDataFn( val );
|
|
|
1233 }
|
|
|
1234 } );
|
|
|
1235
|
|
|
1236 return function (data, type, row, meta) {
|
|
|
1237 var t = o[type] || o._;
|
|
|
1238 return t !== undefined ?
|
|
|
1239 t(data, type, row, meta) :
|
|
|
1240 data;
|
|
|
1241 };
|
|
|
1242 }
|
|
|
1243 else if ( mSource === null )
|
|
|
1244 {
|
|
|
1245 /* Give an empty string for rendering / sorting etc */
|
|
|
1246 return function (data) { // type, row and meta also passed, but not used
|
|
|
1247 return data;
|
|
|
1248 };
|
|
|
1249 }
|
|
|
1250 else if ( typeof mSource === 'function' )
|
|
|
1251 {
|
|
|
1252 return function (data, type, row, meta) {
|
|
|
1253 return mSource( data, type, row, meta );
|
|
|
1254 };
|
|
|
1255 }
|
|
|
1256 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
|
|
|
1257 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
|
|
|
1258 {
|
|
|
1259 /* If there is a . in the source string then the data source is in a
|
|
|
1260 * nested object so we loop over the data for each level to get the next
|
|
|
1261 * level down. On each loop we test for undefined, and if found immediately
|
|
|
1262 * return. This allows entire objects to be missing and sDefaultContent to
|
|
|
1263 * be used if defined, rather than throwing an error
|
|
|
1264 */
|
|
|
1265 var fetchData = function (data, type, src) {
|
|
|
1266 var arrayNotation, funcNotation, out, innerSrc;
|
|
|
1267
|
|
|
1268 if ( src !== "" )
|
|
|
1269 {
|
|
|
1270 var a = _fnSplitObjNotation( src );
|
|
|
1271
|
|
|
1272 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
|
|
|
1273 {
|
|
|
1274 // Check if we are dealing with special notation
|
|
|
1275 arrayNotation = a[i].match(__reArray);
|
|
|
1276 funcNotation = a[i].match(__reFn);
|
|
|
1277
|
|
|
1278 if ( arrayNotation )
|
|
|
1279 {
|
|
|
1280 // Array notation
|
|
|
1281 a[i] = a[i].replace(__reArray, '');
|
|
|
1282
|
|
|
1283 // Condition allows simply [] to be passed in
|
|
|
1284 if ( a[i] !== "" ) {
|
|
|
1285 data = data[ a[i] ];
|
|
|
1286 }
|
|
|
1287 out = [];
|
|
|
1288
|
|
|
1289 // Get the remainder of the nested object to get
|
|
|
1290 a.splice( 0, i+1 );
|
|
|
1291 innerSrc = a.join('.');
|
|
|
1292
|
|
|
1293 // Traverse each entry in the array getting the properties requested
|
|
|
1294 if ( $.isArray( data ) ) {
|
|
|
1295 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
|
|
|
1296 out.push( fetchData( data[j], type, innerSrc ) );
|
|
|
1297 }
|
|
|
1298 }
|
|
|
1299
|
|
|
1300 // If a string is given in between the array notation indicators, that
|
|
|
1301 // is used to join the strings together, otherwise an array is returned
|
|
|
1302 var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
|
|
|
1303 data = (join==="") ? out : out.join(join);
|
|
|
1304
|
|
|
1305 // The inner call to fetchData has already traversed through the remainder
|
|
|
1306 // of the source requested, so we exit from the loop
|
|
|
1307 break;
|
|
|
1308 }
|
|
|
1309 else if ( funcNotation )
|
|
|
1310 {
|
|
|
1311 // Function call
|
|
|
1312 a[i] = a[i].replace(__reFn, '');
|
|
|
1313 data = data[ a[i] ]();
|
|
|
1314 continue;
|
|
|
1315 }
|
|
|
1316
|
|
|
1317 if ( data === null || data[ a[i] ] === undefined )
|
|
|
1318 {
|
|
|
1319 return undefined;
|
|
|
1320 }
|
|
|
1321 data = data[ a[i] ];
|
|
|
1322 }
|
|
|
1323 }
|
|
|
1324
|
|
|
1325 return data;
|
|
|
1326 };
|
|
|
1327
|
|
|
1328 return function (data, type) { // row and meta also passed, but not used
|
|
|
1329 return fetchData( data, type, mSource );
|
|
|
1330 };
|
|
|
1331 }
|
|
|
1332 else
|
|
|
1333 {
|
|
|
1334 /* Array or flat object mapping */
|
|
|
1335 return function (data, type) { // row and meta also passed, but not used
|
|
|
1336 return data[mSource];
|
|
|
1337 };
|
|
|
1338 }
|
|
|
1339 }
|
|
|
1340
|
|
|
1341
|
|
|
1342 /**
|
|
|
1343 * Return a function that can be used to set data from a source object, taking
|
|
|
1344 * into account the ability to use nested objects as a source
|
|
|
1345 * @param {string|int|function} mSource The data source for the object
|
|
|
1346 * @returns {function} Data set function
|
|
|
1347 * @memberof DataTable#oApi
|
|
|
1348 */
|
|
|
1349 function _fnSetObjectDataFn( mSource )
|
|
|
1350 {
|
|
|
1351 if ( $.isPlainObject( mSource ) )
|
|
|
1352 {
|
|
|
1353 /* Unlike get, only the underscore (global) option is used for for
|
|
|
1354 * setting data since we don't know the type here. This is why an object
|
|
|
1355 * option is not documented for `mData` (which is read/write), but it is
|
|
|
1356 * for `mRender` which is read only.
|
|
|
1357 */
|
|
|
1358 return _fnSetObjectDataFn( mSource._ );
|
|
|
1359 }
|
|
|
1360 else if ( mSource === null )
|
|
|
1361 {
|
|
|
1362 /* Nothing to do when the data source is null */
|
|
|
1363 return function () {};
|
|
|
1364 }
|
|
|
1365 else if ( typeof mSource === 'function' )
|
|
|
1366 {
|
|
|
1367 return function (data, val, meta) {
|
|
|
1368 mSource( data, 'set', val, meta );
|
|
|
1369 };
|
|
|
1370 }
|
|
|
1371 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
|
|
|
1372 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
|
|
|
1373 {
|
|
|
1374 /* Like the get, we need to get data from a nested object */
|
|
|
1375 var setData = function (data, val, src) {
|
|
|
1376 var a = _fnSplitObjNotation( src ), b;
|
|
|
1377 var aLast = a[a.length-1];
|
|
|
1378 var arrayNotation, funcNotation, o, innerSrc;
|
|
|
1379
|
|
|
1380 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
|
|
|
1381 {
|
|
|
1382 // Check if we are dealing with an array notation request
|
|
|
1383 arrayNotation = a[i].match(__reArray);
|
|
|
1384 funcNotation = a[i].match(__reFn);
|
|
|
1385
|
|
|
1386 if ( arrayNotation )
|
|
|
1387 {
|
|
|
1388 a[i] = a[i].replace(__reArray, '');
|
|
|
1389 data[ a[i] ] = [];
|
|
|
1390
|
|
|
1391 // Get the remainder of the nested object to set so we can recurse
|
|
|
1392 b = a.slice();
|
|
|
1393 b.splice( 0, i+1 );
|
|
|
1394 innerSrc = b.join('.');
|
|
|
1395
|
|
|
1396 // Traverse each entry in the array setting the properties requested
|
|
|
1397 if ( $.isArray( val ) )
|
|
|
1398 {
|
|
|
1399 for ( var j=0, jLen=val.length ; j<jLen ; j++ )
|
|
|
1400 {
|
|
|
1401 o = {};
|
|
|
1402 setData( o, val[j], innerSrc );
|
|
|
1403 data[ a[i] ].push( o );
|
|
|
1404 }
|
|
|
1405 }
|
|
|
1406 else
|
|
|
1407 {
|
|
|
1408 // We've been asked to save data to an array, but it
|
|
|
1409 // isn't array data to be saved. Best that can be done
|
|
|
1410 // is to just save the value.
|
|
|
1411 data[ a[i] ] = val;
|
|
|
1412 }
|
|
|
1413
|
|
|
1414 // The inner call to setData has already traversed through the remainder
|
|
|
1415 // of the source and has set the data, thus we can exit here
|
|
|
1416 return;
|
|
|
1417 }
|
|
|
1418 else if ( funcNotation )
|
|
|
1419 {
|
|
|
1420 // Function call
|
|
|
1421 a[i] = a[i].replace(__reFn, '');
|
|
|
1422 data = data[ a[i] ]( val );
|
|
|
1423 }
|
|
|
1424
|
|
|
1425 // If the nested object doesn't currently exist - since we are
|
|
|
1426 // trying to set the value - create it
|
|
|
1427 if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
|
|
|
1428 {
|
|
|
1429 data[ a[i] ] = {};
|
|
|
1430 }
|
|
|
1431 data = data[ a[i] ];
|
|
|
1432 }
|
|
|
1433
|
|
|
1434 // Last item in the input - i.e, the actual set
|
|
|
1435 if ( aLast.match(__reFn ) )
|
|
|
1436 {
|
|
|
1437 // Function call
|
|
|
1438 data = data[ aLast.replace(__reFn, '') ]( val );
|
|
|
1439 }
|
|
|
1440 else
|
|
|
1441 {
|
|
|
1442 // If array notation is used, we just want to strip it and use the property name
|
|
|
1443 // and assign the value. If it isn't used, then we get the result we want anyway
|
|
|
1444 data[ aLast.replace(__reArray, '') ] = val;
|
|
|
1445 }
|
|
|
1446 };
|
|
|
1447
|
|
|
1448 return function (data, val) { // meta is also passed in, but not used
|
|
|
1449 return setData( data, val, mSource );
|
|
|
1450 };
|
|
|
1451 }
|
|
|
1452 else
|
|
|
1453 {
|
|
|
1454 /* Array or flat object mapping */
|
|
|
1455 return function (data, val) { // meta is also passed in, but not used
|
|
|
1456 data[mSource] = val;
|
|
|
1457 };
|
|
|
1458 }
|
|
|
1459 }
|
|
|
1460
|
|
|
1461
|
|
|
1462 /**
|
|
|
1463 * Return an array with the full table data
|
|
|
1464 * @param {object} oSettings dataTables settings object
|
|
|
1465 * @returns array {array} aData Master data array
|
|
|
1466 * @memberof DataTable#oApi
|
|
|
1467 */
|
|
|
1468 function _fnGetDataMaster ( settings )
|
|
|
1469 {
|
|
|
1470 return _pluck( settings.aoData, '_aData' );
|
|
|
1471 }
|
|
|
1472
|
|
|
1473
|
|
|
1474 /**
|
|
|
1475 * Nuke the table
|
|
|
1476 * @param {object} oSettings dataTables settings object
|
|
|
1477 * @memberof DataTable#oApi
|
|
|
1478 */
|
|
|
1479 function _fnClearTable( settings )
|
|
|
1480 {
|
|
|
1481 settings.aoData.length = 0;
|
|
|
1482 settings.aiDisplayMaster.length = 0;
|
|
|
1483 settings.aiDisplay.length = 0;
|
|
|
1484 settings.aIds = {};
|
|
|
1485 }
|
|
|
1486
|
|
|
1487
|
|
|
1488 /**
|
|
|
1489 * Take an array of integers (index array) and remove a target integer (value - not
|
|
|
1490 * the key!)
|
|
|
1491 * @param {array} a Index array to target
|
|
|
1492 * @param {int} iTarget value to find
|
|
|
1493 * @memberof DataTable#oApi
|
|
|
1494 */
|
|
|
1495 function _fnDeleteIndex( a, iTarget, splice )
|
|
|
1496 {
|
|
|
1497 var iTargetIndex = -1;
|
|
|
1498
|
|
|
1499 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
|
|
|
1500 {
|
|
|
1501 if ( a[i] == iTarget )
|
|
|
1502 {
|
|
|
1503 iTargetIndex = i;
|
|
|
1504 }
|
|
|
1505 else if ( a[i] > iTarget )
|
|
|
1506 {
|
|
|
1507 a[i]--;
|
|
|
1508 }
|
|
|
1509 }
|
|
|
1510
|
|
|
1511 if ( iTargetIndex != -1 && splice === undefined )
|
|
|
1512 {
|
|
|
1513 a.splice( iTargetIndex, 1 );
|
|
|
1514 }
|
|
|
1515 }
|
|
|
1516
|
|
|
1517
|
|
|
1518 /**
|
|
|
1519 * Mark cached data as invalid such that a re-read of the data will occur when
|
|
|
1520 * the cached data is next requested. Also update from the data source object.
|
|
|
1521 *
|
|
|
1522 * @param {object} settings DataTables settings object
|
|
|
1523 * @param {int} rowIdx Row index to invalidate
|
|
|
1524 * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
|
|
|
1525 * or 'data'
|
|
|
1526 * @param {int} [colIdx] Column index to invalidate. If undefined the whole
|
|
|
1527 * row will be invalidated
|
|
|
1528 * @memberof DataTable#oApi
|
|
|
1529 *
|
|
|
1530 * @todo For the modularisation of v1.11 this will need to become a callback, so
|
|
|
1531 * the sort and filter methods can subscribe to it. That will required
|
|
|
1532 * initialisation options for sorting, which is why it is not already baked in
|
|
|
1533 */
|
|
|
1534 function _fnInvalidate( settings, rowIdx, src, colIdx )
|
|
|
1535 {
|
|
|
1536 var row = settings.aoData[ rowIdx ];
|
|
|
1537 var i, ien;
|
|
|
1538 var cellWrite = function ( cell, col ) {
|
|
|
1539 // This is very frustrating, but in IE if you just write directly
|
|
|
1540 // to innerHTML, and elements that are overwritten are GC'ed,
|
|
|
1541 // even if there is a reference to them elsewhere
|
|
|
1542 while ( cell.childNodes.length ) {
|
|
|
1543 cell.removeChild( cell.firstChild );
|
|
|
1544 }
|
|
|
1545
|
|
|
1546 cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
|
|
|
1547 };
|
|
|
1548
|
|
|
1549 // Are we reading last data from DOM or the data object?
|
|
|
1550 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
|
|
|
1551 // Read the data from the DOM
|
|
|
1552 row._aData = _fnGetRowElements(
|
|
|
1553 settings, row, colIdx, colIdx === undefined ? undefined : row._aData
|
|
|
1554 )
|
|
|
1555 .data;
|
|
|
1556 }
|
|
|
1557 else {
|
|
|
1558 // Reading from data object, update the DOM
|
|
|
1559 var cells = row.anCells;
|
|
|
1560
|
|
|
1561 if ( cells ) {
|
|
|
1562 if ( colIdx !== undefined ) {
|
|
|
1563 cellWrite( cells[colIdx], colIdx );
|
|
|
1564 }
|
|
|
1565 else {
|
|
|
1566 for ( i=0, ien=cells.length ; i<ien ; i++ ) {
|
|
|
1567 cellWrite( cells[i], i );
|
|
|
1568 }
|
|
|
1569 }
|
|
|
1570 }
|
|
|
1571 }
|
|
|
1572
|
|
|
1573 // For both row and cell invalidation, the cached data for sorting and
|
|
|
1574 // filtering is nulled out
|
|
|
1575 row._aSortData = null;
|
|
|
1576 row._aFilterData = null;
|
|
|
1577
|
|
|
1578 // Invalidate the type for a specific column (if given) or all columns since
|
|
|
1579 // the data might have changed
|
|
|
1580 var cols = settings.aoColumns;
|
|
|
1581 if ( colIdx !== undefined ) {
|
|
|
1582 cols[ colIdx ].sType = null;
|
|
|
1583 }
|
|
|
1584 else {
|
|
|
1585 for ( i=0, ien=cols.length ; i<ien ; i++ ) {
|
|
|
1586 cols[i].sType = null;
|
|
|
1587 }
|
|
|
1588
|
|
|
1589 // Update DataTables special `DT_*` attributes for the row
|
|
|
1590 _fnRowAttributes( settings, row );
|
|
|
1591 }
|
|
|
1592 }
|
|
|
1593
|
|
|
1594
|
|
|
1595 /**
|
|
|
1596 * Build a data source object from an HTML row, reading the contents of the
|
|
|
1597 * cells that are in the row.
|
|
|
1598 *
|
|
|
1599 * @param {object} settings DataTables settings object
|
|
|
1600 * @param {node|object} TR element from which to read data or existing row
|
|
|
1601 * object from which to re-read the data from the cells
|
|
|
1602 * @param {int} [colIdx] Optional column index
|
|
|
1603 * @param {array|object} [d] Data source object. If `colIdx` is given then this
|
|
|
1604 * parameter should also be given and will be used to write the data into.
|
|
|
1605 * Only the column in question will be written
|
|
|
1606 * @returns {object} Object with two parameters: `data` the data read, in
|
|
|
1607 * document order, and `cells` and array of nodes (they can be useful to the
|
|
|
1608 * caller, so rather than needing a second traversal to get them, just return
|
|
|
1609 * them from here).
|
|
|
1610 * @memberof DataTable#oApi
|
|
|
1611 */
|
|
|
1612 function _fnGetRowElements( settings, row, colIdx, d )
|
|
|
1613 {
|
|
|
1614 var
|
|
|
1615 tds = [],
|
|
|
1616 td = row.firstChild,
|
|
|
1617 name, col, o, i=0, contents,
|
|
|
1618 columns = settings.aoColumns,
|
|
|
1619 objectRead = settings._rowReadObject;
|
|
|
1620
|
|
|
1621 // Allow the data object to be passed in, or construct
|
|
|
1622 d = d !== undefined ?
|
|
|
1623 d :
|
|
|
1624 objectRead ?
|
|
|
1625 {} :
|
|
|
1626 [];
|
|
|
1627
|
|
|
1628 var attr = function ( str, td ) {
|
|
|
1629 if ( typeof str === 'string' ) {
|
|
|
1630 var idx = str.indexOf('@');
|
|
|
1631
|
|
|
1632 if ( idx !== -1 ) {
|
|
|
1633 var attr = str.substring( idx+1 );
|
|
|
1634 var setter = _fnSetObjectDataFn( str );
|
|
|
1635 setter( d, td.getAttribute( attr ) );
|
|
|
1636 }
|
|
|
1637 }
|
|
|
1638 };
|
|
|
1639
|
|
|
1640 // Read data from a cell and store into the data object
|
|
|
1641 var cellProcess = function ( cell ) {
|
|
|
1642 if ( colIdx === undefined || colIdx === i ) {
|
|
|
1643 col = columns[i];
|
|
|
1644 contents = $.trim(cell.innerHTML);
|
|
|
1645
|
|
|
1646 if ( col && col._bAttrSrc ) {
|
|
|
1647 var setter = _fnSetObjectDataFn( col.mData._ );
|
|
|
1648 setter( d, contents );
|
|
|
1649
|
|
|
1650 attr( col.mData.sort, cell );
|
|
|
1651 attr( col.mData.type, cell );
|
|
|
1652 attr( col.mData.filter, cell );
|
|
|
1653 }
|
|
|
1654 else {
|
|
|
1655 // Depending on the `data` option for the columns the data can
|
|
|
1656 // be read to either an object or an array.
|
|
|
1657 if ( objectRead ) {
|
|
|
1658 if ( ! col._setter ) {
|
|
|
1659 // Cache the setter function
|
|
|
1660 col._setter = _fnSetObjectDataFn( col.mData );
|
|
|
1661 }
|
|
|
1662 col._setter( d, contents );
|
|
|
1663 }
|
|
|
1664 else {
|
|
|
1665 d[i] = contents;
|
|
|
1666 }
|
|
|
1667 }
|
|
|
1668 }
|
|
|
1669
|
|
|
1670 i++;
|
|
|
1671 };
|
|
|
1672
|
|
|
1673 if ( td ) {
|
|
|
1674 // `tr` element was passed in
|
|
|
1675 while ( td ) {
|
|
|
1676 name = td.nodeName.toUpperCase();
|
|
|
1677
|
|
|
1678 if ( name == "TD" || name == "TH" ) {
|
|
|
1679 cellProcess( td );
|
|
|
1680 tds.push( td );
|
|
|
1681 }
|
|
|
1682
|
|
|
1683 td = td.nextSibling;
|
|
|
1684 }
|
|
|
1685 }
|
|
|
1686 else {
|
|
|
1687 // Existing row object passed in
|
|
|
1688 tds = row.anCells;
|
|
|
1689
|
|
|
1690 for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
|
|
|
1691 cellProcess( tds[j] );
|
|
|
1692 }
|
|
|
1693 }
|
|
|
1694
|
|
|
1695 // Read the ID from the DOM if present
|
|
|
1696 var rowNode = td ? row : row.nTr;
|
|
|
1697
|
|
|
1698 if ( rowNode ) {
|
|
|
1699 var id = rowNode.getAttribute( 'id' );
|
|
|
1700
|
|
|
1701 if ( id ) {
|
|
|
1702 _fnSetObjectDataFn( settings.rowId )( d, id );
|
|
|
1703 }
|
|
|
1704 }
|
|
|
1705
|
|
|
1706 return {
|
|
|
1707 data: d,
|
|
|
1708 cells: tds
|
|
|
1709 };
|
|
|
1710 }
|
|
|
1711 /**
|
|
|
1712 * Create a new TR element (and it's TD children) for a row
|
|
|
1713 * @param {object} oSettings dataTables settings object
|
|
|
1714 * @param {int} iRow Row to consider
|
|
|
1715 * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
|
|
|
1716 * DataTables will create a row automatically
|
|
|
1717 * @param {array} [anTds] Array of TD|TH elements for the row - must be given
|
|
|
1718 * if nTr is.
|
|
|
1719 * @memberof DataTable#oApi
|
|
|
1720 */
|
|
|
1721 function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
|
|
|
1722 {
|
|
|
1723 var
|
|
|
1724 row = oSettings.aoData[iRow],
|
|
|
1725 rowData = row._aData,
|
|
|
1726 cells = [],
|
|
|
1727 nTr, nTd, oCol,
|
|
|
1728 i, iLen;
|
|
|
1729
|
|
|
1730 if ( row.nTr === null )
|
|
|
1731 {
|
|
|
1732 nTr = nTrIn || document.createElement('tr');
|
|
|
1733
|
|
|
1734 row.nTr = nTr;
|
|
|
1735 row.anCells = cells;
|
|
|
1736
|
|
|
1737 /* Use a private property on the node to allow reserve mapping from the node
|
|
|
1738 * to the aoData array for fast look up
|
|
|
1739 */
|
|
|
1740 nTr._DT_RowIndex = iRow;
|
|
|
1741
|
|
|
1742 /* Special parameters can be given by the data source to be used on the row */
|
|
|
1743 _fnRowAttributes( oSettings, row );
|
|
|
1744
|
|
|
1745 /* Process each column */
|
|
|
1746 for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
|
|
|
1747 {
|
|
|
1748 oCol = oSettings.aoColumns[i];
|
|
|
1749
|
|
|
1750 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
|
|
|
1751 cells.push( nTd );
|
|
|
1752
|
|
|
1753 // Need to create the HTML if new, or if a rendering function is defined
|
|
|
1754 if ( !nTrIn || oCol.mRender || oCol.mData !== i )
|
|
|
1755 {
|
|
|
1756 nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
|
|
|
1757 }
|
|
|
1758
|
|
|
1759 /* Add user defined class */
|
|
|
1760 if ( oCol.sClass )
|
|
|
1761 {
|
|
|
1762 nTd.className += ' '+oCol.sClass;
|
|
|
1763 }
|
|
|
1764
|
|
|
1765 // Visibility - add or remove as required
|
|
|
1766 if ( oCol.bVisible && ! nTrIn )
|
|
|
1767 {
|
|
|
1768 nTr.appendChild( nTd );
|
|
|
1769 }
|
|
|
1770 else if ( ! oCol.bVisible && nTrIn )
|
|
|
1771 {
|
|
|
1772 nTd.parentNode.removeChild( nTd );
|
|
|
1773 }
|
|
|
1774
|
|
|
1775 if ( oCol.fnCreatedCell )
|
|
|
1776 {
|
|
|
1777 oCol.fnCreatedCell.call( oSettings.oInstance,
|
|
|
1778 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
|
|
|
1779 );
|
|
|
1780 }
|
|
|
1781 }
|
|
|
1782
|
|
|
1783 _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
|
|
|
1784 }
|
|
|
1785
|
|
|
1786 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
|
|
|
1787 // and deployed
|
|
|
1788 row.nTr.setAttribute( 'role', 'row' );
|
|
|
1789 }
|
|
|
1790
|
|
|
1791
|
|
|
1792 /**
|
|
|
1793 * Add attributes to a row based on the special `DT_*` parameters in a data
|
|
|
1794 * source object.
|
|
|
1795 * @param {object} settings DataTables settings object
|
|
|
1796 * @param {object} DataTables row object for the row to be modified
|
|
|
1797 * @memberof DataTable#oApi
|
|
|
1798 */
|
|
|
1799 function _fnRowAttributes( settings, row )
|
|
|
1800 {
|
|
|
1801 var tr = row.nTr;
|
|
|
1802 var data = row._aData;
|
|
|
1803
|
|
|
1804 if ( tr ) {
|
|
|
1805 var id = settings.rowIdFn( data );
|
|
|
1806
|
|
|
1807 if ( id ) {
|
|
|
1808 tr.id = id;
|
|
|
1809 }
|
|
|
1810
|
|
|
1811 if ( data.DT_RowClass ) {
|
|
|
1812 // Remove any classes added by DT_RowClass before
|
|
|
1813 var a = data.DT_RowClass.split(' ');
|
|
|
1814 row.__rowc = row.__rowc ?
|
|
|
1815 _unique( row.__rowc.concat( a ) ) :
|
|
|
1816 a;
|
|
|
1817
|
|
|
1818 $(tr)
|
|
|
1819 .removeClass( row.__rowc.join(' ') )
|
|
|
1820 .addClass( data.DT_RowClass );
|
|
|
1821 }
|
|
|
1822
|
|
|
1823 if ( data.DT_RowAttr ) {
|
|
|
1824 $(tr).attr( data.DT_RowAttr );
|
|
|
1825 }
|
|
|
1826
|
|
|
1827 if ( data.DT_RowData ) {
|
|
|
1828 $(tr).data( data.DT_RowData );
|
|
|
1829 }
|
|
|
1830 }
|
|
|
1831 }
|
|
|
1832
|
|
|
1833
|
|
|
1834 /**
|
|
|
1835 * Create the HTML header for the table
|
|
|
1836 * @param {object} oSettings dataTables settings object
|
|
|
1837 * @memberof DataTable#oApi
|
|
|
1838 */
|
|
|
1839 function _fnBuildHead( oSettings )
|
|
|
1840 {
|
|
|
1841 var i, ien, cell, row, column;
|
|
|
1842 var thead = oSettings.nTHead;
|
|
|
1843 var tfoot = oSettings.nTFoot;
|
|
|
1844 var createHeader = $('th, td', thead).length === 0;
|
|
|
1845 var classes = oSettings.oClasses;
|
|
|
1846 var columns = oSettings.aoColumns;
|
|
|
1847
|
|
|
1848 if ( createHeader ) {
|
|
|
1849 row = $('<tr/>').appendTo( thead );
|
|
|
1850 }
|
|
|
1851
|
|
|
1852 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
|
|
1853 column = columns[i];
|
|
|
1854 cell = $( column.nTh ).addClass( column.sClass );
|
|
|
1855
|
|
|
1856 if ( createHeader ) {
|
|
|
1857 cell.appendTo( row );
|
|
|
1858 }
|
|
|
1859
|
|
|
1860 // 1.11 move into sorting
|
|
|
1861 if ( oSettings.oFeatures.bSort ) {
|
|
|
1862 cell.addClass( column.sSortingClass );
|
|
|
1863
|
|
|
1864 if ( column.bSortable !== false ) {
|
|
|
1865 cell
|
|
|
1866 .attr( 'tabindex', oSettings.iTabIndex )
|
|
|
1867 .attr( 'aria-controls', oSettings.sTableId );
|
|
|
1868
|
|
|
1869 _fnSortAttachListener( oSettings, column.nTh, i );
|
|
|
1870 }
|
|
|
1871 }
|
|
|
1872
|
|
|
1873 if ( column.sTitle != cell[0].innerHTML ) {
|
|
|
1874 cell.html( column.sTitle );
|
|
|
1875 }
|
|
|
1876
|
|
|
1877 _fnRenderer( oSettings, 'header' )(
|
|
|
1878 oSettings, cell, column, classes
|
|
|
1879 );
|
|
|
1880 }
|
|
|
1881
|
|
|
1882 if ( createHeader ) {
|
|
|
1883 _fnDetectHeader( oSettings.aoHeader, thead );
|
|
|
1884 }
|
|
|
1885
|
|
|
1886 /* ARIA role for the rows */
|
|
|
1887 $(thead).find('>tr').attr('role', 'row');
|
|
|
1888
|
|
|
1889 /* Deal with the footer - add classes if required */
|
|
|
1890 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
|
|
|
1891 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
|
|
|
1892
|
|
|
1893 // Cache the footer cells. Note that we only take the cells from the first
|
|
|
1894 // row in the footer. If there is more than one row the user wants to
|
|
|
1895 // interact with, they need to use the table().foot() method. Note also this
|
|
|
1896 // allows cells to be used for multiple columns using colspan
|
|
|
1897 if ( tfoot !== null ) {
|
|
|
1898 var cells = oSettings.aoFooter[0];
|
|
|
1899
|
|
|
1900 for ( i=0, ien=cells.length ; i<ien ; i++ ) {
|
|
|
1901 column = columns[i];
|
|
|
1902 column.nTf = cells[i].cell;
|
|
|
1903
|
|
|
1904 if ( column.sClass ) {
|
|
|
1905 $(column.nTf).addClass( column.sClass );
|
|
|
1906 }
|
|
|
1907 }
|
|
|
1908 }
|
|
|
1909 }
|
|
|
1910
|
|
|
1911
|
|
|
1912 /**
|
|
|
1913 * Draw the header (or footer) element based on the column visibility states. The
|
|
|
1914 * methodology here is to use the layout array from _fnDetectHeader, modified for
|
|
|
1915 * the instantaneous column visibility, to construct the new layout. The grid is
|
|
|
1916 * traversed over cell at a time in a rows x columns grid fashion, although each
|
|
|
1917 * cell insert can cover multiple elements in the grid - which is tracks using the
|
|
|
1918 * aApplied array. Cell inserts in the grid will only occur where there isn't
|
|
|
1919 * already a cell in that position.
|
|
|
1920 * @param {object} oSettings dataTables settings object
|
|
|
1921 * @param array {objects} aoSource Layout array from _fnDetectHeader
|
|
|
1922 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
|
|
|
1923 * @memberof DataTable#oApi
|
|
|
1924 */
|
|
|
1925 function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
|
|
|
1926 {
|
|
|
1927 var i, iLen, j, jLen, k, kLen, n, nLocalTr;
|
|
|
1928 var aoLocal = [];
|
|
|
1929 var aApplied = [];
|
|
|
1930 var iColumns = oSettings.aoColumns.length;
|
|
|
1931 var iRowspan, iColspan;
|
|
|
1932
|
|
|
1933 if ( ! aoSource )
|
|
|
1934 {
|
|
|
1935 return;
|
|
|
1936 }
|
|
|
1937
|
|
|
1938 if ( bIncludeHidden === undefined )
|
|
|
1939 {
|
|
|
1940 bIncludeHidden = false;
|
|
|
1941 }
|
|
|
1942
|
|
|
1943 /* Make a copy of the master layout array, but without the visible columns in it */
|
|
|
1944 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
|
|
|
1945 {
|
|
|
1946 aoLocal[i] = aoSource[i].slice();
|
|
|
1947 aoLocal[i].nTr = aoSource[i].nTr;
|
|
|
1948
|
|
|
1949 /* Remove any columns which are currently hidden */
|
|
|
1950 for ( j=iColumns-1 ; j>=0 ; j-- )
|
|
|
1951 {
|
|
|
1952 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
|
|
|
1953 {
|
|
|
1954 aoLocal[i].splice( j, 1 );
|
|
|
1955 }
|
|
|
1956 }
|
|
|
1957
|
|
|
1958 /* Prep the applied array - it needs an element for each row */
|
|
|
1959 aApplied.push( [] );
|
|
|
1960 }
|
|
|
1961
|
|
|
1962 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
|
|
|
1963 {
|
|
|
1964 nLocalTr = aoLocal[i].nTr;
|
|
|
1965
|
|
|
1966 /* All cells are going to be replaced, so empty out the row */
|
|
|
1967 if ( nLocalTr )
|
|
|
1968 {
|
|
|
1969 while( (n = nLocalTr.firstChild) )
|
|
|
1970 {
|
|
|
1971 nLocalTr.removeChild( n );
|
|
|
1972 }
|
|
|
1973 }
|
|
|
1974
|
|
|
1975 for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
|
|
|
1976 {
|
|
|
1977 iRowspan = 1;
|
|
|
1978 iColspan = 1;
|
|
|
1979
|
|
|
1980 /* Check to see if there is already a cell (row/colspan) covering our target
|
|
|
1981 * insert point. If there is, then there is nothing to do.
|
|
|
1982 */
|
|
|
1983 if ( aApplied[i][j] === undefined )
|
|
|
1984 {
|
|
|
1985 nLocalTr.appendChild( aoLocal[i][j].cell );
|
|
|
1986 aApplied[i][j] = 1;
|
|
|
1987
|
|
|
1988 /* Expand the cell to cover as many rows as needed */
|
|
|
1989 while ( aoLocal[i+iRowspan] !== undefined &&
|
|
|
1990 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
|
|
|
1991 {
|
|
|
1992 aApplied[i+iRowspan][j] = 1;
|
|
|
1993 iRowspan++;
|
|
|
1994 }
|
|
|
1995
|
|
|
1996 /* Expand the cell to cover as many columns as needed */
|
|
|
1997 while ( aoLocal[i][j+iColspan] !== undefined &&
|
|
|
1998 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
|
|
|
1999 {
|
|
|
2000 /* Must update the applied array over the rows for the columns */
|
|
|
2001 for ( k=0 ; k<iRowspan ; k++ )
|
|
|
2002 {
|
|
|
2003 aApplied[i+k][j+iColspan] = 1;
|
|
|
2004 }
|
|
|
2005 iColspan++;
|
|
|
2006 }
|
|
|
2007
|
|
|
2008 /* Do the actual expansion in the DOM */
|
|
|
2009 $(aoLocal[i][j].cell)
|
|
|
2010 .attr('rowspan', iRowspan)
|
|
|
2011 .attr('colspan', iColspan);
|
|
|
2012 }
|
|
|
2013 }
|
|
|
2014 }
|
|
|
2015 }
|
|
|
2016
|
|
|
2017
|
|
|
2018 /**
|
|
|
2019 * Insert the required TR nodes into the table for display
|
|
|
2020 * @param {object} oSettings dataTables settings object
|
|
|
2021 * @memberof DataTable#oApi
|
|
|
2022 */
|
|
|
2023 function _fnDraw( oSettings )
|
|
|
2024 {
|
|
|
2025 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
|
|
|
2026 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
|
|
|
2027 if ( $.inArray( false, aPreDraw ) !== -1 )
|
|
|
2028 {
|
|
|
2029 _fnProcessingDisplay( oSettings, false );
|
|
|
2030 return;
|
|
|
2031 }
|
|
|
2032
|
|
|
2033 var i, iLen, n;
|
|
|
2034 var anRows = [];
|
|
|
2035 var iRowCount = 0;
|
|
|
2036 var asStripeClasses = oSettings.asStripeClasses;
|
|
|
2037 var iStripes = asStripeClasses.length;
|
|
|
2038 var iOpenRows = oSettings.aoOpenRows.length;
|
|
|
2039 var oLang = oSettings.oLanguage;
|
|
|
2040 var iInitDisplayStart = oSettings.iInitDisplayStart;
|
|
|
2041 var bServerSide = _fnDataSource( oSettings ) == 'ssp';
|
|
|
2042 var aiDisplay = oSettings.aiDisplay;
|
|
|
2043
|
|
|
2044 oSettings.bDrawing = true;
|
|
|
2045
|
|
|
2046 /* Check and see if we have an initial draw position from state saving */
|
|
|
2047 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
|
|
|
2048 {
|
|
|
2049 oSettings._iDisplayStart = bServerSide ?
|
|
|
2050 iInitDisplayStart :
|
|
|
2051 iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
|
|
|
2052 0 :
|
|
|
2053 iInitDisplayStart;
|
|
|
2054
|
|
|
2055 oSettings.iInitDisplayStart = -1;
|
|
|
2056 }
|
|
|
2057
|
|
|
2058 var iDisplayStart = oSettings._iDisplayStart;
|
|
|
2059 var iDisplayEnd = oSettings.fnDisplayEnd();
|
|
|
2060
|
|
|
2061 /* Server-side processing draw intercept */
|
|
|
2062 if ( oSettings.bDeferLoading )
|
|
|
2063 {
|
|
|
2064 oSettings.bDeferLoading = false;
|
|
|
2065 oSettings.iDraw++;
|
|
|
2066 _fnProcessingDisplay( oSettings, false );
|
|
|
2067 }
|
|
|
2068 else if ( !bServerSide )
|
|
|
2069 {
|
|
|
2070 oSettings.iDraw++;
|
|
|
2071 }
|
|
|
2072 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
|
|
|
2073 {
|
|
|
2074 return;
|
|
|
2075 }
|
|
|
2076
|
|
|
2077 if ( aiDisplay.length !== 0 )
|
|
|
2078 {
|
|
|
2079 var iStart = bServerSide ? 0 : iDisplayStart;
|
|
|
2080 var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
|
|
|
2081
|
|
|
2082 for ( var j=iStart ; j<iEnd ; j++ )
|
|
|
2083 {
|
|
|
2084 var iDataIndex = aiDisplay[j];
|
|
|
2085 var aoData = oSettings.aoData[ iDataIndex ];
|
|
|
2086 if ( aoData.nTr === null )
|
|
|
2087 {
|
|
|
2088 _fnCreateTr( oSettings, iDataIndex );
|
|
|
2089 }
|
|
|
2090
|
|
|
2091 var nRow = aoData.nTr;
|
|
|
2092
|
|
|
2093 /* Remove the old striping classes and then add the new one */
|
|
|
2094 if ( iStripes !== 0 )
|
|
|
2095 {
|
|
|
2096 var sStripe = asStripeClasses[ iRowCount % iStripes ];
|
|
|
2097 if ( aoData._sRowStripe != sStripe )
|
|
|
2098 {
|
|
|
2099 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
|
|
|
2100 aoData._sRowStripe = sStripe;
|
|
|
2101 }
|
|
|
2102 }
|
|
|
2103
|
|
|
2104 // Row callback functions - might want to manipulate the row
|
|
|
2105 // iRowCount and j are not currently documented. Are they at all
|
|
|
2106 // useful?
|
|
|
2107 _fnCallbackFire( oSettings, 'aoRowCallback', null,
|
|
|
2108 [nRow, aoData._aData, iRowCount, j] );
|
|
|
2109
|
|
|
2110 anRows.push( nRow );
|
|
|
2111 iRowCount++;
|
|
|
2112 }
|
|
|
2113 }
|
|
|
2114 else
|
|
|
2115 {
|
|
|
2116 /* Table is empty - create a row with an empty message in it */
|
|
|
2117 var sZero = oLang.sZeroRecords;
|
|
|
2118 if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' )
|
|
|
2119 {
|
|
|
2120 sZero = oLang.sLoadingRecords;
|
|
|
2121 }
|
|
|
2122 else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
|
|
|
2123 {
|
|
|
2124 sZero = oLang.sEmptyTable;
|
|
|
2125 }
|
|
|
2126
|
|
|
2127 anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
|
|
|
2128 .append( $('<td />', {
|
|
|
2129 'valign': 'top',
|
|
|
2130 'colSpan': _fnVisbleColumns( oSettings ),
|
|
|
2131 'class': oSettings.oClasses.sRowEmpty
|
|
|
2132 } ).html( sZero ) )[0];
|
|
|
2133 }
|
|
|
2134
|
|
|
2135 /* Header and footer callbacks */
|
|
|
2136 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
|
|
|
2137 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
|
|
|
2138
|
|
|
2139 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
|
|
|
2140 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
|
|
|
2141
|
|
|
2142 var body = $(oSettings.nTBody);
|
|
|
2143
|
|
|
2144 body.children().detach();
|
|
|
2145 body.append( $(anRows) );
|
|
|
2146
|
|
|
2147 /* Call all required callback functions for the end of a draw */
|
|
|
2148 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
|
|
|
2149
|
|
|
2150 /* Draw is complete, sorting and filtering must be as well */
|
|
|
2151 oSettings.bSorted = false;
|
|
|
2152 oSettings.bFiltered = false;
|
|
|
2153 oSettings.bDrawing = false;
|
|
|
2154 }
|
|
|
2155
|
|
|
2156
|
|
|
2157 /**
|
|
|
2158 * Redraw the table - taking account of the various features which are enabled
|
|
|
2159 * @param {object} oSettings dataTables settings object
|
|
|
2160 * @param {boolean} [holdPosition] Keep the current paging position. By default
|
|
|
2161 * the paging is reset to the first page
|
|
|
2162 * @memberof DataTable#oApi
|
|
|
2163 */
|
|
|
2164 function _fnReDraw( settings, holdPosition )
|
|
|
2165 {
|
|
|
2166 var
|
|
|
2167 features = settings.oFeatures,
|
|
|
2168 sort = features.bSort,
|
|
|
2169 filter = features.bFilter;
|
|
|
2170
|
|
|
2171 if ( sort ) {
|
|
|
2172 _fnSort( settings );
|
|
|
2173 }
|
|
|
2174
|
|
|
2175 if ( filter ) {
|
|
|
2176 _fnFilterComplete( settings, settings.oPreviousSearch );
|
|
|
2177 }
|
|
|
2178 else {
|
|
|
2179 // No filtering, so we want to just use the display master
|
|
|
2180 settings.aiDisplay = settings.aiDisplayMaster.slice();
|
|
|
2181 }
|
|
|
2182
|
|
|
2183 if ( holdPosition !== true ) {
|
|
|
2184 settings._iDisplayStart = 0;
|
|
|
2185 }
|
|
|
2186
|
|
|
2187 // Let any modules know about the draw hold position state (used by
|
|
|
2188 // scrolling internally)
|
|
|
2189 settings._drawHold = holdPosition;
|
|
|
2190
|
|
|
2191 _fnDraw( settings );
|
|
|
2192
|
|
|
2193 settings._drawHold = false;
|
|
|
2194 }
|
|
|
2195
|
|
|
2196
|
|
|
2197 /**
|
|
|
2198 * Add the options to the page HTML for the table
|
|
|
2199 * @param {object} oSettings dataTables settings object
|
|
|
2200 * @memberof DataTable#oApi
|
|
|
2201 */
|
|
|
2202 function _fnAddOptionsHtml ( oSettings )
|
|
|
2203 {
|
|
|
2204 var classes = oSettings.oClasses;
|
|
|
2205 var table = $(oSettings.nTable);
|
|
|
2206 var holding = $('<div/>').insertBefore( table ); // Holding element for speed
|
|
|
2207 var features = oSettings.oFeatures;
|
|
|
2208
|
|
|
2209 // All DataTables are wrapped in a div
|
|
|
2210 var insert = $('<div/>', {
|
|
|
2211 id: oSettings.sTableId+'_wrapper',
|
|
|
2212 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
|
|
|
2213 } );
|
|
|
2214
|
|
|
2215 oSettings.nHolding = holding[0];
|
|
|
2216 oSettings.nTableWrapper = insert[0];
|
|
|
2217 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
|
|
|
2218
|
|
|
2219 /* Loop over the user set positioning and place the elements as needed */
|
|
|
2220 var aDom = oSettings.sDom.split('');
|
|
|
2221 var featureNode, cOption, nNewNode, cNext, sAttr, j;
|
|
|
2222 for ( var i=0 ; i<aDom.length ; i++ )
|
|
|
2223 {
|
|
|
2224 featureNode = null;
|
|
|
2225 cOption = aDom[i];
|
|
|
2226
|
|
|
2227 if ( cOption == '<' )
|
|
|
2228 {
|
|
|
2229 /* New container div */
|
|
|
2230 nNewNode = $('<div/>')[0];
|
|
|
2231
|
|
|
2232 /* Check to see if we should append an id and/or a class name to the container */
|
|
|
2233 cNext = aDom[i+1];
|
|
|
2234 if ( cNext == "'" || cNext == '"' )
|
|
|
2235 {
|
|
|
2236 sAttr = "";
|
|
|
2237 j = 2;
|
|
|
2238 while ( aDom[i+j] != cNext )
|
|
|
2239 {
|
|
|
2240 sAttr += aDom[i+j];
|
|
|
2241 j++;
|
|
|
2242 }
|
|
|
2243
|
|
|
2244 /* Replace jQuery UI constants @todo depreciated */
|
|
|
2245 if ( sAttr == "H" )
|
|
|
2246 {
|
|
|
2247 sAttr = classes.sJUIHeader;
|
|
|
2248 }
|
|
|
2249 else if ( sAttr == "F" )
|
|
|
2250 {
|
|
|
2251 sAttr = classes.sJUIFooter;
|
|
|
2252 }
|
|
|
2253
|
|
|
2254 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
|
|
|
2255 * breaks the string into parts and applies them as needed
|
|
|
2256 */
|
|
|
2257 if ( sAttr.indexOf('.') != -1 )
|
|
|
2258 {
|
|
|
2259 var aSplit = sAttr.split('.');
|
|
|
2260 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
|
|
|
2261 nNewNode.className = aSplit[1];
|
|
|
2262 }
|
|
|
2263 else if ( sAttr.charAt(0) == "#" )
|
|
|
2264 {
|
|
|
2265 nNewNode.id = sAttr.substr(1, sAttr.length-1);
|
|
|
2266 }
|
|
|
2267 else
|
|
|
2268 {
|
|
|
2269 nNewNode.className = sAttr;
|
|
|
2270 }
|
|
|
2271
|
|
|
2272 i += j; /* Move along the position array */
|
|
|
2273 }
|
|
|
2274
|
|
|
2275 insert.append( nNewNode );
|
|
|
2276 insert = $(nNewNode);
|
|
|
2277 }
|
|
|
2278 else if ( cOption == '>' )
|
|
|
2279 {
|
|
|
2280 /* End container div */
|
|
|
2281 insert = insert.parent();
|
|
|
2282 }
|
|
|
2283 // @todo Move options into their own plugins?
|
|
|
2284 else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
|
|
|
2285 {
|
|
|
2286 /* Length */
|
|
|
2287 featureNode = _fnFeatureHtmlLength( oSettings );
|
|
|
2288 }
|
|
|
2289 else if ( cOption == 'f' && features.bFilter )
|
|
|
2290 {
|
|
|
2291 /* Filter */
|
|
|
2292 featureNode = _fnFeatureHtmlFilter( oSettings );
|
|
|
2293 }
|
|
|
2294 else if ( cOption == 'r' && features.bProcessing )
|
|
|
2295 {
|
|
|
2296 /* pRocessing */
|
|
|
2297 featureNode = _fnFeatureHtmlProcessing( oSettings );
|
|
|
2298 }
|
|
|
2299 else if ( cOption == 't' )
|
|
|
2300 {
|
|
|
2301 /* Table */
|
|
|
2302 featureNode = _fnFeatureHtmlTable( oSettings );
|
|
|
2303 }
|
|
|
2304 else if ( cOption == 'i' && features.bInfo )
|
|
|
2305 {
|
|
|
2306 /* Info */
|
|
|
2307 featureNode = _fnFeatureHtmlInfo( oSettings );
|
|
|
2308 }
|
|
|
2309 else if ( cOption == 'p' && features.bPaginate )
|
|
|
2310 {
|
|
|
2311 /* Pagination */
|
|
|
2312 featureNode = _fnFeatureHtmlPaginate( oSettings );
|
|
|
2313 }
|
|
|
2314 else if ( DataTable.ext.feature.length !== 0 )
|
|
|
2315 {
|
|
|
2316 /* Plug-in features */
|
|
|
2317 var aoFeatures = DataTable.ext.feature;
|
|
|
2318 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
|
|
|
2319 {
|
|
|
2320 if ( cOption == aoFeatures[k].cFeature )
|
|
|
2321 {
|
|
|
2322 featureNode = aoFeatures[k].fnInit( oSettings );
|
|
|
2323 break;
|
|
|
2324 }
|
|
|
2325 }
|
|
|
2326 }
|
|
|
2327
|
|
|
2328 /* Add to the 2D features array */
|
|
|
2329 if ( featureNode )
|
|
|
2330 {
|
|
|
2331 var aanFeatures = oSettings.aanFeatures;
|
|
|
2332
|
|
|
2333 if ( ! aanFeatures[cOption] )
|
|
|
2334 {
|
|
|
2335 aanFeatures[cOption] = [];
|
|
|
2336 }
|
|
|
2337
|
|
|
2338 aanFeatures[cOption].push( featureNode );
|
|
|
2339 insert.append( featureNode );
|
|
|
2340 }
|
|
|
2341 }
|
|
|
2342
|
|
|
2343 /* Built our DOM structure - replace the holding div with what we want */
|
|
|
2344 holding.replaceWith( insert );
|
|
|
2345 oSettings.nHolding = null;
|
|
|
2346 }
|
|
|
2347
|
|
|
2348
|
|
|
2349 /**
|
|
|
2350 * Use the DOM source to create up an array of header cells. The idea here is to
|
|
|
2351 * create a layout grid (array) of rows x columns, which contains a reference
|
|
|
2352 * to the cell that that point in the grid (regardless of col/rowspan), such that
|
|
|
2353 * any column / row could be removed and the new grid constructed
|
|
|
2354 * @param array {object} aLayout Array to store the calculated layout in
|
|
|
2355 * @param {node} nThead The header/footer element for the table
|
|
|
2356 * @memberof DataTable#oApi
|
|
|
2357 */
|
|
|
2358 function _fnDetectHeader ( aLayout, nThead )
|
|
|
2359 {
|
|
|
2360 var nTrs = $(nThead).children('tr');
|
|
|
2361 var nTr, nCell;
|
|
|
2362 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
|
|
|
2363 var bUnique;
|
|
|
2364 var fnShiftCol = function ( a, i, j ) {
|
|
|
2365 var k = a[i];
|
|
|
2366 while ( k[j] ) {
|
|
|
2367 j++;
|
|
|
2368 }
|
|
|
2369 return j;
|
|
|
2370 };
|
|
|
2371
|
|
|
2372 aLayout.splice( 0, aLayout.length );
|
|
|
2373
|
|
|
2374 /* We know how many rows there are in the layout - so prep it */
|
|
|
2375 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
|
|
|
2376 {
|
|
|
2377 aLayout.push( [] );
|
|
|
2378 }
|
|
|
2379
|
|
|
2380 /* Calculate a layout array */
|
|
|
2381 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
|
|
|
2382 {
|
|
|
2383 nTr = nTrs[i];
|
|
|
2384 iColumn = 0;
|
|
|
2385
|
|
|
2386 /* For every cell in the row... */
|
|
|
2387 nCell = nTr.firstChild;
|
|
|
2388 while ( nCell ) {
|
|
|
2389 if ( nCell.nodeName.toUpperCase() == "TD" ||
|
|
|
2390 nCell.nodeName.toUpperCase() == "TH" )
|
|
|
2391 {
|
|
|
2392 /* Get the col and rowspan attributes from the DOM and sanitise them */
|
|
|
2393 iColspan = nCell.getAttribute('colspan') * 1;
|
|
|
2394 iRowspan = nCell.getAttribute('rowspan') * 1;
|
|
|
2395 iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
|
|
|
2396 iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
|
|
|
2397
|
|
|
2398 /* There might be colspan cells already in this row, so shift our target
|
|
|
2399 * accordingly
|
|
|
2400 */
|
|
|
2401 iColShifted = fnShiftCol( aLayout, i, iColumn );
|
|
|
2402
|
|
|
2403 /* Cache calculation for unique columns */
|
|
|
2404 bUnique = iColspan === 1 ? true : false;
|
|
|
2405
|
|
|
2406 /* If there is col / rowspan, copy the information into the layout grid */
|
|
|
2407 for ( l=0 ; l<iColspan ; l++ )
|
|
|
2408 {
|
|
|
2409 for ( k=0 ; k<iRowspan ; k++ )
|
|
|
2410 {
|
|
|
2411 aLayout[i+k][iColShifted+l] = {
|
|
|
2412 "cell": nCell,
|
|
|
2413 "unique": bUnique
|
|
|
2414 };
|
|
|
2415 aLayout[i+k].nTr = nTr;
|
|
|
2416 }
|
|
|
2417 }
|
|
|
2418 }
|
|
|
2419 nCell = nCell.nextSibling;
|
|
|
2420 }
|
|
|
2421 }
|
|
|
2422 }
|
|
|
2423
|
|
|
2424
|
|
|
2425 /**
|
|
|
2426 * Get an array of unique th elements, one for each column
|
|
|
2427 * @param {object} oSettings dataTables settings object
|
|
|
2428 * @param {node} nHeader automatically detect the layout from this node - optional
|
|
|
2429 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
|
|
|
2430 * @returns array {node} aReturn list of unique th's
|
|
|
2431 * @memberof DataTable#oApi
|
|
|
2432 */
|
|
|
2433 function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
|
|
|
2434 {
|
|
|
2435 var aReturn = [];
|
|
|
2436 if ( !aLayout )
|
|
|
2437 {
|
|
|
2438 aLayout = oSettings.aoHeader;
|
|
|
2439 if ( nHeader )
|
|
|
2440 {
|
|
|
2441 aLayout = [];
|
|
|
2442 _fnDetectHeader( aLayout, nHeader );
|
|
|
2443 }
|
|
|
2444 }
|
|
|
2445
|
|
|
2446 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
|
|
|
2447 {
|
|
|
2448 for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
|
|
|
2449 {
|
|
|
2450 if ( aLayout[i][j].unique &&
|
|
|
2451 (!aReturn[j] || !oSettings.bSortCellsTop) )
|
|
|
2452 {
|
|
|
2453 aReturn[j] = aLayout[i][j].cell;
|
|
|
2454 }
|
|
|
2455 }
|
|
|
2456 }
|
|
|
2457
|
|
|
2458 return aReturn;
|
|
|
2459 }
|
|
|
2460
|
|
|
2461 /**
|
|
|
2462 * Create an Ajax call based on the table's settings, taking into account that
|
|
|
2463 * parameters can have multiple forms, and backwards compatibility.
|
|
|
2464 *
|
|
|
2465 * @param {object} oSettings dataTables settings object
|
|
|
2466 * @param {array} data Data to send to the server, required by
|
|
|
2467 * DataTables - may be augmented by developer callbacks
|
|
|
2468 * @param {function} fn Callback function to run when data is obtained
|
|
|
2469 */
|
|
|
2470 function _fnBuildAjax( oSettings, data, fn )
|
|
|
2471 {
|
|
|
2472 // Compatibility with 1.9-, allow fnServerData and event to manipulate
|
|
|
2473 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
|
|
|
2474
|
|
|
2475 // Convert to object based for 1.10+ if using the old array scheme which can
|
|
|
2476 // come from server-side processing or serverParams
|
|
|
2477 if ( data && $.isArray(data) ) {
|
|
|
2478 var tmp = {};
|
|
|
2479 var rbracket = /(.*?)\[\]$/;
|
|
|
2480
|
|
|
2481 $.each( data, function (key, val) {
|
|
|
2482 var match = val.name.match(rbracket);
|
|
|
2483
|
|
|
2484 if ( match ) {
|
|
|
2485 // Support for arrays
|
|
|
2486 var name = match[0];
|
|
|
2487
|
|
|
2488 if ( ! tmp[ name ] ) {
|
|
|
2489 tmp[ name ] = [];
|
|
|
2490 }
|
|
|
2491 tmp[ name ].push( val.value );
|
|
|
2492 }
|
|
|
2493 else {
|
|
|
2494 tmp[val.name] = val.value;
|
|
|
2495 }
|
|
|
2496 } );
|
|
|
2497 data = tmp;
|
|
|
2498 }
|
|
|
2499
|
|
|
2500 var ajaxData;
|
|
|
2501 var ajax = oSettings.ajax;
|
|
|
2502 var instance = oSettings.oInstance;
|
|
|
2503 var callback = function ( json ) {
|
|
|
2504 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
|
|
|
2505 fn( json );
|
|
|
2506 };
|
|
|
2507
|
|
|
2508 if ( $.isPlainObject( ajax ) && ajax.data )
|
|
|
2509 {
|
|
|
2510 ajaxData = ajax.data;
|
|
|
2511
|
|
|
2512 var newData = $.isFunction( ajaxData ) ?
|
|
|
2513 ajaxData( data, oSettings ) : // fn can manipulate data or return
|
|
|
2514 ajaxData; // an object object or array to merge
|
|
|
2515
|
|
|
2516 // If the function returned something, use that alone
|
|
|
2517 data = $.isFunction( ajaxData ) && newData ?
|
|
|
2518 newData :
|
|
|
2519 $.extend( true, data, newData );
|
|
|
2520
|
|
|
2521 // Remove the data property as we've resolved it already and don't want
|
|
|
2522 // jQuery to do it again (it is restored at the end of the function)
|
|
|
2523 delete ajax.data;
|
|
|
2524 }
|
|
|
2525
|
|
|
2526 var baseAjax = {
|
|
|
2527 "data": data,
|
|
|
2528 "success": function (json) {
|
|
|
2529 var error = json.error || json.sError;
|
|
|
2530 if ( error ) {
|
|
|
2531 _fnLog( oSettings, 0, error );
|
|
|
2532 }
|
|
|
2533
|
|
|
2534 oSettings.json = json;
|
|
|
2535 callback( json );
|
|
|
2536 },
|
|
|
2537 "dataType": "json",
|
|
|
2538 "cache": false,
|
|
|
2539 "type": oSettings.sServerMethod,
|
|
|
2540 "error": function (xhr, error, thrown) {
|
|
|
2541 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
|
|
|
2542
|
|
|
2543 if ( $.inArray( true, ret ) === -1 ) {
|
|
|
2544 if ( error == "parsererror" ) {
|
|
|
2545 _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
|
|
|
2546 }
|
|
|
2547 else if ( xhr.readyState === 4 ) {
|
|
|
2548 _fnLog( oSettings, 0, 'Ajax error', 7 );
|
|
|
2549 }
|
|
|
2550 }
|
|
|
2551
|
|
|
2552 _fnProcessingDisplay( oSettings, false );
|
|
|
2553 }
|
|
|
2554 };
|
|
|
2555
|
|
|
2556 // Store the data submitted for the API
|
|
|
2557 oSettings.oAjaxData = data;
|
|
|
2558
|
|
|
2559 // Allow plug-ins and external processes to modify the data
|
|
|
2560 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
|
|
|
2561
|
|
|
2562 if ( oSettings.fnServerData )
|
|
|
2563 {
|
|
|
2564 // DataTables 1.9- compatibility
|
|
|
2565 oSettings.fnServerData.call( instance,
|
|
|
2566 oSettings.sAjaxSource,
|
|
|
2567 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
|
|
|
2568 return { name: key, value: val };
|
|
|
2569 } ),
|
|
|
2570 callback,
|
|
|
2571 oSettings
|
|
|
2572 );
|
|
|
2573 }
|
|
|
2574 else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
|
|
|
2575 {
|
|
|
2576 // DataTables 1.9- compatibility
|
|
|
2577 oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
|
|
|
2578 url: ajax || oSettings.sAjaxSource
|
|
|
2579 } ) );
|
|
|
2580 }
|
|
|
2581 else if ( $.isFunction( ajax ) )
|
|
|
2582 {
|
|
|
2583 // Is a function - let the caller define what needs to be done
|
|
|
2584 oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
|
|
|
2585 }
|
|
|
2586 else
|
|
|
2587 {
|
|
|
2588 // Object to extend the base settings
|
|
|
2589 oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
|
|
|
2590
|
|
|
2591 // Restore for next time around
|
|
|
2592 ajax.data = ajaxData;
|
|
|
2593 }
|
|
|
2594 }
|
|
|
2595
|
|
|
2596
|
|
|
2597 /**
|
|
|
2598 * Update the table using an Ajax call
|
|
|
2599 * @param {object} settings dataTables settings object
|
|
|
2600 * @returns {boolean} Block the table drawing or not
|
|
|
2601 * @memberof DataTable#oApi
|
|
|
2602 */
|
|
|
2603 function _fnAjaxUpdate( settings )
|
|
|
2604 {
|
|
|
2605 if ( settings.bAjaxDataGet ) {
|
|
|
2606 settings.iDraw++;
|
|
|
2607 _fnProcessingDisplay( settings, true );
|
|
|
2608
|
|
|
2609 _fnBuildAjax(
|
|
|
2610 settings,
|
|
|
2611 _fnAjaxParameters( settings ),
|
|
|
2612 function(json) {
|
|
|
2613 _fnAjaxUpdateDraw( settings, json );
|
|
|
2614 }
|
|
|
2615 );
|
|
|
2616
|
|
|
2617 return false;
|
|
|
2618 }
|
|
|
2619 return true;
|
|
|
2620 }
|
|
|
2621
|
|
|
2622
|
|
|
2623 /**
|
|
|
2624 * Build up the parameters in an object needed for a server-side processing
|
|
|
2625 * request. Note that this is basically done twice, is different ways - a modern
|
|
|
2626 * method which is used by default in DataTables 1.10 which uses objects and
|
|
|
2627 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
|
|
|
2628 * the sAjaxSource option is used in the initialisation, or the legacyAjax
|
|
|
2629 * option is set.
|
|
|
2630 * @param {object} oSettings dataTables settings object
|
|
|
2631 * @returns {bool} block the table drawing or not
|
|
|
2632 * @memberof DataTable#oApi
|
|
|
2633 */
|
|
|
2634 function _fnAjaxParameters( settings )
|
|
|
2635 {
|
|
|
2636 var
|
|
|
2637 columns = settings.aoColumns,
|
|
|
2638 columnCount = columns.length,
|
|
|
2639 features = settings.oFeatures,
|
|
|
2640 preSearch = settings.oPreviousSearch,
|
|
|
2641 preColSearch = settings.aoPreSearchCols,
|
|
|
2642 i, data = [], dataProp, column, columnSearch,
|
|
|
2643 sort = _fnSortFlatten( settings ),
|
|
|
2644 displayStart = settings._iDisplayStart,
|
|
|
2645 displayLength = features.bPaginate !== false ?
|
|
|
2646 settings._iDisplayLength :
|
|
|
2647 -1;
|
|
|
2648
|
|
|
2649 var param = function ( name, value ) {
|
|
|
2650 data.push( { 'name': name, 'value': value } );
|
|
|
2651 };
|
|
|
2652
|
|
|
2653 // DataTables 1.9- compatible method
|
|
|
2654 param( 'sEcho', settings.iDraw );
|
|
|
2655 param( 'iColumns', columnCount );
|
|
|
2656 param( 'sColumns', _pluck( columns, 'sName' ).join(',') );
|
|
|
2657 param( 'iDisplayStart', displayStart );
|
|
|
2658 param( 'iDisplayLength', displayLength );
|
|
|
2659
|
|
|
2660 // DataTables 1.10+ method
|
|
|
2661 var d = {
|
|
|
2662 draw: settings.iDraw,
|
|
|
2663 columns: [],
|
|
|
2664 order: [],
|
|
|
2665 start: displayStart,
|
|
|
2666 length: displayLength,
|
|
|
2667 search: {
|
|
|
2668 value: preSearch.sSearch,
|
|
|
2669 regex: preSearch.bRegex
|
|
|
2670 }
|
|
|
2671 };
|
|
|
2672
|
|
|
2673 for ( i=0 ; i<columnCount ; i++ ) {
|
|
|
2674 column = columns[i];
|
|
|
2675 columnSearch = preColSearch[i];
|
|
|
2676 dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
|
|
|
2677
|
|
|
2678 d.columns.push( {
|
|
|
2679 data: dataProp,
|
|
|
2680 name: column.sName,
|
|
|
2681 searchable: column.bSearchable,
|
|
|
2682 orderable: column.bSortable,
|
|
|
2683 search: {
|
|
|
2684 value: columnSearch.sSearch,
|
|
|
2685 regex: columnSearch.bRegex
|
|
|
2686 }
|
|
|
2687 } );
|
|
|
2688
|
|
|
2689 param( "mDataProp_"+i, dataProp );
|
|
|
2690
|
|
|
2691 if ( features.bFilter ) {
|
|
|
2692 param( 'sSearch_'+i, columnSearch.sSearch );
|
|
|
2693 param( 'bRegex_'+i, columnSearch.bRegex );
|
|
|
2694 param( 'bSearchable_'+i, column.bSearchable );
|
|
|
2695 }
|
|
|
2696
|
|
|
2697 if ( features.bSort ) {
|
|
|
2698 param( 'bSortable_'+i, column.bSortable );
|
|
|
2699 }
|
|
|
2700 }
|
|
|
2701
|
|
|
2702 if ( features.bFilter ) {
|
|
|
2703 param( 'sSearch', preSearch.sSearch );
|
|
|
2704 param( 'bRegex', preSearch.bRegex );
|
|
|
2705 }
|
|
|
2706
|
|
|
2707 if ( features.bSort ) {
|
|
|
2708 $.each( sort, function ( i, val ) {
|
|
|
2709 d.order.push( { column: val.col, dir: val.dir } );
|
|
|
2710
|
|
|
2711 param( 'iSortCol_'+i, val.col );
|
|
|
2712 param( 'sSortDir_'+i, val.dir );
|
|
|
2713 } );
|
|
|
2714
|
|
|
2715 param( 'iSortingCols', sort.length );
|
|
|
2716 }
|
|
|
2717
|
|
|
2718 // If the legacy.ajax parameter is null, then we automatically decide which
|
|
|
2719 // form to use, based on sAjaxSource
|
|
|
2720 var legacy = DataTable.ext.legacy.ajax;
|
|
|
2721 if ( legacy === null ) {
|
|
|
2722 return settings.sAjaxSource ? data : d;
|
|
|
2723 }
|
|
|
2724
|
|
|
2725 // Otherwise, if legacy has been specified then we use that to decide on the
|
|
|
2726 // form
|
|
|
2727 return legacy ? data : d;
|
|
|
2728 }
|
|
|
2729
|
|
|
2730
|
|
|
2731 /**
|
|
|
2732 * Data the data from the server (nuking the old) and redraw the table
|
|
|
2733 * @param {object} oSettings dataTables settings object
|
|
|
2734 * @param {object} json json data return from the server.
|
|
|
2735 * @param {string} json.sEcho Tracking flag for DataTables to match requests
|
|
|
2736 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
|
|
|
2737 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
|
|
|
2738 * @param {array} json.aaData The data to display on this page
|
|
|
2739 * @param {string} [json.sColumns] Column ordering (sName, comma separated)
|
|
|
2740 * @memberof DataTable#oApi
|
|
|
2741 */
|
|
|
2742 function _fnAjaxUpdateDraw ( settings, json )
|
|
|
2743 {
|
|
|
2744 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
|
|
|
2745 // Support both
|
|
|
2746 var compat = function ( old, modern ) {
|
|
|
2747 return json[old] !== undefined ? json[old] : json[modern];
|
|
|
2748 };
|
|
|
2749
|
|
|
2750 var data = _fnAjaxDataSrc( settings, json );
|
|
|
2751 var draw = compat( 'sEcho', 'draw' );
|
|
|
2752 var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );
|
|
|
2753 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
|
|
|
2754
|
|
|
2755 if ( draw ) {
|
|
|
2756 // Protect against out of sequence returns
|
|
|
2757 if ( draw*1 < settings.iDraw ) {
|
|
|
2758 return;
|
|
|
2759 }
|
|
|
2760 settings.iDraw = draw * 1;
|
|
|
2761 }
|
|
|
2762
|
|
|
2763 _fnClearTable( settings );
|
|
|
2764 settings._iRecordsTotal = parseInt(recordsTotal, 10);
|
|
|
2765 settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
|
|
|
2766
|
|
|
2767 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
2768 _fnAddData( settings, data[i] );
|
|
|
2769 }
|
|
|
2770 settings.aiDisplay = settings.aiDisplayMaster.slice();
|
|
|
2771
|
|
|
2772 settings.bAjaxDataGet = false;
|
|
|
2773 _fnDraw( settings );
|
|
|
2774
|
|
|
2775 if ( ! settings._bInitComplete ) {
|
|
|
2776 _fnInitComplete( settings, json );
|
|
|
2777 }
|
|
|
2778
|
|
|
2779 settings.bAjaxDataGet = true;
|
|
|
2780 _fnProcessingDisplay( settings, false );
|
|
|
2781 }
|
|
|
2782
|
|
|
2783
|
|
|
2784 /**
|
|
|
2785 * Get the data from the JSON data source to use for drawing a table. Using
|
|
|
2786 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
|
|
|
2787 * source object, or from a processing function.
|
|
|
2788 * @param {object} oSettings dataTables settings object
|
|
|
2789 * @param {object} json Data source object / array from the server
|
|
|
2790 * @return {array} Array of data to use
|
|
|
2791 */
|
|
|
2792 function _fnAjaxDataSrc ( oSettings, json )
|
|
|
2793 {
|
|
|
2794 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
|
|
|
2795 oSettings.ajax.dataSrc :
|
|
|
2796 oSettings.sAjaxDataProp; // Compatibility with 1.9-.
|
|
|
2797
|
|
|
2798 // Compatibility with 1.9-. In order to read from aaData, check if the
|
|
|
2799 // default has been changed, if not, check for aaData
|
|
|
2800 if ( dataSrc === 'data' ) {
|
|
|
2801 return json.aaData || json[dataSrc];
|
|
|
2802 }
|
|
|
2803
|
|
|
2804 return dataSrc !== "" ?
|
|
|
2805 _fnGetObjectDataFn( dataSrc )( json ) :
|
|
|
2806 json;
|
|
|
2807 }
|
|
|
2808
|
|
|
2809 /**
|
|
|
2810 * Generate the node required for filtering text
|
|
|
2811 * @returns {node} Filter control element
|
|
|
2812 * @param {object} oSettings dataTables settings object
|
|
|
2813 * @memberof DataTable#oApi
|
|
|
2814 */
|
|
|
2815 function _fnFeatureHtmlFilter ( settings )
|
|
|
2816 {
|
|
|
2817 var classes = settings.oClasses;
|
|
|
2818 var tableId = settings.sTableId;
|
|
|
2819 var language = settings.oLanguage;
|
|
|
2820 var previousSearch = settings.oPreviousSearch;
|
|
|
2821 var features = settings.aanFeatures;
|
|
|
2822 var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
|
|
|
2823
|
|
|
2824 var str = language.sSearch;
|
|
|
2825 str = str.match(/_INPUT_/) ?
|
|
|
2826 str.replace('_INPUT_', input) :
|
|
|
2827 str+input;
|
|
|
2828
|
|
|
2829 var filter = $('<div/>', {
|
|
|
2830 'id': ! features.f ? tableId+'_filter' : null,
|
|
|
2831 'class': classes.sFilter
|
|
|
2832 } )
|
|
|
2833 .append( $('<label/>' ).append( str ) );
|
|
|
2834
|
|
|
2835 var searchFn = function() {
|
|
|
2836 /* Update all other filter input elements for the new display */
|
|
|
2837 var n = features.f;
|
|
|
2838 var val = !this.value ? "" : this.value; // mental IE8 fix :-(
|
|
|
2839
|
|
|
2840 /* Now do the filter */
|
|
|
2841 if ( val != previousSearch.sSearch ) {
|
|
|
2842 _fnFilterComplete( settings, {
|
|
|
2843 "sSearch": val,
|
|
|
2844 "bRegex": previousSearch.bRegex,
|
|
|
2845 "bSmart": previousSearch.bSmart ,
|
|
|
2846 "bCaseInsensitive": previousSearch.bCaseInsensitive
|
|
|
2847 } );
|
|
|
2848
|
|
|
2849 // Need to redraw, without resorting
|
|
|
2850 settings._iDisplayStart = 0;
|
|
|
2851 _fnDraw( settings );
|
|
|
2852 }
|
|
|
2853 };
|
|
|
2854
|
|
|
2855 var searchDelay = settings.searchDelay !== null ?
|
|
|
2856 settings.searchDelay :
|
|
|
2857 _fnDataSource( settings ) === 'ssp' ?
|
|
|
2858 400 :
|
|
|
2859 0;
|
|
|
2860
|
|
|
2861 var jqFilter = $('input', filter)
|
|
|
2862 .val( previousSearch.sSearch )
|
|
|
2863 .attr( 'placeholder', language.sSearchPlaceholder )
|
|
|
2864 .bind(
|
|
|
2865 'keyup.DT search.DT input.DT paste.DT cut.DT',
|
|
|
2866 searchDelay ?
|
|
|
2867 _fnThrottle( searchFn, searchDelay ) :
|
|
|
2868 searchFn
|
|
|
2869 )
|
|
|
2870 .bind( 'keypress.DT', function(e) {
|
|
|
2871 /* Prevent form submission */
|
|
|
2872 if ( e.keyCode == 13 ) {
|
|
|
2873 return false;
|
|
|
2874 }
|
|
|
2875 } )
|
|
|
2876 .attr('aria-controls', tableId);
|
|
|
2877
|
|
|
2878 // Update the input elements whenever the table is filtered
|
|
|
2879 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
|
|
|
2880 if ( settings === s ) {
|
|
|
2881 // IE9 throws an 'unknown error' if document.activeElement is used
|
|
|
2882 // inside an iframe or frame...
|
|
|
2883 try {
|
|
|
2884 if ( jqFilter[0] !== document.activeElement ) {
|
|
|
2885 jqFilter.val( previousSearch.sSearch );
|
|
|
2886 }
|
|
|
2887 }
|
|
|
2888 catch ( e ) {}
|
|
|
2889 }
|
|
|
2890 } );
|
|
|
2891
|
|
|
2892 return filter[0];
|
|
|
2893 }
|
|
|
2894
|
|
|
2895
|
|
|
2896 /**
|
|
|
2897 * Filter the table using both the global filter and column based filtering
|
|
|
2898 * @param {object} oSettings dataTables settings object
|
|
|
2899 * @param {object} oSearch search information
|
|
|
2900 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
|
|
|
2901 * @memberof DataTable#oApi
|
|
|
2902 */
|
|
|
2903 function _fnFilterComplete ( oSettings, oInput, iForce )
|
|
|
2904 {
|
|
|
2905 var oPrevSearch = oSettings.oPreviousSearch;
|
|
|
2906 var aoPrevSearch = oSettings.aoPreSearchCols;
|
|
|
2907 var fnSaveFilter = function ( oFilter ) {
|
|
|
2908 /* Save the filtering values */
|
|
|
2909 oPrevSearch.sSearch = oFilter.sSearch;
|
|
|
2910 oPrevSearch.bRegex = oFilter.bRegex;
|
|
|
2911 oPrevSearch.bSmart = oFilter.bSmart;
|
|
|
2912 oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
|
|
|
2913 };
|
|
|
2914 var fnRegex = function ( o ) {
|
|
|
2915 // Backwards compatibility with the bEscapeRegex option
|
|
|
2916 return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
|
|
|
2917 };
|
|
|
2918
|
|
|
2919 // Resolve any column types that are unknown due to addition or invalidation
|
|
|
2920 // @todo As per sort - can this be moved into an event handler?
|
|
|
2921 _fnColumnTypes( oSettings );
|
|
|
2922
|
|
|
2923 /* In server-side processing all filtering is done by the server, so no point hanging around here */
|
|
|
2924 if ( _fnDataSource( oSettings ) != 'ssp' )
|
|
|
2925 {
|
|
|
2926 /* Global filter */
|
|
|
2927 _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
|
|
|
2928 fnSaveFilter( oInput );
|
|
|
2929
|
|
|
2930 /* Now do the individual column filter */
|
|
|
2931 for ( var i=0 ; i<aoPrevSearch.length ; i++ )
|
|
|
2932 {
|
|
|
2933 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
|
|
|
2934 aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
|
|
|
2935 }
|
|
|
2936
|
|
|
2937 /* Custom filtering */
|
|
|
2938 _fnFilterCustom( oSettings );
|
|
|
2939 }
|
|
|
2940 else
|
|
|
2941 {
|
|
|
2942 fnSaveFilter( oInput );
|
|
|
2943 }
|
|
|
2944
|
|
|
2945 /* Tell the draw function we have been filtering */
|
|
|
2946 oSettings.bFiltered = true;
|
|
|
2947 _fnCallbackFire( oSettings, null, 'search', [oSettings] );
|
|
|
2948 }
|
|
|
2949
|
|
|
2950
|
|
|
2951 /**
|
|
|
2952 * Apply custom filtering functions
|
|
|
2953 * @param {object} oSettings dataTables settings object
|
|
|
2954 * @memberof DataTable#oApi
|
|
|
2955 */
|
|
|
2956 function _fnFilterCustom( settings )
|
|
|
2957 {
|
|
|
2958 var filters = DataTable.ext.search;
|
|
|
2959 var displayRows = settings.aiDisplay;
|
|
|
2960 var row, rowIdx;
|
|
|
2961
|
|
|
2962 for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
|
|
|
2963 var rows = [];
|
|
|
2964
|
|
|
2965 // Loop over each row and see if it should be included
|
|
|
2966 for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
|
|
|
2967 rowIdx = displayRows[ j ];
|
|
|
2968 row = settings.aoData[ rowIdx ];
|
|
|
2969
|
|
|
2970 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
|
|
|
2971 rows.push( rowIdx );
|
|
|
2972 }
|
|
|
2973 }
|
|
|
2974
|
|
|
2975 // So the array reference doesn't break set the results into the
|
|
|
2976 // existing array
|
|
|
2977 displayRows.length = 0;
|
|
|
2978 $.merge( displayRows, rows );
|
|
|
2979 }
|
|
|
2980 }
|
|
|
2981
|
|
|
2982
|
|
|
2983 /**
|
|
|
2984 * Filter the table on a per-column basis
|
|
|
2985 * @param {object} oSettings dataTables settings object
|
|
|
2986 * @param {string} sInput string to filter on
|
|
|
2987 * @param {int} iColumn column to filter
|
|
|
2988 * @param {bool} bRegex treat search string as a regular expression or not
|
|
|
2989 * @param {bool} bSmart use smart filtering or not
|
|
|
2990 * @param {bool} bCaseInsensitive Do case insenstive matching or not
|
|
|
2991 * @memberof DataTable#oApi
|
|
|
2992 */
|
|
|
2993 function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
|
|
|
2994 {
|
|
|
2995 if ( searchStr === '' ) {
|
|
|
2996 return;
|
|
|
2997 }
|
|
|
2998
|
|
|
2999 var data;
|
|
|
3000 var display = settings.aiDisplay;
|
|
|
3001 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
|
|
|
3002
|
|
|
3003 for ( var i=display.length-1 ; i>=0 ; i-- ) {
|
|
|
3004 data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
|
|
|
3005
|
|
|
3006 if ( ! rpSearch.test( data ) ) {
|
|
|
3007 display.splice( i, 1 );
|
|
|
3008 }
|
|
|
3009 }
|
|
|
3010 }
|
|
|
3011
|
|
|
3012
|
|
|
3013 /**
|
|
|
3014 * Filter the data table based on user input and draw the table
|
|
|
3015 * @param {object} settings dataTables settings object
|
|
|
3016 * @param {string} input string to filter on
|
|
|
3017 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
|
|
|
3018 * @param {bool} regex treat as a regular expression or not
|
|
|
3019 * @param {bool} smart perform smart filtering or not
|
|
|
3020 * @param {bool} caseInsensitive Do case insenstive matching or not
|
|
|
3021 * @memberof DataTable#oApi
|
|
|
3022 */
|
|
|
3023 function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
|
|
|
3024 {
|
|
|
3025 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
|
|
|
3026 var prevSearch = settings.oPreviousSearch.sSearch;
|
|
|
3027 var displayMaster = settings.aiDisplayMaster;
|
|
|
3028 var display, invalidated, i;
|
|
|
3029
|
|
|
3030 // Need to take account of custom filtering functions - always filter
|
|
|
3031 if ( DataTable.ext.search.length !== 0 ) {
|
|
|
3032 force = true;
|
|
|
3033 }
|
|
|
3034
|
|
|
3035 // Check if any of the rows were invalidated
|
|
|
3036 invalidated = _fnFilterData( settings );
|
|
|
3037
|
|
|
3038 // If the input is blank - we just want the full data set
|
|
|
3039 if ( input.length <= 0 ) {
|
|
|
3040 settings.aiDisplay = displayMaster.slice();
|
|
|
3041 }
|
|
|
3042 else {
|
|
|
3043 // New search - start from the master array
|
|
|
3044 if ( invalidated ||
|
|
|
3045 force ||
|
|
|
3046 prevSearch.length > input.length ||
|
|
|
3047 input.indexOf(prevSearch) !== 0 ||
|
|
|
3048 settings.bSorted // On resort, the display master needs to be
|
|
|
3049 // re-filtered since indexes will have changed
|
|
|
3050 ) {
|
|
|
3051 settings.aiDisplay = displayMaster.slice();
|
|
|
3052 }
|
|
|
3053
|
|
|
3054 // Search the display array
|
|
|
3055 display = settings.aiDisplay;
|
|
|
3056
|
|
|
3057 for ( i=display.length-1 ; i>=0 ; i-- ) {
|
|
|
3058 if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
|
|
|
3059 display.splice( i, 1 );
|
|
|
3060 }
|
|
|
3061 }
|
|
|
3062 }
|
|
|
3063 }
|
|
|
3064
|
|
|
3065
|
|
|
3066 /**
|
|
|
3067 * Build a regular expression object suitable for searching a table
|
|
|
3068 * @param {string} sSearch string to search for
|
|
|
3069 * @param {bool} bRegex treat as a regular expression or not
|
|
|
3070 * @param {bool} bSmart perform smart filtering or not
|
|
|
3071 * @param {bool} bCaseInsensitive Do case insensitive matching or not
|
|
|
3072 * @returns {RegExp} constructed object
|
|
|
3073 * @memberof DataTable#oApi
|
|
|
3074 */
|
|
|
3075 function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
|
|
|
3076 {
|
|
|
3077 search = regex ?
|
|
|
3078 search :
|
|
|
3079 _fnEscapeRegex( search );
|
|
|
3080
|
|
|
3081 if ( smart ) {
|
|
|
3082 /* For smart filtering we want to allow the search to work regardless of
|
|
|
3083 * word order. We also want double quoted text to be preserved, so word
|
|
|
3084 * order is important - a la google. So this is what we want to
|
|
|
3085 * generate:
|
|
|
3086 *
|
|
|
3087 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
|
|
|
3088 */
|
|
|
3089 var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
|
|
|
3090 if ( word.charAt(0) === '"' ) {
|
|
|
3091 var m = word.match( /^"(.*)"$/ );
|
|
|
3092 word = m ? m[1] : word;
|
|
|
3093 }
|
|
|
3094
|
|
|
3095 return word.replace('"', '');
|
|
|
3096 } );
|
|
|
3097
|
|
|
3098 search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
|
|
|
3099 }
|
|
|
3100
|
|
|
3101 return new RegExp( search, caseInsensitive ? 'i' : '' );
|
|
|
3102 }
|
|
|
3103
|
|
|
3104
|
|
|
3105 /**
|
|
|
3106 * Escape a string such that it can be used in a regular expression
|
|
|
3107 * @param {string} sVal string to escape
|
|
|
3108 * @returns {string} escaped string
|
|
|
3109 * @memberof DataTable#oApi
|
|
|
3110 */
|
|
|
3111 function _fnEscapeRegex ( sVal )
|
|
|
3112 {
|
|
|
3113 return sVal.replace( _re_escape_regex, '\\$1' );
|
|
|
3114 }
|
|
|
3115
|
|
|
3116
|
|
|
3117
|
|
|
3118 var __filter_div = $('<div>')[0];
|
|
|
3119 var __filter_div_textContent = __filter_div.textContent !== undefined;
|
|
|
3120
|
|
|
3121 // Update the filtering data for each row if needed (by invalidation or first run)
|
|
|
3122 function _fnFilterData ( settings )
|
|
|
3123 {
|
|
|
3124 var columns = settings.aoColumns;
|
|
|
3125 var column;
|
|
|
3126 var i, j, ien, jen, filterData, cellData, row;
|
|
|
3127 var fomatters = DataTable.ext.type.search;
|
|
|
3128 var wasInvalidated = false;
|
|
|
3129
|
|
|
3130 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
|
3131 row = settings.aoData[i];
|
|
|
3132
|
|
|
3133 if ( ! row._aFilterData ) {
|
|
|
3134 filterData = [];
|
|
|
3135
|
|
|
3136 for ( j=0, jen=columns.length ; j<jen ; j++ ) {
|
|
|
3137 column = columns[j];
|
|
|
3138
|
|
|
3139 if ( column.bSearchable ) {
|
|
|
3140 cellData = _fnGetCellData( settings, i, j, 'filter' );
|
|
|
3141
|
|
|
3142 if ( fomatters[ column.sType ] ) {
|
|
|
3143 cellData = fomatters[ column.sType ]( cellData );
|
|
|
3144 }
|
|
|
3145
|
|
|
3146 // Search in DataTables 1.10 is string based. In 1.11 this
|
|
|
3147 // should be altered to also allow strict type checking.
|
|
|
3148 if ( cellData === null ) {
|
|
|
3149 cellData = '';
|
|
|
3150 }
|
|
|
3151
|
|
|
3152 if ( typeof cellData !== 'string' && cellData.toString ) {
|
|
|
3153 cellData = cellData.toString();
|
|
|
3154 }
|
|
|
3155 }
|
|
|
3156 else {
|
|
|
3157 cellData = '';
|
|
|
3158 }
|
|
|
3159
|
|
|
3160 // If it looks like there is an HTML entity in the string,
|
|
|
3161 // attempt to decode it so sorting works as expected. Note that
|
|
|
3162 // we could use a single line of jQuery to do this, but the DOM
|
|
|
3163 // method used here is much faster http://jsperf.com/html-decode
|
|
|
3164 if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
|
|
|
3165 __filter_div.innerHTML = cellData;
|
|
|
3166 cellData = __filter_div_textContent ?
|
|
|
3167 __filter_div.textContent :
|
|
|
3168 __filter_div.innerText;
|
|
|
3169 }
|
|
|
3170
|
|
|
3171 if ( cellData.replace ) {
|
|
|
3172 cellData = cellData.replace(/[\r\n]/g, '');
|
|
|
3173 }
|
|
|
3174
|
|
|
3175 filterData.push( cellData );
|
|
|
3176 }
|
|
|
3177
|
|
|
3178 row._aFilterData = filterData;
|
|
|
3179 row._sFilterRow = filterData.join(' ');
|
|
|
3180 wasInvalidated = true;
|
|
|
3181 }
|
|
|
3182 }
|
|
|
3183
|
|
|
3184 return wasInvalidated;
|
|
|
3185 }
|
|
|
3186
|
|
|
3187
|
|
|
3188 /**
|
|
|
3189 * Convert from the internal Hungarian notation to camelCase for external
|
|
|
3190 * interaction
|
|
|
3191 * @param {object} obj Object to convert
|
|
|
3192 * @returns {object} Inverted object
|
|
|
3193 * @memberof DataTable#oApi
|
|
|
3194 */
|
|
|
3195 function _fnSearchToCamel ( obj )
|
|
|
3196 {
|
|
|
3197 return {
|
|
|
3198 search: obj.sSearch,
|
|
|
3199 smart: obj.bSmart,
|
|
|
3200 regex: obj.bRegex,
|
|
|
3201 caseInsensitive: obj.bCaseInsensitive
|
|
|
3202 };
|
|
|
3203 }
|
|
|
3204
|
|
|
3205
|
|
|
3206
|
|
|
3207 /**
|
|
|
3208 * Convert from camelCase notation to the internal Hungarian. We could use the
|
|
|
3209 * Hungarian convert function here, but this is cleaner
|
|
|
3210 * @param {object} obj Object to convert
|
|
|
3211 * @returns {object} Inverted object
|
|
|
3212 * @memberof DataTable#oApi
|
|
|
3213 */
|
|
|
3214 function _fnSearchToHung ( obj )
|
|
|
3215 {
|
|
|
3216 return {
|
|
|
3217 sSearch: obj.search,
|
|
|
3218 bSmart: obj.smart,
|
|
|
3219 bRegex: obj.regex,
|
|
|
3220 bCaseInsensitive: obj.caseInsensitive
|
|
|
3221 };
|
|
|
3222 }
|
|
|
3223
|
|
|
3224 /**
|
|
|
3225 * Generate the node required for the info display
|
|
|
3226 * @param {object} oSettings dataTables settings object
|
|
|
3227 * @returns {node} Information element
|
|
|
3228 * @memberof DataTable#oApi
|
|
|
3229 */
|
|
|
3230 function _fnFeatureHtmlInfo ( settings )
|
|
|
3231 {
|
|
|
3232 var
|
|
|
3233 tid = settings.sTableId,
|
|
|
3234 nodes = settings.aanFeatures.i,
|
|
|
3235 n = $('<div/>', {
|
|
|
3236 'class': settings.oClasses.sInfo,
|
|
|
3237 'id': ! nodes ? tid+'_info' : null
|
|
|
3238 } );
|
|
|
3239
|
|
|
3240 if ( ! nodes ) {
|
|
|
3241 // Update display on each draw
|
|
|
3242 settings.aoDrawCallback.push( {
|
|
|
3243 "fn": _fnUpdateInfo,
|
|
|
3244 "sName": "information"
|
|
|
3245 } );
|
|
|
3246
|
|
|
3247 n
|
|
|
3248 .attr( 'role', 'status' )
|
|
|
3249 .attr( 'aria-live', 'polite' );
|
|
|
3250
|
|
|
3251 // Table is described by our info div
|
|
|
3252 $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
|
|
|
3253 }
|
|
|
3254
|
|
|
3255 return n[0];
|
|
|
3256 }
|
|
|
3257
|
|
|
3258
|
|
|
3259 /**
|
|
|
3260 * Update the information elements in the display
|
|
|
3261 * @param {object} settings dataTables settings object
|
|
|
3262 * @memberof DataTable#oApi
|
|
|
3263 */
|
|
|
3264 function _fnUpdateInfo ( settings )
|
|
|
3265 {
|
|
|
3266 /* Show information about the table */
|
|
|
3267 var nodes = settings.aanFeatures.i;
|
|
|
3268 if ( nodes.length === 0 ) {
|
|
|
3269 return;
|
|
|
3270 }
|
|
|
3271
|
|
|
3272 var
|
|
|
3273 lang = settings.oLanguage,
|
|
|
3274 start = settings._iDisplayStart+1,
|
|
|
3275 end = settings.fnDisplayEnd(),
|
|
|
3276 max = settings.fnRecordsTotal(),
|
|
|
3277 total = settings.fnRecordsDisplay(),
|
|
|
3278 out = total ?
|
|
|
3279 lang.sInfo :
|
|
|
3280 lang.sInfoEmpty;
|
|
|
3281
|
|
|
3282 if ( total !== max ) {
|
|
|
3283 /* Record set after filtering */
|
|
|
3284 out += ' ' + lang.sInfoFiltered;
|
|
|
3285 }
|
|
|
3286
|
|
|
3287 // Convert the macros
|
|
|
3288 out += lang.sInfoPostFix;
|
|
|
3289 out = _fnInfoMacros( settings, out );
|
|
|
3290
|
|
|
3291 var callback = lang.fnInfoCallback;
|
|
|
3292 if ( callback !== null ) {
|
|
|
3293 out = callback.call( settings.oInstance,
|
|
|
3294 settings, start, end, max, total, out
|
|
|
3295 );
|
|
|
3296 }
|
|
|
3297
|
|
|
3298 $(nodes).html( out );
|
|
|
3299 }
|
|
|
3300
|
|
|
3301
|
|
|
3302 function _fnInfoMacros ( settings, str )
|
|
|
3303 {
|
|
|
3304 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
|
|
|
3305 // internally
|
|
|
3306 var
|
|
|
3307 formatter = settings.fnFormatNumber,
|
|
|
3308 start = settings._iDisplayStart+1,
|
|
|
3309 len = settings._iDisplayLength,
|
|
|
3310 vis = settings.fnRecordsDisplay(),
|
|
|
3311 all = len === -1;
|
|
|
3312
|
|
|
3313 return str.
|
|
|
3314 replace(/_START_/g, formatter.call( settings, start ) ).
|
|
|
3315 replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ).
|
|
|
3316 replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ).
|
|
|
3317 replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
|
|
|
3318 replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
|
|
|
3319 replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
|
|
|
3320 }
|
|
|
3321
|
|
|
3322
|
|
|
3323
|
|
|
3324 /**
|
|
|
3325 * Draw the table for the first time, adding all required features
|
|
|
3326 * @param {object} settings dataTables settings object
|
|
|
3327 * @memberof DataTable#oApi
|
|
|
3328 */
|
|
|
3329 function _fnInitialise ( settings )
|
|
|
3330 {
|
|
|
3331 var i, iLen, iAjaxStart=settings.iInitDisplayStart;
|
|
|
3332 var columns = settings.aoColumns, column;
|
|
|
3333 var features = settings.oFeatures;
|
|
|
3334 var deferLoading = settings.bDeferLoading; // value modified by the draw
|
|
|
3335
|
|
|
3336 /* Ensure that the table data is fully initialised */
|
|
|
3337 if ( ! settings.bInitialised ) {
|
|
|
3338 setTimeout( function(){ _fnInitialise( settings ); }, 200 );
|
|
|
3339 return;
|
|
|
3340 }
|
|
|
3341
|
|
|
3342 /* Show the display HTML options */
|
|
|
3343 _fnAddOptionsHtml( settings );
|
|
|
3344
|
|
|
3345 /* Build and draw the header / footer for the table */
|
|
|
3346 _fnBuildHead( settings );
|
|
|
3347 _fnDrawHead( settings, settings.aoHeader );
|
|
|
3348 _fnDrawHead( settings, settings.aoFooter );
|
|
|
3349
|
|
|
3350 /* Okay to show that something is going on now */
|
|
|
3351 _fnProcessingDisplay( settings, true );
|
|
|
3352
|
|
|
3353 /* Calculate sizes for columns */
|
|
|
3354 if ( features.bAutoWidth ) {
|
|
|
3355 _fnCalculateColumnWidths( settings );
|
|
|
3356 }
|
|
|
3357
|
|
|
3358 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
|
|
|
3359 column = columns[i];
|
|
|
3360
|
|
|
3361 if ( column.sWidth ) {
|
|
|
3362 column.nTh.style.width = _fnStringToCss( column.sWidth );
|
|
|
3363 }
|
|
|
3364 }
|
|
|
3365
|
|
|
3366 _fnCallbackFire( settings, null, 'preInit', [settings] );
|
|
|
3367
|
|
|
3368 // If there is default sorting required - let's do it. The sort function
|
|
|
3369 // will do the drawing for us. Otherwise we draw the table regardless of the
|
|
|
3370 // Ajax source - this allows the table to look initialised for Ajax sourcing
|
|
|
3371 // data (show 'loading' message possibly)
|
|
|
3372 _fnReDraw( settings );
|
|
|
3373
|
|
|
3374 // Server-side processing init complete is done by _fnAjaxUpdateDraw
|
|
|
3375 var dataSrc = _fnDataSource( settings );
|
|
|
3376 if ( dataSrc != 'ssp' || deferLoading ) {
|
|
|
3377 // if there is an ajax source load the data
|
|
|
3378 if ( dataSrc == 'ajax' ) {
|
|
|
3379 _fnBuildAjax( settings, [], function(json) {
|
|
|
3380 var aData = _fnAjaxDataSrc( settings, json );
|
|
|
3381
|
|
|
3382 // Got the data - add it to the table
|
|
|
3383 for ( i=0 ; i<aData.length ; i++ ) {
|
|
|
3384 _fnAddData( settings, aData[i] );
|
|
|
3385 }
|
|
|
3386
|
|
|
3387 // Reset the init display for cookie saving. We've already done
|
|
|
3388 // a filter, and therefore cleared it before. So we need to make
|
|
|
3389 // it appear 'fresh'
|
|
|
3390 settings.iInitDisplayStart = iAjaxStart;
|
|
|
3391
|
|
|
3392 _fnReDraw( settings );
|
|
|
3393
|
|
|
3394 _fnProcessingDisplay( settings, false );
|
|
|
3395 _fnInitComplete( settings, json );
|
|
|
3396 }, settings );
|
|
|
3397 }
|
|
|
3398 else {
|
|
|
3399 _fnProcessingDisplay( settings, false );
|
|
|
3400 _fnInitComplete( settings );
|
|
|
3401 }
|
|
|
3402 }
|
|
|
3403 }
|
|
|
3404
|
|
|
3405
|
|
|
3406 /**
|
|
|
3407 * Draw the table for the first time, adding all required features
|
|
|
3408 * @param {object} oSettings dataTables settings object
|
|
|
3409 * @param {object} [json] JSON from the server that completed the table, if using Ajax source
|
|
|
3410 * with client-side processing (optional)
|
|
|
3411 * @memberof DataTable#oApi
|
|
|
3412 */
|
|
|
3413 function _fnInitComplete ( settings, json )
|
|
|
3414 {
|
|
|
3415 settings._bInitComplete = true;
|
|
|
3416
|
|
|
3417 // When data was added after the initialisation (data or Ajax) we need to
|
|
|
3418 // calculate the column sizing
|
|
|
3419 if ( json || settings.oInit.aaData ) {
|
|
|
3420 _fnAdjustColumnSizing( settings );
|
|
|
3421 }
|
|
|
3422
|
|
|
3423 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
|
|
|
3424 }
|
|
|
3425
|
|
|
3426
|
|
|
3427 function _fnLengthChange ( settings, val )
|
|
|
3428 {
|
|
|
3429 var len = parseInt( val, 10 );
|
|
|
3430 settings._iDisplayLength = len;
|
|
|
3431
|
|
|
3432 _fnLengthOverflow( settings );
|
|
|
3433
|
|
|
3434 // Fire length change event
|
|
|
3435 _fnCallbackFire( settings, null, 'length', [settings, len] );
|
|
|
3436 }
|
|
|
3437
|
|
|
3438
|
|
|
3439 /**
|
|
|
3440 * Generate the node required for user display length changing
|
|
|
3441 * @param {object} settings dataTables settings object
|
|
|
3442 * @returns {node} Display length feature node
|
|
|
3443 * @memberof DataTable#oApi
|
|
|
3444 */
|
|
|
3445 function _fnFeatureHtmlLength ( settings )
|
|
|
3446 {
|
|
|
3447 var
|
|
|
3448 classes = settings.oClasses,
|
|
|
3449 tableId = settings.sTableId,
|
|
|
3450 menu = settings.aLengthMenu,
|
|
|
3451 d2 = $.isArray( menu[0] ),
|
|
|
3452 lengths = d2 ? menu[0] : menu,
|
|
|
3453 language = d2 ? menu[1] : menu;
|
|
|
3454
|
|
|
3455 var select = $('<select/>', {
|
|
|
3456 'name': tableId+'_length',
|
|
|
3457 'aria-controls': tableId,
|
|
|
3458 'class': classes.sLengthSelect
|
|
|
3459 } );
|
|
|
3460
|
|
|
3461 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
|
|
|
3462 select[0][ i ] = new Option( language[i], lengths[i] );
|
|
|
3463 }
|
|
|
3464
|
|
|
3465 var div = $('<div><label/></div>').addClass( classes.sLength );
|
|
|
3466 if ( ! settings.aanFeatures.l ) {
|
|
|
3467 div[0].id = tableId+'_length';
|
|
|
3468 }
|
|
|
3469
|
|
|
3470 div.children().append(
|
|
|
3471 settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
|
|
|
3472 );
|
|
|
3473
|
|
|
3474 // Can't use `select` variable as user might provide their own and the
|
|
|
3475 // reference is broken by the use of outerHTML
|
|
|
3476 $('select', div)
|
|
|
3477 .val( settings._iDisplayLength )
|
|
|
3478 .bind( 'change.DT', function(e) {
|
|
|
3479 _fnLengthChange( settings, $(this).val() );
|
|
|
3480 _fnDraw( settings );
|
|
|
3481 } );
|
|
|
3482
|
|
|
3483 // Update node value whenever anything changes the table's length
|
|
|
3484 $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
|
|
|
3485 if ( settings === s ) {
|
|
|
3486 $('select', div).val( len );
|
|
|
3487 }
|
|
|
3488 } );
|
|
|
3489
|
|
|
3490 return div[0];
|
|
|
3491 }
|
|
|
3492
|
|
|
3493
|
|
|
3494
|
|
|
3495 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
|
3496 * Note that most of the paging logic is done in
|
|
|
3497 * DataTable.ext.pager
|
|
|
3498 */
|
|
|
3499
|
|
|
3500 /**
|
|
|
3501 * Generate the node required for default pagination
|
|
|
3502 * @param {object} oSettings dataTables settings object
|
|
|
3503 * @returns {node} Pagination feature node
|
|
|
3504 * @memberof DataTable#oApi
|
|
|
3505 */
|
|
|
3506 function _fnFeatureHtmlPaginate ( settings )
|
|
|
3507 {
|
|
|
3508 var
|
|
|
3509 type = settings.sPaginationType,
|
|
|
3510 plugin = DataTable.ext.pager[ type ],
|
|
|
3511 modern = typeof plugin === 'function',
|
|
|
3512 redraw = function( settings ) {
|
|
|
3513 _fnDraw( settings );
|
|
|
3514 },
|
|
|
3515 node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
|
|
|
3516 features = settings.aanFeatures;
|
|
|
3517
|
|
|
3518 if ( ! modern ) {
|
|
|
3519 plugin.fnInit( settings, node, redraw );
|
|
|
3520 }
|
|
|
3521
|
|
|
3522 /* Add a draw callback for the pagination on first instance, to update the paging display */
|
|
|
3523 if ( ! features.p )
|
|
|
3524 {
|
|
|
3525 node.id = settings.sTableId+'_paginate';
|
|
|
3526
|
|
|
3527 settings.aoDrawCallback.push( {
|
|
|
3528 "fn": function( settings ) {
|
|
|
3529 if ( modern ) {
|
|
|
3530 var
|
|
|
3531 start = settings._iDisplayStart,
|
|
|
3532 len = settings._iDisplayLength,
|
|
|
3533 visRecords = settings.fnRecordsDisplay(),
|
|
|
3534 all = len === -1,
|
|
|
3535 page = all ? 0 : Math.ceil( start / len ),
|
|
|
3536 pages = all ? 1 : Math.ceil( visRecords / len ),
|
|
|
3537 buttons = plugin(page, pages),
|
|
|
3538 i, ien;
|
|
|
3539
|
|
|
3540 for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
|
|
|
3541 _fnRenderer( settings, 'pageButton' )(
|
|
|
3542 settings, features.p[i], i, buttons, page, pages
|
|
|
3543 );
|
|
|
3544 }
|
|
|
3545 }
|
|
|
3546 else {
|
|
|
3547 plugin.fnUpdate( settings, redraw );
|
|
|
3548 }
|
|
|
3549 },
|
|
|
3550 "sName": "pagination"
|
|
|
3551 } );
|
|
|
3552 }
|
|
|
3553
|
|
|
3554 return node;
|
|
|
3555 }
|
|
|
3556
|
|
|
3557
|
|
|
3558 /**
|
|
|
3559 * Alter the display settings to change the page
|
|
|
3560 * @param {object} settings DataTables settings object
|
|
|
3561 * @param {string|int} action Paging action to take: "first", "previous",
|
|
|
3562 * "next" or "last" or page number to jump to (integer)
|
|
|
3563 * @param [bool] redraw Automatically draw the update or not
|
|
|
3564 * @returns {bool} true page has changed, false - no change
|
|
|
3565 * @memberof DataTable#oApi
|
|
|
3566 */
|
|
|
3567 function _fnPageChange ( settings, action, redraw )
|
|
|
3568 {
|
|
|
3569 var
|
|
|
3570 start = settings._iDisplayStart,
|
|
|
3571 len = settings._iDisplayLength,
|
|
|
3572 records = settings.fnRecordsDisplay();
|
|
|
3573
|
|
|
3574 if ( records === 0 || len === -1 )
|
|
|
3575 {
|
|
|
3576 start = 0;
|
|
|
3577 }
|
|
|
3578 else if ( typeof action === "number" )
|
|
|
3579 {
|
|
|
3580 start = action * len;
|
|
|
3581
|
|
|
3582 if ( start > records )
|
|
|
3583 {
|
|
|
3584 start = 0;
|
|
|
3585 }
|
|
|
3586 }
|
|
|
3587 else if ( action == "first" )
|
|
|
3588 {
|
|
|
3589 start = 0;
|
|
|
3590 }
|
|
|
3591 else if ( action == "previous" )
|
|
|
3592 {
|
|
|
3593 start = len >= 0 ?
|
|
|
3594 start - len :
|
|
|
3595 0;
|
|
|
3596
|
|
|
3597 if ( start < 0 )
|
|
|
3598 {
|
|
|
3599 start = 0;
|
|
|
3600 }
|
|
|
3601 }
|
|
|
3602 else if ( action == "next" )
|
|
|
3603 {
|
|
|
3604 if ( start + len < records )
|
|
|
3605 {
|
|
|
3606 start += len;
|
|
|
3607 }
|
|
|
3608 }
|
|
|
3609 else if ( action == "last" )
|
|
|
3610 {
|
|
|
3611 start = Math.floor( (records-1) / len) * len;
|
|
|
3612 }
|
|
|
3613 else
|
|
|
3614 {
|
|
|
3615 _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
|
|
|
3616 }
|
|
|
3617
|
|
|
3618 var changed = settings._iDisplayStart !== start;
|
|
|
3619 settings._iDisplayStart = start;
|
|
|
3620
|
|
|
3621 if ( changed ) {
|
|
|
3622 _fnCallbackFire( settings, null, 'page', [settings] );
|
|
|
3623
|
|
|
3624 if ( redraw ) {
|
|
|
3625 _fnDraw( settings );
|
|
|
3626 }
|
|
|
3627 }
|
|
|
3628
|
|
|
3629 return changed;
|
|
|
3630 }
|
|
|
3631
|
|
|
3632
|
|
|
3633
|
|
|
3634 /**
|
|
|
3635 * Generate the node required for the processing node
|
|
|
3636 * @param {object} settings dataTables settings object
|
|
|
3637 * @returns {node} Processing element
|
|
|
3638 * @memberof DataTable#oApi
|
|
|
3639 */
|
|
|
3640 function _fnFeatureHtmlProcessing ( settings )
|
|
|
3641 {
|
|
|
3642 return $('<div/>', {
|
|
|
3643 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
|
|
|
3644 'class': settings.oClasses.sProcessing
|
|
|
3645 } )
|
|
|
3646 .html( settings.oLanguage.sProcessing )
|
|
|
3647 .insertBefore( settings.nTable )[0];
|
|
|
3648 }
|
|
|
3649
|
|
|
3650
|
|
|
3651 /**
|
|
|
3652 * Display or hide the processing indicator
|
|
|
3653 * @param {object} settings dataTables settings object
|
|
|
3654 * @param {bool} show Show the processing indicator (true) or not (false)
|
|
|
3655 * @memberof DataTable#oApi
|
|
|
3656 */
|
|
|
3657 function _fnProcessingDisplay ( settings, show )
|
|
|
3658 {
|
|
|
3659 if ( settings.oFeatures.bProcessing ) {
|
|
|
3660 $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
|
|
|
3661 }
|
|
|
3662
|
|
|
3663 _fnCallbackFire( settings, null, 'processing', [settings, show] );
|
|
|
3664 }
|
|
|
3665
|
|
|
3666 /**
|
|
|
3667 * Add any control elements for the table - specifically scrolling
|
|
|
3668 * @param {object} settings dataTables settings object
|
|
|
3669 * @returns {node} Node to add to the DOM
|
|
|
3670 * @memberof DataTable#oApi
|
|
|
3671 */
|
|
|
3672 function _fnFeatureHtmlTable ( settings )
|
|
|
3673 {
|
|
|
3674 var table = $(settings.nTable);
|
|
|
3675
|
|
|
3676 // Add the ARIA grid role to the table
|
|
|
3677 table.attr( 'role', 'grid' );
|
|
|
3678
|
|
|
3679 // Scrolling from here on in
|
|
|
3680 var scroll = settings.oScroll;
|
|
|
3681
|
|
|
3682 if ( scroll.sX === '' && scroll.sY === '' ) {
|
|
|
3683 return settings.nTable;
|
|
|
3684 }
|
|
|
3685
|
|
|
3686 var scrollX = scroll.sX;
|
|
|
3687 var scrollY = scroll.sY;
|
|
|
3688 var classes = settings.oClasses;
|
|
|
3689 var caption = table.children('caption');
|
|
|
3690 var captionSide = caption.length ? caption[0]._captionSide : null;
|
|
|
3691 var headerClone = $( table[0].cloneNode(false) );
|
|
|
3692 var footerClone = $( table[0].cloneNode(false) );
|
|
|
3693 var footer = table.children('tfoot');
|
|
|
3694 var _div = '<div/>';
|
|
|
3695 var size = function ( s ) {
|
|
|
3696 return !s ? null : _fnStringToCss( s );
|
|
|
3697 };
|
|
|
3698
|
|
|
3699 // This is fairly messy, but with x scrolling enabled, if the table has a
|
|
|
3700 // width attribute, regardless of any width applied using the column width
|
|
|
3701 // options, the browser will shrink or grow the table as needed to fit into
|
|
|
3702 // that 100%. That would make the width options useless. So we remove it.
|
|
|
3703 // This is okay, under the assumption that width:100% is applied to the
|
|
|
3704 // table in CSS (it is in the default stylesheet) which will set the table
|
|
|
3705 // width as appropriate (the attribute and css behave differently...)
|
|
|
3706 if ( scroll.sX && table.attr('width') === '100%' ) {
|
|
|
3707 table.removeAttr('width');
|
|
|
3708 }
|
|
|
3709
|
|
|
3710 if ( ! footer.length ) {
|
|
|
3711 footer = null;
|
|
|
3712 }
|
|
|
3713
|
|
|
3714 /*
|
|
|
3715 * The HTML structure that we want to generate in this function is:
|
|
|
3716 * div - scroller
|
|
|
3717 * div - scroll head
|
|
|
3718 * div - scroll head inner
|
|
|
3719 * table - scroll head table
|
|
|
3720 * thead - thead
|
|
|
3721 * div - scroll body
|
|
|
3722 * table - table (master table)
|
|
|
3723 * thead - thead clone for sizing
|
|
|
3724 * tbody - tbody
|
|
|
3725 * div - scroll foot
|
|
|
3726 * div - scroll foot inner
|
|
|
3727 * table - scroll foot table
|
|
|
3728 * tfoot - tfoot
|
|
|
3729 */
|
|
|
3730 var scroller = $( _div, { 'class': classes.sScrollWrapper } )
|
|
|
3731 .append(
|
|
|
3732 $(_div, { 'class': classes.sScrollHead } )
|
|
|
3733 .css( {
|
|
|
3734 overflow: 'hidden',
|
|
|
3735 position: 'relative',
|
|
|
3736 border: 0,
|
|
|
3737 width: scrollX ? size(scrollX) : '100%'
|
|
|
3738 } )
|
|
|
3739 .append(
|
|
|
3740 $(_div, { 'class': classes.sScrollHeadInner } )
|
|
|
3741 .css( {
|
|
|
3742 'box-sizing': 'content-box',
|
|
|
3743 width: scroll.sXInner || '100%'
|
|
|
3744 } )
|
|
|
3745 .append(
|
|
|
3746 headerClone
|
|
|
3747 .removeAttr('id')
|
|
|
3748 .css( 'margin-left', 0 )
|
|
|
3749 .append( captionSide === 'top' ? caption : null )
|
|
|
3750 .append(
|
|
|
3751 table.children('thead')
|
|
|
3752 )
|
|
|
3753 )
|
|
|
3754 )
|
|
|
3755 )
|
|
|
3756 .append(
|
|
|
3757 $(_div, { 'class': classes.sScrollBody } )
|
|
|
3758 .css( {
|
|
|
3759 position: 'relative',
|
|
|
3760 overflow: 'auto',
|
|
|
3761 width: size( scrollX )
|
|
|
3762 } )
|
|
|
3763 .append( table )
|
|
|
3764 );
|
|
|
3765
|
|
|
3766 if ( footer ) {
|
|
|
3767 scroller.append(
|
|
|
3768 $(_div, { 'class': classes.sScrollFoot } )
|
|
|
3769 .css( {
|
|
|
3770 overflow: 'hidden',
|
|
|
3771 border: 0,
|
|
|
3772 width: scrollX ? size(scrollX) : '100%'
|
|
|
3773 } )
|
|
|
3774 .append(
|
|
|
3775 $(_div, { 'class': classes.sScrollFootInner } )
|
|
|
3776 .append(
|
|
|
3777 footerClone
|
|
|
3778 .removeAttr('id')
|
|
|
3779 .css( 'margin-left', 0 )
|
|
|
3780 .append( captionSide === 'bottom' ? caption : null )
|
|
|
3781 .append(
|
|
|
3782 table.children('tfoot')
|
|
|
3783 )
|
|
|
3784 )
|
|
|
3785 )
|
|
|
3786 );
|
|
|
3787 }
|
|
|
3788
|
|
|
3789 var children = scroller.children();
|
|
|
3790 var scrollHead = children[0];
|
|
|
3791 var scrollBody = children[1];
|
|
|
3792 var scrollFoot = footer ? children[2] : null;
|
|
|
3793
|
|
|
3794 // When the body is scrolled, then we also want to scroll the headers
|
|
|
3795 if ( scrollX ) {
|
|
|
3796 $(scrollBody).on( 'scroll.DT', function (e) {
|
|
|
3797 var scrollLeft = this.scrollLeft;
|
|
|
3798
|
|
|
3799 scrollHead.scrollLeft = scrollLeft;
|
|
|
3800
|
|
|
3801 if ( footer ) {
|
|
|
3802 scrollFoot.scrollLeft = scrollLeft;
|
|
|
3803 }
|
|
|
3804 } );
|
|
|
3805 }
|
|
|
3806
|
|
|
3807 $(scrollBody).css(
|
|
|
3808 scrollY && scroll.bCollapse ? 'max-height' : 'height',
|
|
|
3809 scrollY
|
|
|
3810 );
|
|
|
3811
|
|
|
3812 settings.nScrollHead = scrollHead;
|
|
|
3813 settings.nScrollBody = scrollBody;
|
|
|
3814 settings.nScrollFoot = scrollFoot;
|
|
|
3815
|
|
|
3816 // On redraw - align columns
|
|
|
3817 settings.aoDrawCallback.push( {
|
|
|
3818 "fn": _fnScrollDraw,
|
|
|
3819 "sName": "scrolling"
|
|
|
3820 } );
|
|
|
3821
|
|
|
3822 return scroller[0];
|
|
|
3823 }
|
|
|
3824
|
|
|
3825
|
|
|
3826
|
|
|
3827 /**
|
|
|
3828 * Update the header, footer and body tables for resizing - i.e. column
|
|
|
3829 * alignment.
|
|
|
3830 *
|
|
|
3831 * Welcome to the most horrible function DataTables. The process that this
|
|
|
3832 * function follows is basically:
|
|
|
3833 * 1. Re-create the table inside the scrolling div
|
|
|
3834 * 2. Take live measurements from the DOM
|
|
|
3835 * 3. Apply the measurements to align the columns
|
|
|
3836 * 4. Clean up
|
|
|
3837 *
|
|
|
3838 * @param {object} settings dataTables settings object
|
|
|
3839 * @memberof DataTable#oApi
|
|
|
3840 */
|
|
|
3841 function _fnScrollDraw ( settings )
|
|
|
3842 {
|
|
|
3843 // Given that this is such a monster function, a lot of variables are use
|
|
|
3844 // to try and keep the minimised size as small as possible
|
|
|
3845 var
|
|
|
3846 scroll = settings.oScroll,
|
|
|
3847 scrollX = scroll.sX,
|
|
|
3848 scrollXInner = scroll.sXInner,
|
|
|
3849 scrollY = scroll.sY,
|
|
|
3850 barWidth = scroll.iBarWidth,
|
|
|
3851 divHeader = $(settings.nScrollHead),
|
|
|
3852 divHeaderStyle = divHeader[0].style,
|
|
|
3853 divHeaderInner = divHeader.children('div'),
|
|
|
3854 divHeaderInnerStyle = divHeaderInner[0].style,
|
|
|
3855 divHeaderTable = divHeaderInner.children('table'),
|
|
|
3856 divBodyEl = settings.nScrollBody,
|
|
|
3857 divBody = $(divBodyEl),
|
|
|
3858 divBodyStyle = divBodyEl.style,
|
|
|
3859 divFooter = $(settings.nScrollFoot),
|
|
|
3860 divFooterInner = divFooter.children('div'),
|
|
|
3861 divFooterTable = divFooterInner.children('table'),
|
|
|
3862 header = $(settings.nTHead),
|
|
|
3863 table = $(settings.nTable),
|
|
|
3864 tableEl = table[0],
|
|
|
3865 tableStyle = tableEl.style,
|
|
|
3866 footer = settings.nTFoot ? $(settings.nTFoot) : null,
|
|
|
3867 browser = settings.oBrowser,
|
|
|
3868 ie67 = browser.bScrollOversize,
|
|
|
3869 headerTrgEls, footerTrgEls,
|
|
|
3870 headerSrcEls, footerSrcEls,
|
|
|
3871 headerCopy, footerCopy,
|
|
|
3872 headerWidths=[], footerWidths=[],
|
|
|
3873 headerContent=[],
|
|
|
3874 idx, correction, sanityWidth,
|
|
|
3875 zeroOut = function(nSizer) {
|
|
|
3876 var style = nSizer.style;
|
|
|
3877 style.paddingTop = "0";
|
|
|
3878 style.paddingBottom = "0";
|
|
|
3879 style.borderTopWidth = "0";
|
|
|
3880 style.borderBottomWidth = "0";
|
|
|
3881 style.height = 0;
|
|
|
3882 };
|
|
|
3883
|
|
|
3884 /*
|
|
|
3885 * 1. Re-create the table inside the scrolling div
|
|
|
3886 */
|
|
|
3887
|
|
|
3888 // Remove the old minimised thead and tfoot elements in the inner table
|
|
|
3889 table.children('thead, tfoot').remove();
|
|
|
3890
|
|
|
3891 // Clone the current header and footer elements and then place it into the inner table
|
|
|
3892 headerCopy = header.clone().prependTo( table );
|
|
|
3893 headerTrgEls = header.find('tr'); // original header is in its own table
|
|
|
3894 headerSrcEls = headerCopy.find('tr');
|
|
|
3895 headerCopy.find('th, td').removeAttr('tabindex');
|
|
|
3896
|
|
|
3897 if ( footer ) {
|
|
|
3898 footerCopy = footer.clone().prependTo( table );
|
|
|
3899 footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
|
|
|
3900 footerSrcEls = footerCopy.find('tr');
|
|
|
3901 }
|
|
|
3902
|
|
|
3903
|
|
|
3904 /*
|
|
|
3905 * 2. Take live measurements from the DOM - do not alter the DOM itself!
|
|
|
3906 */
|
|
|
3907
|
|
|
3908 // Remove old sizing and apply the calculated column widths
|
|
|
3909 // Get the unique column headers in the newly created (cloned) header. We want to apply the
|
|
|
3910 // calculated sizes to this header
|
|
|
3911 if ( ! scrollX )
|
|
|
3912 {
|
|
|
3913 divBodyStyle.width = '100%';
|
|
|
3914 divHeader[0].style.width = '100%';
|
|
|
3915 }
|
|
|
3916
|
|
|
3917 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
|
|
|
3918 idx = _fnVisibleToColumnIndex( settings, i );
|
|
|
3919 el.style.width = settings.aoColumns[idx].sWidth;
|
|
|
3920 } );
|
|
|
3921
|
|
|
3922 if ( footer ) {
|
|
|
3923 _fnApplyToChildren( function(n) {
|
|
|
3924 n.style.width = "";
|
|
|
3925 }, footerSrcEls );
|
|
|
3926 }
|
|
|
3927
|
|
|
3928 // Size the table as a whole
|
|
|
3929 sanityWidth = table.outerWidth();
|
|
|
3930 if ( scrollX === "" ) {
|
|
|
3931 // No x scrolling
|
|
|
3932 tableStyle.width = "100%";
|
|
|
3933
|
|
|
3934 // IE7 will make the width of the table when 100% include the scrollbar
|
|
|
3935 // - which is shouldn't. When there is a scrollbar we need to take this
|
|
|
3936 // into account.
|
|
|
3937 if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
|
|
|
3938 divBody.css('overflow-y') == "scroll")
|
|
|
3939 ) {
|
|
|
3940 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
|
|
|
3941 }
|
|
|
3942
|
|
|
3943 // Recalculate the sanity width
|
|
|
3944 sanityWidth = table.outerWidth();
|
|
|
3945 }
|
|
|
3946 else if ( scrollXInner !== "" ) {
|
|
|
3947 // legacy x scroll inner has been given - use it
|
|
|
3948 tableStyle.width = _fnStringToCss(scrollXInner);
|
|
|
3949
|
|
|
3950 // Recalculate the sanity width
|
|
|
3951 sanityWidth = table.outerWidth();
|
|
|
3952 }
|
|
|
3953
|
|
|
3954 // Hidden header should have zero height, so remove padding and borders. Then
|
|
|
3955 // set the width based on the real headers
|
|
|
3956
|
|
|
3957 // Apply all styles in one pass
|
|
|
3958 _fnApplyToChildren( zeroOut, headerSrcEls );
|
|
|
3959
|
|
|
3960 // Read all widths in next pass
|
|
|
3961 _fnApplyToChildren( function(nSizer) {
|
|
|
3962 headerContent.push( nSizer.innerHTML );
|
|
|
3963 headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
|
|
|
3964 }, headerSrcEls );
|
|
|
3965
|
|
|
3966 // Apply all widths in final pass
|
|
|
3967 _fnApplyToChildren( function(nToSize, i) {
|
|
|
3968 nToSize.style.width = headerWidths[i];
|
|
|
3969 }, headerTrgEls );
|
|
|
3970
|
|
|
3971 $(headerSrcEls).height(0);
|
|
|
3972
|
|
|
3973 /* Same again with the footer if we have one */
|
|
|
3974 if ( footer )
|
|
|
3975 {
|
|
|
3976 _fnApplyToChildren( zeroOut, footerSrcEls );
|
|
|
3977
|
|
|
3978 _fnApplyToChildren( function(nSizer) {
|
|
|
3979 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
|
|
|
3980 }, footerSrcEls );
|
|
|
3981
|
|
|
3982 _fnApplyToChildren( function(nToSize, i) {
|
|
|
3983 nToSize.style.width = footerWidths[i];
|
|
|
3984 }, footerTrgEls );
|
|
|
3985
|
|
|
3986 $(footerSrcEls).height(0);
|
|
|
3987 }
|
|
|
3988
|
|
|
3989
|
|
|
3990 /*
|
|
|
3991 * 3. Apply the measurements
|
|
|
3992 */
|
|
|
3993
|
|
|
3994 // "Hide" the header and footer that we used for the sizing. We need to keep
|
|
|
3995 // the content of the cell so that the width applied to the header and body
|
|
|
3996 // both match, but we want to hide it completely. We want to also fix their
|
|
|
3997 // width to what they currently are
|
|
|
3998 _fnApplyToChildren( function(nSizer, i) {
|
|
|
3999 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
|
|
|
4000 nSizer.style.width = headerWidths[i];
|
|
|
4001 }, headerSrcEls );
|
|
|
4002
|
|
|
4003 if ( footer )
|
|
|
4004 {
|
|
|
4005 _fnApplyToChildren( function(nSizer, i) {
|
|
|
4006 nSizer.innerHTML = "";
|
|
|
4007 nSizer.style.width = footerWidths[i];
|
|
|
4008 }, footerSrcEls );
|
|
|
4009 }
|
|
|
4010
|
|
|
4011 // Sanity check that the table is of a sensible width. If not then we are going to get
|
|
|
4012 // misalignment - try to prevent this by not allowing the table to shrink below its min width
|
|
|
4013 if ( table.outerWidth() < sanityWidth )
|
|
|
4014 {
|
|
|
4015 // The min width depends upon if we have a vertical scrollbar visible or not */
|
|
|
4016 correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
|
|
|
4017 divBody.css('overflow-y') == "scroll")) ?
|
|
|
4018 sanityWidth+barWidth :
|
|
|
4019 sanityWidth;
|
|
|
4020
|
|
|
4021 // IE6/7 are a law unto themselves...
|
|
|
4022 if ( ie67 && (divBodyEl.scrollHeight >
|
|
|
4023 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
|
|
|
4024 ) {
|
|
|
4025 tableStyle.width = _fnStringToCss( correction-barWidth );
|
|
|
4026 }
|
|
|
4027
|
|
|
4028 // And give the user a warning that we've stopped the table getting too small
|
|
|
4029 if ( scrollX === "" || scrollXInner !== "" ) {
|
|
|
4030 _fnLog( settings, 1, 'Possible column misalignment', 6 );
|
|
|
4031 }
|
|
|
4032 }
|
|
|
4033 else
|
|
|
4034 {
|
|
|
4035 correction = '100%';
|
|
|
4036 }
|
|
|
4037
|
|
|
4038 // Apply to the container elements
|
|
|
4039 divBodyStyle.width = _fnStringToCss( correction );
|
|
|
4040 divHeaderStyle.width = _fnStringToCss( correction );
|
|
|
4041
|
|
|
4042 if ( footer ) {
|
|
|
4043 settings.nScrollFoot.style.width = _fnStringToCss( correction );
|
|
|
4044 }
|
|
|
4045
|
|
|
4046
|
|
|
4047 /*
|
|
|
4048 * 4. Clean up
|
|
|
4049 */
|
|
|
4050 if ( ! scrollY ) {
|
|
|
4051 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
|
|
|
4052 * the scrollbar height from the visible display, rather than adding it on. We need to
|
|
|
4053 * set the height in order to sort this. Don't want to do it in any other browsers.
|
|
|
4054 */
|
|
|
4055 if ( ie67 ) {
|
|
|
4056 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
|
|
|
4057 }
|
|
|
4058 }
|
|
|
4059
|
|
|
4060 /* Finally set the width's of the header and footer tables */
|
|
|
4061 var iOuterWidth = table.outerWidth();
|
|
|
4062 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
|
|
|
4063 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
|
|
|
4064
|
|
|
4065 // Figure out if there are scrollbar present - if so then we need a the header and footer to
|
|
|
4066 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
|
|
|
4067 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
|
|
|
4068 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
|
|
|
4069 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
|
|
|
4070
|
|
|
4071 if ( footer ) {
|
|
|
4072 divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
|
|
|
4073 divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
|
|
|
4074 divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
|
|
|
4075 }
|
|
|
4076
|
|
|
4077 /* Adjust the position of the header in case we loose the y-scrollbar */
|
|
|
4078 divBody.scroll();
|
|
|
4079
|
|
|
4080 // If sorting or filtering has occurred, jump the scrolling back to the top
|
|
|
4081 // only if we aren't holding the position
|
|
|
4082 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
|
|
|
4083 divBodyEl.scrollTop = 0;
|
|
|
4084 }
|
|
|
4085 }
|
|
|
4086
|
|
|
4087
|
|
|
4088
|
|
|
4089 /**
|
|
|
4090 * Apply a given function to the display child nodes of an element array (typically
|
|
|
4091 * TD children of TR rows
|
|
|
4092 * @param {function} fn Method to apply to the objects
|
|
|
4093 * @param array {nodes} an1 List of elements to look through for display children
|
|
|
4094 * @param array {nodes} an2 Another list (identical structure to the first) - optional
|
|
|
4095 * @memberof DataTable#oApi
|
|
|
4096 */
|
|
|
4097 function _fnApplyToChildren( fn, an1, an2 )
|
|
|
4098 {
|
|
|
4099 var index=0, i=0, iLen=an1.length;
|
|
|
4100 var nNode1, nNode2;
|
|
|
4101
|
|
|
4102 while ( i < iLen ) {
|
|
|
4103 nNode1 = an1[i].firstChild;
|
|
|
4104 nNode2 = an2 ? an2[i].firstChild : null;
|
|
|
4105
|
|
|
4106 while ( nNode1 ) {
|
|
|
4107 if ( nNode1.nodeType === 1 ) {
|
|
|
4108 if ( an2 ) {
|
|
|
4109 fn( nNode1, nNode2, index );
|
|
|
4110 }
|
|
|
4111 else {
|
|
|
4112 fn( nNode1, index );
|
|
|
4113 }
|
|
|
4114
|
|
|
4115 index++;
|
|
|
4116 }
|
|
|
4117
|
|
|
4118 nNode1 = nNode1.nextSibling;
|
|
|
4119 nNode2 = an2 ? nNode2.nextSibling : null;
|
|
|
4120 }
|
|
|
4121
|
|
|
4122 i++;
|
|
|
4123 }
|
|
|
4124 }
|
|
|
4125
|
|
|
4126
|
|
|
4127
|
|
|
4128 var __re_html_remove = /<.*?>/g;
|
|
|
4129
|
|
|
4130
|
|
|
4131 /**
|
|
|
4132 * Calculate the width of columns for the table
|
|
|
4133 * @param {object} oSettings dataTables settings object
|
|
|
4134 * @memberof DataTable#oApi
|
|
|
4135 */
|
|
|
4136 function _fnCalculateColumnWidths ( oSettings )
|
|
|
4137 {
|
|
|
4138 var
|
|
|
4139 table = oSettings.nTable,
|
|
|
4140 columns = oSettings.aoColumns,
|
|
|
4141 scroll = oSettings.oScroll,
|
|
|
4142 scrollY = scroll.sY,
|
|
|
4143 scrollX = scroll.sX,
|
|
|
4144 scrollXInner = scroll.sXInner,
|
|
|
4145 columnCount = columns.length,
|
|
|
4146 visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
|
|
|
4147 headerCells = $('th', oSettings.nTHead),
|
|
|
4148 tableWidthAttr = table.getAttribute('width'), // from DOM element
|
|
|
4149 tableContainer = table.parentNode,
|
|
|
4150 userInputs = false,
|
|
|
4151 i, column, columnIdx, width, outerWidth,
|
|
|
4152 browser = oSettings.oBrowser,
|
|
|
4153 ie67 = browser.bScrollOversize;
|
|
|
4154
|
|
|
4155 var styleWidth = table.style.width;
|
|
|
4156 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
|
|
|
4157 tableWidthAttr = styleWidth;
|
|
|
4158 }
|
|
|
4159
|
|
|
4160 /* Convert any user input sizes into pixel sizes */
|
|
|
4161 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
|
4162 column = columns[ visibleColumns[i] ];
|
|
|
4163
|
|
|
4164 if ( column.sWidth !== null ) {
|
|
|
4165 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
|
|
|
4166
|
|
|
4167 userInputs = true;
|
|
|
4168 }
|
|
|
4169 }
|
|
|
4170
|
|
|
4171 /* If the number of columns in the DOM equals the number that we have to
|
|
|
4172 * process in DataTables, then we can use the offsets that are created by
|
|
|
4173 * the web- browser. No custom sizes can be set in order for this to happen,
|
|
|
4174 * nor scrolling used
|
|
|
4175 */
|
|
|
4176 if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
|
|
|
4177 columnCount == _fnVisbleColumns( oSettings ) &&
|
|
|
4178 columnCount == headerCells.length
|
|
|
4179 ) {
|
|
|
4180 for ( i=0 ; i<columnCount ; i++ ) {
|
|
|
4181 var colIdx = _fnVisibleToColumnIndex( oSettings, i );
|
|
|
4182
|
|
|
4183 if ( colIdx ) {
|
|
|
4184 columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
|
|
|
4185 }
|
|
|
4186 }
|
|
|
4187 }
|
|
|
4188 else
|
|
|
4189 {
|
|
|
4190 // Otherwise construct a single row, worst case, table with the widest
|
|
|
4191 // node in the data, assign any user defined widths, then insert it into
|
|
|
4192 // the DOM and allow the browser to do all the hard work of calculating
|
|
|
4193 // table widths
|
|
|
4194 var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
|
|
|
4195 .css( 'visibility', 'hidden' )
|
|
|
4196 .removeAttr( 'id' );
|
|
|
4197
|
|
|
4198 // Clean up the table body
|
|
|
4199 tmpTable.find('tbody tr').remove();
|
|
|
4200 var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
|
|
|
4201
|
|
|
4202 // Clone the table header and footer - we can't use the header / footer
|
|
|
4203 // from the cloned table, since if scrolling is active, the table's
|
|
|
4204 // real header and footer are contained in different table tags
|
|
|
4205 tmpTable.find('thead, tfoot').remove();
|
|
|
4206 tmpTable
|
|
|
4207 .append( $(oSettings.nTHead).clone() )
|
|
|
4208 .append( $(oSettings.nTFoot).clone() );
|
|
|
4209
|
|
|
4210 // Remove any assigned widths from the footer (from scrolling)
|
|
|
4211 tmpTable.find('tfoot th, tfoot td').css('width', '');
|
|
|
4212
|
|
|
4213 // Apply custom sizing to the cloned header
|
|
|
4214 headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
|
|
|
4215
|
|
|
4216 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
|
4217 column = columns[ visibleColumns[i] ];
|
|
|
4218
|
|
|
4219 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
|
|
|
4220 _fnStringToCss( column.sWidthOrig ) :
|
|
|
4221 '';
|
|
|
4222 }
|
|
|
4223
|
|
|
4224 // Find the widest cell for each column and put it into the table
|
|
|
4225 if ( oSettings.aoData.length ) {
|
|
|
4226 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
|
4227 columnIdx = visibleColumns[i];
|
|
|
4228 column = columns[ columnIdx ];
|
|
|
4229
|
|
|
4230 $( _fnGetWidestNode( oSettings, columnIdx ) )
|
|
|
4231 .clone( false )
|
|
|
4232 .append( column.sContentPadding )
|
|
|
4233 .appendTo( tr );
|
|
|
4234 }
|
|
|
4235 }
|
|
|
4236
|
|
|
4237 // Table has been built, attach to the document so we can work with it.
|
|
|
4238 // A holding element is used, positioned at the top of the container
|
|
|
4239 // with minimal height, so it has no effect on if the container scrolls
|
|
|
4240 // or not. Otherwise it might trigger scrolling when it actually isn't
|
|
|
4241 // needed
|
|
|
4242 var holder = $('<div/>').css( scrollX || scrollY ?
|
|
|
4243 {
|
|
|
4244 position: 'absolute',
|
|
|
4245 top: 0,
|
|
|
4246 left: 0,
|
|
|
4247 height: 1,
|
|
|
4248 right: 0,
|
|
|
4249 overflow: 'hidden'
|
|
|
4250 } :
|
|
|
4251 {}
|
|
|
4252 )
|
|
|
4253 .append( tmpTable )
|
|
|
4254 .appendTo( tableContainer );
|
|
|
4255
|
|
|
4256 // When scrolling (X or Y) we want to set the width of the table as
|
|
|
4257 // appropriate. However, when not scrolling leave the table width as it
|
|
|
4258 // is. This results in slightly different, but I think correct behaviour
|
|
|
4259 if ( scrollX && scrollXInner ) {
|
|
|
4260 tmpTable.width( scrollXInner );
|
|
|
4261 }
|
|
|
4262 else if ( scrollX ) {
|
|
|
4263 tmpTable.css( 'width', 'auto' );
|
|
|
4264
|
|
|
4265 if ( tmpTable.width() < tableContainer.clientWidth ) {
|
|
|
4266 tmpTable.width( tableContainer.clientWidth );
|
|
|
4267 }
|
|
|
4268 }
|
|
|
4269 else if ( scrollY ) {
|
|
|
4270 tmpTable.width( tableContainer.clientWidth );
|
|
|
4271 }
|
|
|
4272 else if ( tableWidthAttr ) {
|
|
|
4273 tmpTable.width( tableWidthAttr );
|
|
|
4274 }
|
|
|
4275
|
|
|
4276 // Browsers need a bit of a hand when a width is assigned to any columns
|
|
|
4277 // when x-scrolling as they tend to collapse the table to the min-width,
|
|
|
4278 // even if we sent the column widths. So we need to keep track of what
|
|
|
4279 // the table width should be by summing the user given values, and the
|
|
|
4280 // automatic values
|
|
|
4281 if ( scrollX )
|
|
|
4282 {
|
|
|
4283 var total = 0;
|
|
|
4284
|
|
|
4285 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
|
4286 column = columns[ visibleColumns[i] ];
|
|
|
4287
|
|
|
4288 // Much prefer to use getBoundingClientRect due to its sub-pixel
|
|
|
4289 // resolution, but IE8- do not support the width property.
|
|
|
4290 outerWidth = browser.bBounding ?
|
|
|
4291 headerCells[i].getBoundingClientRect().width :
|
|
|
4292 $(headerCells[i]).outerWidth();
|
|
|
4293
|
|
|
4294 total += column.sWidthOrig === null ?
|
|
|
4295 outerWidth :
|
|
|
4296 parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
|
|
|
4297 }
|
|
|
4298
|
|
|
4299 tmpTable.width( _fnStringToCss( total ) );
|
|
|
4300 table.style.width = _fnStringToCss( total );
|
|
|
4301 }
|
|
|
4302
|
|
|
4303 // Get the width of each column in the constructed table
|
|
|
4304 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
|
4305 column = columns[ visibleColumns[i] ];
|
|
|
4306 width = $(headerCells[i]).width();
|
|
|
4307
|
|
|
4308 if ( width ) {
|
|
|
4309 column.sWidth = _fnStringToCss( width );
|
|
|
4310 }
|
|
|
4311 }
|
|
|
4312
|
|
|
4313 table.style.width = _fnStringToCss( tmpTable.css('width') );
|
|
|
4314
|
|
|
4315 // Finished with the table - ditch it
|
|
|
4316 holder.remove();
|
|
|
4317 }
|
|
|
4318
|
|
|
4319 // If there is a width attr, we want to attach an event listener which
|
|
|
4320 // allows the table sizing to automatically adjust when the window is
|
|
|
4321 // resized. Use the width attr rather than CSS, since we can't know if the
|
|
|
4322 // CSS is a relative value or absolute - DOM read is always px.
|
|
|
4323 if ( tableWidthAttr ) {
|
|
|
4324 table.style.width = _fnStringToCss( tableWidthAttr );
|
|
|
4325 }
|
|
|
4326
|
|
|
4327 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
|
|
|
4328 var bindResize = function () {
|
|
|
4329 $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
|
|
|
4330 _fnAdjustColumnSizing( oSettings );
|
|
|
4331 } ) );
|
|
|
4332 };
|
|
|
4333
|
|
|
4334 // IE6/7 will crash if we bind a resize event handler on page load.
|
|
|
4335 // To be removed in 1.11 which drops IE6/7 support
|
|
|
4336 if ( ie67 ) {
|
|
|
4337 setTimeout( bindResize, 1000 );
|
|
|
4338 }
|
|
|
4339 else {
|
|
|
4340 bindResize();
|
|
|
4341 }
|
|
|
4342
|
|
|
4343 oSettings._reszEvt = true;
|
|
|
4344 }
|
|
|
4345 }
|
|
|
4346
|
|
|
4347
|
|
|
4348 /**
|
|
|
4349 * Throttle the calls to a function. Arguments and context are maintained for
|
|
|
4350 * the throttled function
|
|
|
4351 * @param {function} fn Function to be called
|
|
|
4352 * @param {int} [freq=200] call frequency in mS
|
|
|
4353 * @returns {function} wrapped function
|
|
|
4354 * @memberof DataTable#oApi
|
|
|
4355 */
|
|
|
4356 function _fnThrottle( fn, freq ) {
|
|
|
4357 var
|
|
|
4358 frequency = freq !== undefined ? freq : 200,
|
|
|
4359 last,
|
|
|
4360 timer;
|
|
|
4361
|
|
|
4362 return function () {
|
|
|
4363 var
|
|
|
4364 that = this,
|
|
|
4365 now = +new Date(),
|
|
|
4366 args = arguments;
|
|
|
4367
|
|
|
4368 if ( last && now < last + frequency ) {
|
|
|
4369 clearTimeout( timer );
|
|
|
4370
|
|
|
4371 timer = setTimeout( function () {
|
|
|
4372 last = undefined;
|
|
|
4373 fn.apply( that, args );
|
|
|
4374 }, frequency );
|
|
|
4375 }
|
|
|
4376 else {
|
|
|
4377 last = now;
|
|
|
4378 fn.apply( that, args );
|
|
|
4379 }
|
|
|
4380 };
|
|
|
4381 }
|
|
|
4382
|
|
|
4383
|
|
|
4384 /**
|
|
|
4385 * Convert a CSS unit width to pixels (e.g. 2em)
|
|
|
4386 * @param {string} width width to be converted
|
|
|
4387 * @param {node} parent parent to get the with for (required for relative widths) - optional
|
|
|
4388 * @returns {int} width in pixels
|
|
|
4389 * @memberof DataTable#oApi
|
|
|
4390 */
|
|
|
4391 function _fnConvertToWidth ( width, parent )
|
|
|
4392 {
|
|
|
4393 if ( ! width ) {
|
|
|
4394 return 0;
|
|
|
4395 }
|
|
|
4396
|
|
|
4397 var n = $('<div/>')
|
|
|
4398 .css( 'width', _fnStringToCss( width ) )
|
|
|
4399 .appendTo( parent || document.body );
|
|
|
4400
|
|
|
4401 var val = n[0].offsetWidth;
|
|
|
4402 n.remove();
|
|
|
4403
|
|
|
4404 return val;
|
|
|
4405 }
|
|
|
4406
|
|
|
4407
|
|
|
4408 /**
|
|
|
4409 * Get the widest node
|
|
|
4410 * @param {object} settings dataTables settings object
|
|
|
4411 * @param {int} colIdx column of interest
|
|
|
4412 * @returns {node} widest table node
|
|
|
4413 * @memberof DataTable#oApi
|
|
|
4414 */
|
|
|
4415 function _fnGetWidestNode( settings, colIdx )
|
|
|
4416 {
|
|
|
4417 var idx = _fnGetMaxLenString( settings, colIdx );
|
|
|
4418 if ( idx < 0 ) {
|
|
|
4419 return null;
|
|
|
4420 }
|
|
|
4421
|
|
|
4422 var data = settings.aoData[ idx ];
|
|
|
4423 return ! data.nTr ? // Might not have been created when deferred rendering
|
|
|
4424 $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
|
|
|
4425 data.anCells[ colIdx ];
|
|
|
4426 }
|
|
|
4427
|
|
|
4428
|
|
|
4429 /**
|
|
|
4430 * Get the maximum strlen for each data column
|
|
|
4431 * @param {object} settings dataTables settings object
|
|
|
4432 * @param {int} colIdx column of interest
|
|
|
4433 * @returns {string} max string length for each column
|
|
|
4434 * @memberof DataTable#oApi
|
|
|
4435 */
|
|
|
4436 function _fnGetMaxLenString( settings, colIdx )
|
|
|
4437 {
|
|
|
4438 var s, max=-1, maxIdx = -1;
|
|
|
4439
|
|
|
4440 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
|
4441 s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
|
|
|
4442 s = s.replace( __re_html_remove, '' );
|
|
|
4443
|
|
|
4444 if ( s.length > max ) {
|
|
|
4445 max = s.length;
|
|
|
4446 maxIdx = i;
|
|
|
4447 }
|
|
|
4448 }
|
|
|
4449
|
|
|
4450 return maxIdx;
|
|
|
4451 }
|
|
|
4452
|
|
|
4453
|
|
|
4454 /**
|
|
|
4455 * Append a CSS unit (only if required) to a string
|
|
|
4456 * @param {string} value to css-ify
|
|
|
4457 * @returns {string} value with css unit
|
|
|
4458 * @memberof DataTable#oApi
|
|
|
4459 */
|
|
|
4460 function _fnStringToCss( s )
|
|
|
4461 {
|
|
|
4462 if ( s === null ) {
|
|
|
4463 return '0px';
|
|
|
4464 }
|
|
|
4465
|
|
|
4466 if ( typeof s == 'number' ) {
|
|
|
4467 return s < 0 ?
|
|
|
4468 '0px' :
|
|
|
4469 s+'px';
|
|
|
4470 }
|
|
|
4471
|
|
|
4472 // Check it has a unit character already
|
|
|
4473 return s.match(/\d$/) ?
|
|
|
4474 s+'px' :
|
|
|
4475 s;
|
|
|
4476 }
|
|
|
4477
|
|
|
4478
|
|
|
4479
|
|
|
4480 function _fnSortFlatten ( settings )
|
|
|
4481 {
|
|
|
4482 var
|
|
|
4483 i, iLen, k, kLen,
|
|
|
4484 aSort = [],
|
|
|
4485 aiOrig = [],
|
|
|
4486 aoColumns = settings.aoColumns,
|
|
|
4487 aDataSort, iCol, sType, srcCol,
|
|
|
4488 fixed = settings.aaSortingFixed,
|
|
|
4489 fixedObj = $.isPlainObject( fixed ),
|
|
|
4490 nestedSort = [],
|
|
|
4491 add = function ( a ) {
|
|
|
4492 if ( a.length && ! $.isArray( a[0] ) ) {
|
|
|
4493 // 1D array
|
|
|
4494 nestedSort.push( a );
|
|
|
4495 }
|
|
|
4496 else {
|
|
|
4497 // 2D array
|
|
|
4498 $.merge( nestedSort, a );
|
|
|
4499 }
|
|
|
4500 };
|
|
|
4501
|
|
|
4502 // Build the sort array, with pre-fix and post-fix options if they have been
|
|
|
4503 // specified
|
|
|
4504 if ( $.isArray( fixed ) ) {
|
|
|
4505 add( fixed );
|
|
|
4506 }
|
|
|
4507
|
|
|
4508 if ( fixedObj && fixed.pre ) {
|
|
|
4509 add( fixed.pre );
|
|
|
4510 }
|
|
|
4511
|
|
|
4512 add( settings.aaSorting );
|
|
|
4513
|
|
|
4514 if (fixedObj && fixed.post ) {
|
|
|
4515 add( fixed.post );
|
|
|
4516 }
|
|
|
4517
|
|
|
4518 for ( i=0 ; i<nestedSort.length ; i++ )
|
|
|
4519 {
|
|
|
4520 srcCol = nestedSort[i][0];
|
|
|
4521 aDataSort = aoColumns[ srcCol ].aDataSort;
|
|
|
4522
|
|
|
4523 for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
|
|
|
4524 {
|
|
|
4525 iCol = aDataSort[k];
|
|
|
4526 sType = aoColumns[ iCol ].sType || 'string';
|
|
|
4527
|
|
|
4528 if ( nestedSort[i]._idx === undefined ) {
|
|
|
4529 nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
|
|
|
4530 }
|
|
|
4531
|
|
|
4532 aSort.push( {
|
|
|
4533 src: srcCol,
|
|
|
4534 col: iCol,
|
|
|
4535 dir: nestedSort[i][1],
|
|
|
4536 index: nestedSort[i]._idx,
|
|
|
4537 type: sType,
|
|
|
4538 formatter: DataTable.ext.type.order[ sType+"-pre" ]
|
|
|
4539 } );
|
|
|
4540 }
|
|
|
4541 }
|
|
|
4542
|
|
|
4543 return aSort;
|
|
|
4544 }
|
|
|
4545
|
|
|
4546 /**
|
|
|
4547 * Change the order of the table
|
|
|
4548 * @param {object} oSettings dataTables settings object
|
|
|
4549 * @memberof DataTable#oApi
|
|
|
4550 * @todo This really needs split up!
|
|
|
4551 */
|
|
|
4552 function _fnSort ( oSettings )
|
|
|
4553 {
|
|
|
4554 var
|
|
|
4555 i, ien, iLen, j, jLen, k, kLen,
|
|
|
4556 sDataType, nTh,
|
|
|
4557 aiOrig = [],
|
|
|
4558 oExtSort = DataTable.ext.type.order,
|
|
|
4559 aoData = oSettings.aoData,
|
|
|
4560 aoColumns = oSettings.aoColumns,
|
|
|
4561 aDataSort, data, iCol, sType, oSort,
|
|
|
4562 formatters = 0,
|
|
|
4563 sortCol,
|
|
|
4564 displayMaster = oSettings.aiDisplayMaster,
|
|
|
4565 aSort;
|
|
|
4566
|
|
|
4567 // Resolve any column types that are unknown due to addition or invalidation
|
|
|
4568 // @todo Can this be moved into a 'data-ready' handler which is called when
|
|
|
4569 // data is going to be used in the table?
|
|
|
4570 _fnColumnTypes( oSettings );
|
|
|
4571
|
|
|
4572 aSort = _fnSortFlatten( oSettings );
|
|
|
4573
|
|
|
4574 for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
|
|
|
4575 sortCol = aSort[i];
|
|
|
4576
|
|
|
4577 // Track if we can use the fast sort algorithm
|
|
|
4578 if ( sortCol.formatter ) {
|
|
|
4579 formatters++;
|
|
|
4580 }
|
|
|
4581
|
|
|
4582 // Load the data needed for the sort, for each cell
|
|
|
4583 _fnSortData( oSettings, sortCol.col );
|
|
|
4584 }
|
|
|
4585
|
|
|
4586 /* No sorting required if server-side or no sorting array */
|
|
|
4587 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
|
|
|
4588 {
|
|
|
4589 // Create a value - key array of the current row positions such that we can use their
|
|
|
4590 // current position during the sort, if values match, in order to perform stable sorting
|
|
|
4591 for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
|
|
|
4592 aiOrig[ displayMaster[i] ] = i;
|
|
|
4593 }
|
|
|
4594
|
|
|
4595 /* Do the sort - here we want multi-column sorting based on a given data source (column)
|
|
|
4596 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
|
|
|
4597 * follow on it's own, but this is what we want (example two column sorting):
|
|
|
4598 * fnLocalSorting = function(a,b){
|
|
|
4599 * var iTest;
|
|
|
4600 * iTest = oSort['string-asc']('data11', 'data12');
|
|
|
4601 * if (iTest !== 0)
|
|
|
4602 * return iTest;
|
|
|
4603 * iTest = oSort['numeric-desc']('data21', 'data22');
|
|
|
4604 * if (iTest !== 0)
|
|
|
4605 * return iTest;
|
|
|
4606 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
|
|
|
4607 * }
|
|
|
4608 * Basically we have a test for each sorting column, if the data in that column is equal,
|
|
|
4609 * test the next column. If all columns match, then we use a numeric sort on the row
|
|
|
4610 * positions in the original data array to provide a stable sort.
|
|
|
4611 *
|
|
|
4612 * Note - I know it seems excessive to have two sorting methods, but the first is around
|
|
|
4613 * 15% faster, so the second is only maintained for backwards compatibility with sorting
|
|
|
4614 * methods which do not have a pre-sort formatting function.
|
|
|
4615 */
|
|
|
4616 if ( formatters === aSort.length ) {
|
|
|
4617 // All sort types have formatting functions
|
|
|
4618 displayMaster.sort( function ( a, b ) {
|
|
|
4619 var
|
|
|
4620 x, y, k, test, sort,
|
|
|
4621 len=aSort.length,
|
|
|
4622 dataA = aoData[a]._aSortData,
|
|
|
4623 dataB = aoData[b]._aSortData;
|
|
|
4624
|
|
|
4625 for ( k=0 ; k<len ; k++ ) {
|
|
|
4626 sort = aSort[k];
|
|
|
4627
|
|
|
4628 x = dataA[ sort.col ];
|
|
|
4629 y = dataB[ sort.col ];
|
|
|
4630
|
|
|
4631 test = x<y ? -1 : x>y ? 1 : 0;
|
|
|
4632 if ( test !== 0 ) {
|
|
|
4633 return sort.dir === 'asc' ? test : -test;
|
|
|
4634 }
|
|
|
4635 }
|
|
|
4636
|
|
|
4637 x = aiOrig[a];
|
|
|
4638 y = aiOrig[b];
|
|
|
4639 return x<y ? -1 : x>y ? 1 : 0;
|
|
|
4640 } );
|
|
|
4641 }
|
|
|
4642 else {
|
|
|
4643 // Depreciated - remove in 1.11 (providing a plug-in option)
|
|
|
4644 // Not all sort types have formatting methods, so we have to call their sorting
|
|
|
4645 // methods.
|
|
|
4646 displayMaster.sort( function ( a, b ) {
|
|
|
4647 var
|
|
|
4648 x, y, k, l, test, sort, fn,
|
|
|
4649 len=aSort.length,
|
|
|
4650 dataA = aoData[a]._aSortData,
|
|
|
4651 dataB = aoData[b]._aSortData;
|
|
|
4652
|
|
|
4653 for ( k=0 ; k<len ; k++ ) {
|
|
|
4654 sort = aSort[k];
|
|
|
4655
|
|
|
4656 x = dataA[ sort.col ];
|
|
|
4657 y = dataB[ sort.col ];
|
|
|
4658
|
|
|
4659 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
|
|
|
4660 test = fn( x, y );
|
|
|
4661 if ( test !== 0 ) {
|
|
|
4662 return test;
|
|
|
4663 }
|
|
|
4664 }
|
|
|
4665
|
|
|
4666 x = aiOrig[a];
|
|
|
4667 y = aiOrig[b];
|
|
|
4668 return x<y ? -1 : x>y ? 1 : 0;
|
|
|
4669 } );
|
|
|
4670 }
|
|
|
4671 }
|
|
|
4672
|
|
|
4673 /* Tell the draw function that we have sorted the data */
|
|
|
4674 oSettings.bSorted = true;
|
|
|
4675 }
|
|
|
4676
|
|
|
4677
|
|
|
4678 function _fnSortAria ( settings )
|
|
|
4679 {
|
|
|
4680 var label;
|
|
|
4681 var nextSort;
|
|
|
4682 var columns = settings.aoColumns;
|
|
|
4683 var aSort = _fnSortFlatten( settings );
|
|
|
4684 var oAria = settings.oLanguage.oAria;
|
|
|
4685
|
|
|
4686 // ARIA attributes - need to loop all columns, to update all (removing old
|
|
|
4687 // attributes as needed)
|
|
|
4688 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
|
|
|
4689 {
|
|
|
4690 var col = columns[i];
|
|
|
4691 var asSorting = col.asSorting;
|
|
|
4692 var sTitle = col.sTitle.replace( /<.*?>/g, "" );
|
|
|
4693 var th = col.nTh;
|
|
|
4694
|
|
|
4695 // IE7 is throwing an error when setting these properties with jQuery's
|
|
|
4696 // attr() and removeAttr() methods...
|
|
|
4697 th.removeAttribute('aria-sort');
|
|
|
4698
|
|
|
4699 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
|
|
|
4700 if ( col.bSortable ) {
|
|
|
4701 if ( aSort.length > 0 && aSort[0].col == i ) {
|
|
|
4702 th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
|
|
|
4703 nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
|
|
|
4704 }
|
|
|
4705 else {
|
|
|
4706 nextSort = asSorting[0];
|
|
|
4707 }
|
|
|
4708
|
|
|
4709 label = sTitle + ( nextSort === "asc" ?
|
|
|
4710 oAria.sSortAscending :
|
|
|
4711 oAria.sSortDescending
|
|
|
4712 );
|
|
|
4713 }
|
|
|
4714 else {
|
|
|
4715 label = sTitle;
|
|
|
4716 }
|
|
|
4717
|
|
|
4718 th.setAttribute('aria-label', label);
|
|
|
4719 }
|
|
|
4720 }
|
|
|
4721
|
|
|
4722
|
|
|
4723 /**
|
|
|
4724 * Function to run on user sort request
|
|
|
4725 * @param {object} settings dataTables settings object
|
|
|
4726 * @param {node} attachTo node to attach the handler to
|
|
|
4727 * @param {int} colIdx column sorting index
|
|
|
4728 * @param {boolean} [append=false] Append the requested sort to the existing
|
|
|
4729 * sort if true (i.e. multi-column sort)
|
|
|
4730 * @param {function} [callback] callback function
|
|
|
4731 * @memberof DataTable#oApi
|
|
|
4732 */
|
|
|
4733 function _fnSortListener ( settings, colIdx, append, callback )
|
|
|
4734 {
|
|
|
4735 var col = settings.aoColumns[ colIdx ];
|
|
|
4736 var sorting = settings.aaSorting;
|
|
|
4737 var asSorting = col.asSorting;
|
|
|
4738 var nextSortIdx;
|
|
|
4739 var next = function ( a, overflow ) {
|
|
|
4740 var idx = a._idx;
|
|
|
4741 if ( idx === undefined ) {
|
|
|
4742 idx = $.inArray( a[1], asSorting );
|
|
|
4743 }
|
|
|
4744
|
|
|
4745 return idx+1 < asSorting.length ?
|
|
|
4746 idx+1 :
|
|
|
4747 overflow ?
|
|
|
4748 null :
|
|
|
4749 0;
|
|
|
4750 };
|
|
|
4751
|
|
|
4752 // Convert to 2D array if needed
|
|
|
4753 if ( typeof sorting[0] === 'number' ) {
|
|
|
4754 sorting = settings.aaSorting = [ sorting ];
|
|
|
4755 }
|
|
|
4756
|
|
|
4757 // If appending the sort then we are multi-column sorting
|
|
|
4758 if ( append && settings.oFeatures.bSortMulti ) {
|
|
|
4759 // Are we already doing some kind of sort on this column?
|
|
|
4760 var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
|
|
|
4761
|
|
|
4762 if ( sortIdx !== -1 ) {
|
|
|
4763 // Yes, modify the sort
|
|
|
4764 nextSortIdx = next( sorting[sortIdx], true );
|
|
|
4765
|
|
|
4766 if ( nextSortIdx === null && sorting.length === 1 ) {
|
|
|
4767 nextSortIdx = 0; // can't remove sorting completely
|
|
|
4768 }
|
|
|
4769
|
|
|
4770 if ( nextSortIdx === null ) {
|
|
|
4771 sorting.splice( sortIdx, 1 );
|
|
|
4772 }
|
|
|
4773 else {
|
|
|
4774 sorting[sortIdx][1] = asSorting[ nextSortIdx ];
|
|
|
4775 sorting[sortIdx]._idx = nextSortIdx;
|
|
|
4776 }
|
|
|
4777 }
|
|
|
4778 else {
|
|
|
4779 // No sort on this column yet
|
|
|
4780 sorting.push( [ colIdx, asSorting[0], 0 ] );
|
|
|
4781 sorting[sorting.length-1]._idx = 0;
|
|
|
4782 }
|
|
|
4783 }
|
|
|
4784 else if ( sorting.length && sorting[0][0] == colIdx ) {
|
|
|
4785 // Single column - already sorting on this column, modify the sort
|
|
|
4786 nextSortIdx = next( sorting[0] );
|
|
|
4787
|
|
|
4788 sorting.length = 1;
|
|
|
4789 sorting[0][1] = asSorting[ nextSortIdx ];
|
|
|
4790 sorting[0]._idx = nextSortIdx;
|
|
|
4791 }
|
|
|
4792 else {
|
|
|
4793 // Single column - sort only on this column
|
|
|
4794 sorting.length = 0;
|
|
|
4795 sorting.push( [ colIdx, asSorting[0] ] );
|
|
|
4796 sorting[0]._idx = 0;
|
|
|
4797 }
|
|
|
4798
|
|
|
4799 // Run the sort by calling a full redraw
|
|
|
4800 _fnReDraw( settings );
|
|
|
4801
|
|
|
4802 // callback used for async user interaction
|
|
|
4803 if ( typeof callback == 'function' ) {
|
|
|
4804 callback( settings );
|
|
|
4805 }
|
|
|
4806 }
|
|
|
4807
|
|
|
4808
|
|
|
4809 /**
|
|
|
4810 * Attach a sort handler (click) to a node
|
|
|
4811 * @param {object} settings dataTables settings object
|
|
|
4812 * @param {node} attachTo node to attach the handler to
|
|
|
4813 * @param {int} colIdx column sorting index
|
|
|
4814 * @param {function} [callback] callback function
|
|
|
4815 * @memberof DataTable#oApi
|
|
|
4816 */
|
|
|
4817 function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
|
|
|
4818 {
|
|
|
4819 var col = settings.aoColumns[ colIdx ];
|
|
|
4820
|
|
|
4821 _fnBindAction( attachTo, {}, function (e) {
|
|
|
4822 /* If the column is not sortable - don't to anything */
|
|
|
4823 if ( col.bSortable === false ) {
|
|
|
4824 return;
|
|
|
4825 }
|
|
|
4826
|
|
|
4827 // If processing is enabled use a timeout to allow the processing
|
|
|
4828 // display to be shown - otherwise to it synchronously
|
|
|
4829 if ( settings.oFeatures.bProcessing ) {
|
|
|
4830 _fnProcessingDisplay( settings, true );
|
|
|
4831
|
|
|
4832 setTimeout( function() {
|
|
|
4833 _fnSortListener( settings, colIdx, e.shiftKey, callback );
|
|
|
4834
|
|
|
4835 // In server-side processing, the draw callback will remove the
|
|
|
4836 // processing display
|
|
|
4837 if ( _fnDataSource( settings ) !== 'ssp' ) {
|
|
|
4838 _fnProcessingDisplay( settings, false );
|
|
|
4839 }
|
|
|
4840 }, 0 );
|
|
|
4841 }
|
|
|
4842 else {
|
|
|
4843 _fnSortListener( settings, colIdx, e.shiftKey, callback );
|
|
|
4844 }
|
|
|
4845 } );
|
|
|
4846 }
|
|
|
4847
|
|
|
4848
|
|
|
4849 /**
|
|
|
4850 * Set the sorting classes on table's body, Note: it is safe to call this function
|
|
|
4851 * when bSort and bSortClasses are false
|
|
|
4852 * @param {object} oSettings dataTables settings object
|
|
|
4853 * @memberof DataTable#oApi
|
|
|
4854 */
|
|
|
4855 function _fnSortingClasses( settings )
|
|
|
4856 {
|
|
|
4857 var oldSort = settings.aLastSort;
|
|
|
4858 var sortClass = settings.oClasses.sSortColumn;
|
|
|
4859 var sort = _fnSortFlatten( settings );
|
|
|
4860 var features = settings.oFeatures;
|
|
|
4861 var i, ien, colIdx;
|
|
|
4862
|
|
|
4863 if ( features.bSort && features.bSortClasses ) {
|
|
|
4864 // Remove old sorting classes
|
|
|
4865 for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
|
|
|
4866 colIdx = oldSort[i].src;
|
|
|
4867
|
|
|
4868 // Remove column sorting
|
|
|
4869 $( _pluck( settings.aoData, 'anCells', colIdx ) )
|
|
|
4870 .removeClass( sortClass + (i<2 ? i+1 : 3) );
|
|
|
4871 }
|
|
|
4872
|
|
|
4873 // Add new column sorting
|
|
|
4874 for ( i=0, ien=sort.length ; i<ien ; i++ ) {
|
|
|
4875 colIdx = sort[i].src;
|
|
|
4876
|
|
|
4877 $( _pluck( settings.aoData, 'anCells', colIdx ) )
|
|
|
4878 .addClass( sortClass + (i<2 ? i+1 : 3) );
|
|
|
4879 }
|
|
|
4880 }
|
|
|
4881
|
|
|
4882 settings.aLastSort = sort;
|
|
|
4883 }
|
|
|
4884
|
|
|
4885
|
|
|
4886 // Get the data to sort a column, be it from cache, fresh (populating the
|
|
|
4887 // cache), or from a sort formatter
|
|
|
4888 function _fnSortData( settings, idx )
|
|
|
4889 {
|
|
|
4890 // Custom sorting function - provided by the sort data type
|
|
|
4891 var column = settings.aoColumns[ idx ];
|
|
|
4892 var customSort = DataTable.ext.order[ column.sSortDataType ];
|
|
|
4893 var customData;
|
|
|
4894
|
|
|
4895 if ( customSort ) {
|
|
|
4896 customData = customSort.call( settings.oInstance, settings, idx,
|
|
|
4897 _fnColumnIndexToVisible( settings, idx )
|
|
|
4898 );
|
|
|
4899 }
|
|
|
4900
|
|
|
4901 // Use / populate cache
|
|
|
4902 var row, cellData;
|
|
|
4903 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
|
|
|
4904
|
|
|
4905 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
|
4906 row = settings.aoData[i];
|
|
|
4907
|
|
|
4908 if ( ! row._aSortData ) {
|
|
|
4909 row._aSortData = [];
|
|
|
4910 }
|
|
|
4911
|
|
|
4912 if ( ! row._aSortData[idx] || customSort ) {
|
|
|
4913 cellData = customSort ?
|
|
|
4914 customData[i] : // If there was a custom sort function, use data from there
|
|
|
4915 _fnGetCellData( settings, i, idx, 'sort' );
|
|
|
4916
|
|
|
4917 row._aSortData[ idx ] = formatter ?
|
|
|
4918 formatter( cellData ) :
|
|
|
4919 cellData;
|
|
|
4920 }
|
|
|
4921 }
|
|
|
4922 }
|
|
|
4923
|
|
|
4924
|
|
|
4925
|
|
|
4926 /**
|
|
|
4927 * Save the state of a table
|
|
|
4928 * @param {object} oSettings dataTables settings object
|
|
|
4929 * @memberof DataTable#oApi
|
|
|
4930 */
|
|
|
4931 function _fnSaveState ( settings )
|
|
|
4932 {
|
|
|
4933 if ( !settings.oFeatures.bStateSave || settings.bDestroying )
|
|
|
4934 {
|
|
|
4935 return;
|
|
|
4936 }
|
|
|
4937
|
|
|
4938 /* Store the interesting variables */
|
|
|
4939 var state = {
|
|
|
4940 time: +new Date(),
|
|
|
4941 start: settings._iDisplayStart,
|
|
|
4942 length: settings._iDisplayLength,
|
|
|
4943 order: $.extend( true, [], settings.aaSorting ),
|
|
|
4944 search: _fnSearchToCamel( settings.oPreviousSearch ),
|
|
|
4945 columns: $.map( settings.aoColumns, function ( col, i ) {
|
|
|
4946 return {
|
|
|
4947 visible: col.bVisible,
|
|
|
4948 search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
|
|
|
4949 };
|
|
|
4950 } )
|
|
|
4951 };
|
|
|
4952
|
|
|
4953 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
|
|
|
4954
|
|
|
4955 settings.oSavedState = state;
|
|
|
4956 settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
|
|
|
4957 }
|
|
|
4958
|
|
|
4959
|
|
|
4960 /**
|
|
|
4961 * Attempt to load a saved table state
|
|
|
4962 * @param {object} oSettings dataTables settings object
|
|
|
4963 * @param {object} oInit DataTables init object so we can override settings
|
|
|
4964 * @memberof DataTable#oApi
|
|
|
4965 */
|
|
|
4966 function _fnLoadState ( settings, oInit )
|
|
|
4967 {
|
|
|
4968 var i, ien;
|
|
|
4969 var columns = settings.aoColumns;
|
|
|
4970
|
|
|
4971 if ( ! settings.oFeatures.bStateSave ) {
|
|
|
4972 return;
|
|
|
4973 }
|
|
|
4974
|
|
|
4975 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
|
|
|
4976 if ( ! state || ! state.time ) {
|
|
|
4977 return;
|
|
|
4978 }
|
|
|
4979
|
|
|
4980 /* Allow custom and plug-in manipulation functions to alter the saved data set and
|
|
|
4981 * cancelling of loading by returning false
|
|
|
4982 */
|
|
|
4983 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
|
|
|
4984 if ( $.inArray( false, abStateLoad ) !== -1 ) {
|
|
|
4985 return;
|
|
|
4986 }
|
|
|
4987
|
|
|
4988 /* Reject old data */
|
|
|
4989 var duration = settings.iStateDuration;
|
|
|
4990 if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
|
|
|
4991 return;
|
|
|
4992 }
|
|
|
4993
|
|
|
4994 // Number of columns have changed - all bets are off, no restore of settings
|
|
|
4995 if ( columns.length !== state.columns.length ) {
|
|
|
4996 return;
|
|
|
4997 }
|
|
|
4998
|
|
|
4999 // Store the saved state so it might be accessed at any time
|
|
|
5000 settings.oLoadedState = $.extend( true, {}, state );
|
|
|
5001
|
|
|
5002 // Restore key features - todo - for 1.11 this needs to be done by
|
|
|
5003 // subscribed events
|
|
|
5004 if ( state.start !== undefined ) {
|
|
|
5005 settings._iDisplayStart = state.start;
|
|
|
5006 settings.iInitDisplayStart = state.start;
|
|
|
5007 }
|
|
|
5008 if ( state.length !== undefined ) {
|
|
|
5009 settings._iDisplayLength = state.length;
|
|
|
5010 }
|
|
|
5011
|
|
|
5012 // Order
|
|
|
5013 if ( state.order !== undefined ) {
|
|
|
5014 settings.aaSorting = [];
|
|
|
5015 $.each( state.order, function ( i, col ) {
|
|
|
5016 settings.aaSorting.push( col[0] >= columns.length ?
|
|
|
5017 [ 0, col[1] ] :
|
|
|
5018 col
|
|
|
5019 );
|
|
|
5020 } );
|
|
|
5021 }
|
|
|
5022
|
|
|
5023 // Search
|
|
|
5024 if ( state.search !== undefined ) {
|
|
|
5025 $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
|
|
|
5026 }
|
|
|
5027
|
|
|
5028 // Columns
|
|
|
5029 for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
|
|
|
5030 var col = state.columns[i];
|
|
|
5031
|
|
|
5032 // Visibility
|
|
|
5033 if ( col.visible !== undefined ) {
|
|
|
5034 columns[i].bVisible = col.visible;
|
|
|
5035 }
|
|
|
5036
|
|
|
5037 // Search
|
|
|
5038 if ( col.search !== undefined ) {
|
|
|
5039 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
|
|
|
5040 }
|
|
|
5041 }
|
|
|
5042
|
|
|
5043 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
|
|
|
5044 }
|
|
|
5045
|
|
|
5046
|
|
|
5047 /**
|
|
|
5048 * Return the settings object for a particular table
|
|
|
5049 * @param {node} table table we are using as a dataTable
|
|
|
5050 * @returns {object} Settings object - or null if not found
|
|
|
5051 * @memberof DataTable#oApi
|
|
|
5052 */
|
|
|
5053 function _fnSettingsFromNode ( table )
|
|
|
5054 {
|
|
|
5055 var settings = DataTable.settings;
|
|
|
5056 var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
|
|
|
5057
|
|
|
5058 return idx !== -1 ?
|
|
|
5059 settings[ idx ] :
|
|
|
5060 null;
|
|
|
5061 }
|
|
|
5062
|
|
|
5063
|
|
|
5064 /**
|
|
|
5065 * Log an error message
|
|
|
5066 * @param {object} settings dataTables settings object
|
|
|
5067 * @param {int} level log error messages, or display them to the user
|
|
|
5068 * @param {string} msg error message
|
|
|
5069 * @param {int} tn Technical note id to get more information about the error.
|
|
|
5070 * @memberof DataTable#oApi
|
|
|
5071 */
|
|
|
5072 function _fnLog( settings, level, msg, tn )
|
|
|
5073 {
|
|
|
5074 msg = 'DataTables warning: '+
|
|
|
5075 (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
|
|
|
5076
|
|
|
5077 if ( tn ) {
|
|
|
5078 msg += '. For more information about this error, please see '+
|
|
|
5079 'http://datatables.net/tn/'+tn;
|
|
|
5080 }
|
|
|
5081
|
|
|
5082 if ( ! level ) {
|
|
|
5083 // Backwards compatibility pre 1.10
|
|
|
5084 var ext = DataTable.ext;
|
|
|
5085 var type = ext.sErrMode || ext.errMode;
|
|
|
5086
|
|
|
5087 if ( settings ) {
|
|
|
5088 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
|
|
|
5089 }
|
|
|
5090
|
|
|
5091 if ( type == 'alert' ) {
|
|
|
5092 alert( msg );
|
|
|
5093 }
|
|
|
5094 else if ( type == 'throw' ) {
|
|
|
5095 throw new Error(msg);
|
|
|
5096 }
|
|
|
5097 else if ( typeof type == 'function' ) {
|
|
|
5098 type( settings, tn, msg );
|
|
|
5099 }
|
|
|
5100 }
|
|
|
5101 else if ( window.console && console.log ) {
|
|
|
5102 console.log( msg );
|
|
|
5103 }
|
|
|
5104 }
|
|
|
5105
|
|
|
5106
|
|
|
5107 /**
|
|
|
5108 * See if a property is defined on one object, if so assign it to the other object
|
|
|
5109 * @param {object} ret target object
|
|
|
5110 * @param {object} src source object
|
|
|
5111 * @param {string} name property
|
|
|
5112 * @param {string} [mappedName] name to map too - optional, name used if not given
|
|
|
5113 * @memberof DataTable#oApi
|
|
|
5114 */
|
|
|
5115 function _fnMap( ret, src, name, mappedName )
|
|
|
5116 {
|
|
|
5117 if ( $.isArray( name ) ) {
|
|
|
5118 $.each( name, function (i, val) {
|
|
|
5119 if ( $.isArray( val ) ) {
|
|
|
5120 _fnMap( ret, src, val[0], val[1] );
|
|
|
5121 }
|
|
|
5122 else {
|
|
|
5123 _fnMap( ret, src, val );
|
|
|
5124 }
|
|
|
5125 } );
|
|
|
5126
|
|
|
5127 return;
|
|
|
5128 }
|
|
|
5129
|
|
|
5130 if ( mappedName === undefined ) {
|
|
|
5131 mappedName = name;
|
|
|
5132 }
|
|
|
5133
|
|
|
5134 if ( src[name] !== undefined ) {
|
|
|
5135 ret[mappedName] = src[name];
|
|
|
5136 }
|
|
|
5137 }
|
|
|
5138
|
|
|
5139
|
|
|
5140 /**
|
|
|
5141 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
|
|
|
5142 * shallow copy arrays. The reason we need to do this, is that we don't want to
|
|
|
5143 * deep copy array init values (such as aaSorting) since the dev wouldn't be
|
|
|
5144 * able to override them, but we do want to deep copy arrays.
|
|
|
5145 * @param {object} out Object to extend
|
|
|
5146 * @param {object} extender Object from which the properties will be applied to
|
|
|
5147 * out
|
|
|
5148 * @param {boolean} breakRefs If true, then arrays will be sliced to take an
|
|
|
5149 * independent copy with the exception of the `data` or `aaData` parameters
|
|
|
5150 * if they are present. This is so you can pass in a collection to
|
|
|
5151 * DataTables and have that used as your data source without breaking the
|
|
|
5152 * references
|
|
|
5153 * @returns {object} out Reference, just for convenience - out === the return.
|
|
|
5154 * @memberof DataTable#oApi
|
|
|
5155 * @todo This doesn't take account of arrays inside the deep copied objects.
|
|
|
5156 */
|
|
|
5157 function _fnExtend( out, extender, breakRefs )
|
|
|
5158 {
|
|
|
5159 var val;
|
|
|
5160
|
|
|
5161 for ( var prop in extender ) {
|
|
|
5162 if ( extender.hasOwnProperty(prop) ) {
|
|
|
5163 val = extender[prop];
|
|
|
5164
|
|
|
5165 if ( $.isPlainObject( val ) ) {
|
|
|
5166 if ( ! $.isPlainObject( out[prop] ) ) {
|
|
|
5167 out[prop] = {};
|
|
|
5168 }
|
|
|
5169 $.extend( true, out[prop], val );
|
|
|
5170 }
|
|
|
5171 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
|
|
|
5172 out[prop] = val.slice();
|
|
|
5173 }
|
|
|
5174 else {
|
|
|
5175 out[prop] = val;
|
|
|
5176 }
|
|
|
5177 }
|
|
|
5178 }
|
|
|
5179
|
|
|
5180 return out;
|
|
|
5181 }
|
|
|
5182
|
|
|
5183
|
|
|
5184 /**
|
|
|
5185 * Bind an event handers to allow a click or return key to activate the callback.
|
|
|
5186 * This is good for accessibility since a return on the keyboard will have the
|
|
|
5187 * same effect as a click, if the element has focus.
|
|
|
5188 * @param {element} n Element to bind the action to
|
|
|
5189 * @param {object} oData Data object to pass to the triggered function
|
|
|
5190 * @param {function} fn Callback function for when the event is triggered
|
|
|
5191 * @memberof DataTable#oApi
|
|
|
5192 */
|
|
|
5193 function _fnBindAction( n, oData, fn )
|
|
|
5194 {
|
|
|
5195 $(n)
|
|
|
5196 .bind( 'click.DT', oData, function (e) {
|
|
|
5197 n.blur(); // Remove focus outline for mouse users
|
|
|
5198 fn(e);
|
|
|
5199 } )
|
|
|
5200 .bind( 'keypress.DT', oData, function (e){
|
|
|
5201 if ( e.which === 13 ) {
|
|
|
5202 e.preventDefault();
|
|
|
5203 fn(e);
|
|
|
5204 }
|
|
|
5205 } )
|
|
|
5206 .bind( 'selectstart.DT', function () {
|
|
|
5207 /* Take the brutal approach to cancelling text selection */
|
|
|
5208 return false;
|
|
|
5209 } );
|
|
|
5210 }
|
|
|
5211
|
|
|
5212
|
|
|
5213 /**
|
|
|
5214 * Register a callback function. Easily allows a callback function to be added to
|
|
|
5215 * an array store of callback functions that can then all be called together.
|
|
|
5216 * @param {object} oSettings dataTables settings object
|
|
|
5217 * @param {string} sStore Name of the array storage for the callbacks in oSettings
|
|
|
5218 * @param {function} fn Function to be called back
|
|
|
5219 * @param {string} sName Identifying name for the callback (i.e. a label)
|
|
|
5220 * @memberof DataTable#oApi
|
|
|
5221 */
|
|
|
5222 function _fnCallbackReg( oSettings, sStore, fn, sName )
|
|
|
5223 {
|
|
|
5224 if ( fn )
|
|
|
5225 {
|
|
|
5226 oSettings[sStore].push( {
|
|
|
5227 "fn": fn,
|
|
|
5228 "sName": sName
|
|
|
5229 } );
|
|
|
5230 }
|
|
|
5231 }
|
|
|
5232
|
|
|
5233
|
|
|
5234 /**
|
|
|
5235 * Fire callback functions and trigger events. Note that the loop over the
|
|
|
5236 * callback array store is done backwards! Further note that you do not want to
|
|
|
5237 * fire off triggers in time sensitive applications (for example cell creation)
|
|
|
5238 * as its slow.
|
|
|
5239 * @param {object} settings dataTables settings object
|
|
|
5240 * @param {string} callbackArr Name of the array storage for the callbacks in
|
|
|
5241 * oSettings
|
|
|
5242 * @param {string} eventName Name of the jQuery custom event to trigger. If
|
|
|
5243 * null no trigger is fired
|
|
|
5244 * @param {array} args Array of arguments to pass to the callback function /
|
|
|
5245 * trigger
|
|
|
5246 * @memberof DataTable#oApi
|
|
|
5247 */
|
|
|
5248 function _fnCallbackFire( settings, callbackArr, eventName, args )
|
|
|
5249 {
|
|
|
5250 var ret = [];
|
|
|
5251
|
|
|
5252 if ( callbackArr ) {
|
|
|
5253 ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
|
|
|
5254 return val.fn.apply( settings.oInstance, args );
|
|
|
5255 } );
|
|
|
5256 }
|
|
|
5257
|
|
|
5258 if ( eventName !== null ) {
|
|
|
5259 var e = $.Event( eventName+'.dt' );
|
|
|
5260
|
|
|
5261 $(settings.nTable).trigger( e, args );
|
|
|
5262
|
|
|
5263 ret.push( e.result );
|
|
|
5264 }
|
|
|
5265
|
|
|
5266 return ret;
|
|
|
5267 }
|
|
|
5268
|
|
|
5269
|
|
|
5270 function _fnLengthOverflow ( settings )
|
|
|
5271 {
|
|
|
5272 var
|
|
|
5273 start = settings._iDisplayStart,
|
|
|
5274 end = settings.fnDisplayEnd(),
|
|
|
5275 len = settings._iDisplayLength;
|
|
|
5276
|
|
|
5277 /* If we have space to show extra rows (backing up from the end point - then do so */
|
|
|
5278 if ( start >= end )
|
|
|
5279 {
|
|
|
5280 start = end - len;
|
|
|
5281 }
|
|
|
5282
|
|
|
5283 // Keep the start record on the current page
|
|
|
5284 start -= (start % len);
|
|
|
5285
|
|
|
5286 if ( len === -1 || start < 0 )
|
|
|
5287 {
|
|
|
5288 start = 0;
|
|
|
5289 }
|
|
|
5290
|
|
|
5291 settings._iDisplayStart = start;
|
|
|
5292 }
|
|
|
5293
|
|
|
5294
|
|
|
5295 function _fnRenderer( settings, type )
|
|
|
5296 {
|
|
|
5297 var renderer = settings.renderer;
|
|
|
5298 var host = DataTable.ext.renderer[type];
|
|
|
5299
|
|
|
5300 if ( $.isPlainObject( renderer ) && renderer[type] ) {
|
|
|
5301 // Specific renderer for this type. If available use it, otherwise use
|
|
|
5302 // the default.
|
|
|
5303 return host[renderer[type]] || host._;
|
|
|
5304 }
|
|
|
5305 else if ( typeof renderer === 'string' ) {
|
|
|
5306 // Common renderer - if there is one available for this type use it,
|
|
|
5307 // otherwise use the default
|
|
|
5308 return host[renderer] || host._;
|
|
|
5309 }
|
|
|
5310
|
|
|
5311 // Use the default
|
|
|
5312 return host._;
|
|
|
5313 }
|
|
|
5314
|
|
|
5315
|
|
|
5316 /**
|
|
|
5317 * Detect the data source being used for the table. Used to simplify the code
|
|
|
5318 * a little (ajax) and to make it compress a little smaller.
|
|
|
5319 *
|
|
|
5320 * @param {object} settings dataTables settings object
|
|
|
5321 * @returns {string} Data source
|
|
|
5322 * @memberof DataTable#oApi
|
|
|
5323 */
|
|
|
5324 function _fnDataSource ( settings )
|
|
|
5325 {
|
|
|
5326 if ( settings.oFeatures.bServerSide ) {
|
|
|
5327 return 'ssp';
|
|
|
5328 }
|
|
|
5329 else if ( settings.ajax || settings.sAjaxSource ) {
|
|
|
5330 return 'ajax';
|
|
|
5331 }
|
|
|
5332 return 'dom';
|
|
|
5333 }
|
|
|
5334
|
|
|
5335
|
|
|
5336 DataTable = function( options )
|
|
|
5337 {
|
|
|
5338 /**
|
|
|
5339 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
|
|
|
5340 * return the resulting jQuery object.
|
|
|
5341 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
|
|
|
5342 * @param {object} [oOpts] Optional parameters for modifying the rows to be included
|
|
|
5343 * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
|
|
|
5344 * criterion ("applied") or all TR elements (i.e. no filter).
|
|
|
5345 * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
|
|
|
5346 * Can be either 'current', whereby the current sorting of the table is used, or
|
|
|
5347 * 'original' whereby the original order the data was read into the table is used.
|
|
|
5348 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
|
|
|
5349 * ("current") or not ("all"). If 'current' is given, then order is assumed to be
|
|
|
5350 * 'current' and filter is 'applied', regardless of what they might be given as.
|
|
|
5351 * @returns {object} jQuery object, filtered by the given selector.
|
|
|
5352 * @dtopt API
|
|
|
5353 * @deprecated Since v1.10
|
|
|
5354 *
|
|
|
5355 * @example
|
|
|
5356 * $(document).ready(function() {
|
|
|
5357 * var oTable = $('#example').dataTable();
|
|
|
5358 *
|
|
|
5359 * // Highlight every second row
|
|
|
5360 * oTable.$('tr:odd').css('backgroundColor', 'blue');
|
|
|
5361 * } );
|
|
|
5362 *
|
|
|
5363 * @example
|
|
|
5364 * $(document).ready(function() {
|
|
|
5365 * var oTable = $('#example').dataTable();
|
|
|
5366 *
|
|
|
5367 * // Filter to rows with 'Webkit' in them, add a background colour and then
|
|
|
5368 * // remove the filter, thus highlighting the 'Webkit' rows only.
|
|
|
5369 * oTable.fnFilter('Webkit');
|
|
|
5370 * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
|
|
|
5371 * oTable.fnFilter('');
|
|
|
5372 * } );
|
|
|
5373 */
|
|
|
5374 this.$ = function ( sSelector, oOpts )
|
|
|
5375 {
|
|
|
5376 return this.api(true).$( sSelector, oOpts );
|
|
|
5377 };
|
|
|
5378
|
|
|
5379
|
|
|
5380 /**
|
|
|
5381 * Almost identical to $ in operation, but in this case returns the data for the matched
|
|
|
5382 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
|
|
|
5383 * rather than any descendants, so the data can be obtained for the row/cell. If matching
|
|
|
5384 * rows are found, the data returned is the original data array/object that was used to
|
|
|
5385 * create the row (or a generated array if from a DOM source).
|
|
|
5386 *
|
|
|
5387 * This method is often useful in-combination with $ where both functions are given the
|
|
|
5388 * same parameters and the array indexes will match identically.
|
|
|
5389 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
|
|
|
5390 * @param {object} [oOpts] Optional parameters for modifying the rows to be included
|
|
|
5391 * @param {string} [oOpts.filter=none] Select elements that meet the current filter
|
|
|
5392 * criterion ("applied") or all elements (i.e. no filter).
|
|
|
5393 * @param {string} [oOpts.order=current] Order of the data in the processed array.
|
|
|
5394 * Can be either 'current', whereby the current sorting of the table is used, or
|
|
|
5395 * 'original' whereby the original order the data was read into the table is used.
|
|
|
5396 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
|
|
|
5397 * ("current") or not ("all"). If 'current' is given, then order is assumed to be
|
|
|
5398 * 'current' and filter is 'applied', regardless of what they might be given as.
|
|
|
5399 * @returns {array} Data for the matched elements. If any elements, as a result of the
|
|
|
5400 * selector, were not TR, TD or TH elements in the DataTable, they will have a null
|
|
|
5401 * entry in the array.
|
|
|
5402 * @dtopt API
|
|
|
5403 * @deprecated Since v1.10
|
|
|
5404 *
|
|
|
5405 * @example
|
|
|
5406 * $(document).ready(function() {
|
|
|
5407 * var oTable = $('#example').dataTable();
|
|
|
5408 *
|
|
|
5409 * // Get the data from the first row in the table
|
|
|
5410 * var data = oTable._('tr:first');
|
|
|
5411 *
|
|
|
5412 * // Do something useful with the data
|
|
|
5413 * alert( "First cell is: "+data[0] );
|
|
|
5414 * } );
|
|
|
5415 *
|
|
|
5416 * @example
|
|
|
5417 * $(document).ready(function() {
|
|
|
5418 * var oTable = $('#example').dataTable();
|
|
|
5419 *
|
|
|
5420 * // Filter to 'Webkit' and get all data for
|
|
|
5421 * oTable.fnFilter('Webkit');
|
|
|
5422 * var data = oTable._('tr', {"search": "applied"});
|
|
|
5423 *
|
|
|
5424 * // Do something with the data
|
|
|
5425 * alert( data.length+" rows matched the search" );
|
|
|
5426 * } );
|
|
|
5427 */
|
|
|
5428 this._ = function ( sSelector, oOpts )
|
|
|
5429 {
|
|
|
5430 return this.api(true).rows( sSelector, oOpts ).data();
|
|
|
5431 };
|
|
|
5432
|
|
|
5433
|
|
|
5434 /**
|
|
|
5435 * Create a DataTables Api instance, with the currently selected tables for
|
|
|
5436 * the Api's context.
|
|
|
5437 * @param {boolean} [traditional=false] Set the API instance's context to be
|
|
|
5438 * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
|
|
|
5439 * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
|
|
|
5440 * or if all tables captured in the jQuery object should be used.
|
|
|
5441 * @return {DataTables.Api}
|
|
|
5442 */
|
|
|
5443 this.api = function ( traditional )
|
|
|
5444 {
|
|
|
5445 return traditional ?
|
|
|
5446 new _Api(
|
|
|
5447 _fnSettingsFromNode( this[ _ext.iApiIndex ] )
|
|
|
5448 ) :
|
|
|
5449 new _Api( this );
|
|
|
5450 };
|
|
|
5451
|
|
|
5452
|
|
|
5453 /**
|
|
|
5454 * Add a single new row or multiple rows of data to the table. Please note
|
|
|
5455 * that this is suitable for client-side processing only - if you are using
|
|
|
5456 * server-side processing (i.e. "bServerSide": true), then to add data, you
|
|
|
5457 * must add it to the data source, i.e. the server-side, through an Ajax call.
|
|
|
5458 * @param {array|object} data The data to be added to the table. This can be:
|
|
|
5459 * <ul>
|
|
|
5460 * <li>1D array of data - add a single row with the data provided</li>
|
|
|
5461 * <li>2D array of arrays - add multiple rows in a single call</li>
|
|
|
5462 * <li>object - data object when using <i>mData</i></li>
|
|
|
5463 * <li>array of objects - multiple data objects when using <i>mData</i></li>
|
|
|
5464 * </ul>
|
|
|
5465 * @param {bool} [redraw=true] redraw the table or not
|
|
|
5466 * @returns {array} An array of integers, representing the list of indexes in
|
|
|
5467 * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
|
|
|
5468 * the table.
|
|
|
5469 * @dtopt API
|
|
|
5470 * @deprecated Since v1.10
|
|
|
5471 *
|
|
|
5472 * @example
|
|
|
5473 * // Global var for counter
|
|
|
5474 * var giCount = 2;
|
|
|
5475 *
|
|
|
5476 * $(document).ready(function() {
|
|
|
5477 * $('#example').dataTable();
|
|
|
5478 * } );
|
|
|
5479 *
|
|
|
5480 * function fnClickAddRow() {
|
|
|
5481 * $('#example').dataTable().fnAddData( [
|
|
|
5482 * giCount+".1",
|
|
|
5483 * giCount+".2",
|
|
|
5484 * giCount+".3",
|
|
|
5485 * giCount+".4" ]
|
|
|
5486 * );
|
|
|
5487 *
|
|
|
5488 * giCount++;
|
|
|
5489 * }
|
|
|
5490 */
|
|
|
5491 this.fnAddData = function( data, redraw )
|
|
|
5492 {
|
|
|
5493 var api = this.api( true );
|
|
|
5494
|
|
|
5495 /* Check if we want to add multiple rows or not */
|
|
|
5496 var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
|
|
|
5497 api.rows.add( data ) :
|
|
|
5498 api.row.add( data );
|
|
|
5499
|
|
|
5500 if ( redraw === undefined || redraw ) {
|
|
|
5501 api.draw();
|
|
|
5502 }
|
|
|
5503
|
|
|
5504 return rows.flatten().toArray();
|
|
|
5505 };
|
|
|
5506
|
|
|
5507
|
|
|
5508 /**
|
|
|
5509 * This function will make DataTables recalculate the column sizes, based on the data
|
|
|
5510 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
|
|
|
5511 * through the sWidth parameter). This can be useful when the width of the table's
|
|
|
5512 * parent element changes (for example a window resize).
|
|
|
5513 * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
|
|
|
5514 * @dtopt API
|
|
|
5515 * @deprecated Since v1.10
|
|
|
5516 *
|
|
|
5517 * @example
|
|
|
5518 * $(document).ready(function() {
|
|
|
5519 * var oTable = $('#example').dataTable( {
|
|
|
5520 * "sScrollY": "200px",
|
|
|
5521 * "bPaginate": false
|
|
|
5522 * } );
|
|
|
5523 *
|
|
|
5524 * $(window).bind('resize', function () {
|
|
|
5525 * oTable.fnAdjustColumnSizing();
|
|
|
5526 * } );
|
|
|
5527 * } );
|
|
|
5528 */
|
|
|
5529 this.fnAdjustColumnSizing = function ( bRedraw )
|
|
|
5530 {
|
|
|
5531 var api = this.api( true ).columns.adjust();
|
|
|
5532 var settings = api.settings()[0];
|
|
|
5533 var scroll = settings.oScroll;
|
|
|
5534
|
|
|
5535 if ( bRedraw === undefined || bRedraw ) {
|
|
|
5536 api.draw( false );
|
|
|
5537 }
|
|
|
5538 else if ( scroll.sX !== "" || scroll.sY !== "" ) {
|
|
|
5539 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
|
|
|
5540 _fnScrollDraw( settings );
|
|
|
5541 }
|
|
|
5542 };
|
|
|
5543
|
|
|
5544
|
|
|
5545 /**
|
|
|
5546 * Quickly and simply clear a table
|
|
|
5547 * @param {bool} [bRedraw=true] redraw the table or not
|
|
|
5548 * @dtopt API
|
|
|
5549 * @deprecated Since v1.10
|
|
|
5550 *
|
|
|
5551 * @example
|
|
|
5552 * $(document).ready(function() {
|
|
|
5553 * var oTable = $('#example').dataTable();
|
|
|
5554 *
|
|
|
5555 * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
|
|
|
5556 * oTable.fnClearTable();
|
|
|
5557 * } );
|
|
|
5558 */
|
|
|
5559 this.fnClearTable = function( bRedraw )
|
|
|
5560 {
|
|
|
5561 var api = this.api( true ).clear();
|
|
|
5562
|
|
|
5563 if ( bRedraw === undefined || bRedraw ) {
|
|
|
5564 api.draw();
|
|
|
5565 }
|
|
|
5566 };
|
|
|
5567
|
|
|
5568
|
|
|
5569 /**
|
|
|
5570 * The exact opposite of 'opening' a row, this function will close any rows which
|
|
|
5571 * are currently 'open'.
|
|
|
5572 * @param {node} nTr the table row to 'close'
|
|
|
5573 * @returns {int} 0 on success, or 1 if failed (can't find the row)
|
|
|
5574 * @dtopt API
|
|
|
5575 * @deprecated Since v1.10
|
|
|
5576 *
|
|
|
5577 * @example
|
|
|
5578 * $(document).ready(function() {
|
|
|
5579 * var oTable;
|
|
|
5580 *
|
|
|
5581 * // 'open' an information row when a row is clicked on
|
|
|
5582 * $('#example tbody tr').click( function () {
|
|
|
5583 * if ( oTable.fnIsOpen(this) ) {
|
|
|
5584 * oTable.fnClose( this );
|
|
|
5585 * } else {
|
|
|
5586 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
|
|
|
5587 * }
|
|
|
5588 * } );
|
|
|
5589 *
|
|
|
5590 * oTable = $('#example').dataTable();
|
|
|
5591 * } );
|
|
|
5592 */
|
|
|
5593 this.fnClose = function( nTr )
|
|
|
5594 {
|
|
|
5595 this.api( true ).row( nTr ).child.hide();
|
|
|
5596 };
|
|
|
5597
|
|
|
5598
|
|
|
5599 /**
|
|
|
5600 * Remove a row for the table
|
|
|
5601 * @param {mixed} target The index of the row from aoData to be deleted, or
|
|
|
5602 * the TR element you want to delete
|
|
|
5603 * @param {function|null} [callBack] Callback function
|
|
|
5604 * @param {bool} [redraw=true] Redraw the table or not
|
|
|
5605 * @returns {array} The row that was deleted
|
|
|
5606 * @dtopt API
|
|
|
5607 * @deprecated Since v1.10
|
|
|
5608 *
|
|
|
5609 * @example
|
|
|
5610 * $(document).ready(function() {
|
|
|
5611 * var oTable = $('#example').dataTable();
|
|
|
5612 *
|
|
|
5613 * // Immediately remove the first row
|
|
|
5614 * oTable.fnDeleteRow( 0 );
|
|
|
5615 * } );
|
|
|
5616 */
|
|
|
5617 this.fnDeleteRow = function( target, callback, redraw )
|
|
|
5618 {
|
|
|
5619 var api = this.api( true );
|
|
|
5620 var rows = api.rows( target );
|
|
|
5621 var settings = rows.settings()[0];
|
|
|
5622 var data = settings.aoData[ rows[0][0] ];
|
|
|
5623
|
|
|
5624 rows.remove();
|
|
|
5625
|
|
|
5626 if ( callback ) {
|
|
|
5627 callback.call( this, settings, data );
|
|
|
5628 }
|
|
|
5629
|
|
|
5630 if ( redraw === undefined || redraw ) {
|
|
|
5631 api.draw();
|
|
|
5632 }
|
|
|
5633
|
|
|
5634 return data;
|
|
|
5635 };
|
|
|
5636
|
|
|
5637
|
|
|
5638 /**
|
|
|
5639 * Restore the table to it's original state in the DOM by removing all of DataTables
|
|
|
5640 * enhancements, alterations to the DOM structure of the table and event listeners.
|
|
|
5641 * @param {boolean} [remove=false] Completely remove the table from the DOM
|
|
|
5642 * @dtopt API
|
|
|
5643 * @deprecated Since v1.10
|
|
|
5644 *
|
|
|
5645 * @example
|
|
|
5646 * $(document).ready(function() {
|
|
|
5647 * // This example is fairly pointless in reality, but shows how fnDestroy can be used
|
|
|
5648 * var oTable = $('#example').dataTable();
|
|
|
5649 * oTable.fnDestroy();
|
|
|
5650 * } );
|
|
|
5651 */
|
|
|
5652 this.fnDestroy = function ( remove )
|
|
|
5653 {
|
|
|
5654 this.api( true ).destroy( remove );
|
|
|
5655 };
|
|
|
5656
|
|
|
5657
|
|
|
5658 /**
|
|
|
5659 * Redraw the table
|
|
|
5660 * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
|
|
|
5661 * @dtopt API
|
|
|
5662 * @deprecated Since v1.10
|
|
|
5663 *
|
|
|
5664 * @example
|
|
|
5665 * $(document).ready(function() {
|
|
|
5666 * var oTable = $('#example').dataTable();
|
|
|
5667 *
|
|
|
5668 * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
|
|
|
5669 * oTable.fnDraw();
|
|
|
5670 * } );
|
|
|
5671 */
|
|
|
5672 this.fnDraw = function( complete )
|
|
|
5673 {
|
|
|
5674 // Note that this isn't an exact match to the old call to _fnDraw - it takes
|
|
|
5675 // into account the new data, but can hold position.
|
|
|
5676 this.api( true ).draw( complete );
|
|
|
5677 };
|
|
|
5678
|
|
|
5679
|
|
|
5680 /**
|
|
|
5681 * Filter the input based on data
|
|
|
5682 * @param {string} sInput String to filter the table on
|
|
|
5683 * @param {int|null} [iColumn] Column to limit filtering to
|
|
|
5684 * @param {bool} [bRegex=false] Treat as regular expression or not
|
|
|
5685 * @param {bool} [bSmart=true] Perform smart filtering or not
|
|
|
5686 * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
|
|
|
5687 * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
|
|
|
5688 * @dtopt API
|
|
|
5689 * @deprecated Since v1.10
|
|
|
5690 *
|
|
|
5691 * @example
|
|
|
5692 * $(document).ready(function() {
|
|
|
5693 * var oTable = $('#example').dataTable();
|
|
|
5694 *
|
|
|
5695 * // Sometime later - filter...
|
|
|
5696 * oTable.fnFilter( 'test string' );
|
|
|
5697 * } );
|
|
|
5698 */
|
|
|
5699 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
|
|
|
5700 {
|
|
|
5701 var api = this.api( true );
|
|
|
5702
|
|
|
5703 if ( iColumn === null || iColumn === undefined ) {
|
|
|
5704 api.search( sInput, bRegex, bSmart, bCaseInsensitive );
|
|
|
5705 }
|
|
|
5706 else {
|
|
|
5707 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
|
|
|
5708 }
|
|
|
5709
|
|
|
5710 api.draw();
|
|
|
5711 };
|
|
|
5712
|
|
|
5713
|
|
|
5714 /**
|
|
|
5715 * Get the data for the whole table, an individual row or an individual cell based on the
|
|
|
5716 * provided parameters.
|
|
|
5717 * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
|
|
|
5718 * a TR node then the data source for the whole row will be returned. If given as a
|
|
|
5719 * TD/TH cell node then iCol will be automatically calculated and the data for the
|
|
|
5720 * cell returned. If given as an integer, then this is treated as the aoData internal
|
|
|
5721 * data index for the row (see fnGetPosition) and the data for that row used.
|
|
|
5722 * @param {int} [col] Optional column index that you want the data of.
|
|
|
5723 * @returns {array|object|string} If mRow is undefined, then the data for all rows is
|
|
|
5724 * returned. If mRow is defined, just data for that row, and is iCol is
|
|
|
5725 * defined, only data for the designated cell is returned.
|
|
|
5726 * @dtopt API
|
|
|
5727 * @deprecated Since v1.10
|
|
|
5728 *
|
|
|
5729 * @example
|
|
|
5730 * // Row data
|
|
|
5731 * $(document).ready(function() {
|
|
|
5732 * oTable = $('#example').dataTable();
|
|
|
5733 *
|
|
|
5734 * oTable.$('tr').click( function () {
|
|
|
5735 * var data = oTable.fnGetData( this );
|
|
|
5736 * // ... do something with the array / object of data for the row
|
|
|
5737 * } );
|
|
|
5738 * } );
|
|
|
5739 *
|
|
|
5740 * @example
|
|
|
5741 * // Individual cell data
|
|
|
5742 * $(document).ready(function() {
|
|
|
5743 * oTable = $('#example').dataTable();
|
|
|
5744 *
|
|
|
5745 * oTable.$('td').click( function () {
|
|
|
5746 * var sData = oTable.fnGetData( this );
|
|
|
5747 * alert( 'The cell clicked on had the value of '+sData );
|
|
|
5748 * } );
|
|
|
5749 * } );
|
|
|
5750 */
|
|
|
5751 this.fnGetData = function( src, col )
|
|
|
5752 {
|
|
|
5753 var api = this.api( true );
|
|
|
5754
|
|
|
5755 if ( src !== undefined ) {
|
|
|
5756 var type = src.nodeName ? src.nodeName.toLowerCase() : '';
|
|
|
5757
|
|
|
5758 return col !== undefined || type == 'td' || type == 'th' ?
|
|
|
5759 api.cell( src, col ).data() :
|
|
|
5760 api.row( src ).data() || null;
|
|
|
5761 }
|
|
|
5762
|
|
|
5763 return api.data().toArray();
|
|
|
5764 };
|
|
|
5765
|
|
|
5766
|
|
|
5767 /**
|
|
|
5768 * Get an array of the TR nodes that are used in the table's body. Note that you will
|
|
|
5769 * typically want to use the '$' API method in preference to this as it is more
|
|
|
5770 * flexible.
|
|
|
5771 * @param {int} [iRow] Optional row index for the TR element you want
|
|
|
5772 * @returns {array|node} If iRow is undefined, returns an array of all TR elements
|
|
|
5773 * in the table's body, or iRow is defined, just the TR element requested.
|
|
|
5774 * @dtopt API
|
|
|
5775 * @deprecated Since v1.10
|
|
|
5776 *
|
|
|
5777 * @example
|
|
|
5778 * $(document).ready(function() {
|
|
|
5779 * var oTable = $('#example').dataTable();
|
|
|
5780 *
|
|
|
5781 * // Get the nodes from the table
|
|
|
5782 * var nNodes = oTable.fnGetNodes( );
|
|
|
5783 * } );
|
|
|
5784 */
|
|
|
5785 this.fnGetNodes = function( iRow )
|
|
|
5786 {
|
|
|
5787 var api = this.api( true );
|
|
|
5788
|
|
|
5789 return iRow !== undefined ?
|
|
|
5790 api.row( iRow ).node() :
|
|
|
5791 api.rows().nodes().flatten().toArray();
|
|
|
5792 };
|
|
|
5793
|
|
|
5794
|
|
|
5795 /**
|
|
|
5796 * Get the array indexes of a particular cell from it's DOM element
|
|
|
5797 * and column index including hidden columns
|
|
|
5798 * @param {node} node this can either be a TR, TD or TH in the table's body
|
|
|
5799 * @returns {int} If nNode is given as a TR, then a single index is returned, or
|
|
|
5800 * if given as a cell, an array of [row index, column index (visible),
|
|
|
5801 * column index (all)] is given.
|
|
|
5802 * @dtopt API
|
|
|
5803 * @deprecated Since v1.10
|
|
|
5804 *
|
|
|
5805 * @example
|
|
|
5806 * $(document).ready(function() {
|
|
|
5807 * $('#example tbody td').click( function () {
|
|
|
5808 * // Get the position of the current data from the node
|
|
|
5809 * var aPos = oTable.fnGetPosition( this );
|
|
|
5810 *
|
|
|
5811 * // Get the data array for this row
|
|
|
5812 * var aData = oTable.fnGetData( aPos[0] );
|
|
|
5813 *
|
|
|
5814 * // Update the data array and return the value
|
|
|
5815 * aData[ aPos[1] ] = 'clicked';
|
|
|
5816 * this.innerHTML = 'clicked';
|
|
|
5817 * } );
|
|
|
5818 *
|
|
|
5819 * // Init DataTables
|
|
|
5820 * oTable = $('#example').dataTable();
|
|
|
5821 * } );
|
|
|
5822 */
|
|
|
5823 this.fnGetPosition = function( node )
|
|
|
5824 {
|
|
|
5825 var api = this.api( true );
|
|
|
5826 var nodeName = node.nodeName.toUpperCase();
|
|
|
5827
|
|
|
5828 if ( nodeName == 'TR' ) {
|
|
|
5829 return api.row( node ).index();
|
|
|
5830 }
|
|
|
5831 else if ( nodeName == 'TD' || nodeName == 'TH' ) {
|
|
|
5832 var cell = api.cell( node ).index();
|
|
|
5833
|
|
|
5834 return [
|
|
|
5835 cell.row,
|
|
|
5836 cell.columnVisible,
|
|
|
5837 cell.column
|
|
|
5838 ];
|
|
|
5839 }
|
|
|
5840 return null;
|
|
|
5841 };
|
|
|
5842
|
|
|
5843
|
|
|
5844 /**
|
|
|
5845 * Check to see if a row is 'open' or not.
|
|
|
5846 * @param {node} nTr the table row to check
|
|
|
5847 * @returns {boolean} true if the row is currently open, false otherwise
|
|
|
5848 * @dtopt API
|
|
|
5849 * @deprecated Since v1.10
|
|
|
5850 *
|
|
|
5851 * @example
|
|
|
5852 * $(document).ready(function() {
|
|
|
5853 * var oTable;
|
|
|
5854 *
|
|
|
5855 * // 'open' an information row when a row is clicked on
|
|
|
5856 * $('#example tbody tr').click( function () {
|
|
|
5857 * if ( oTable.fnIsOpen(this) ) {
|
|
|
5858 * oTable.fnClose( this );
|
|
|
5859 * } else {
|
|
|
5860 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
|
|
|
5861 * }
|
|
|
5862 * } );
|
|
|
5863 *
|
|
|
5864 * oTable = $('#example').dataTable();
|
|
|
5865 * } );
|
|
|
5866 */
|
|
|
5867 this.fnIsOpen = function( nTr )
|
|
|
5868 {
|
|
|
5869 return this.api( true ).row( nTr ).child.isShown();
|
|
|
5870 };
|
|
|
5871
|
|
|
5872
|
|
|
5873 /**
|
|
|
5874 * This function will place a new row directly after a row which is currently
|
|
|
5875 * on display on the page, with the HTML contents that is passed into the
|
|
|
5876 * function. This can be used, for example, to ask for confirmation that a
|
|
|
5877 * particular record should be deleted.
|
|
|
5878 * @param {node} nTr The table row to 'open'
|
|
|
5879 * @param {string|node|jQuery} mHtml The HTML to put into the row
|
|
|
5880 * @param {string} sClass Class to give the new TD cell
|
|
|
5881 * @returns {node} The row opened. Note that if the table row passed in as the
|
|
|
5882 * first parameter, is not found in the table, this method will silently
|
|
|
5883 * return.
|
|
|
5884 * @dtopt API
|
|
|
5885 * @deprecated Since v1.10
|
|
|
5886 *
|
|
|
5887 * @example
|
|
|
5888 * $(document).ready(function() {
|
|
|
5889 * var oTable;
|
|
|
5890 *
|
|
|
5891 * // 'open' an information row when a row is clicked on
|
|
|
5892 * $('#example tbody tr').click( function () {
|
|
|
5893 * if ( oTable.fnIsOpen(this) ) {
|
|
|
5894 * oTable.fnClose( this );
|
|
|
5895 * } else {
|
|
|
5896 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
|
|
|
5897 * }
|
|
|
5898 * } );
|
|
|
5899 *
|
|
|
5900 * oTable = $('#example').dataTable();
|
|
|
5901 * } );
|
|
|
5902 */
|
|
|
5903 this.fnOpen = function( nTr, mHtml, sClass )
|
|
|
5904 {
|
|
|
5905 return this.api( true )
|
|
|
5906 .row( nTr )
|
|
|
5907 .child( mHtml, sClass )
|
|
|
5908 .show()
|
|
|
5909 .child()[0];
|
|
|
5910 };
|
|
|
5911
|
|
|
5912
|
|
|
5913 /**
|
|
|
5914 * Change the pagination - provides the internal logic for pagination in a simple API
|
|
|
5915 * function. With this function you can have a DataTables table go to the next,
|
|
|
5916 * previous, first or last pages.
|
|
|
5917 * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
|
|
|
5918 * or page number to jump to (integer), note that page 0 is the first page.
|
|
|
5919 * @param {bool} [bRedraw=true] Redraw the table or not
|
|
|
5920 * @dtopt API
|
|
|
5921 * @deprecated Since v1.10
|
|
|
5922 *
|
|
|
5923 * @example
|
|
|
5924 * $(document).ready(function() {
|
|
|
5925 * var oTable = $('#example').dataTable();
|
|
|
5926 * oTable.fnPageChange( 'next' );
|
|
|
5927 * } );
|
|
|
5928 */
|
|
|
5929 this.fnPageChange = function ( mAction, bRedraw )
|
|
|
5930 {
|
|
|
5931 var api = this.api( true ).page( mAction );
|
|
|
5932
|
|
|
5933 if ( bRedraw === undefined || bRedraw ) {
|
|
|
5934 api.draw(false);
|
|
|
5935 }
|
|
|
5936 };
|
|
|
5937
|
|
|
5938
|
|
|
5939 /**
|
|
|
5940 * Show a particular column
|
|
|
5941 * @param {int} iCol The column whose display should be changed
|
|
|
5942 * @param {bool} bShow Show (true) or hide (false) the column
|
|
|
5943 * @param {bool} [bRedraw=true] Redraw the table or not
|
|
|
5944 * @dtopt API
|
|
|
5945 * @deprecated Since v1.10
|
|
|
5946 *
|
|
|
5947 * @example
|
|
|
5948 * $(document).ready(function() {
|
|
|
5949 * var oTable = $('#example').dataTable();
|
|
|
5950 *
|
|
|
5951 * // Hide the second column after initialisation
|
|
|
5952 * oTable.fnSetColumnVis( 1, false );
|
|
|
5953 * } );
|
|
|
5954 */
|
|
|
5955 this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
|
|
|
5956 {
|
|
|
5957 var api = this.api( true ).column( iCol ).visible( bShow );
|
|
|
5958
|
|
|
5959 if ( bRedraw === undefined || bRedraw ) {
|
|
|
5960 api.columns.adjust().draw();
|
|
|
5961 }
|
|
|
5962 };
|
|
|
5963
|
|
|
5964
|
|
|
5965 /**
|
|
|
5966 * Get the settings for a particular table for external manipulation
|
|
|
5967 * @returns {object} DataTables settings object. See
|
|
|
5968 * {@link DataTable.models.oSettings}
|
|
|
5969 * @dtopt API
|
|
|
5970 * @deprecated Since v1.10
|
|
|
5971 *
|
|
|
5972 * @example
|
|
|
5973 * $(document).ready(function() {
|
|
|
5974 * var oTable = $('#example').dataTable();
|
|
|
5975 * var oSettings = oTable.fnSettings();
|
|
|
5976 *
|
|
|
5977 * // Show an example parameter from the settings
|
|
|
5978 * alert( oSettings._iDisplayStart );
|
|
|
5979 * } );
|
|
|
5980 */
|
|
|
5981 this.fnSettings = function()
|
|
|
5982 {
|
|
|
5983 return _fnSettingsFromNode( this[_ext.iApiIndex] );
|
|
|
5984 };
|
|
|
5985
|
|
|
5986
|
|
|
5987 /**
|
|
|
5988 * Sort the table by a particular column
|
|
|
5989 * @param {int} iCol the data index to sort on. Note that this will not match the
|
|
|
5990 * 'display index' if you have hidden data entries
|
|
|
5991 * @dtopt API
|
|
|
5992 * @deprecated Since v1.10
|
|
|
5993 *
|
|
|
5994 * @example
|
|
|
5995 * $(document).ready(function() {
|
|
|
5996 * var oTable = $('#example').dataTable();
|
|
|
5997 *
|
|
|
5998 * // Sort immediately with columns 0 and 1
|
|
|
5999 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
|
|
|
6000 * } );
|
|
|
6001 */
|
|
|
6002 this.fnSort = function( aaSort )
|
|
|
6003 {
|
|
|
6004 this.api( true ).order( aaSort ).draw();
|
|
|
6005 };
|
|
|
6006
|
|
|
6007
|
|
|
6008 /**
|
|
|
6009 * Attach a sort listener to an element for a given column
|
|
|
6010 * @param {node} nNode the element to attach the sort listener to
|
|
|
6011 * @param {int} iColumn the column that a click on this node will sort on
|
|
|
6012 * @param {function} [fnCallback] callback function when sort is run
|
|
|
6013 * @dtopt API
|
|
|
6014 * @deprecated Since v1.10
|
|
|
6015 *
|
|
|
6016 * @example
|
|
|
6017 * $(document).ready(function() {
|
|
|
6018 * var oTable = $('#example').dataTable();
|
|
|
6019 *
|
|
|
6020 * // Sort on column 1, when 'sorter' is clicked on
|
|
|
6021 * oTable.fnSortListener( document.getElementById('sorter'), 1 );
|
|
|
6022 * } );
|
|
|
6023 */
|
|
|
6024 this.fnSortListener = function( nNode, iColumn, fnCallback )
|
|
|
6025 {
|
|
|
6026 this.api( true ).order.listener( nNode, iColumn, fnCallback );
|
|
|
6027 };
|
|
|
6028
|
|
|
6029
|
|
|
6030 /**
|
|
|
6031 * Update a table cell or row - this method will accept either a single value to
|
|
|
6032 * update the cell with, an array of values with one element for each column or
|
|
|
6033 * an object in the same format as the original data source. The function is
|
|
|
6034 * self-referencing in order to make the multi column updates easier.
|
|
|
6035 * @param {object|array|string} mData Data to update the cell/row with
|
|
|
6036 * @param {node|int} mRow TR element you want to update or the aoData index
|
|
|
6037 * @param {int} [iColumn] The column to update, give as null or undefined to
|
|
|
6038 * update a whole row.
|
|
|
6039 * @param {bool} [bRedraw=true] Redraw the table or not
|
|
|
6040 * @param {bool} [bAction=true] Perform pre-draw actions or not
|
|
|
6041 * @returns {int} 0 on success, 1 on error
|
|
|
6042 * @dtopt API
|
|
|
6043 * @deprecated Since v1.10
|
|
|
6044 *
|
|
|
6045 * @example
|
|
|
6046 * $(document).ready(function() {
|
|
|
6047 * var oTable = $('#example').dataTable();
|
|
|
6048 * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
|
|
|
6049 * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
|
|
|
6050 * } );
|
|
|
6051 */
|
|
|
6052 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
|
|
|
6053 {
|
|
|
6054 var api = this.api( true );
|
|
|
6055
|
|
|
6056 if ( iColumn === undefined || iColumn === null ) {
|
|
|
6057 api.row( mRow ).data( mData );
|
|
|
6058 }
|
|
|
6059 else {
|
|
|
6060 api.cell( mRow, iColumn ).data( mData );
|
|
|
6061 }
|
|
|
6062
|
|
|
6063 if ( bAction === undefined || bAction ) {
|
|
|
6064 api.columns.adjust();
|
|
|
6065 }
|
|
|
6066
|
|
|
6067 if ( bRedraw === undefined || bRedraw ) {
|
|
|
6068 api.draw();
|
|
|
6069 }
|
|
|
6070 return 0;
|
|
|
6071 };
|
|
|
6072
|
|
|
6073
|
|
|
6074 /**
|
|
|
6075 * Provide a common method for plug-ins to check the version of DataTables being used, in order
|
|
|
6076 * to ensure compatibility.
|
|
|
6077 * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
|
|
|
6078 * formats "X" and "X.Y" are also acceptable.
|
|
|
6079 * @returns {boolean} true if this version of DataTables is greater or equal to the required
|
|
|
6080 * version, or false if this version of DataTales is not suitable
|
|
|
6081 * @method
|
|
|
6082 * @dtopt API
|
|
|
6083 * @deprecated Since v1.10
|
|
|
6084 *
|
|
|
6085 * @example
|
|
|
6086 * $(document).ready(function() {
|
|
|
6087 * var oTable = $('#example').dataTable();
|
|
|
6088 * alert( oTable.fnVersionCheck( '1.9.0' ) );
|
|
|
6089 * } );
|
|
|
6090 */
|
|
|
6091 this.fnVersionCheck = _ext.fnVersionCheck;
|
|
|
6092
|
|
|
6093
|
|
|
6094 var _that = this;
|
|
|
6095 var emptyInit = options === undefined;
|
|
|
6096 var len = this.length;
|
|
|
6097
|
|
|
6098 if ( emptyInit ) {
|
|
|
6099 options = {};
|
|
|
6100 }
|
|
|
6101
|
|
|
6102 this.oApi = this.internal = _ext.internal;
|
|
|
6103
|
|
|
6104 // Extend with old style plug-in API methods
|
|
|
6105 for ( var fn in DataTable.ext.internal ) {
|
|
|
6106 if ( fn ) {
|
|
|
6107 this[fn] = _fnExternApiFunc(fn);
|
|
|
6108 }
|
|
|
6109 }
|
|
|
6110
|
|
|
6111 this.each(function() {
|
|
|
6112 // For each initialisation we want to give it a clean initialisation
|
|
|
6113 // object that can be bashed around
|
|
|
6114 var o = {};
|
|
|
6115 var oInit = len > 1 ? // optimisation for single table case
|
|
|
6116 _fnExtend( o, options, true ) :
|
|
|
6117 options;
|
|
|
6118
|
|
|
6119 /*global oInit,_that,emptyInit*/
|
|
|
6120 var i=0, iLen, j, jLen, k, kLen;
|
|
|
6121 var sId = this.getAttribute( 'id' );
|
|
|
6122 var bInitHandedOff = false;
|
|
|
6123 var defaults = DataTable.defaults;
|
|
|
6124 var $this = $(this);
|
|
|
6125
|
|
|
6126
|
|
|
6127 /* Sanity check */
|
|
|
6128 if ( this.nodeName.toLowerCase() != 'table' )
|
|
|
6129 {
|
|
|
6130 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
|
|
|
6131 return;
|
|
|
6132 }
|
|
|
6133
|
|
|
6134 /* Backwards compatibility for the defaults */
|
|
|
6135 _fnCompatOpts( defaults );
|
|
|
6136 _fnCompatCols( defaults.column );
|
|
|
6137
|
|
|
6138 /* Convert the camel-case defaults to Hungarian */
|
|
|
6139 _fnCamelToHungarian( defaults, defaults, true );
|
|
|
6140 _fnCamelToHungarian( defaults.column, defaults.column, true );
|
|
|
6141
|
|
|
6142 /* Setting up the initialisation object */
|
|
|
6143 _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
|
|
|
6144
|
|
|
6145
|
|
|
6146
|
|
|
6147 /* Check to see if we are re-initialising a table */
|
|
|
6148 var allSettings = DataTable.settings;
|
|
|
6149 for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
|
|
|
6150 {
|
|
|
6151 var s = allSettings[i];
|
|
|
6152
|
|
|
6153 /* Base check on table node */
|
|
|
6154 if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
|
|
|
6155 {
|
|
|
6156 var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
|
|
|
6157 var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
|
|
|
6158
|
|
|
6159 if ( emptyInit || bRetrieve )
|
|
|
6160 {
|
|
|
6161 return s.oInstance;
|
|
|
6162 }
|
|
|
6163 else if ( bDestroy )
|
|
|
6164 {
|
|
|
6165 s.oInstance.fnDestroy();
|
|
|
6166 break;
|
|
|
6167 }
|
|
|
6168 else
|
|
|
6169 {
|
|
|
6170 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
|
|
|
6171 return;
|
|
|
6172 }
|
|
|
6173 }
|
|
|
6174
|
|
|
6175 /* If the element we are initialising has the same ID as a table which was previously
|
|
|
6176 * initialised, but the table nodes don't match (from before) then we destroy the old
|
|
|
6177 * instance by simply deleting it. This is under the assumption that the table has been
|
|
|
6178 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
|
|
|
6179 */
|
|
|
6180 if ( s.sTableId == this.id )
|
|
|
6181 {
|
|
|
6182 allSettings.splice( i, 1 );
|
|
|
6183 break;
|
|
|
6184 }
|
|
|
6185 }
|
|
|
6186
|
|
|
6187 /* Ensure the table has an ID - required for accessibility */
|
|
|
6188 if ( sId === null || sId === "" )
|
|
|
6189 {
|
|
|
6190 sId = "DataTables_Table_"+(DataTable.ext._unique++);
|
|
|
6191 this.id = sId;
|
|
|
6192 }
|
|
|
6193
|
|
|
6194 /* Create the settings object for this table and set some of the default parameters */
|
|
|
6195 var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
|
|
|
6196 "sDestroyWidth": $this[0].style.width,
|
|
|
6197 "sInstance": sId,
|
|
|
6198 "sTableId": sId
|
|
|
6199 } );
|
|
|
6200 oSettings.nTable = this;
|
|
|
6201 oSettings.oApi = _that.internal;
|
|
|
6202 oSettings.oInit = oInit;
|
|
|
6203
|
|
|
6204 allSettings.push( oSettings );
|
|
|
6205
|
|
|
6206 // Need to add the instance after the instance after the settings object has been added
|
|
|
6207 // to the settings array, so we can self reference the table instance if more than one
|
|
|
6208 oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
|
|
|
6209
|
|
|
6210 // Backwards compatibility, before we apply all the defaults
|
|
|
6211 _fnCompatOpts( oInit );
|
|
|
6212
|
|
|
6213 if ( oInit.oLanguage )
|
|
|
6214 {
|
|
|
6215 _fnLanguageCompat( oInit.oLanguage );
|
|
|
6216 }
|
|
|
6217
|
|
|
6218 // If the length menu is given, but the init display length is not, use the length menu
|
|
|
6219 if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
|
|
|
6220 {
|
|
|
6221 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
|
|
|
6222 oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
|
|
|
6223 }
|
|
|
6224
|
|
|
6225 // Apply the defaults and init options to make a single init object will all
|
|
|
6226 // options defined from defaults and instance options.
|
|
|
6227 oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
|
|
|
6228
|
|
|
6229
|
|
|
6230 // Map the initialisation options onto the settings object
|
|
|
6231 _fnMap( oSettings.oFeatures, oInit, [
|
|
|
6232 "bPaginate",
|
|
|
6233 "bLengthChange",
|
|
|
6234 "bFilter",
|
|
|
6235 "bSort",
|
|
|
6236 "bSortMulti",
|
|
|
6237 "bInfo",
|
|
|
6238 "bProcessing",
|
|
|
6239 "bAutoWidth",
|
|
|
6240 "bSortClasses",
|
|
|
6241 "bServerSide",
|
|
|
6242 "bDeferRender"
|
|
|
6243 ] );
|
|
|
6244 _fnMap( oSettings, oInit, [
|
|
|
6245 "asStripeClasses",
|
|
|
6246 "ajax",
|
|
|
6247 "fnServerData",
|
|
|
6248 "fnFormatNumber",
|
|
|
6249 "sServerMethod",
|
|
|
6250 "aaSorting",
|
|
|
6251 "aaSortingFixed",
|
|
|
6252 "aLengthMenu",
|
|
|
6253 "sPaginationType",
|
|
|
6254 "sAjaxSource",
|
|
|
6255 "sAjaxDataProp",
|
|
|
6256 "iStateDuration",
|
|
|
6257 "sDom",
|
|
|
6258 "bSortCellsTop",
|
|
|
6259 "iTabIndex",
|
|
|
6260 "fnStateLoadCallback",
|
|
|
6261 "fnStateSaveCallback",
|
|
|
6262 "renderer",
|
|
|
6263 "searchDelay",
|
|
|
6264 "rowId",
|
|
|
6265 [ "iCookieDuration", "iStateDuration" ], // backwards compat
|
|
|
6266 [ "oSearch", "oPreviousSearch" ],
|
|
|
6267 [ "aoSearchCols", "aoPreSearchCols" ],
|
|
|
6268 [ "iDisplayLength", "_iDisplayLength" ],
|
|
|
6269 [ "bJQueryUI", "bJUI" ]
|
|
|
6270 ] );
|
|
|
6271 _fnMap( oSettings.oScroll, oInit, [
|
|
|
6272 [ "sScrollX", "sX" ],
|
|
|
6273 [ "sScrollXInner", "sXInner" ],
|
|
|
6274 [ "sScrollY", "sY" ],
|
|
|
6275 [ "bScrollCollapse", "bCollapse" ]
|
|
|
6276 ] );
|
|
|
6277 _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
|
|
|
6278
|
|
|
6279 /* Callback functions which are array driven */
|
|
|
6280 _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
|
|
|
6281 _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
|
|
|
6282 _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
|
|
|
6283 _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
|
|
|
6284 _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
|
|
|
6285 _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
|
|
|
6286 _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
|
|
|
6287 _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
|
|
|
6288 _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
|
|
|
6289 _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
|
|
|
6290 _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
|
|
|
6291
|
|
|
6292 oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
|
|
|
6293
|
|
|
6294 /* Browser support detection */
|
|
|
6295 _fnBrowserDetect( oSettings );
|
|
|
6296
|
|
|
6297 var oClasses = oSettings.oClasses;
|
|
|
6298
|
|
|
6299 // @todo Remove in 1.11
|
|
|
6300 if ( oInit.bJQueryUI )
|
|
|
6301 {
|
|
|
6302 /* Use the JUI classes object for display. You could clone the oStdClasses object if
|
|
|
6303 * you want to have multiple tables with multiple independent classes
|
|
|
6304 */
|
|
|
6305 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
|
|
|
6306
|
|
|
6307 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
|
|
|
6308 {
|
|
|
6309 /* Set the DOM to use a layout suitable for jQuery UI's theming */
|
|
|
6310 oSettings.sDom = '<"H"lfr>t<"F"ip>';
|
|
|
6311 }
|
|
|
6312
|
|
|
6313 if ( ! oSettings.renderer ) {
|
|
|
6314 oSettings.renderer = 'jqueryui';
|
|
|
6315 }
|
|
|
6316 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
|
|
|
6317 oSettings.renderer.header = 'jqueryui';
|
|
|
6318 }
|
|
|
6319 }
|
|
|
6320 else
|
|
|
6321 {
|
|
|
6322 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
|
|
|
6323 }
|
|
|
6324 $this.addClass( oClasses.sTable );
|
|
|
6325
|
|
|
6326
|
|
|
6327 if ( oSettings.iInitDisplayStart === undefined )
|
|
|
6328 {
|
|
|
6329 /* Display start point, taking into account the save saving */
|
|
|
6330 oSettings.iInitDisplayStart = oInit.iDisplayStart;
|
|
|
6331 oSettings._iDisplayStart = oInit.iDisplayStart;
|
|
|
6332 }
|
|
|
6333
|
|
|
6334 if ( oInit.iDeferLoading !== null )
|
|
|
6335 {
|
|
|
6336 oSettings.bDeferLoading = true;
|
|
|
6337 var tmp = $.isArray( oInit.iDeferLoading );
|
|
|
6338 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
|
|
|
6339 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
|
|
|
6340 }
|
|
|
6341
|
|
|
6342 /* Language definitions */
|
|
|
6343 var oLanguage = oSettings.oLanguage;
|
|
|
6344 $.extend( true, oLanguage, oInit.oLanguage );
|
|
|
6345
|
|
|
6346 if ( oLanguage.sUrl !== "" )
|
|
|
6347 {
|
|
|
6348 /* Get the language definitions from a file - because this Ajax call makes the language
|
|
|
6349 * get async to the remainder of this function we use bInitHandedOff to indicate that
|
|
|
6350 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
|
|
|
6351 */
|
|
|
6352 $.ajax( {
|
|
|
6353 dataType: 'json',
|
|
|
6354 url: oLanguage.sUrl,
|
|
|
6355 success: function ( json ) {
|
|
|
6356 _fnLanguageCompat( json );
|
|
|
6357 _fnCamelToHungarian( defaults.oLanguage, json );
|
|
|
6358 $.extend( true, oLanguage, json );
|
|
|
6359 _fnInitialise( oSettings );
|
|
|
6360 },
|
|
|
6361 error: function () {
|
|
|
6362 // Error occurred loading language file, continue on as best we can
|
|
|
6363 _fnInitialise( oSettings );
|
|
|
6364 }
|
|
|
6365 } );
|
|
|
6366 bInitHandedOff = true;
|
|
|
6367 }
|
|
|
6368
|
|
|
6369 /*
|
|
|
6370 * Stripes
|
|
|
6371 */
|
|
|
6372 if ( oInit.asStripeClasses === null )
|
|
|
6373 {
|
|
|
6374 oSettings.asStripeClasses =[
|
|
|
6375 oClasses.sStripeOdd,
|
|
|
6376 oClasses.sStripeEven
|
|
|
6377 ];
|
|
|
6378 }
|
|
|
6379
|
|
|
6380 /* Remove row stripe classes if they are already on the table row */
|
|
|
6381 var stripeClasses = oSettings.asStripeClasses;
|
|
|
6382 var rowOne = $this.children('tbody').find('tr').eq(0);
|
|
|
6383 if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
|
|
|
6384 return rowOne.hasClass(el);
|
|
|
6385 } ) ) !== -1 ) {
|
|
|
6386 $('tbody tr', this).removeClass( stripeClasses.join(' ') );
|
|
|
6387 oSettings.asDestroyStripes = stripeClasses.slice();
|
|
|
6388 }
|
|
|
6389
|
|
|
6390 /*
|
|
|
6391 * Columns
|
|
|
6392 * See if we should load columns automatically or use defined ones
|
|
|
6393 */
|
|
|
6394 var anThs = [];
|
|
|
6395 var aoColumnsInit;
|
|
|
6396 var nThead = this.getElementsByTagName('thead');
|
|
|
6397 if ( nThead.length !== 0 )
|
|
|
6398 {
|
|
|
6399 _fnDetectHeader( oSettings.aoHeader, nThead[0] );
|
|
|
6400 anThs = _fnGetUniqueThs( oSettings );
|
|
|
6401 }
|
|
|
6402
|
|
|
6403 /* If not given a column array, generate one with nulls */
|
|
|
6404 if ( oInit.aoColumns === null )
|
|
|
6405 {
|
|
|
6406 aoColumnsInit = [];
|
|
|
6407 for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
|
|
|
6408 {
|
|
|
6409 aoColumnsInit.push( null );
|
|
|
6410 }
|
|
|
6411 }
|
|
|
6412 else
|
|
|
6413 {
|
|
|
6414 aoColumnsInit = oInit.aoColumns;
|
|
|
6415 }
|
|
|
6416
|
|
|
6417 /* Add the columns */
|
|
|
6418 for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
|
|
|
6419 {
|
|
|
6420 _fnAddColumn( oSettings, anThs ? anThs[i] : null );
|
|
|
6421 }
|
|
|
6422
|
|
|
6423 /* Apply the column definitions */
|
|
|
6424 _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
|
|
|
6425 _fnColumnOptions( oSettings, iCol, oDef );
|
|
|
6426 } );
|
|
|
6427
|
|
|
6428 /* HTML5 attribute detection - build an mData object automatically if the
|
|
|
6429 * attributes are found
|
|
|
6430 */
|
|
|
6431 if ( rowOne.length ) {
|
|
|
6432 var a = function ( cell, name ) {
|
|
|
6433 return cell.getAttribute( 'data-'+name ) !== null ? name : null;
|
|
|
6434 };
|
|
|
6435
|
|
|
6436 $( rowOne[0] ).children('th, td').each( function (i, cell) {
|
|
|
6437 var col = oSettings.aoColumns[i];
|
|
|
6438
|
|
|
6439 if ( col.mData === i ) {
|
|
|
6440 var sort = a( cell, 'sort' ) || a( cell, 'order' );
|
|
|
6441 var filter = a( cell, 'filter' ) || a( cell, 'search' );
|
|
|
6442
|
|
|
6443 if ( sort !== null || filter !== null ) {
|
|
|
6444 col.mData = {
|
|
|
6445 _: i+'.display',
|
|
|
6446 sort: sort !== null ? i+'.@data-'+sort : undefined,
|
|
|
6447 type: sort !== null ? i+'.@data-'+sort : undefined,
|
|
|
6448 filter: filter !== null ? i+'.@data-'+filter : undefined
|
|
|
6449 };
|
|
|
6450
|
|
|
6451 _fnColumnOptions( oSettings, i );
|
|
|
6452 }
|
|
|
6453 }
|
|
|
6454 } );
|
|
|
6455 }
|
|
|
6456
|
|
|
6457 var features = oSettings.oFeatures;
|
|
|
6458
|
|
|
6459 /* Must be done after everything which can be overridden by the state saving! */
|
|
|
6460 if ( oInit.bStateSave )
|
|
|
6461 {
|
|
|
6462 features.bStateSave = true;
|
|
|
6463 _fnLoadState( oSettings, oInit );
|
|
|
6464 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
|
|
|
6465 }
|
|
|
6466
|
|
|
6467
|
|
|
6468 /*
|
|
|
6469 * Sorting
|
|
|
6470 * @todo For modularisation (1.11) this needs to do into a sort start up handler
|
|
|
6471 */
|
|
|
6472
|
|
|
6473 // If aaSorting is not defined, then we use the first indicator in asSorting
|
|
|
6474 // in case that has been altered, so the default sort reflects that option
|
|
|
6475 if ( oInit.aaSorting === undefined )
|
|
|
6476 {
|
|
|
6477 var sorting = oSettings.aaSorting;
|
|
|
6478 for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
|
|
|
6479 {
|
|
|
6480 sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
|
|
|
6481 }
|
|
|
6482 }
|
|
|
6483
|
|
|
6484 /* Do a first pass on the sorting classes (allows any size changes to be taken into
|
|
|
6485 * account, and also will apply sorting disabled classes if disabled
|
|
|
6486 */
|
|
|
6487 _fnSortingClasses( oSettings );
|
|
|
6488
|
|
|
6489 if ( features.bSort )
|
|
|
6490 {
|
|
|
6491 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
|
|
|
6492 if ( oSettings.bSorted ) {
|
|
|
6493 var aSort = _fnSortFlatten( oSettings );
|
|
|
6494 var sortedColumns = {};
|
|
|
6495
|
|
|
6496 $.each( aSort, function (i, val) {
|
|
|
6497 sortedColumns[ val.src ] = val.dir;
|
|
|
6498 } );
|
|
|
6499
|
|
|
6500 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
|
|
|
6501 _fnSortAria( oSettings );
|
|
|
6502 }
|
|
|
6503 } );
|
|
|
6504 }
|
|
|
6505
|
|
|
6506 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
|
|
|
6507 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
|
|
|
6508 _fnSortingClasses( oSettings );
|
|
|
6509 }
|
|
|
6510 }, 'sc' );
|
|
|
6511
|
|
|
6512
|
|
|
6513 /*
|
|
|
6514 * Final init
|
|
|
6515 * Cache the header, body and footer as required, creating them if needed
|
|
|
6516 */
|
|
|
6517
|
|
|
6518 // Work around for Webkit bug 83867 - store the caption-side before removing from doc
|
|
|
6519 var captions = $this.children('caption').each( function () {
|
|
|
6520 this._captionSide = $this.css('caption-side');
|
|
|
6521 } );
|
|
|
6522
|
|
|
6523 var thead = $this.children('thead');
|
|
|
6524 if ( thead.length === 0 )
|
|
|
6525 {
|
|
|
6526 thead = $('<thead/>').appendTo(this);
|
|
|
6527 }
|
|
|
6528 oSettings.nTHead = thead[0];
|
|
|
6529
|
|
|
6530 var tbody = $this.children('tbody');
|
|
|
6531 if ( tbody.length === 0 )
|
|
|
6532 {
|
|
|
6533 tbody = $('<tbody/>').appendTo(this);
|
|
|
6534 }
|
|
|
6535 oSettings.nTBody = tbody[0];
|
|
|
6536
|
|
|
6537 var tfoot = $this.children('tfoot');
|
|
|
6538 if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
|
|
|
6539 {
|
|
|
6540 // If we are a scrolling table, and no footer has been given, then we need to create
|
|
|
6541 // a tfoot element for the caption element to be appended to
|
|
|
6542 tfoot = $('<tfoot/>').appendTo(this);
|
|
|
6543 }
|
|
|
6544
|
|
|
6545 if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
|
|
|
6546 $this.addClass( oClasses.sNoFooter );
|
|
|
6547 }
|
|
|
6548 else if ( tfoot.length > 0 ) {
|
|
|
6549 oSettings.nTFoot = tfoot[0];
|
|
|
6550 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
|
|
|
6551 }
|
|
|
6552
|
|
|
6553 /* Check if there is data passing into the constructor */
|
|
|
6554 if ( oInit.aaData )
|
|
|
6555 {
|
|
|
6556 for ( i=0 ; i<oInit.aaData.length ; i++ )
|
|
|
6557 {
|
|
|
6558 _fnAddData( oSettings, oInit.aaData[ i ] );
|
|
|
6559 }
|
|
|
6560 }
|
|
|
6561 else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
|
|
|
6562 {
|
|
|
6563 /* Grab the data from the page - only do this when deferred loading or no Ajax
|
|
|
6564 * source since there is no point in reading the DOM data if we are then going
|
|
|
6565 * to replace it with Ajax data
|
|
|
6566 */
|
|
|
6567 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
|
|
|
6568 }
|
|
|
6569
|
|
|
6570 /* Copy the data index array */
|
|
|
6571 oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
|
|
|
6572
|
|
|
6573 /* Initialisation complete - table can be drawn */
|
|
|
6574 oSettings.bInitialised = true;
|
|
|
6575
|
|
|
6576 /* Check if we need to initialise the table (it might not have been handed off to the
|
|
|
6577 * language processor)
|
|
|
6578 */
|
|
|
6579 if ( bInitHandedOff === false )
|
|
|
6580 {
|
|
|
6581 _fnInitialise( oSettings );
|
|
|
6582 }
|
|
|
6583 } );
|
|
|
6584 _that = null;
|
|
|
6585 return this;
|
|
|
6586 };
|
|
|
6587
|
|
|
6588
|
|
|
6589
|
|
|
6590 /**
|
|
|
6591 * Computed structure of the DataTables API, defined by the options passed to
|
|
|
6592 * `DataTable.Api.register()` when building the API.
|
|
|
6593 *
|
|
|
6594 * The structure is built in order to speed creation and extension of the Api
|
|
|
6595 * objects since the extensions are effectively pre-parsed.
|
|
|
6596 *
|
|
|
6597 * The array is an array of objects with the following structure, where this
|
|
|
6598 * base array represents the Api prototype base:
|
|
|
6599 *
|
|
|
6600 * [
|
|
|
6601 * {
|
|
|
6602 * name: 'data' -- string - Property name
|
|
|
6603 * val: function () {}, -- function - Api method (or undefined if just an object
|
|
|
6604 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
|
|
|
6605 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
|
|
|
6606 * },
|
|
|
6607 * {
|
|
|
6608 * name: 'row'
|
|
|
6609 * val: {},
|
|
|
6610 * methodExt: [ ... ],
|
|
|
6611 * propExt: [
|
|
|
6612 * {
|
|
|
6613 * name: 'data'
|
|
|
6614 * val: function () {},
|
|
|
6615 * methodExt: [ ... ],
|
|
|
6616 * propExt: [ ... ]
|
|
|
6617 * },
|
|
|
6618 * ...
|
|
|
6619 * ]
|
|
|
6620 * }
|
|
|
6621 * ]
|
|
|
6622 *
|
|
|
6623 * @type {Array}
|
|
|
6624 * @ignore
|
|
|
6625 */
|
|
|
6626 var __apiStruct = [];
|
|
|
6627
|
|
|
6628
|
|
|
6629 /**
|
|
|
6630 * `Array.prototype` reference.
|
|
|
6631 *
|
|
|
6632 * @type object
|
|
|
6633 * @ignore
|
|
|
6634 */
|
|
|
6635 var __arrayProto = Array.prototype;
|
|
|
6636
|
|
|
6637
|
|
|
6638 /**
|
|
|
6639 * Abstraction for `context` parameter of the `Api` constructor to allow it to
|
|
|
6640 * take several different forms for ease of use.
|
|
|
6641 *
|
|
|
6642 * Each of the input parameter types will be converted to a DataTables settings
|
|
|
6643 * object where possible.
|
|
|
6644 *
|
|
|
6645 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
|
|
|
6646 * of:
|
|
|
6647 *
|
|
|
6648 * * `string` - jQuery selector. Any DataTables' matching the given selector
|
|
|
6649 * with be found and used.
|
|
|
6650 * * `node` - `TABLE` node which has already been formed into a DataTable.
|
|
|
6651 * * `jQuery` - A jQuery object of `TABLE` nodes.
|
|
|
6652 * * `object` - DataTables settings object
|
|
|
6653 * * `DataTables.Api` - API instance
|
|
|
6654 * @return {array|null} Matching DataTables settings objects. `null` or
|
|
|
6655 * `undefined` is returned if no matching DataTable is found.
|
|
|
6656 * @ignore
|
|
|
6657 */
|
|
|
6658 var _toSettings = function ( mixed )
|
|
|
6659 {
|
|
|
6660 var idx, jq;
|
|
|
6661 var settings = DataTable.settings;
|
|
|
6662 var tables = $.map( settings, function (el, i) {
|
|
|
6663 return el.nTable;
|
|
|
6664 } );
|
|
|
6665
|
|
|
6666 if ( ! mixed ) {
|
|
|
6667 return [];
|
|
|
6668 }
|
|
|
6669 else if ( mixed.nTable && mixed.oApi ) {
|
|
|
6670 // DataTables settings object
|
|
|
6671 return [ mixed ];
|
|
|
6672 }
|
|
|
6673 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
|
|
|
6674 // Table node
|
|
|
6675 idx = $.inArray( mixed, tables );
|
|
|
6676 return idx !== -1 ? [ settings[idx] ] : null;
|
|
|
6677 }
|
|
|
6678 else if ( mixed && typeof mixed.settings === 'function' ) {
|
|
|
6679 return mixed.settings().toArray();
|
|
|
6680 }
|
|
|
6681 else if ( typeof mixed === 'string' ) {
|
|
|
6682 // jQuery selector
|
|
|
6683 jq = $(mixed);
|
|
|
6684 }
|
|
|
6685 else if ( mixed instanceof $ ) {
|
|
|
6686 // jQuery object (also DataTables instance)
|
|
|
6687 jq = mixed;
|
|
|
6688 }
|
|
|
6689
|
|
|
6690 if ( jq ) {
|
|
|
6691 return jq.map( function(i) {
|
|
|
6692 idx = $.inArray( this, tables );
|
|
|
6693 return idx !== -1 ? settings[idx] : null;
|
|
|
6694 } ).toArray();
|
|
|
6695 }
|
|
|
6696 };
|
|
|
6697
|
|
|
6698
|
|
|
6699 /**
|
|
|
6700 * DataTables API class - used to control and interface with one or more
|
|
|
6701 * DataTables enhanced tables.
|
|
|
6702 *
|
|
|
6703 * The API class is heavily based on jQuery, presenting a chainable interface
|
|
|
6704 * that you can use to interact with tables. Each instance of the API class has
|
|
|
6705 * a "context" - i.e. the tables that it will operate on. This could be a single
|
|
|
6706 * table, all tables on a page or a sub-set thereof.
|
|
|
6707 *
|
|
|
6708 * Additionally the API is designed to allow you to easily work with the data in
|
|
|
6709 * the tables, retrieving and manipulating it as required. This is done by
|
|
|
6710 * presenting the API class as an array like interface. The contents of the
|
|
|
6711 * array depend upon the actions requested by each method (for example
|
|
|
6712 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
|
|
|
6713 * return an array of objects or arrays depending upon your table's
|
|
|
6714 * configuration). The API object has a number of array like methods (`push`,
|
|
|
6715 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
|
|
|
6716 * `unique` etc) to assist your working with the data held in a table.
|
|
|
6717 *
|
|
|
6718 * Most methods (those which return an Api instance) are chainable, which means
|
|
|
6719 * the return from a method call also has all of the methods available that the
|
|
|
6720 * top level object had. For example, these two calls are equivalent:
|
|
|
6721 *
|
|
|
6722 * // Not chained
|
|
|
6723 * api.row.add( {...} );
|
|
|
6724 * api.draw();
|
|
|
6725 *
|
|
|
6726 * // Chained
|
|
|
6727 * api.row.add( {...} ).draw();
|
|
|
6728 *
|
|
|
6729 * @class DataTable.Api
|
|
|
6730 * @param {array|object|string|jQuery} context DataTable identifier. This is
|
|
|
6731 * used to define which DataTables enhanced tables this API will operate on.
|
|
|
6732 * Can be one of:
|
|
|
6733 *
|
|
|
6734 * * `string` - jQuery selector. Any DataTables' matching the given selector
|
|
|
6735 * with be found and used.
|
|
|
6736 * * `node` - `TABLE` node which has already been formed into a DataTable.
|
|
|
6737 * * `jQuery` - A jQuery object of `TABLE` nodes.
|
|
|
6738 * * `object` - DataTables settings object
|
|
|
6739 * @param {array} [data] Data to initialise the Api instance with.
|
|
|
6740 *
|
|
|
6741 * @example
|
|
|
6742 * // Direct initialisation during DataTables construction
|
|
|
6743 * var api = $('#example').DataTable();
|
|
|
6744 *
|
|
|
6745 * @example
|
|
|
6746 * // Initialisation using a DataTables jQuery object
|
|
|
6747 * var api = $('#example').dataTable().api();
|
|
|
6748 *
|
|
|
6749 * @example
|
|
|
6750 * // Initialisation as a constructor
|
|
|
6751 * var api = new $.fn.DataTable.Api( 'table.dataTable' );
|
|
|
6752 */
|
|
|
6753 _Api = function ( context, data )
|
|
|
6754 {
|
|
|
6755 if ( ! (this instanceof _Api) ) {
|
|
|
6756 return new _Api( context, data );
|
|
|
6757 }
|
|
|
6758
|
|
|
6759 var settings = [];
|
|
|
6760 var ctxSettings = function ( o ) {
|
|
|
6761 var a = _toSettings( o );
|
|
|
6762 if ( a ) {
|
|
|
6763 settings = settings.concat( a );
|
|
|
6764 }
|
|
|
6765 };
|
|
|
6766
|
|
|
6767 if ( $.isArray( context ) ) {
|
|
|
6768 for ( var i=0, ien=context.length ; i<ien ; i++ ) {
|
|
|
6769 ctxSettings( context[i] );
|
|
|
6770 }
|
|
|
6771 }
|
|
|
6772 else {
|
|
|
6773 ctxSettings( context );
|
|
|
6774 }
|
|
|
6775
|
|
|
6776 // Remove duplicates
|
|
|
6777 this.context = _unique( settings );
|
|
|
6778
|
|
|
6779 // Initial data
|
|
|
6780 if ( data ) {
|
|
|
6781 $.merge( this, data );
|
|
|
6782 }
|
|
|
6783
|
|
|
6784 // selector
|
|
|
6785 this.selector = {
|
|
|
6786 rows: null,
|
|
|
6787 cols: null,
|
|
|
6788 opts: null
|
|
|
6789 };
|
|
|
6790
|
|
|
6791 _Api.extend( this, this, __apiStruct );
|
|
|
6792 };
|
|
|
6793
|
|
|
6794 DataTable.Api = _Api;
|
|
|
6795
|
|
|
6796 // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
|
|
|
6797 // isPlainObject.
|
|
|
6798 $.extend( _Api.prototype, {
|
|
|
6799 any: function ()
|
|
|
6800 {
|
|
|
6801 return this.count() !== 0;
|
|
|
6802 },
|
|
|
6803
|
|
|
6804
|
|
|
6805 concat: __arrayProto.concat,
|
|
|
6806
|
|
|
6807
|
|
|
6808 context: [], // array of table settings objects
|
|
|
6809
|
|
|
6810
|
|
|
6811 count: function ()
|
|
|
6812 {
|
|
|
6813 return this.flatten().length;
|
|
|
6814 },
|
|
|
6815
|
|
|
6816
|
|
|
6817 each: function ( fn )
|
|
|
6818 {
|
|
|
6819 for ( var i=0, ien=this.length ; i<ien; i++ ) {
|
|
|
6820 fn.call( this, this[i], i, this );
|
|
|
6821 }
|
|
|
6822
|
|
|
6823 return this;
|
|
|
6824 },
|
|
|
6825
|
|
|
6826
|
|
|
6827 eq: function ( idx )
|
|
|
6828 {
|
|
|
6829 var ctx = this.context;
|
|
|
6830
|
|
|
6831 return ctx.length > idx ?
|
|
|
6832 new _Api( ctx[idx], this[idx] ) :
|
|
|
6833 null;
|
|
|
6834 },
|
|
|
6835
|
|
|
6836
|
|
|
6837 filter: function ( fn )
|
|
|
6838 {
|
|
|
6839 var a = [];
|
|
|
6840
|
|
|
6841 if ( __arrayProto.filter ) {
|
|
|
6842 a = __arrayProto.filter.call( this, fn, this );
|
|
|
6843 }
|
|
|
6844 else {
|
|
|
6845 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
|
|
|
6846 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
|
|
|
6847 if ( fn.call( this, this[i], i, this ) ) {
|
|
|
6848 a.push( this[i] );
|
|
|
6849 }
|
|
|
6850 }
|
|
|
6851 }
|
|
|
6852
|
|
|
6853 return new _Api( this.context, a );
|
|
|
6854 },
|
|
|
6855
|
|
|
6856
|
|
|
6857 flatten: function ()
|
|
|
6858 {
|
|
|
6859 var a = [];
|
|
|
6860 return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
|
|
|
6861 },
|
|
|
6862
|
|
|
6863
|
|
|
6864 join: __arrayProto.join,
|
|
|
6865
|
|
|
6866
|
|
|
6867 indexOf: __arrayProto.indexOf || function (obj, start)
|
|
|
6868 {
|
|
|
6869 for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
|
|
|
6870 if ( this[i] === obj ) {
|
|
|
6871 return i;
|
|
|
6872 }
|
|
|
6873 }
|
|
|
6874 return -1;
|
|
|
6875 },
|
|
|
6876
|
|
|
6877 iterator: function ( flatten, type, fn, alwaysNew ) {
|
|
|
6878 var
|
|
|
6879 a = [], ret,
|
|
|
6880 i, ien, j, jen,
|
|
|
6881 context = this.context,
|
|
|
6882 rows, items, item,
|
|
|
6883 selector = this.selector;
|
|
|
6884
|
|
|
6885 // Argument shifting
|
|
|
6886 if ( typeof flatten === 'string' ) {
|
|
|
6887 alwaysNew = fn;
|
|
|
6888 fn = type;
|
|
|
6889 type = flatten;
|
|
|
6890 flatten = false;
|
|
|
6891 }
|
|
|
6892
|
|
|
6893 for ( i=0, ien=context.length ; i<ien ; i++ ) {
|
|
|
6894 var apiInst = new _Api( context[i] );
|
|
|
6895
|
|
|
6896 if ( type === 'table' ) {
|
|
|
6897 ret = fn.call( apiInst, context[i], i );
|
|
|
6898
|
|
|
6899 if ( ret !== undefined ) {
|
|
|
6900 a.push( ret );
|
|
|
6901 }
|
|
|
6902 }
|
|
|
6903 else if ( type === 'columns' || type === 'rows' ) {
|
|
|
6904 // this has same length as context - one entry for each table
|
|
|
6905 ret = fn.call( apiInst, context[i], this[i], i );
|
|
|
6906
|
|
|
6907 if ( ret !== undefined ) {
|
|
|
6908 a.push( ret );
|
|
|
6909 }
|
|
|
6910 }
|
|
|
6911 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
|
|
|
6912 // columns and rows share the same structure.
|
|
|
6913 // 'this' is an array of column indexes for each context
|
|
|
6914 items = this[i];
|
|
|
6915
|
|
|
6916 if ( type === 'column-rows' ) {
|
|
|
6917 rows = _selector_row_indexes( context[i], selector.opts );
|
|
|
6918 }
|
|
|
6919
|
|
|
6920 for ( j=0, jen=items.length ; j<jen ; j++ ) {
|
|
|
6921 item = items[j];
|
|
|
6922
|
|
|
6923 if ( type === 'cell' ) {
|
|
|
6924 ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
|
|
|
6925 }
|
|
|
6926 else {
|
|
|
6927 ret = fn.call( apiInst, context[i], item, i, j, rows );
|
|
|
6928 }
|
|
|
6929
|
|
|
6930 if ( ret !== undefined ) {
|
|
|
6931 a.push( ret );
|
|
|
6932 }
|
|
|
6933 }
|
|
|
6934 }
|
|
|
6935 }
|
|
|
6936
|
|
|
6937 if ( a.length || alwaysNew ) {
|
|
|
6938 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
|
|
|
6939 var apiSelector = api.selector;
|
|
|
6940 apiSelector.rows = selector.rows;
|
|
|
6941 apiSelector.cols = selector.cols;
|
|
|
6942 apiSelector.opts = selector.opts;
|
|
|
6943 return api;
|
|
|
6944 }
|
|
|
6945 return this;
|
|
|
6946 },
|
|
|
6947
|
|
|
6948
|
|
|
6949 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
|
|
|
6950 {
|
|
|
6951 // Bit cheeky...
|
|
|
6952 return this.indexOf.apply( this.toArray.reverse(), arguments );
|
|
|
6953 },
|
|
|
6954
|
|
|
6955
|
|
|
6956 length: 0,
|
|
|
6957
|
|
|
6958
|
|
|
6959 map: function ( fn )
|
|
|
6960 {
|
|
|
6961 var a = [];
|
|
|
6962
|
|
|
6963 if ( __arrayProto.map ) {
|
|
|
6964 a = __arrayProto.map.call( this, fn, this );
|
|
|
6965 }
|
|
|
6966 else {
|
|
|
6967 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
|
|
|
6968 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
|
|
|
6969 a.push( fn.call( this, this[i], i ) );
|
|
|
6970 }
|
|
|
6971 }
|
|
|
6972
|
|
|
6973 return new _Api( this.context, a );
|
|
|
6974 },
|
|
|
6975
|
|
|
6976
|
|
|
6977 pluck: function ( prop )
|
|
|
6978 {
|
|
|
6979 return this.map( function ( el ) {
|
|
|
6980 return el[ prop ];
|
|
|
6981 } );
|
|
|
6982 },
|
|
|
6983
|
|
|
6984 pop: __arrayProto.pop,
|
|
|
6985
|
|
|
6986
|
|
|
6987 push: __arrayProto.push,
|
|
|
6988
|
|
|
6989
|
|
|
6990 // Does not return an API instance
|
|
|
6991 reduce: __arrayProto.reduce || function ( fn, init )
|
|
|
6992 {
|
|
|
6993 return _fnReduce( this, fn, init, 0, this.length, 1 );
|
|
|
6994 },
|
|
|
6995
|
|
|
6996
|
|
|
6997 reduceRight: __arrayProto.reduceRight || function ( fn, init )
|
|
|
6998 {
|
|
|
6999 return _fnReduce( this, fn, init, this.length-1, -1, -1 );
|
|
|
7000 },
|
|
|
7001
|
|
|
7002
|
|
|
7003 reverse: __arrayProto.reverse,
|
|
|
7004
|
|
|
7005
|
|
|
7006 // Object with rows, columns and opts
|
|
|
7007 selector: null,
|
|
|
7008
|
|
|
7009
|
|
|
7010 shift: __arrayProto.shift,
|
|
|
7011
|
|
|
7012
|
|
|
7013 sort: __arrayProto.sort, // ? name - order?
|
|
|
7014
|
|
|
7015
|
|
|
7016 splice: __arrayProto.splice,
|
|
|
7017
|
|
|
7018
|
|
|
7019 toArray: function ()
|
|
|
7020 {
|
|
|
7021 return __arrayProto.slice.call( this );
|
|
|
7022 },
|
|
|
7023
|
|
|
7024
|
|
|
7025 to$: function ()
|
|
|
7026 {
|
|
|
7027 return $( this );
|
|
|
7028 },
|
|
|
7029
|
|
|
7030
|
|
|
7031 toJQuery: function ()
|
|
|
7032 {
|
|
|
7033 return $( this );
|
|
|
7034 },
|
|
|
7035
|
|
|
7036
|
|
|
7037 unique: function ()
|
|
|
7038 {
|
|
|
7039 return new _Api( this.context, _unique(this) );
|
|
|
7040 },
|
|
|
7041
|
|
|
7042
|
|
|
7043 unshift: __arrayProto.unshift
|
|
|
7044 } );
|
|
|
7045
|
|
|
7046
|
|
|
7047 _Api.extend = function ( scope, obj, ext )
|
|
|
7048 {
|
|
|
7049 // Only extend API instances and static properties of the API
|
|
|
7050 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
|
|
|
7051 return;
|
|
|
7052 }
|
|
|
7053
|
|
|
7054 var
|
|
|
7055 i, ien,
|
|
|
7056 j, jen,
|
|
|
7057 struct, inner,
|
|
|
7058 methodScoping = function ( scope, fn, struc ) {
|
|
|
7059 return function () {
|
|
|
7060 var ret = fn.apply( scope, arguments );
|
|
|
7061
|
|
|
7062 // Method extension
|
|
|
7063 _Api.extend( ret, ret, struc.methodExt );
|
|
|
7064 return ret;
|
|
|
7065 };
|
|
|
7066 };
|
|
|
7067
|
|
|
7068 for ( i=0, ien=ext.length ; i<ien ; i++ ) {
|
|
|
7069 struct = ext[i];
|
|
|
7070
|
|
|
7071 // Value
|
|
|
7072 obj[ struct.name ] = typeof struct.val === 'function' ?
|
|
|
7073 methodScoping( scope, struct.val, struct ) :
|
|
|
7074 $.isPlainObject( struct.val ) ?
|
|
|
7075 {} :
|
|
|
7076 struct.val;
|
|
|
7077
|
|
|
7078 obj[ struct.name ].__dt_wrapper = true;
|
|
|
7079
|
|
|
7080 // Property extension
|
|
|
7081 _Api.extend( scope, obj[ struct.name ], struct.propExt );
|
|
|
7082 }
|
|
|
7083 };
|
|
|
7084
|
|
|
7085
|
|
|
7086 // @todo - Is there need for an augment function?
|
|
|
7087 // _Api.augment = function ( inst, name )
|
|
|
7088 // {
|
|
|
7089 // // Find src object in the structure from the name
|
|
|
7090 // var parts = name.split('.');
|
|
|
7091
|
|
|
7092 // _Api.extend( inst, obj );
|
|
|
7093 // };
|
|
|
7094
|
|
|
7095
|
|
|
7096 // [
|
|
|
7097 // {
|
|
|
7098 // name: 'data' -- string - Property name
|
|
|
7099 // val: function () {}, -- function - Api method (or undefined if just an object
|
|
|
7100 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
|
|
|
7101 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
|
|
|
7102 // },
|
|
|
7103 // {
|
|
|
7104 // name: 'row'
|
|
|
7105 // val: {},
|
|
|
7106 // methodExt: [ ... ],
|
|
|
7107 // propExt: [
|
|
|
7108 // {
|
|
|
7109 // name: 'data'
|
|
|
7110 // val: function () {},
|
|
|
7111 // methodExt: [ ... ],
|
|
|
7112 // propExt: [ ... ]
|
|
|
7113 // },
|
|
|
7114 // ...
|
|
|
7115 // ]
|
|
|
7116 // }
|
|
|
7117 // ]
|
|
|
7118
|
|
|
7119 _Api.register = _api_register = function ( name, val )
|
|
|
7120 {
|
|
|
7121 if ( $.isArray( name ) ) {
|
|
|
7122 for ( var j=0, jen=name.length ; j<jen ; j++ ) {
|
|
|
7123 _Api.register( name[j], val );
|
|
|
7124 }
|
|
|
7125 return;
|
|
|
7126 }
|
|
|
7127
|
|
|
7128 var
|
|
|
7129 i, ien,
|
|
|
7130 heir = name.split('.'),
|
|
|
7131 struct = __apiStruct,
|
|
|
7132 key, method;
|
|
|
7133
|
|
|
7134 var find = function ( src, name ) {
|
|
|
7135 for ( var i=0, ien=src.length ; i<ien ; i++ ) {
|
|
|
7136 if ( src[i].name === name ) {
|
|
|
7137 return src[i];
|
|
|
7138 }
|
|
|
7139 }
|
|
|
7140 return null;
|
|
|
7141 };
|
|
|
7142
|
|
|
7143 for ( i=0, ien=heir.length ; i<ien ; i++ ) {
|
|
|
7144 method = heir[i].indexOf('()') !== -1;
|
|
|
7145 key = method ?
|
|
|
7146 heir[i].replace('()', '') :
|
|
|
7147 heir[i];
|
|
|
7148
|
|
|
7149 var src = find( struct, key );
|
|
|
7150 if ( ! src ) {
|
|
|
7151 src = {
|
|
|
7152 name: key,
|
|
|
7153 val: {},
|
|
|
7154 methodExt: [],
|
|
|
7155 propExt: []
|
|
|
7156 };
|
|
|
7157 struct.push( src );
|
|
|
7158 }
|
|
|
7159
|
|
|
7160 if ( i === ien-1 ) {
|
|
|
7161 src.val = val;
|
|
|
7162 }
|
|
|
7163 else {
|
|
|
7164 struct = method ?
|
|
|
7165 src.methodExt :
|
|
|
7166 src.propExt;
|
|
|
7167 }
|
|
|
7168 }
|
|
|
7169 };
|
|
|
7170
|
|
|
7171
|
|
|
7172 _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
|
|
|
7173 _Api.register( pluralName, val );
|
|
|
7174
|
|
|
7175 _Api.register( singularName, function () {
|
|
|
7176 var ret = val.apply( this, arguments );
|
|
|
7177
|
|
|
7178 if ( ret === this ) {
|
|
|
7179 // Returned item is the API instance that was passed in, return it
|
|
|
7180 return this;
|
|
|
7181 }
|
|
|
7182 else if ( ret instanceof _Api ) {
|
|
|
7183 // New API instance returned, want the value from the first item
|
|
|
7184 // in the returned array for the singular result.
|
|
|
7185 return ret.length ?
|
|
|
7186 $.isArray( ret[0] ) ?
|
|
|
7187 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
|
|
|
7188 ret[0] :
|
|
|
7189 undefined;
|
|
|
7190 }
|
|
|
7191
|
|
|
7192 // Non-API return - just fire it back
|
|
|
7193 return ret;
|
|
|
7194 } );
|
|
|
7195 };
|
|
|
7196
|
|
|
7197
|
|
|
7198 /**
|
|
|
7199 * Selector for HTML tables. Apply the given selector to the give array of
|
|
|
7200 * DataTables settings objects.
|
|
|
7201 *
|
|
|
7202 * @param {string|integer} [selector] jQuery selector string or integer
|
|
|
7203 * @param {array} Array of DataTables settings objects to be filtered
|
|
|
7204 * @return {array}
|
|
|
7205 * @ignore
|
|
|
7206 */
|
|
|
7207 var __table_selector = function ( selector, a )
|
|
|
7208 {
|
|
|
7209 // Integer is used to pick out a table by index
|
|
|
7210 if ( typeof selector === 'number' ) {
|
|
|
7211 return [ a[ selector ] ];
|
|
|
7212 }
|
|
|
7213
|
|
|
7214 // Perform a jQuery selector on the table nodes
|
|
|
7215 var nodes = $.map( a, function (el, i) {
|
|
|
7216 return el.nTable;
|
|
|
7217 } );
|
|
|
7218
|
|
|
7219 return $(nodes)
|
|
|
7220 .filter( selector )
|
|
|
7221 .map( function (i) {
|
|
|
7222 // Need to translate back from the table node to the settings
|
|
|
7223 var idx = $.inArray( this, nodes );
|
|
|
7224 return a[ idx ];
|
|
|
7225 } )
|
|
|
7226 .toArray();
|
|
|
7227 };
|
|
|
7228
|
|
|
7229
|
|
|
7230
|
|
|
7231 /**
|
|
|
7232 * Context selector for the API's context (i.e. the tables the API instance
|
|
|
7233 * refers to.
|
|
|
7234 *
|
|
|
7235 * @name DataTable.Api#tables
|
|
|
7236 * @param {string|integer} [selector] Selector to pick which tables the iterator
|
|
|
7237 * should operate on. If not given, all tables in the current context are
|
|
|
7238 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
|
|
|
7239 * select multiple tables or as an integer to select a single table.
|
|
|
7240 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
|
|
|
7241 */
|
|
|
7242 _api_register( 'tables()', function ( selector ) {
|
|
|
7243 // A new instance is created if there was a selector specified
|
|
|
7244 return selector ?
|
|
|
7245 new _Api( __table_selector( selector, this.context ) ) :
|
|
|
7246 this;
|
|
|
7247 } );
|
|
|
7248
|
|
|
7249
|
|
|
7250 _api_register( 'table()', function ( selector ) {
|
|
|
7251 var tables = this.tables( selector );
|
|
|
7252 var ctx = tables.context;
|
|
|
7253
|
|
|
7254 // Truncate to the first matched table
|
|
|
7255 return ctx.length ?
|
|
|
7256 new _Api( ctx[0] ) :
|
|
|
7257 tables;
|
|
|
7258 } );
|
|
|
7259
|
|
|
7260
|
|
|
7261 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
|
|
|
7262 return this.iterator( 'table', function ( ctx ) {
|
|
|
7263 return ctx.nTable;
|
|
|
7264 }, 1 );
|
|
|
7265 } );
|
|
|
7266
|
|
|
7267
|
|
|
7268 _api_registerPlural( 'tables().body()', 'table().body()' , function () {
|
|
|
7269 return this.iterator( 'table', function ( ctx ) {
|
|
|
7270 return ctx.nTBody;
|
|
|
7271 }, 1 );
|
|
|
7272 } );
|
|
|
7273
|
|
|
7274
|
|
|
7275 _api_registerPlural( 'tables().header()', 'table().header()' , function () {
|
|
|
7276 return this.iterator( 'table', function ( ctx ) {
|
|
|
7277 return ctx.nTHead;
|
|
|
7278 }, 1 );
|
|
|
7279 } );
|
|
|
7280
|
|
|
7281
|
|
|
7282 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
|
|
|
7283 return this.iterator( 'table', function ( ctx ) {
|
|
|
7284 return ctx.nTFoot;
|
|
|
7285 }, 1 );
|
|
|
7286 } );
|
|
|
7287
|
|
|
7288
|
|
|
7289 _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
|
|
|
7290 return this.iterator( 'table', function ( ctx ) {
|
|
|
7291 return ctx.nTableWrapper;
|
|
|
7292 }, 1 );
|
|
|
7293 } );
|
|
|
7294
|
|
|
7295
|
|
|
7296
|
|
|
7297 /**
|
|
|
7298 * Redraw the tables in the current context.
|
|
|
7299 */
|
|
|
7300 _api_register( 'draw()', function ( paging ) {
|
|
|
7301 return this.iterator( 'table', function ( settings ) {
|
|
|
7302 if ( paging === 'page' ) {
|
|
|
7303 _fnDraw( settings );
|
|
|
7304 }
|
|
|
7305 else {
|
|
|
7306 if ( typeof paging === 'string' ) {
|
|
|
7307 paging = paging === 'full-hold' ?
|
|
|
7308 false :
|
|
|
7309 true;
|
|
|
7310 }
|
|
|
7311
|
|
|
7312 _fnReDraw( settings, paging===false );
|
|
|
7313 }
|
|
|
7314 } );
|
|
|
7315 } );
|
|
|
7316
|
|
|
7317
|
|
|
7318
|
|
|
7319 /**
|
|
|
7320 * Get the current page index.
|
|
|
7321 *
|
|
|
7322 * @return {integer} Current page index (zero based)
|
|
|
7323 *//**
|
|
|
7324 * Set the current page.
|
|
|
7325 *
|
|
|
7326 * Note that if you attempt to show a page which does not exist, DataTables will
|
|
|
7327 * not throw an error, but rather reset the paging.
|
|
|
7328 *
|
|
|
7329 * @param {integer|string} action The paging action to take. This can be one of:
|
|
|
7330 * * `integer` - The page index to jump to
|
|
|
7331 * * `string` - An action to take:
|
|
|
7332 * * `first` - Jump to first page.
|
|
|
7333 * * `next` - Jump to the next page
|
|
|
7334 * * `previous` - Jump to previous page
|
|
|
7335 * * `last` - Jump to the last page.
|
|
|
7336 * @returns {DataTables.Api} this
|
|
|
7337 */
|
|
|
7338 _api_register( 'page()', function ( action ) {
|
|
|
7339 if ( action === undefined ) {
|
|
|
7340 return this.page.info().page; // not an expensive call
|
|
|
7341 }
|
|
|
7342
|
|
|
7343 // else, have an action to take on all tables
|
|
|
7344 return this.iterator( 'table', function ( settings ) {
|
|
|
7345 _fnPageChange( settings, action );
|
|
|
7346 } );
|
|
|
7347 } );
|
|
|
7348
|
|
|
7349
|
|
|
7350 /**
|
|
|
7351 * Paging information for the first table in the current context.
|
|
|
7352 *
|
|
|
7353 * If you require paging information for another table, use the `table()` method
|
|
|
7354 * with a suitable selector.
|
|
|
7355 *
|
|
|
7356 * @return {object} Object with the following properties set:
|
|
|
7357 * * `page` - Current page index (zero based - i.e. the first page is `0`)
|
|
|
7358 * * `pages` - Total number of pages
|
|
|
7359 * * `start` - Display index for the first record shown on the current page
|
|
|
7360 * * `end` - Display index for the last record shown on the current page
|
|
|
7361 * * `length` - Display length (number of records). Note that generally `start
|
|
|
7362 * + length = end`, but this is not always true, for example if there are
|
|
|
7363 * only 2 records to show on the final page, with a length of 10.
|
|
|
7364 * * `recordsTotal` - Full data set length
|
|
|
7365 * * `recordsDisplay` - Data set length once the current filtering criterion
|
|
|
7366 * are applied.
|
|
|
7367 */
|
|
|
7368 _api_register( 'page.info()', function ( action ) {
|
|
|
7369 if ( this.context.length === 0 ) {
|
|
|
7370 return undefined;
|
|
|
7371 }
|
|
|
7372
|
|
|
7373 var
|
|
|
7374 settings = this.context[0],
|
|
|
7375 start = settings._iDisplayStart,
|
|
|
7376 len = settings._iDisplayLength,
|
|
|
7377 visRecords = settings.fnRecordsDisplay(),
|
|
|
7378 all = len === -1;
|
|
|
7379
|
|
|
7380 return {
|
|
|
7381 "page": all ? 0 : Math.floor( start / len ),
|
|
|
7382 "pages": all ? 1 : Math.ceil( visRecords / len ),
|
|
|
7383 "start": start,
|
|
|
7384 "end": settings.fnDisplayEnd(),
|
|
|
7385 "length": len,
|
|
|
7386 "recordsTotal": settings.fnRecordsTotal(),
|
|
|
7387 "recordsDisplay": visRecords,
|
|
|
7388 "serverSide": _fnDataSource( settings ) === 'ssp'
|
|
|
7389 };
|
|
|
7390 } );
|
|
|
7391
|
|
|
7392
|
|
|
7393 /**
|
|
|
7394 * Get the current page length.
|
|
|
7395 *
|
|
|
7396 * @return {integer} Current page length. Note `-1` indicates that all records
|
|
|
7397 * are to be shown.
|
|
|
7398 *//**
|
|
|
7399 * Set the current page length.
|
|
|
7400 *
|
|
|
7401 * @param {integer} Page length to set. Use `-1` to show all records.
|
|
|
7402 * @returns {DataTables.Api} this
|
|
|
7403 */
|
|
|
7404 _api_register( 'page.len()', function ( len ) {
|
|
|
7405 // Note that we can't call this function 'length()' because `length`
|
|
|
7406 // is a Javascript property of functions which defines how many arguments
|
|
|
7407 // the function expects.
|
|
|
7408 if ( len === undefined ) {
|
|
|
7409 return this.context.length !== 0 ?
|
|
|
7410 this.context[0]._iDisplayLength :
|
|
|
7411 undefined;
|
|
|
7412 }
|
|
|
7413
|
|
|
7414 // else, set the page length
|
|
|
7415 return this.iterator( 'table', function ( settings ) {
|
|
|
7416 _fnLengthChange( settings, len );
|
|
|
7417 } );
|
|
|
7418 } );
|
|
|
7419
|
|
|
7420
|
|
|
7421
|
|
|
7422 var __reload = function ( settings, holdPosition, callback ) {
|
|
|
7423 // Use the draw event to trigger a callback
|
|
|
7424 if ( callback ) {
|
|
|
7425 var api = new _Api( settings );
|
|
|
7426
|
|
|
7427 api.one( 'draw', function () {
|
|
|
7428 callback( api.ajax.json() );
|
|
|
7429 } );
|
|
|
7430 }
|
|
|
7431
|
|
|
7432 if ( _fnDataSource( settings ) == 'ssp' ) {
|
|
|
7433 _fnReDraw( settings, holdPosition );
|
|
|
7434 }
|
|
|
7435 else {
|
|
|
7436 _fnProcessingDisplay( settings, true );
|
|
|
7437
|
|
|
7438 // Cancel an existing request
|
|
|
7439 var xhr = settings.jqXHR;
|
|
|
7440 if ( xhr && xhr.readyState !== 4 ) {
|
|
|
7441 xhr.abort();
|
|
|
7442 }
|
|
|
7443
|
|
|
7444 // Trigger xhr
|
|
|
7445 _fnBuildAjax( settings, [], function( json ) {
|
|
|
7446 _fnClearTable( settings );
|
|
|
7447
|
|
|
7448 var data = _fnAjaxDataSrc( settings, json );
|
|
|
7449 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
7450 _fnAddData( settings, data[i] );
|
|
|
7451 }
|
|
|
7452
|
|
|
7453 _fnReDraw( settings, holdPosition );
|
|
|
7454 _fnProcessingDisplay( settings, false );
|
|
|
7455 } );
|
|
|
7456 }
|
|
|
7457 };
|
|
|
7458
|
|
|
7459
|
|
|
7460 /**
|
|
|
7461 * Get the JSON response from the last Ajax request that DataTables made to the
|
|
|
7462 * server. Note that this returns the JSON from the first table in the current
|
|
|
7463 * context.
|
|
|
7464 *
|
|
|
7465 * @return {object} JSON received from the server.
|
|
|
7466 */
|
|
|
7467 _api_register( 'ajax.json()', function () {
|
|
|
7468 var ctx = this.context;
|
|
|
7469
|
|
|
7470 if ( ctx.length > 0 ) {
|
|
|
7471 return ctx[0].json;
|
|
|
7472 }
|
|
|
7473
|
|
|
7474 // else return undefined;
|
|
|
7475 } );
|
|
|
7476
|
|
|
7477
|
|
|
7478 /**
|
|
|
7479 * Get the data submitted in the last Ajax request
|
|
|
7480 */
|
|
|
7481 _api_register( 'ajax.params()', function () {
|
|
|
7482 var ctx = this.context;
|
|
|
7483
|
|
|
7484 if ( ctx.length > 0 ) {
|
|
|
7485 return ctx[0].oAjaxData;
|
|
|
7486 }
|
|
|
7487
|
|
|
7488 // else return undefined;
|
|
|
7489 } );
|
|
|
7490
|
|
|
7491
|
|
|
7492 /**
|
|
|
7493 * Reload tables from the Ajax data source. Note that this function will
|
|
|
7494 * automatically re-draw the table when the remote data has been loaded.
|
|
|
7495 *
|
|
|
7496 * @param {boolean} [reset=true] Reset (default) or hold the current paging
|
|
|
7497 * position. A full re-sort and re-filter is performed when this method is
|
|
|
7498 * called, which is why the pagination reset is the default action.
|
|
|
7499 * @returns {DataTables.Api} this
|
|
|
7500 */
|
|
|
7501 _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
|
|
|
7502 return this.iterator( 'table', function (settings) {
|
|
|
7503 __reload( settings, resetPaging===false, callback );
|
|
|
7504 } );
|
|
|
7505 } );
|
|
|
7506
|
|
|
7507
|
|
|
7508 /**
|
|
|
7509 * Get the current Ajax URL. Note that this returns the URL from the first
|
|
|
7510 * table in the current context.
|
|
|
7511 *
|
|
|
7512 * @return {string} Current Ajax source URL
|
|
|
7513 *//**
|
|
|
7514 * Set the Ajax URL. Note that this will set the URL for all tables in the
|
|
|
7515 * current context.
|
|
|
7516 *
|
|
|
7517 * @param {string} url URL to set.
|
|
|
7518 * @returns {DataTables.Api} this
|
|
|
7519 */
|
|
|
7520 _api_register( 'ajax.url()', function ( url ) {
|
|
|
7521 var ctx = this.context;
|
|
|
7522
|
|
|
7523 if ( url === undefined ) {
|
|
|
7524 // get
|
|
|
7525 if ( ctx.length === 0 ) {
|
|
|
7526 return undefined;
|
|
|
7527 }
|
|
|
7528 ctx = ctx[0];
|
|
|
7529
|
|
|
7530 return ctx.ajax ?
|
|
|
7531 $.isPlainObject( ctx.ajax ) ?
|
|
|
7532 ctx.ajax.url :
|
|
|
7533 ctx.ajax :
|
|
|
7534 ctx.sAjaxSource;
|
|
|
7535 }
|
|
|
7536
|
|
|
7537 // set
|
|
|
7538 return this.iterator( 'table', function ( settings ) {
|
|
|
7539 if ( $.isPlainObject( settings.ajax ) ) {
|
|
|
7540 settings.ajax.url = url;
|
|
|
7541 }
|
|
|
7542 else {
|
|
|
7543 settings.ajax = url;
|
|
|
7544 }
|
|
|
7545 // No need to consider sAjaxSource here since DataTables gives priority
|
|
|
7546 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
|
|
|
7547 // value of `sAjaxSource` redundant.
|
|
|
7548 } );
|
|
|
7549 } );
|
|
|
7550
|
|
|
7551
|
|
|
7552 /**
|
|
|
7553 * Load data from the newly set Ajax URL. Note that this method is only
|
|
|
7554 * available when `ajax.url()` is used to set a URL. Additionally, this method
|
|
|
7555 * has the same effect as calling `ajax.reload()` but is provided for
|
|
|
7556 * convenience when setting a new URL. Like `ajax.reload()` it will
|
|
|
7557 * automatically redraw the table once the remote data has been loaded.
|
|
|
7558 *
|
|
|
7559 * @returns {DataTables.Api} this
|
|
|
7560 */
|
|
|
7561 _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
|
|
|
7562 // Same as a reload, but makes sense to present it for easy access after a
|
|
|
7563 // url change
|
|
|
7564 return this.iterator( 'table', function ( ctx ) {
|
|
|
7565 __reload( ctx, resetPaging===false, callback );
|
|
|
7566 } );
|
|
|
7567 } );
|
|
|
7568
|
|
|
7569
|
|
|
7570
|
|
|
7571
|
|
|
7572 var _selector_run = function ( type, selector, selectFn, settings, opts )
|
|
|
7573 {
|
|
|
7574 var
|
|
|
7575 out = [], res,
|
|
|
7576 a, i, ien, j, jen,
|
|
|
7577 selectorType = typeof selector;
|
|
|
7578
|
|
|
7579 // Can't just check for isArray here, as an API or jQuery instance might be
|
|
|
7580 // given with their array like look
|
|
|
7581 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
|
|
|
7582 selector = [ selector ];
|
|
|
7583 }
|
|
|
7584
|
|
|
7585 for ( i=0, ien=selector.length ; i<ien ; i++ ) {
|
|
|
7586 a = selector[i] && selector[i].split ?
|
|
|
7587 selector[i].split(',') :
|
|
|
7588 [ selector[i] ];
|
|
|
7589
|
|
|
7590 for ( j=0, jen=a.length ; j<jen ; j++ ) {
|
|
|
7591 res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
|
|
|
7592
|
|
|
7593 if ( res && res.length ) {
|
|
|
7594 out = out.concat( res );
|
|
|
7595 }
|
|
|
7596 }
|
|
|
7597 }
|
|
|
7598
|
|
|
7599 // selector extensions
|
|
|
7600 var ext = _ext.selector[ type ];
|
|
|
7601 if ( ext.length ) {
|
|
|
7602 for ( i=0, ien=ext.length ; i<ien ; i++ ) {
|
|
|
7603 out = ext[i]( settings, opts, out );
|
|
|
7604 }
|
|
|
7605 }
|
|
|
7606
|
|
|
7607 return _unique( out );
|
|
|
7608 };
|
|
|
7609
|
|
|
7610
|
|
|
7611 var _selector_opts = function ( opts )
|
|
|
7612 {
|
|
|
7613 if ( ! opts ) {
|
|
|
7614 opts = {};
|
|
|
7615 }
|
|
|
7616
|
|
|
7617 // Backwards compatibility for 1.9- which used the terminology filter rather
|
|
|
7618 // than search
|
|
|
7619 if ( opts.filter && opts.search === undefined ) {
|
|
|
7620 opts.search = opts.filter;
|
|
|
7621 }
|
|
|
7622
|
|
|
7623 return $.extend( {
|
|
|
7624 search: 'none',
|
|
|
7625 order: 'current',
|
|
|
7626 page: 'all'
|
|
|
7627 }, opts );
|
|
|
7628 };
|
|
|
7629
|
|
|
7630
|
|
|
7631 var _selector_first = function ( inst )
|
|
|
7632 {
|
|
|
7633 // Reduce the API instance to the first item found
|
|
|
7634 for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
|
|
|
7635 if ( inst[i].length > 0 ) {
|
|
|
7636 // Assign the first element to the first item in the instance
|
|
|
7637 // and truncate the instance and context
|
|
|
7638 inst[0] = inst[i];
|
|
|
7639 inst[0].length = 1;
|
|
|
7640 inst.length = 1;
|
|
|
7641 inst.context = [ inst.context[i] ];
|
|
|
7642
|
|
|
7643 return inst;
|
|
|
7644 }
|
|
|
7645 }
|
|
|
7646
|
|
|
7647 // Not found - return an empty instance
|
|
|
7648 inst.length = 0;
|
|
|
7649 return inst;
|
|
|
7650 };
|
|
|
7651
|
|
|
7652
|
|
|
7653 var _selector_row_indexes = function ( settings, opts )
|
|
|
7654 {
|
|
|
7655 var
|
|
|
7656 i, ien, tmp, a=[],
|
|
|
7657 displayFiltered = settings.aiDisplay,
|
|
|
7658 displayMaster = settings.aiDisplayMaster;
|
|
|
7659
|
|
|
7660 var
|
|
|
7661 search = opts.search, // none, applied, removed
|
|
|
7662 order = opts.order, // applied, current, index (original - compatibility with 1.9)
|
|
|
7663 page = opts.page; // all, current
|
|
|
7664
|
|
|
7665 if ( _fnDataSource( settings ) == 'ssp' ) {
|
|
|
7666 // In server-side processing mode, most options are irrelevant since
|
|
|
7667 // rows not shown don't exist and the index order is the applied order
|
|
|
7668 // Removed is a special case - for consistency just return an empty
|
|
|
7669 // array
|
|
|
7670 return search === 'removed' ?
|
|
|
7671 [] :
|
|
|
7672 _range( 0, displayMaster.length );
|
|
|
7673 }
|
|
|
7674 else if ( page == 'current' ) {
|
|
|
7675 // Current page implies that order=current and fitler=applied, since it is
|
|
|
7676 // fairly senseless otherwise, regardless of what order and search actually
|
|
|
7677 // are
|
|
|
7678 for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
|
|
|
7679 a.push( displayFiltered[i] );
|
|
|
7680 }
|
|
|
7681 }
|
|
|
7682 else if ( order == 'current' || order == 'applied' ) {
|
|
|
7683 a = search == 'none' ?
|
|
|
7684 displayMaster.slice() : // no search
|
|
|
7685 search == 'applied' ?
|
|
|
7686 displayFiltered.slice() : // applied search
|
|
|
7687 $.map( displayMaster, function (el, i) { // removed search
|
|
|
7688 return $.inArray( el, displayFiltered ) === -1 ? el : null;
|
|
|
7689 } );
|
|
|
7690 }
|
|
|
7691 else if ( order == 'index' || order == 'original' ) {
|
|
|
7692 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
|
7693 if ( search == 'none' ) {
|
|
|
7694 a.push( i );
|
|
|
7695 }
|
|
|
7696 else { // applied | removed
|
|
|
7697 tmp = $.inArray( i, displayFiltered );
|
|
|
7698
|
|
|
7699 if ((tmp === -1 && search == 'removed') ||
|
|
|
7700 (tmp >= 0 && search == 'applied') )
|
|
|
7701 {
|
|
|
7702 a.push( i );
|
|
|
7703 }
|
|
|
7704 }
|
|
|
7705 }
|
|
|
7706 }
|
|
|
7707
|
|
|
7708 return a;
|
|
|
7709 };
|
|
|
7710
|
|
|
7711
|
|
|
7712 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
|
7713 * Rows
|
|
|
7714 *
|
|
|
7715 * {} - no selector - use all available rows
|
|
|
7716 * {integer} - row aoData index
|
|
|
7717 * {node} - TR node
|
|
|
7718 * {string} - jQuery selector to apply to the TR elements
|
|
|
7719 * {array} - jQuery array of nodes, or simply an array of TR nodes
|
|
|
7720 *
|
|
|
7721 */
|
|
|
7722
|
|
|
7723
|
|
|
7724 var __row_selector = function ( settings, selector, opts )
|
|
|
7725 {
|
|
|
7726 var run = function ( sel ) {
|
|
|
7727 var selInt = _intVal( sel );
|
|
|
7728 var i, ien;
|
|
|
7729
|
|
|
7730 // Short cut - selector is a number and no options provided (default is
|
|
|
7731 // all records, so no need to check if the index is in there, since it
|
|
|
7732 // must be - dev error if the index doesn't exist).
|
|
|
7733 if ( selInt !== null && ! opts ) {
|
|
|
7734 return [ selInt ];
|
|
|
7735 }
|
|
|
7736
|
|
|
7737 var rows = _selector_row_indexes( settings, opts );
|
|
|
7738
|
|
|
7739 if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
|
|
|
7740 // Selector - integer
|
|
|
7741 return [ selInt ];
|
|
|
7742 }
|
|
|
7743 else if ( ! sel ) {
|
|
|
7744 // Selector - none
|
|
|
7745 return rows;
|
|
|
7746 }
|
|
|
7747
|
|
|
7748 // Selector - function
|
|
|
7749 if ( typeof sel === 'function' ) {
|
|
|
7750 return $.map( rows, function (idx) {
|
|
|
7751 var row = settings.aoData[ idx ];
|
|
|
7752 return sel( idx, row._aData, row.nTr ) ? idx : null;
|
|
|
7753 } );
|
|
|
7754 }
|
|
|
7755
|
|
|
7756 // Get nodes in the order from the `rows` array with null values removed
|
|
|
7757 var nodes = _removeEmpty(
|
|
|
7758 _pluck_order( settings.aoData, rows, 'nTr' )
|
|
|
7759 );
|
|
|
7760
|
|
|
7761 // Selector - node
|
|
|
7762 if ( sel.nodeName ) {
|
|
|
7763 if ( $.inArray( sel, nodes ) !== -1 ) {
|
|
|
7764 return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table
|
|
|
7765 // and DataTables adds a prop for fast lookup
|
|
|
7766 }
|
|
|
7767 }
|
|
|
7768
|
|
|
7769 // ID selector. Want to always be able to select rows by id, regardless
|
|
|
7770 // of if the tr element has been created or not, so can't rely upon
|
|
|
7771 // jQuery here - hence a custom implementation. This does not match
|
|
|
7772 // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
|
|
|
7773 // but to select it using a CSS selector engine (like Sizzle or
|
|
|
7774 // querySelect) it would need to need to be escaped for some characters.
|
|
|
7775 // DataTables simplifies this for row selectors since you can select
|
|
|
7776 // only a row. A # indicates an id any anything that follows is the id -
|
|
|
7777 // unescaped.
|
|
|
7778 if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
|
|
|
7779 // get row index from id
|
|
|
7780 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
|
|
|
7781 if ( rowObj !== undefined ) {
|
|
|
7782 return [ rowObj.idx ];
|
|
|
7783 }
|
|
|
7784
|
|
|
7785 // need to fall through to jQuery in case there is DOM id that
|
|
|
7786 // matches
|
|
|
7787 }
|
|
|
7788
|
|
|
7789 // Selector - jQuery selector string, array of nodes or jQuery object/
|
|
|
7790 // As jQuery's .filter() allows jQuery objects to be passed in filter,
|
|
|
7791 // it also allows arrays, so this will cope with all three options
|
|
|
7792 return $(nodes)
|
|
|
7793 .filter( sel )
|
|
|
7794 .map( function () {
|
|
|
7795 return this._DT_RowIndex;
|
|
|
7796 } )
|
|
|
7797 .toArray();
|
|
|
7798 };
|
|
|
7799
|
|
|
7800 return _selector_run( 'row', selector, run, settings, opts );
|
|
|
7801 };
|
|
|
7802
|
|
|
7803
|
|
|
7804 _api_register( 'rows()', function ( selector, opts ) {
|
|
|
7805 // argument shifting
|
|
|
7806 if ( selector === undefined ) {
|
|
|
7807 selector = '';
|
|
|
7808 }
|
|
|
7809 else if ( $.isPlainObject( selector ) ) {
|
|
|
7810 opts = selector;
|
|
|
7811 selector = '';
|
|
|
7812 }
|
|
|
7813
|
|
|
7814 opts = _selector_opts( opts );
|
|
|
7815
|
|
|
7816 var inst = this.iterator( 'table', function ( settings ) {
|
|
|
7817 return __row_selector( settings, selector, opts );
|
|
|
7818 }, 1 );
|
|
|
7819
|
|
|
7820 // Want argument shifting here and in __row_selector?
|
|
|
7821 inst.selector.rows = selector;
|
|
|
7822 inst.selector.opts = opts;
|
|
|
7823
|
|
|
7824 return inst;
|
|
|
7825 } );
|
|
|
7826
|
|
|
7827 _api_register( 'rows().nodes()', function () {
|
|
|
7828 return this.iterator( 'row', function ( settings, row ) {
|
|
|
7829 return settings.aoData[ row ].nTr || undefined;
|
|
|
7830 }, 1 );
|
|
|
7831 } );
|
|
|
7832
|
|
|
7833 _api_register( 'rows().data()', function () {
|
|
|
7834 return this.iterator( true, 'rows', function ( settings, rows ) {
|
|
|
7835 return _pluck_order( settings.aoData, rows, '_aData' );
|
|
|
7836 }, 1 );
|
|
|
7837 } );
|
|
|
7838
|
|
|
7839 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
|
|
|
7840 return this.iterator( 'row', function ( settings, row ) {
|
|
|
7841 var r = settings.aoData[ row ];
|
|
|
7842 return type === 'search' ? r._aFilterData : r._aSortData;
|
|
|
7843 }, 1 );
|
|
|
7844 } );
|
|
|
7845
|
|
|
7846 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
|
|
|
7847 return this.iterator( 'row', function ( settings, row ) {
|
|
|
7848 _fnInvalidate( settings, row, src );
|
|
|
7849 } );
|
|
|
7850 } );
|
|
|
7851
|
|
|
7852 _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
|
|
|
7853 return this.iterator( 'row', function ( settings, row ) {
|
|
|
7854 return row;
|
|
|
7855 }, 1 );
|
|
|
7856 } );
|
|
|
7857
|
|
|
7858 _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
|
|
|
7859 var a = [];
|
|
|
7860 var context = this.context;
|
|
|
7861
|
|
|
7862 // `iterator` will drop undefined values, but in this case we want them
|
|
|
7863 for ( var i=0, ien=context.length ; i<ien ; i++ ) {
|
|
|
7864 for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
|
|
|
7865 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
|
|
|
7866 a.push( (hash === true ? '#' : '' )+ id );
|
|
|
7867 }
|
|
|
7868 }
|
|
|
7869
|
|
|
7870 return new _Api( context, a );
|
|
|
7871 } );
|
|
|
7872
|
|
|
7873 _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
|
|
|
7874 var that = this;
|
|
|
7875
|
|
|
7876 this.iterator( 'row', function ( settings, row, thatIdx ) {
|
|
|
7877 var data = settings.aoData;
|
|
|
7878 var rowData = data[ row ];
|
|
|
7879
|
|
|
7880 data.splice( row, 1 );
|
|
|
7881
|
|
|
7882 // Update the _DT_RowIndex parameter on all rows in the table
|
|
|
7883 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
7884 if ( data[i].nTr !== null ) {
|
|
|
7885 data[i].nTr._DT_RowIndex = i;
|
|
|
7886 }
|
|
|
7887 }
|
|
|
7888
|
|
|
7889 // Delete from the display arrays
|
|
|
7890 _fnDeleteIndex( settings.aiDisplayMaster, row );
|
|
|
7891 _fnDeleteIndex( settings.aiDisplay, row );
|
|
|
7892 _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
|
|
|
7893
|
|
|
7894 // Check for an 'overflow' they case for displaying the table
|
|
|
7895 _fnLengthOverflow( settings );
|
|
|
7896
|
|
|
7897 // Remove the row's ID reference if there is one
|
|
|
7898 var id = settings.rowIdFn( rowData._aData );
|
|
|
7899 if ( id !== undefined ) {
|
|
|
7900 delete settings.aIds[ id ];
|
|
|
7901 }
|
|
|
7902 } );
|
|
|
7903
|
|
|
7904 this.iterator( 'table', function ( settings ) {
|
|
|
7905 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
|
7906 settings.aoData[i].idx = i;
|
|
|
7907 }
|
|
|
7908 } );
|
|
|
7909
|
|
|
7910 return this;
|
|
|
7911 } );
|
|
|
7912
|
|
|
7913
|
|
|
7914 _api_register( 'rows.add()', function ( rows ) {
|
|
|
7915 var newRows = this.iterator( 'table', function ( settings ) {
|
|
|
7916 var row, i, ien;
|
|
|
7917 var out = [];
|
|
|
7918
|
|
|
7919 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
|
|
|
7920 row = rows[i];
|
|
|
7921
|
|
|
7922 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
|
|
|
7923 out.push( _fnAddTr( settings, row )[0] );
|
|
|
7924 }
|
|
|
7925 else {
|
|
|
7926 out.push( _fnAddData( settings, row ) );
|
|
|
7927 }
|
|
|
7928 }
|
|
|
7929
|
|
|
7930 return out;
|
|
|
7931 }, 1 );
|
|
|
7932
|
|
|
7933 // Return an Api.rows() extended instance, so rows().nodes() etc can be used
|
|
|
7934 var modRows = this.rows( -1 );
|
|
|
7935 modRows.pop();
|
|
|
7936 $.merge( modRows, newRows );
|
|
|
7937
|
|
|
7938 return modRows;
|
|
|
7939 } );
|
|
|
7940
|
|
|
7941
|
|
|
7942
|
|
|
7943
|
|
|
7944
|
|
|
7945 /**
|
|
|
7946 *
|
|
|
7947 */
|
|
|
7948 _api_register( 'row()', function ( selector, opts ) {
|
|
|
7949 return _selector_first( this.rows( selector, opts ) );
|
|
|
7950 } );
|
|
|
7951
|
|
|
7952
|
|
|
7953 _api_register( 'row().data()', function ( data ) {
|
|
|
7954 var ctx = this.context;
|
|
|
7955
|
|
|
7956 if ( data === undefined ) {
|
|
|
7957 // Get
|
|
|
7958 return ctx.length && this.length ?
|
|
|
7959 ctx[0].aoData[ this[0] ]._aData :
|
|
|
7960 undefined;
|
|
|
7961 }
|
|
|
7962
|
|
|
7963 // Set
|
|
|
7964 ctx[0].aoData[ this[0] ]._aData = data;
|
|
|
7965
|
|
|
7966 // Automatically invalidate
|
|
|
7967 _fnInvalidate( ctx[0], this[0], 'data' );
|
|
|
7968
|
|
|
7969 return this;
|
|
|
7970 } );
|
|
|
7971
|
|
|
7972
|
|
|
7973 _api_register( 'row().node()', function () {
|
|
|
7974 var ctx = this.context;
|
|
|
7975
|
|
|
7976 return ctx.length && this.length ?
|
|
|
7977 ctx[0].aoData[ this[0] ].nTr || null :
|
|
|
7978 null;
|
|
|
7979 } );
|
|
|
7980
|
|
|
7981
|
|
|
7982 _api_register( 'row.add()', function ( row ) {
|
|
|
7983 // Allow a jQuery object to be passed in - only a single row is added from
|
|
|
7984 // it though - the first element in the set
|
|
|
7985 if ( row instanceof $ && row.length ) {
|
|
|
7986 row = row[0];
|
|
|
7987 }
|
|
|
7988
|
|
|
7989 var rows = this.iterator( 'table', function ( settings ) {
|
|
|
7990 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
|
|
|
7991 return _fnAddTr( settings, row )[0];
|
|
|
7992 }
|
|
|
7993 return _fnAddData( settings, row );
|
|
|
7994 } );
|
|
|
7995
|
|
|
7996 // Return an Api.rows() extended instance, with the newly added row selected
|
|
|
7997 return this.row( rows[0] );
|
|
|
7998 } );
|
|
|
7999
|
|
|
8000
|
|
|
8001
|
|
|
8002 var __details_add = function ( ctx, row, data, klass )
|
|
|
8003 {
|
|
|
8004 // Convert to array of TR elements
|
|
|
8005 var rows = [];
|
|
|
8006 var addRow = function ( r, k ) {
|
|
|
8007 // Recursion to allow for arrays of jQuery objects
|
|
|
8008 if ( $.isArray( r ) || r instanceof $ ) {
|
|
|
8009 for ( var i=0, ien=r.length ; i<ien ; i++ ) {
|
|
|
8010 addRow( r[i], k );
|
|
|
8011 }
|
|
|
8012 return;
|
|
|
8013 }
|
|
|
8014
|
|
|
8015 // If we get a TR element, then just add it directly - up to the dev
|
|
|
8016 // to add the correct number of columns etc
|
|
|
8017 if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
|
|
|
8018 rows.push( r );
|
|
|
8019 }
|
|
|
8020 else {
|
|
|
8021 // Otherwise create a row with a wrapper
|
|
|
8022 var created = $('<tr><td/></tr>').addClass( k );
|
|
|
8023 $('td', created)
|
|
|
8024 .addClass( k )
|
|
|
8025 .html( r )
|
|
|
8026 [0].colSpan = _fnVisbleColumns( ctx );
|
|
|
8027
|
|
|
8028 rows.push( created[0] );
|
|
|
8029 }
|
|
|
8030 };
|
|
|
8031
|
|
|
8032 addRow( data, klass );
|
|
|
8033
|
|
|
8034 if ( row._details ) {
|
|
|
8035 row._details.remove();
|
|
|
8036 }
|
|
|
8037
|
|
|
8038 row._details = $(rows);
|
|
|
8039
|
|
|
8040 // If the children were already shown, that state should be retained
|
|
|
8041 if ( row._detailsShow ) {
|
|
|
8042 row._details.insertAfter( row.nTr );
|
|
|
8043 }
|
|
|
8044 };
|
|
|
8045
|
|
|
8046
|
|
|
8047 var __details_remove = function ( api, idx )
|
|
|
8048 {
|
|
|
8049 var ctx = api.context;
|
|
|
8050
|
|
|
8051 if ( ctx.length ) {
|
|
|
8052 var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
|
|
|
8053
|
|
|
8054 if ( row && row._details ) {
|
|
|
8055 row._details.remove();
|
|
|
8056
|
|
|
8057 row._detailsShow = undefined;
|
|
|
8058 row._details = undefined;
|
|
|
8059 }
|
|
|
8060 }
|
|
|
8061 };
|
|
|
8062
|
|
|
8063
|
|
|
8064 var __details_display = function ( api, show ) {
|
|
|
8065 var ctx = api.context;
|
|
|
8066
|
|
|
8067 if ( ctx.length && api.length ) {
|
|
|
8068 var row = ctx[0].aoData[ api[0] ];
|
|
|
8069
|
|
|
8070 if ( row._details ) {
|
|
|
8071 row._detailsShow = show;
|
|
|
8072
|
|
|
8073 if ( show ) {
|
|
|
8074 row._details.insertAfter( row.nTr );
|
|
|
8075 }
|
|
|
8076 else {
|
|
|
8077 row._details.detach();
|
|
|
8078 }
|
|
|
8079
|
|
|
8080 __details_events( ctx[0] );
|
|
|
8081 }
|
|
|
8082 }
|
|
|
8083 };
|
|
|
8084
|
|
|
8085
|
|
|
8086 var __details_events = function ( settings )
|
|
|
8087 {
|
|
|
8088 var api = new _Api( settings );
|
|
|
8089 var namespace = '.dt.DT_details';
|
|
|
8090 var drawEvent = 'draw'+namespace;
|
|
|
8091 var colvisEvent = 'column-visibility'+namespace;
|
|
|
8092 var destroyEvent = 'destroy'+namespace;
|
|
|
8093 var data = settings.aoData;
|
|
|
8094
|
|
|
8095 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
|
|
|
8096
|
|
|
8097 if ( _pluck( data, '_details' ).length > 0 ) {
|
|
|
8098 // On each draw, insert the required elements into the document
|
|
|
8099 api.on( drawEvent, function ( e, ctx ) {
|
|
|
8100 if ( settings !== ctx ) {
|
|
|
8101 return;
|
|
|
8102 }
|
|
|
8103
|
|
|
8104 api.rows( {page:'current'} ).eq(0).each( function (idx) {
|
|
|
8105 // Internal data grab
|
|
|
8106 var row = data[ idx ];
|
|
|
8107
|
|
|
8108 if ( row._detailsShow ) {
|
|
|
8109 row._details.insertAfter( row.nTr );
|
|
|
8110 }
|
|
|
8111 } );
|
|
|
8112 } );
|
|
|
8113
|
|
|
8114 // Column visibility change - update the colspan
|
|
|
8115 api.on( colvisEvent, function ( e, ctx, idx, vis ) {
|
|
|
8116 if ( settings !== ctx ) {
|
|
|
8117 return;
|
|
|
8118 }
|
|
|
8119
|
|
|
8120 // Update the colspan for the details rows (note, only if it already has
|
|
|
8121 // a colspan)
|
|
|
8122 var row, visible = _fnVisbleColumns( ctx );
|
|
|
8123
|
|
|
8124 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
8125 row = data[i];
|
|
|
8126
|
|
|
8127 if ( row._details ) {
|
|
|
8128 row._details.children('td[colspan]').attr('colspan', visible );
|
|
|
8129 }
|
|
|
8130 }
|
|
|
8131 } );
|
|
|
8132
|
|
|
8133 // Table destroyed - nuke any child rows
|
|
|
8134 api.on( destroyEvent, function ( e, ctx ) {
|
|
|
8135 if ( settings !== ctx ) {
|
|
|
8136 return;
|
|
|
8137 }
|
|
|
8138
|
|
|
8139 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
8140 if ( data[i]._details ) {
|
|
|
8141 __details_remove( api, i );
|
|
|
8142 }
|
|
|
8143 }
|
|
|
8144 } );
|
|
|
8145 }
|
|
|
8146 };
|
|
|
8147
|
|
|
8148 // Strings for the method names to help minification
|
|
|
8149 var _emp = '';
|
|
|
8150 var _child_obj = _emp+'row().child';
|
|
|
8151 var _child_mth = _child_obj+'()';
|
|
|
8152
|
|
|
8153 // data can be:
|
|
|
8154 // tr
|
|
|
8155 // string
|
|
|
8156 // jQuery or array of any of the above
|
|
|
8157 _api_register( _child_mth, function ( data, klass ) {
|
|
|
8158 var ctx = this.context;
|
|
|
8159
|
|
|
8160 if ( data === undefined ) {
|
|
|
8161 // get
|
|
|
8162 return ctx.length && this.length ?
|
|
|
8163 ctx[0].aoData[ this[0] ]._details :
|
|
|
8164 undefined;
|
|
|
8165 }
|
|
|
8166 else if ( data === true ) {
|
|
|
8167 // show
|
|
|
8168 this.child.show();
|
|
|
8169 }
|
|
|
8170 else if ( data === false ) {
|
|
|
8171 // remove
|
|
|
8172 __details_remove( this );
|
|
|
8173 }
|
|
|
8174 else if ( ctx.length && this.length ) {
|
|
|
8175 // set
|
|
|
8176 __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
|
|
|
8177 }
|
|
|
8178
|
|
|
8179 return this;
|
|
|
8180 } );
|
|
|
8181
|
|
|
8182
|
|
|
8183 _api_register( [
|
|
|
8184 _child_obj+'.show()',
|
|
|
8185 _child_mth+'.show()' // only when `child()` was called with parameters (without
|
|
|
8186 ], function ( show ) { // it returns an object and this method is not executed)
|
|
|
8187 __details_display( this, true );
|
|
|
8188 return this;
|
|
|
8189 } );
|
|
|
8190
|
|
|
8191
|
|
|
8192 _api_register( [
|
|
|
8193 _child_obj+'.hide()',
|
|
|
8194 _child_mth+'.hide()' // only when `child()` was called with parameters (without
|
|
|
8195 ], function () { // it returns an object and this method is not executed)
|
|
|
8196 __details_display( this, false );
|
|
|
8197 return this;
|
|
|
8198 } );
|
|
|
8199
|
|
|
8200
|
|
|
8201 _api_register( [
|
|
|
8202 _child_obj+'.remove()',
|
|
|
8203 _child_mth+'.remove()' // only when `child()` was called with parameters (without
|
|
|
8204 ], function () { // it returns an object and this method is not executed)
|
|
|
8205 __details_remove( this );
|
|
|
8206 return this;
|
|
|
8207 } );
|
|
|
8208
|
|
|
8209
|
|
|
8210 _api_register( _child_obj+'.isShown()', function () {
|
|
|
8211 var ctx = this.context;
|
|
|
8212
|
|
|
8213 if ( ctx.length && this.length ) {
|
|
|
8214 // _detailsShown as false or undefined will fall through to return false
|
|
|
8215 return ctx[0].aoData[ this[0] ]._detailsShow || false;
|
|
|
8216 }
|
|
|
8217 return false;
|
|
|
8218 } );
|
|
|
8219
|
|
|
8220
|
|
|
8221
|
|
|
8222 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
|
8223 * Columns
|
|
|
8224 *
|
|
|
8225 * {integer} - column index (>=0 count from left, <0 count from right)
|
|
|
8226 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
|
|
|
8227 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
|
|
|
8228 * "{string}:name" - column name
|
|
|
8229 * "{string}" - jQuery selector on column header nodes
|
|
|
8230 *
|
|
|
8231 */
|
|
|
8232
|
|
|
8233 // can be an array of these items, comma separated list, or an array of comma
|
|
|
8234 // separated lists
|
|
|
8235
|
|
|
8236 var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
|
|
|
8237
|
|
|
8238
|
|
|
8239 // r1 and r2 are redundant - but it means that the parameters match for the
|
|
|
8240 // iterator callback in columns().data()
|
|
|
8241 var __columnData = function ( settings, column, r1, r2, rows ) {
|
|
|
8242 var a = [];
|
|
|
8243 for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
|
|
|
8244 a.push( _fnGetCellData( settings, rows[row], column ) );
|
|
|
8245 }
|
|
|
8246 return a;
|
|
|
8247 };
|
|
|
8248
|
|
|
8249
|
|
|
8250 var __column_selector = function ( settings, selector, opts )
|
|
|
8251 {
|
|
|
8252 var
|
|
|
8253 columns = settings.aoColumns,
|
|
|
8254 names = _pluck( columns, 'sName' ),
|
|
|
8255 nodes = _pluck( columns, 'nTh' );
|
|
|
8256
|
|
|
8257 var run = function ( s ) {
|
|
|
8258 var selInt = _intVal( s );
|
|
|
8259
|
|
|
8260 // Selector - all
|
|
|
8261 if ( s === '' ) {
|
|
|
8262 return _range( columns.length );
|
|
|
8263 }
|
|
|
8264
|
|
|
8265 // Selector - index
|
|
|
8266 if ( selInt !== null ) {
|
|
|
8267 return [ selInt >= 0 ?
|
|
|
8268 selInt : // Count from left
|
|
|
8269 columns.length + selInt // Count from right (+ because its a negative value)
|
|
|
8270 ];
|
|
|
8271 }
|
|
|
8272
|
|
|
8273 // Selector = function
|
|
|
8274 if ( typeof s === 'function' ) {
|
|
|
8275 var rows = _selector_row_indexes( settings, opts );
|
|
|
8276
|
|
|
8277 return $.map( columns, function (col, idx) {
|
|
|
8278 return s(
|
|
|
8279 idx,
|
|
|
8280 __columnData( settings, idx, 0, 0, rows ),
|
|
|
8281 nodes[ idx ]
|
|
|
8282 ) ? idx : null;
|
|
|
8283 } );
|
|
|
8284 }
|
|
|
8285
|
|
|
8286 // jQuery or string selector
|
|
|
8287 var match = typeof s === 'string' ?
|
|
|
8288 s.match( __re_column_selector ) :
|
|
|
8289 '';
|
|
|
8290
|
|
|
8291 if ( match ) {
|
|
|
8292 switch( match[2] ) {
|
|
|
8293 case 'visIdx':
|
|
|
8294 case 'visible':
|
|
|
8295 var idx = parseInt( match[1], 10 );
|
|
|
8296 // Visible index given, convert to column index
|
|
|
8297 if ( idx < 0 ) {
|
|
|
8298 // Counting from the right
|
|
|
8299 var visColumns = $.map( columns, function (col,i) {
|
|
|
8300 return col.bVisible ? i : null;
|
|
|
8301 } );
|
|
|
8302 return [ visColumns[ visColumns.length + idx ] ];
|
|
|
8303 }
|
|
|
8304 // Counting from the left
|
|
|
8305 return [ _fnVisibleToColumnIndex( settings, idx ) ];
|
|
|
8306
|
|
|
8307 case 'name':
|
|
|
8308 // match by name. `names` is column index complete and in order
|
|
|
8309 return $.map( names, function (name, i) {
|
|
|
8310 return name === match[1] ? i : null;
|
|
|
8311 } );
|
|
|
8312 }
|
|
|
8313 }
|
|
|
8314 else {
|
|
|
8315 // jQuery selector on the TH elements for the columns
|
|
|
8316 return $( nodes )
|
|
|
8317 .filter( s )
|
|
|
8318 .map( function () {
|
|
|
8319 return $.inArray( this, nodes ); // `nodes` is column index complete and in order
|
|
|
8320 } )
|
|
|
8321 .toArray();
|
|
|
8322 }
|
|
|
8323 };
|
|
|
8324
|
|
|
8325 return _selector_run( 'column', selector, run, settings, opts );
|
|
|
8326 };
|
|
|
8327
|
|
|
8328
|
|
|
8329 var __setColumnVis = function ( settings, column, vis, recalc ) {
|
|
|
8330 var
|
|
|
8331 cols = settings.aoColumns,
|
|
|
8332 col = cols[ column ],
|
|
|
8333 data = settings.aoData,
|
|
|
8334 row, cells, i, ien, tr;
|
|
|
8335
|
|
|
8336 // Get
|
|
|
8337 if ( vis === undefined ) {
|
|
|
8338 return col.bVisible;
|
|
|
8339 }
|
|
|
8340
|
|
|
8341 // Set
|
|
|
8342 // No change
|
|
|
8343 if ( col.bVisible === vis ) {
|
|
|
8344 return;
|
|
|
8345 }
|
|
|
8346
|
|
|
8347 if ( vis ) {
|
|
|
8348 // Insert column
|
|
|
8349 // Need to decide if we should use appendChild or insertBefore
|
|
|
8350 var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
|
|
|
8351
|
|
|
8352 for ( i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
8353 tr = data[i].nTr;
|
|
|
8354 cells = data[i].anCells;
|
|
|
8355
|
|
|
8356 if ( tr ) {
|
|
|
8357 // insertBefore can act like appendChild if 2nd arg is null
|
|
|
8358 tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
|
|
|
8359 }
|
|
|
8360 }
|
|
|
8361 }
|
|
|
8362 else {
|
|
|
8363 // Remove column
|
|
|
8364 $( _pluck( settings.aoData, 'anCells', column ) ).detach();
|
|
|
8365 }
|
|
|
8366
|
|
|
8367 // Common actions
|
|
|
8368 col.bVisible = vis;
|
|
|
8369 _fnDrawHead( settings, settings.aoHeader );
|
|
|
8370 _fnDrawHead( settings, settings.aoFooter );
|
|
|
8371
|
|
|
8372 if ( recalc === undefined || recalc ) {
|
|
|
8373 // Automatically adjust column sizing
|
|
|
8374 _fnAdjustColumnSizing( settings );
|
|
|
8375
|
|
|
8376 // Realign columns for scrolling
|
|
|
8377 if ( settings.oScroll.sX || settings.oScroll.sY ) {
|
|
|
8378 _fnScrollDraw( settings );
|
|
|
8379 }
|
|
|
8380 }
|
|
|
8381
|
|
|
8382 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
|
|
|
8383
|
|
|
8384 _fnSaveState( settings );
|
|
|
8385 };
|
|
|
8386
|
|
|
8387
|
|
|
8388 _api_register( 'columns()', function ( selector, opts ) {
|
|
|
8389 // argument shifting
|
|
|
8390 if ( selector === undefined ) {
|
|
|
8391 selector = '';
|
|
|
8392 }
|
|
|
8393 else if ( $.isPlainObject( selector ) ) {
|
|
|
8394 opts = selector;
|
|
|
8395 selector = '';
|
|
|
8396 }
|
|
|
8397
|
|
|
8398 opts = _selector_opts( opts );
|
|
|
8399
|
|
|
8400 var inst = this.iterator( 'table', function ( settings ) {
|
|
|
8401 return __column_selector( settings, selector, opts );
|
|
|
8402 }, 1 );
|
|
|
8403
|
|
|
8404 // Want argument shifting here and in _row_selector?
|
|
|
8405 inst.selector.cols = selector;
|
|
|
8406 inst.selector.opts = opts;
|
|
|
8407
|
|
|
8408 return inst;
|
|
|
8409 } );
|
|
|
8410
|
|
|
8411 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
|
|
|
8412 return this.iterator( 'column', function ( settings, column ) {
|
|
|
8413 return settings.aoColumns[column].nTh;
|
|
|
8414 }, 1 );
|
|
|
8415 } );
|
|
|
8416
|
|
|
8417 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
|
|
|
8418 return this.iterator( 'column', function ( settings, column ) {
|
|
|
8419 return settings.aoColumns[column].nTf;
|
|
|
8420 }, 1 );
|
|
|
8421 } );
|
|
|
8422
|
|
|
8423 _api_registerPlural( 'columns().data()', 'column().data()', function () {
|
|
|
8424 return this.iterator( 'column-rows', __columnData, 1 );
|
|
|
8425 } );
|
|
|
8426
|
|
|
8427 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
|
|
|
8428 return this.iterator( 'column', function ( settings, column ) {
|
|
|
8429 return settings.aoColumns[column].mData;
|
|
|
8430 }, 1 );
|
|
|
8431 } );
|
|
|
8432
|
|
|
8433 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
|
|
|
8434 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
|
|
|
8435 return _pluck_order( settings.aoData, rows,
|
|
|
8436 type === 'search' ? '_aFilterData' : '_aSortData', column
|
|
|
8437 );
|
|
|
8438 }, 1 );
|
|
|
8439 } );
|
|
|
8440
|
|
|
8441 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
|
|
|
8442 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
|
|
|
8443 return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
|
|
|
8444 }, 1 );
|
|
|
8445 } );
|
|
|
8446
|
|
|
8447 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
|
|
|
8448 return this.iterator( 'column', function ( settings, column ) {
|
|
|
8449 if ( vis === undefined ) {
|
|
|
8450 return settings.aoColumns[ column ].bVisible;
|
|
|
8451 } // else
|
|
|
8452 __setColumnVis( settings, column, vis, calc );
|
|
|
8453 } );
|
|
|
8454 } );
|
|
|
8455
|
|
|
8456 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
|
|
|
8457 return this.iterator( 'column', function ( settings, column ) {
|
|
|
8458 return type === 'visible' ?
|
|
|
8459 _fnColumnIndexToVisible( settings, column ) :
|
|
|
8460 column;
|
|
|
8461 }, 1 );
|
|
|
8462 } );
|
|
|
8463
|
|
|
8464 _api_register( 'columns.adjust()', function () {
|
|
|
8465 return this.iterator( 'table', function ( settings ) {
|
|
|
8466 _fnAdjustColumnSizing( settings );
|
|
|
8467 }, 1 );
|
|
|
8468 } );
|
|
|
8469
|
|
|
8470 _api_register( 'column.index()', function ( type, idx ) {
|
|
|
8471 if ( this.context.length !== 0 ) {
|
|
|
8472 var ctx = this.context[0];
|
|
|
8473
|
|
|
8474 if ( type === 'fromVisible' || type === 'toData' ) {
|
|
|
8475 return _fnVisibleToColumnIndex( ctx, idx );
|
|
|
8476 }
|
|
|
8477 else if ( type === 'fromData' || type === 'toVisible' ) {
|
|
|
8478 return _fnColumnIndexToVisible( ctx, idx );
|
|
|
8479 }
|
|
|
8480 }
|
|
|
8481 } );
|
|
|
8482
|
|
|
8483 _api_register( 'column()', function ( selector, opts ) {
|
|
|
8484 return _selector_first( this.columns( selector, opts ) );
|
|
|
8485 } );
|
|
|
8486
|
|
|
8487
|
|
|
8488
|
|
|
8489
|
|
|
8490 var __cell_selector = function ( settings, selector, opts )
|
|
|
8491 {
|
|
|
8492 var data = settings.aoData;
|
|
|
8493 var rows = _selector_row_indexes( settings, opts );
|
|
|
8494 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
|
|
|
8495 var allCells = $( [].concat.apply([], cells) );
|
|
|
8496 var row;
|
|
|
8497 var columns = settings.aoColumns.length;
|
|
|
8498 var a, i, ien, j, o, host;
|
|
|
8499
|
|
|
8500 var run = function ( s ) {
|
|
|
8501 var fnSelector = typeof s === 'function';
|
|
|
8502
|
|
|
8503 if ( s === null || s === undefined || fnSelector ) {
|
|
|
8504 // All cells and function selectors
|
|
|
8505 a = [];
|
|
|
8506
|
|
|
8507 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
|
|
|
8508 row = rows[i];
|
|
|
8509
|
|
|
8510 for ( j=0 ; j<columns ; j++ ) {
|
|
|
8511 o = {
|
|
|
8512 row: row,
|
|
|
8513 column: j
|
|
|
8514 };
|
|
|
8515
|
|
|
8516 if ( fnSelector ) {
|
|
|
8517 // Selector - function
|
|
|
8518 host = data[ row ];
|
|
|
8519
|
|
|
8520 if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
|
|
|
8521 a.push( o );
|
|
|
8522 }
|
|
|
8523 }
|
|
|
8524 else {
|
|
|
8525 // Selector - all
|
|
|
8526 a.push( o );
|
|
|
8527 }
|
|
|
8528 }
|
|
|
8529 }
|
|
|
8530
|
|
|
8531 return a;
|
|
|
8532 }
|
|
|
8533
|
|
|
8534 // Selector - index
|
|
|
8535 if ( $.isPlainObject( s ) ) {
|
|
|
8536 return [s];
|
|
|
8537 }
|
|
|
8538
|
|
|
8539 // Selector - jQuery filtered cells
|
|
|
8540 return allCells
|
|
|
8541 .filter( s )
|
|
|
8542 .map( function (i, el) {
|
|
|
8543 if ( el.parentNode ) {
|
|
|
8544 row = el.parentNode._DT_RowIndex;
|
|
|
8545 }
|
|
|
8546 else {
|
|
|
8547 // If no parent node, then the cell is hidden and we'll need
|
|
|
8548 // to traverse the array to find it
|
|
|
8549 for ( i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
8550 if ( $.inArray( el, data[i].anCells ) !== -1 ) {
|
|
|
8551 row = i;
|
|
|
8552 break;
|
|
|
8553 }
|
|
|
8554 }
|
|
|
8555 }
|
|
|
8556
|
|
|
8557 return {
|
|
|
8558 row: row,
|
|
|
8559 column: $.inArray( el, data[ row ].anCells )
|
|
|
8560 };
|
|
|
8561 } )
|
|
|
8562 .toArray();
|
|
|
8563 };
|
|
|
8564
|
|
|
8565 return _selector_run( 'cell', selector, run, settings, opts );
|
|
|
8566 };
|
|
|
8567
|
|
|
8568
|
|
|
8569
|
|
|
8570
|
|
|
8571 _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
|
|
|
8572 // Argument shifting
|
|
|
8573 if ( $.isPlainObject( rowSelector ) ) {
|
|
|
8574 // Indexes
|
|
|
8575 if ( rowSelector.row === undefined ) {
|
|
|
8576 // Selector options in first parameter
|
|
|
8577 opts = rowSelector;
|
|
|
8578 rowSelector = null;
|
|
|
8579 }
|
|
|
8580 else {
|
|
|
8581 // Cell index objects in first parameter
|
|
|
8582 opts = columnSelector;
|
|
|
8583 columnSelector = null;
|
|
|
8584 }
|
|
|
8585 }
|
|
|
8586 if ( $.isPlainObject( columnSelector ) ) {
|
|
|
8587 opts = columnSelector;
|
|
|
8588 columnSelector = null;
|
|
|
8589 }
|
|
|
8590
|
|
|
8591 // Cell selector
|
|
|
8592 if ( columnSelector === null || columnSelector === undefined ) {
|
|
|
8593 return this.iterator( 'table', function ( settings ) {
|
|
|
8594 return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
|
|
|
8595 } );
|
|
|
8596 }
|
|
|
8597
|
|
|
8598 // Row + column selector
|
|
|
8599 var columns = this.columns( columnSelector, opts );
|
|
|
8600 var rows = this.rows( rowSelector, opts );
|
|
|
8601 var a, i, ien, j, jen;
|
|
|
8602
|
|
|
8603 var cells = this.iterator( 'table', function ( settings, idx ) {
|
|
|
8604 a = [];
|
|
|
8605
|
|
|
8606 for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
|
|
|
8607 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
|
|
|
8608 a.push( {
|
|
|
8609 row: rows[idx][i],
|
|
|
8610 column: columns[idx][j]
|
|
|
8611 } );
|
|
|
8612 }
|
|
|
8613 }
|
|
|
8614
|
|
|
8615 return a;
|
|
|
8616 }, 1 );
|
|
|
8617
|
|
|
8618 $.extend( cells.selector, {
|
|
|
8619 cols: columnSelector,
|
|
|
8620 rows: rowSelector,
|
|
|
8621 opts: opts
|
|
|
8622 } );
|
|
|
8623
|
|
|
8624 return cells;
|
|
|
8625 } );
|
|
|
8626
|
|
|
8627
|
|
|
8628 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
|
|
|
8629 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
|
8630 var cells = settings.aoData[ row ].anCells;
|
|
|
8631 return cells ?
|
|
|
8632 cells[ column ] :
|
|
|
8633 undefined;
|
|
|
8634 }, 1 );
|
|
|
8635 } );
|
|
|
8636
|
|
|
8637
|
|
|
8638 _api_register( 'cells().data()', function () {
|
|
|
8639 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
|
8640 return _fnGetCellData( settings, row, column );
|
|
|
8641 }, 1 );
|
|
|
8642 } );
|
|
|
8643
|
|
|
8644
|
|
|
8645 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
|
|
|
8646 type = type === 'search' ? '_aFilterData' : '_aSortData';
|
|
|
8647
|
|
|
8648 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
|
8649 return settings.aoData[ row ][ type ][ column ];
|
|
|
8650 }, 1 );
|
|
|
8651 } );
|
|
|
8652
|
|
|
8653
|
|
|
8654 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
|
|
|
8655 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
|
8656 return _fnGetCellData( settings, row, column, type );
|
|
|
8657 }, 1 );
|
|
|
8658 } );
|
|
|
8659
|
|
|
8660
|
|
|
8661 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
|
|
|
8662 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
|
8663 return {
|
|
|
8664 row: row,
|
|
|
8665 column: column,
|
|
|
8666 columnVisible: _fnColumnIndexToVisible( settings, column )
|
|
|
8667 };
|
|
|
8668 }, 1 );
|
|
|
8669 } );
|
|
|
8670
|
|
|
8671
|
|
|
8672 _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
|
|
|
8673 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
|
8674 _fnInvalidate( settings, row, src, column );
|
|
|
8675 } );
|
|
|
8676 } );
|
|
|
8677
|
|
|
8678
|
|
|
8679
|
|
|
8680 _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
|
|
|
8681 return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
|
|
|
8682 } );
|
|
|
8683
|
|
|
8684
|
|
|
8685 _api_register( 'cell().data()', function ( data ) {
|
|
|
8686 var ctx = this.context;
|
|
|
8687 var cell = this[0];
|
|
|
8688
|
|
|
8689 if ( data === undefined ) {
|
|
|
8690 // Get
|
|
|
8691 return ctx.length && cell.length ?
|
|
|
8692 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
|
|
|
8693 undefined;
|
|
|
8694 }
|
|
|
8695
|
|
|
8696 // Set
|
|
|
8697 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
|
|
|
8698 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
|
|
|
8699
|
|
|
8700 return this;
|
|
|
8701 } );
|
|
|
8702
|
|
|
8703
|
|
|
8704
|
|
|
8705 /**
|
|
|
8706 * Get current ordering (sorting) that has been applied to the table.
|
|
|
8707 *
|
|
|
8708 * @returns {array} 2D array containing the sorting information for the first
|
|
|
8709 * table in the current context. Each element in the parent array represents
|
|
|
8710 * a column being sorted upon (i.e. multi-sorting with two columns would have
|
|
|
8711 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
|
|
|
8712 * the column index that the sorting condition applies to, the second is the
|
|
|
8713 * direction of the sort (`desc` or `asc`) and, optionally, the third is the
|
|
|
8714 * index of the sorting order from the `column.sorting` initialisation array.
|
|
|
8715 *//**
|
|
|
8716 * Set the ordering for the table.
|
|
|
8717 *
|
|
|
8718 * @param {integer} order Column index to sort upon.
|
|
|
8719 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
|
|
|
8720 * @returns {DataTables.Api} this
|
|
|
8721 *//**
|
|
|
8722 * Set the ordering for the table.
|
|
|
8723 *
|
|
|
8724 * @param {array} order 1D array of sorting information to be applied.
|
|
|
8725 * @param {array} [...] Optional additional sorting conditions
|
|
|
8726 * @returns {DataTables.Api} this
|
|
|
8727 *//**
|
|
|
8728 * Set the ordering for the table.
|
|
|
8729 *
|
|
|
8730 * @param {array} order 2D array of sorting information to be applied.
|
|
|
8731 * @returns {DataTables.Api} this
|
|
|
8732 */
|
|
|
8733 _api_register( 'order()', function ( order, dir ) {
|
|
|
8734 var ctx = this.context;
|
|
|
8735
|
|
|
8736 if ( order === undefined ) {
|
|
|
8737 // get
|
|
|
8738 return ctx.length !== 0 ?
|
|
|
8739 ctx[0].aaSorting :
|
|
|
8740 undefined;
|
|
|
8741 }
|
|
|
8742
|
|
|
8743 // set
|
|
|
8744 if ( typeof order === 'number' ) {
|
|
|
8745 // Simple column / direction passed in
|
|
|
8746 order = [ [ order, dir ] ];
|
|
|
8747 }
|
|
|
8748 else if ( ! $.isArray( order[0] ) ) {
|
|
|
8749 // Arguments passed in (list of 1D arrays)
|
|
|
8750 order = Array.prototype.slice.call( arguments );
|
|
|
8751 }
|
|
|
8752 // otherwise a 2D array was passed in
|
|
|
8753
|
|
|
8754 return this.iterator( 'table', function ( settings ) {
|
|
|
8755 settings.aaSorting = order.slice();
|
|
|
8756 } );
|
|
|
8757 } );
|
|
|
8758
|
|
|
8759
|
|
|
8760 /**
|
|
|
8761 * Attach a sort listener to an element for a given column
|
|
|
8762 *
|
|
|
8763 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
|
|
|
8764 * listener to. This can take the form of a single DOM node, a jQuery
|
|
|
8765 * collection of nodes or a jQuery selector which will identify the node(s).
|
|
|
8766 * @param {integer} column the column that a click on this node will sort on
|
|
|
8767 * @param {function} [callback] callback function when sort is run
|
|
|
8768 * @returns {DataTables.Api} this
|
|
|
8769 */
|
|
|
8770 _api_register( 'order.listener()', function ( node, column, callback ) {
|
|
|
8771 return this.iterator( 'table', function ( settings ) {
|
|
|
8772 _fnSortAttachListener( settings, node, column, callback );
|
|
|
8773 } );
|
|
|
8774 } );
|
|
|
8775
|
|
|
8776
|
|
|
8777 // Order by the selected column(s)
|
|
|
8778 _api_register( [
|
|
|
8779 'columns().order()',
|
|
|
8780 'column().order()'
|
|
|
8781 ], function ( dir ) {
|
|
|
8782 var that = this;
|
|
|
8783
|
|
|
8784 return this.iterator( 'table', function ( settings, i ) {
|
|
|
8785 var sort = [];
|
|
|
8786
|
|
|
8787 $.each( that[i], function (j, col) {
|
|
|
8788 sort.push( [ col, dir ] );
|
|
|
8789 } );
|
|
|
8790
|
|
|
8791 settings.aaSorting = sort;
|
|
|
8792 } );
|
|
|
8793 } );
|
|
|
8794
|
|
|
8795
|
|
|
8796
|
|
|
8797 _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
|
|
|
8798 var ctx = this.context;
|
|
|
8799
|
|
|
8800 if ( input === undefined ) {
|
|
|
8801 // get
|
|
|
8802 return ctx.length !== 0 ?
|
|
|
8803 ctx[0].oPreviousSearch.sSearch :
|
|
|
8804 undefined;
|
|
|
8805 }
|
|
|
8806
|
|
|
8807 // set
|
|
|
8808 return this.iterator( 'table', function ( settings ) {
|
|
|
8809 if ( ! settings.oFeatures.bFilter ) {
|
|
|
8810 return;
|
|
|
8811 }
|
|
|
8812
|
|
|
8813 _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
|
|
|
8814 "sSearch": input+"",
|
|
|
8815 "bRegex": regex === null ? false : regex,
|
|
|
8816 "bSmart": smart === null ? true : smart,
|
|
|
8817 "bCaseInsensitive": caseInsen === null ? true : caseInsen
|
|
|
8818 } ), 1 );
|
|
|
8819 } );
|
|
|
8820 } );
|
|
|
8821
|
|
|
8822
|
|
|
8823 _api_registerPlural(
|
|
|
8824 'columns().search()',
|
|
|
8825 'column().search()',
|
|
|
8826 function ( input, regex, smart, caseInsen ) {
|
|
|
8827 return this.iterator( 'column', function ( settings, column ) {
|
|
|
8828 var preSearch = settings.aoPreSearchCols;
|
|
|
8829
|
|
|
8830 if ( input === undefined ) {
|
|
|
8831 // get
|
|
|
8832 return preSearch[ column ].sSearch;
|
|
|
8833 }
|
|
|
8834
|
|
|
8835 // set
|
|
|
8836 if ( ! settings.oFeatures.bFilter ) {
|
|
|
8837 return;
|
|
|
8838 }
|
|
|
8839
|
|
|
8840 $.extend( preSearch[ column ], {
|
|
|
8841 "sSearch": input+"",
|
|
|
8842 "bRegex": regex === null ? false : regex,
|
|
|
8843 "bSmart": smart === null ? true : smart,
|
|
|
8844 "bCaseInsensitive": caseInsen === null ? true : caseInsen
|
|
|
8845 } );
|
|
|
8846
|
|
|
8847 _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
|
|
|
8848 } );
|
|
|
8849 }
|
|
|
8850 );
|
|
|
8851
|
|
|
8852 /*
|
|
|
8853 * State API methods
|
|
|
8854 */
|
|
|
8855
|
|
|
8856 _api_register( 'state()', function () {
|
|
|
8857 return this.context.length ?
|
|
|
8858 this.context[0].oSavedState :
|
|
|
8859 null;
|
|
|
8860 } );
|
|
|
8861
|
|
|
8862
|
|
|
8863 _api_register( 'state.clear()', function () {
|
|
|
8864 return this.iterator( 'table', function ( settings ) {
|
|
|
8865 // Save an empty object
|
|
|
8866 settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
|
|
|
8867 } );
|
|
|
8868 } );
|
|
|
8869
|
|
|
8870
|
|
|
8871 _api_register( 'state.loaded()', function () {
|
|
|
8872 return this.context.length ?
|
|
|
8873 this.context[0].oLoadedState :
|
|
|
8874 null;
|
|
|
8875 } );
|
|
|
8876
|
|
|
8877
|
|
|
8878 _api_register( 'state.save()', function () {
|
|
|
8879 return this.iterator( 'table', function ( settings ) {
|
|
|
8880 _fnSaveState( settings );
|
|
|
8881 } );
|
|
|
8882 } );
|
|
|
8883
|
|
|
8884
|
|
|
8885
|
|
|
8886 /**
|
|
|
8887 * Provide a common method for plug-ins to check the version of DataTables being
|
|
|
8888 * used, in order to ensure compatibility.
|
|
|
8889 *
|
|
|
8890 * @param {string} version Version string to check for, in the format "X.Y.Z".
|
|
|
8891 * Note that the formats "X" and "X.Y" are also acceptable.
|
|
|
8892 * @returns {boolean} true if this version of DataTables is greater or equal to
|
|
|
8893 * the required version, or false if this version of DataTales is not
|
|
|
8894 * suitable
|
|
|
8895 * @static
|
|
|
8896 * @dtopt API-Static
|
|
|
8897 *
|
|
|
8898 * @example
|
|
|
8899 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
|
|
|
8900 */
|
|
|
8901 DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
|
|
|
8902 {
|
|
|
8903 var aThis = DataTable.version.split('.');
|
|
|
8904 var aThat = version.split('.');
|
|
|
8905 var iThis, iThat;
|
|
|
8906
|
|
|
8907 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
|
|
|
8908 iThis = parseInt( aThis[i], 10 ) || 0;
|
|
|
8909 iThat = parseInt( aThat[i], 10 ) || 0;
|
|
|
8910
|
|
|
8911 // Parts are the same, keep comparing
|
|
|
8912 if (iThis === iThat) {
|
|
|
8913 continue;
|
|
|
8914 }
|
|
|
8915
|
|
|
8916 // Parts are different, return immediately
|
|
|
8917 return iThis > iThat;
|
|
|
8918 }
|
|
|
8919
|
|
|
8920 return true;
|
|
|
8921 };
|
|
|
8922
|
|
|
8923
|
|
|
8924 /**
|
|
|
8925 * Check if a `<table>` node is a DataTable table already or not.
|
|
|
8926 *
|
|
|
8927 * @param {node|jquery|string} table Table node, jQuery object or jQuery
|
|
|
8928 * selector for the table to test. Note that if more than more than one
|
|
|
8929 * table is passed on, only the first will be checked
|
|
|
8930 * @returns {boolean} true the table given is a DataTable, or false otherwise
|
|
|
8931 * @static
|
|
|
8932 * @dtopt API-Static
|
|
|
8933 *
|
|
|
8934 * @example
|
|
|
8935 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
|
|
|
8936 * $('#example').dataTable();
|
|
|
8937 * }
|
|
|
8938 */
|
|
|
8939 DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
|
|
|
8940 {
|
|
|
8941 var t = $(table).get(0);
|
|
|
8942 var is = false;
|
|
|
8943
|
|
|
8944 $.each( DataTable.settings, function (i, o) {
|
|
|
8945 var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
|
|
|
8946 var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
|
|
|
8947
|
|
|
8948 if ( o.nTable === t || head === t || foot === t ) {
|
|
|
8949 is = true;
|
|
|
8950 }
|
|
|
8951 } );
|
|
|
8952
|
|
|
8953 return is;
|
|
|
8954 };
|
|
|
8955
|
|
|
8956
|
|
|
8957 /**
|
|
|
8958 * Get all DataTable tables that have been initialised - optionally you can
|
|
|
8959 * select to get only currently visible tables.
|
|
|
8960 *
|
|
|
8961 * @param {boolean} [visible=false] Flag to indicate if you want all (default)
|
|
|
8962 * or visible tables only.
|
|
|
8963 * @returns {array} Array of `table` nodes (not DataTable instances) which are
|
|
|
8964 * DataTables
|
|
|
8965 * @static
|
|
|
8966 * @dtopt API-Static
|
|
|
8967 *
|
|
|
8968 * @example
|
|
|
8969 * $.each( $.fn.dataTable.tables(true), function () {
|
|
|
8970 * $(table).DataTable().columns.adjust();
|
|
|
8971 * } );
|
|
|
8972 */
|
|
|
8973 DataTable.tables = DataTable.fnTables = function ( visible )
|
|
|
8974 {
|
|
|
8975 var api = false;
|
|
|
8976
|
|
|
8977 if ( $.isPlainObject( visible ) ) {
|
|
|
8978 api = visible.api;
|
|
|
8979 visible = visible.visible;
|
|
|
8980 }
|
|
|
8981
|
|
|
8982 var a = $.map( DataTable.settings, function (o) {
|
|
|
8983 if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
|
|
|
8984 return o.nTable;
|
|
|
8985 }
|
|
|
8986 } );
|
|
|
8987
|
|
|
8988 return api ?
|
|
|
8989 new _Api( a ) :
|
|
|
8990 a;
|
|
|
8991 };
|
|
|
8992
|
|
|
8993
|
|
|
8994 /**
|
|
|
8995 * DataTables utility methods
|
|
|
8996 *
|
|
|
8997 * This namespace provides helper methods that DataTables uses internally to
|
|
|
8998 * create a DataTable, but which are not exclusively used only for DataTables.
|
|
|
8999 * These methods can be used by extension authors to save the duplication of
|
|
|
9000 * code.
|
|
|
9001 *
|
|
|
9002 * @namespace
|
|
|
9003 */
|
|
|
9004 DataTable.util = {
|
|
|
9005 /**
|
|
|
9006 * Throttle the calls to a function. Arguments and context are maintained
|
|
|
9007 * for the throttled function.
|
|
|
9008 *
|
|
|
9009 * @param {function} fn Function to be called
|
|
|
9010 * @param {integer} freq Call frequency in mS
|
|
|
9011 * @return {function} Wrapped function
|
|
|
9012 */
|
|
|
9013 throttle: _fnThrottle,
|
|
|
9014
|
|
|
9015
|
|
|
9016 /**
|
|
|
9017 * Escape a string such that it can be used in a regular expression
|
|
|
9018 *
|
|
|
9019 * @param {string} sVal string to escape
|
|
|
9020 * @returns {string} escaped string
|
|
|
9021 */
|
|
|
9022 escapeRegex: _fnEscapeRegex
|
|
|
9023 };
|
|
|
9024
|
|
|
9025
|
|
|
9026 /**
|
|
|
9027 * Convert from camel case parameters to Hungarian notation. This is made public
|
|
|
9028 * for the extensions to provide the same ability as DataTables core to accept
|
|
|
9029 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
|
|
|
9030 * parameters.
|
|
|
9031 *
|
|
|
9032 * @param {object} src The model object which holds all parameters that can be
|
|
|
9033 * mapped.
|
|
|
9034 * @param {object} user The object to convert from camel case to Hungarian.
|
|
|
9035 * @param {boolean} force When set to `true`, properties which already have a
|
|
|
9036 * Hungarian value in the `user` object will be overwritten. Otherwise they
|
|
|
9037 * won't be.
|
|
|
9038 */
|
|
|
9039 DataTable.camelToHungarian = _fnCamelToHungarian;
|
|
|
9040
|
|
|
9041
|
|
|
9042
|
|
|
9043 /**
|
|
|
9044 *
|
|
|
9045 */
|
|
|
9046 _api_register( '$()', function ( selector, opts ) {
|
|
|
9047 var
|
|
|
9048 rows = this.rows( opts ).nodes(), // Get all rows
|
|
|
9049 jqRows = $(rows);
|
|
|
9050
|
|
|
9051 return $( [].concat(
|
|
|
9052 jqRows.filter( selector ).toArray(),
|
|
|
9053 jqRows.find( selector ).toArray()
|
|
|
9054 ) );
|
|
|
9055 } );
|
|
|
9056
|
|
|
9057
|
|
|
9058 // jQuery functions to operate on the tables
|
|
|
9059 $.each( [ 'on', 'one', 'off' ], function (i, key) {
|
|
|
9060 _api_register( key+'()', function ( /* event, handler */ ) {
|
|
|
9061 var args = Array.prototype.slice.call(arguments);
|
|
|
9062
|
|
|
9063 // Add the `dt` namespace automatically if it isn't already present
|
|
|
9064 if ( ! args[0].match(/\.dt\b/) ) {
|
|
|
9065 args[0] += '.dt';
|
|
|
9066 }
|
|
|
9067
|
|
|
9068 var inst = $( this.tables().nodes() );
|
|
|
9069 inst[key].apply( inst, args );
|
|
|
9070 return this;
|
|
|
9071 } );
|
|
|
9072 } );
|
|
|
9073
|
|
|
9074
|
|
|
9075 _api_register( 'clear()', function () {
|
|
|
9076 return this.iterator( 'table', function ( settings ) {
|
|
|
9077 _fnClearTable( settings );
|
|
|
9078 } );
|
|
|
9079 } );
|
|
|
9080
|
|
|
9081
|
|
|
9082 _api_register( 'settings()', function () {
|
|
|
9083 return new _Api( this.context, this.context );
|
|
|
9084 } );
|
|
|
9085
|
|
|
9086
|
|
|
9087 _api_register( 'init()', function () {
|
|
|
9088 var ctx = this.context;
|
|
|
9089 return ctx.length ? ctx[0].oInit : null;
|
|
|
9090 } );
|
|
|
9091
|
|
|
9092
|
|
|
9093 _api_register( 'data()', function () {
|
|
|
9094 return this.iterator( 'table', function ( settings ) {
|
|
|
9095 return _pluck( settings.aoData, '_aData' );
|
|
|
9096 } ).flatten();
|
|
|
9097 } );
|
|
|
9098
|
|
|
9099
|
|
|
9100 _api_register( 'destroy()', function ( remove ) {
|
|
|
9101 remove = remove || false;
|
|
|
9102
|
|
|
9103 return this.iterator( 'table', function ( settings ) {
|
|
|
9104 var orig = settings.nTableWrapper.parentNode;
|
|
|
9105 var classes = settings.oClasses;
|
|
|
9106 var table = settings.nTable;
|
|
|
9107 var tbody = settings.nTBody;
|
|
|
9108 var thead = settings.nTHead;
|
|
|
9109 var tfoot = settings.nTFoot;
|
|
|
9110 var jqTable = $(table);
|
|
|
9111 var jqTbody = $(tbody);
|
|
|
9112 var jqWrapper = $(settings.nTableWrapper);
|
|
|
9113 var rows = $.map( settings.aoData, function (r) { return r.nTr; } );
|
|
|
9114 var i, ien;
|
|
|
9115
|
|
|
9116 // Flag to note that the table is currently being destroyed - no action
|
|
|
9117 // should be taken
|
|
|
9118 settings.bDestroying = true;
|
|
|
9119
|
|
|
9120 // Fire off the destroy callbacks for plug-ins etc
|
|
|
9121 _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
|
|
|
9122
|
|
|
9123 // If not being removed from the document, make all columns visible
|
|
|
9124 if ( ! remove ) {
|
|
|
9125 new _Api( settings ).columns().visible( true );
|
|
|
9126 }
|
|
|
9127
|
|
|
9128 // Blitz all `DT` namespaced events (these are internal events, the
|
|
|
9129 // lowercase, `dt` events are user subscribed and they are responsible
|
|
|
9130 // for removing them
|
|
|
9131 jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
|
|
|
9132 $(window).unbind('.DT-'+settings.sInstance);
|
|
|
9133
|
|
|
9134 // When scrolling we had to break the table up - restore it
|
|
|
9135 if ( table != thead.parentNode ) {
|
|
|
9136 jqTable.children('thead').detach();
|
|
|
9137 jqTable.append( thead );
|
|
|
9138 }
|
|
|
9139
|
|
|
9140 if ( tfoot && table != tfoot.parentNode ) {
|
|
|
9141 jqTable.children('tfoot').detach();
|
|
|
9142 jqTable.append( tfoot );
|
|
|
9143 }
|
|
|
9144
|
|
|
9145 settings.aaSorting = [];
|
|
|
9146 settings.aaSortingFixed = [];
|
|
|
9147 _fnSortingClasses( settings );
|
|
|
9148
|
|
|
9149 $( rows ).removeClass( settings.asStripeClasses.join(' ') );
|
|
|
9150
|
|
|
9151 $('th, td', thead).removeClass( classes.sSortable+' '+
|
|
|
9152 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
|
|
|
9153 );
|
|
|
9154
|
|
|
9155 if ( settings.bJUI ) {
|
|
|
9156 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
|
|
|
9157 $('th, td', thead).each( function () {
|
|
|
9158 var wrapper = $('div.'+classes.sSortJUIWrapper, this);
|
|
|
9159 $(this).append( wrapper.contents() );
|
|
|
9160 wrapper.detach();
|
|
|
9161 } );
|
|
|
9162 }
|
|
|
9163
|
|
|
9164 // Add the TR elements back into the table in their original order
|
|
|
9165 jqTbody.children().detach();
|
|
|
9166 jqTbody.append( rows );
|
|
|
9167
|
|
|
9168 // Remove the DataTables generated nodes, events and classes
|
|
|
9169 var removedMethod = remove ? 'remove' : 'detach';
|
|
|
9170 jqTable[ removedMethod ]();
|
|
|
9171 jqWrapper[ removedMethod ]();
|
|
|
9172
|
|
|
9173 // If we need to reattach the table to the document
|
|
|
9174 if ( ! remove && orig ) {
|
|
|
9175 // insertBefore acts like appendChild if !arg[1]
|
|
|
9176 orig.insertBefore( table, settings.nTableReinsertBefore );
|
|
|
9177
|
|
|
9178 // Restore the width of the original table - was read from the style property,
|
|
|
9179 // so we can restore directly to that
|
|
|
9180 jqTable
|
|
|
9181 .css( 'width', settings.sDestroyWidth )
|
|
|
9182 .removeClass( classes.sTable );
|
|
|
9183
|
|
|
9184 // If the were originally stripe classes - then we add them back here.
|
|
|
9185 // Note this is not fool proof (for example if not all rows had stripe
|
|
|
9186 // classes - but it's a good effort without getting carried away
|
|
|
9187 ien = settings.asDestroyStripes.length;
|
|
|
9188
|
|
|
9189 if ( ien ) {
|
|
|
9190 jqTbody.children().each( function (i) {
|
|
|
9191 $(this).addClass( settings.asDestroyStripes[i % ien] );
|
|
|
9192 } );
|
|
|
9193 }
|
|
|
9194 }
|
|
|
9195
|
|
|
9196 /* Remove the settings object from the settings array */
|
|
|
9197 var idx = $.inArray( settings, DataTable.settings );
|
|
|
9198 if ( idx !== -1 ) {
|
|
|
9199 DataTable.settings.splice( idx, 1 );
|
|
|
9200 }
|
|
|
9201 } );
|
|
|
9202 } );
|
|
|
9203
|
|
|
9204
|
|
|
9205 // Add the `every()` method for rows, columns and cells in a compact form
|
|
|
9206 $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
|
|
|
9207 _api_register( type+'s().every()', function ( fn ) {
|
|
|
9208 return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
|
|
|
9209 // Rows and columns:
|
|
|
9210 // arg1 - index
|
|
|
9211 // arg2 - table counter
|
|
|
9212 // arg3 - loop counter
|
|
|
9213 // arg4 - undefined
|
|
|
9214 // Cells:
|
|
|
9215 // arg1 - row index
|
|
|
9216 // arg2 - column index
|
|
|
9217 // arg3 - table counter
|
|
|
9218 // arg4 - loop counter
|
|
|
9219 fn.call(
|
|
|
9220 new _Api( settings )[ type ]( arg1, type==='cell' ? arg2 : undefined ),
|
|
|
9221 arg1, arg2, arg3, arg4
|
|
|
9222 );
|
|
|
9223 } );
|
|
|
9224 } );
|
|
|
9225 } );
|
|
|
9226
|
|
|
9227
|
|
|
9228 // i18n method for extensions to be able to use the language object from the
|
|
|
9229 // DataTable
|
|
|
9230 _api_register( 'i18n()', function ( token, def, plural ) {
|
|
|
9231 var ctx = this.context[0];
|
|
|
9232 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
|
|
|
9233
|
|
|
9234 if ( resolved === undefined ) {
|
|
|
9235 resolved = def;
|
|
|
9236 }
|
|
|
9237
|
|
|
9238 if ( plural !== undefined && $.isPlainObject( resolved ) ) {
|
|
|
9239 resolved = resolved[ plural ] !== undefined ?
|
|
|
9240 resolved[ plural ] :
|
|
|
9241 resolved._;
|
|
|
9242 }
|
|
|
9243
|
|
|
9244 return resolved.replace( '%d', plural ); // nb: plural might be undefined,
|
|
|
9245 } );
|
|
|
9246
|
|
|
9247 /**
|
|
|
9248 * Version string for plug-ins to check compatibility. Allowed format is
|
|
|
9249 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
|
|
|
9250 * only for non-release builds. See http://semver.org/ for more information.
|
|
|
9251 * @member
|
|
|
9252 * @type string
|
|
|
9253 * @default Version number
|
|
|
9254 */
|
|
|
9255 DataTable.version = "1.10.9";
|
|
|
9256
|
|
|
9257 /**
|
|
|
9258 * Private data store, containing all of the settings objects that are
|
|
|
9259 * created for the tables on a given page.
|
|
|
9260 *
|
|
|
9261 * Note that the `DataTable.settings` object is aliased to
|
|
|
9262 * `jQuery.fn.dataTableExt` through which it may be accessed and
|
|
|
9263 * manipulated, or `jQuery.fn.dataTable.settings`.
|
|
|
9264 * @member
|
|
|
9265 * @type array
|
|
|
9266 * @default []
|
|
|
9267 * @private
|
|
|
9268 */
|
|
|
9269 DataTable.settings = [];
|
|
|
9270
|
|
|
9271 /**
|
|
|
9272 * Object models container, for the various models that DataTables has
|
|
|
9273 * available to it. These models define the objects that are used to hold
|
|
|
9274 * the active state and configuration of the table.
|
|
|
9275 * @namespace
|
|
|
9276 */
|
|
|
9277 DataTable.models = {};
|
|
|
9278
|
|
|
9279
|
|
|
9280
|
|
|
9281 /**
|
|
|
9282 * Template object for the way in which DataTables holds information about
|
|
|
9283 * search information for the global filter and individual column filters.
|
|
|
9284 * @namespace
|
|
|
9285 */
|
|
|
9286 DataTable.models.oSearch = {
|
|
|
9287 /**
|
|
|
9288 * Flag to indicate if the filtering should be case insensitive or not
|
|
|
9289 * @type boolean
|
|
|
9290 * @default true
|
|
|
9291 */
|
|
|
9292 "bCaseInsensitive": true,
|
|
|
9293
|
|
|
9294 /**
|
|
|
9295 * Applied search term
|
|
|
9296 * @type string
|
|
|
9297 * @default <i>Empty string</i>
|
|
|
9298 */
|
|
|
9299 "sSearch": "",
|
|
|
9300
|
|
|
9301 /**
|
|
|
9302 * Flag to indicate if the search term should be interpreted as a
|
|
|
9303 * regular expression (true) or not (false) and therefore and special
|
|
|
9304 * regex characters escaped.
|
|
|
9305 * @type boolean
|
|
|
9306 * @default false
|
|
|
9307 */
|
|
|
9308 "bRegex": false,
|
|
|
9309
|
|
|
9310 /**
|
|
|
9311 * Flag to indicate if DataTables is to use its smart filtering or not.
|
|
|
9312 * @type boolean
|
|
|
9313 * @default true
|
|
|
9314 */
|
|
|
9315 "bSmart": true
|
|
|
9316 };
|
|
|
9317
|
|
|
9318
|
|
|
9319
|
|
|
9320
|
|
|
9321 /**
|
|
|
9322 * Template object for the way in which DataTables holds information about
|
|
|
9323 * each individual row. This is the object format used for the settings
|
|
|
9324 * aoData array.
|
|
|
9325 * @namespace
|
|
|
9326 */
|
|
|
9327 DataTable.models.oRow = {
|
|
|
9328 /**
|
|
|
9329 * TR element for the row
|
|
|
9330 * @type node
|
|
|
9331 * @default null
|
|
|
9332 */
|
|
|
9333 "nTr": null,
|
|
|
9334
|
|
|
9335 /**
|
|
|
9336 * Array of TD elements for each row. This is null until the row has been
|
|
|
9337 * created.
|
|
|
9338 * @type array nodes
|
|
|
9339 * @default []
|
|
|
9340 */
|
|
|
9341 "anCells": null,
|
|
|
9342
|
|
|
9343 /**
|
|
|
9344 * Data object from the original data source for the row. This is either
|
|
|
9345 * an array if using the traditional form of DataTables, or an object if
|
|
|
9346 * using mData options. The exact type will depend on the passed in
|
|
|
9347 * data from the data source, or will be an array if using DOM a data
|
|
|
9348 * source.
|
|
|
9349 * @type array|object
|
|
|
9350 * @default []
|
|
|
9351 */
|
|
|
9352 "_aData": [],
|
|
|
9353
|
|
|
9354 /**
|
|
|
9355 * Sorting data cache - this array is ostensibly the same length as the
|
|
|
9356 * number of columns (although each index is generated only as it is
|
|
|
9357 * needed), and holds the data that is used for sorting each column in the
|
|
|
9358 * row. We do this cache generation at the start of the sort in order that
|
|
|
9359 * the formatting of the sort data need be done only once for each cell
|
|
|
9360 * per sort. This array should not be read from or written to by anything
|
|
|
9361 * other than the master sorting methods.
|
|
|
9362 * @type array
|
|
|
9363 * @default null
|
|
|
9364 * @private
|
|
|
9365 */
|
|
|
9366 "_aSortData": null,
|
|
|
9367
|
|
|
9368 /**
|
|
|
9369 * Per cell filtering data cache. As per the sort data cache, used to
|
|
|
9370 * increase the performance of the filtering in DataTables
|
|
|
9371 * @type array
|
|
|
9372 * @default null
|
|
|
9373 * @private
|
|
|
9374 */
|
|
|
9375 "_aFilterData": null,
|
|
|
9376
|
|
|
9377 /**
|
|
|
9378 * Filtering data cache. This is the same as the cell filtering cache, but
|
|
|
9379 * in this case a string rather than an array. This is easily computed with
|
|
|
9380 * a join on `_aFilterData`, but is provided as a cache so the join isn't
|
|
|
9381 * needed on every search (memory traded for performance)
|
|
|
9382 * @type array
|
|
|
9383 * @default null
|
|
|
9384 * @private
|
|
|
9385 */
|
|
|
9386 "_sFilterRow": null,
|
|
|
9387
|
|
|
9388 /**
|
|
|
9389 * Cache of the class name that DataTables has applied to the row, so we
|
|
|
9390 * can quickly look at this variable rather than needing to do a DOM check
|
|
|
9391 * on className for the nTr property.
|
|
|
9392 * @type string
|
|
|
9393 * @default <i>Empty string</i>
|
|
|
9394 * @private
|
|
|
9395 */
|
|
|
9396 "_sRowStripe": "",
|
|
|
9397
|
|
|
9398 /**
|
|
|
9399 * Denote if the original data source was from the DOM, or the data source
|
|
|
9400 * object. This is used for invalidating data, so DataTables can
|
|
|
9401 * automatically read data from the original source, unless uninstructed
|
|
|
9402 * otherwise.
|
|
|
9403 * @type string
|
|
|
9404 * @default null
|
|
|
9405 * @private
|
|
|
9406 */
|
|
|
9407 "src": null,
|
|
|
9408
|
|
|
9409 /**
|
|
|
9410 * Index in the aoData array. This saves an indexOf lookup when we have the
|
|
|
9411 * object, but want to know the index
|
|
|
9412 * @type integer
|
|
|
9413 * @default -1
|
|
|
9414 * @private
|
|
|
9415 */
|
|
|
9416 "idx": -1
|
|
|
9417 };
|
|
|
9418
|
|
|
9419
|
|
|
9420 /**
|
|
|
9421 * Template object for the column information object in DataTables. This object
|
|
|
9422 * is held in the settings aoColumns array and contains all the information that
|
|
|
9423 * DataTables needs about each individual column.
|
|
|
9424 *
|
|
|
9425 * Note that this object is related to {@link DataTable.defaults.column}
|
|
|
9426 * but this one is the internal data store for DataTables's cache of columns.
|
|
|
9427 * It should NOT be manipulated outside of DataTables. Any configuration should
|
|
|
9428 * be done through the initialisation options.
|
|
|
9429 * @namespace
|
|
|
9430 */
|
|
|
9431 DataTable.models.oColumn = {
|
|
|
9432 /**
|
|
|
9433 * Column index. This could be worked out on-the-fly with $.inArray, but it
|
|
|
9434 * is faster to just hold it as a variable
|
|
|
9435 * @type integer
|
|
|
9436 * @default null
|
|
|
9437 */
|
|
|
9438 "idx": null,
|
|
|
9439
|
|
|
9440 /**
|
|
|
9441 * A list of the columns that sorting should occur on when this column
|
|
|
9442 * is sorted. That this property is an array allows multi-column sorting
|
|
|
9443 * to be defined for a column (for example first name / last name columns
|
|
|
9444 * would benefit from this). The values are integers pointing to the
|
|
|
9445 * columns to be sorted on (typically it will be a single integer pointing
|
|
|
9446 * at itself, but that doesn't need to be the case).
|
|
|
9447 * @type array
|
|
|
9448 */
|
|
|
9449 "aDataSort": null,
|
|
|
9450
|
|
|
9451 /**
|
|
|
9452 * Define the sorting directions that are applied to the column, in sequence
|
|
|
9453 * as the column is repeatedly sorted upon - i.e. the first value is used
|
|
|
9454 * as the sorting direction when the column if first sorted (clicked on).
|
|
|
9455 * Sort it again (click again) and it will move on to the next index.
|
|
|
9456 * Repeat until loop.
|
|
|
9457 * @type array
|
|
|
9458 */
|
|
|
9459 "asSorting": null,
|
|
|
9460
|
|
|
9461 /**
|
|
|
9462 * Flag to indicate if the column is searchable, and thus should be included
|
|
|
9463 * in the filtering or not.
|
|
|
9464 * @type boolean
|
|
|
9465 */
|
|
|
9466 "bSearchable": null,
|
|
|
9467
|
|
|
9468 /**
|
|
|
9469 * Flag to indicate if the column is sortable or not.
|
|
|
9470 * @type boolean
|
|
|
9471 */
|
|
|
9472 "bSortable": null,
|
|
|
9473
|
|
|
9474 /**
|
|
|
9475 * Flag to indicate if the column is currently visible in the table or not
|
|
|
9476 * @type boolean
|
|
|
9477 */
|
|
|
9478 "bVisible": null,
|
|
|
9479
|
|
|
9480 /**
|
|
|
9481 * Store for manual type assignment using the `column.type` option. This
|
|
|
9482 * is held in store so we can manipulate the column's `sType` property.
|
|
|
9483 * @type string
|
|
|
9484 * @default null
|
|
|
9485 * @private
|
|
|
9486 */
|
|
|
9487 "_sManualType": null,
|
|
|
9488
|
|
|
9489 /**
|
|
|
9490 * Flag to indicate if HTML5 data attributes should be used as the data
|
|
|
9491 * source for filtering or sorting. True is either are.
|
|
|
9492 * @type boolean
|
|
|
9493 * @default false
|
|
|
9494 * @private
|
|
|
9495 */
|
|
|
9496 "_bAttrSrc": false,
|
|
|
9497
|
|
|
9498 /**
|
|
|
9499 * Developer definable function that is called whenever a cell is created (Ajax source,
|
|
|
9500 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
|
|
|
9501 * allowing you to modify the DOM element (add background colour for example) when the
|
|
|
9502 * element is available.
|
|
|
9503 * @type function
|
|
|
9504 * @param {element} nTd The TD node that has been created
|
|
|
9505 * @param {*} sData The Data for the cell
|
|
|
9506 * @param {array|object} oData The data for the whole row
|
|
|
9507 * @param {int} iRow The row index for the aoData data store
|
|
|
9508 * @default null
|
|
|
9509 */
|
|
|
9510 "fnCreatedCell": null,
|
|
|
9511
|
|
|
9512 /**
|
|
|
9513 * Function to get data from a cell in a column. You should <b>never</b>
|
|
|
9514 * access data directly through _aData internally in DataTables - always use
|
|
|
9515 * the method attached to this property. It allows mData to function as
|
|
|
9516 * required. This function is automatically assigned by the column
|
|
|
9517 * initialisation method
|
|
|
9518 * @type function
|
|
|
9519 * @param {array|object} oData The data array/object for the array
|
|
|
9520 * (i.e. aoData[]._aData)
|
|
|
9521 * @param {string} sSpecific The specific data type you want to get -
|
|
|
9522 * 'display', 'type' 'filter' 'sort'
|
|
|
9523 * @returns {*} The data for the cell from the given row's data
|
|
|
9524 * @default null
|
|
|
9525 */
|
|
|
9526 "fnGetData": null,
|
|
|
9527
|
|
|
9528 /**
|
|
|
9529 * Function to set data for a cell in the column. You should <b>never</b>
|
|
|
9530 * set the data directly to _aData internally in DataTables - always use
|
|
|
9531 * this method. It allows mData to function as required. This function
|
|
|
9532 * is automatically assigned by the column initialisation method
|
|
|
9533 * @type function
|
|
|
9534 * @param {array|object} oData The data array/object for the array
|
|
|
9535 * (i.e. aoData[]._aData)
|
|
|
9536 * @param {*} sValue Value to set
|
|
|
9537 * @default null
|
|
|
9538 */
|
|
|
9539 "fnSetData": null,
|
|
|
9540
|
|
|
9541 /**
|
|
|
9542 * Property to read the value for the cells in the column from the data
|
|
|
9543 * source array / object. If null, then the default content is used, if a
|
|
|
9544 * function is given then the return from the function is used.
|
|
|
9545 * @type function|int|string|null
|
|
|
9546 * @default null
|
|
|
9547 */
|
|
|
9548 "mData": null,
|
|
|
9549
|
|
|
9550 /**
|
|
|
9551 * Partner property to mData which is used (only when defined) to get
|
|
|
9552 * the data - i.e. it is basically the same as mData, but without the
|
|
|
9553 * 'set' option, and also the data fed to it is the result from mData.
|
|
|
9554 * This is the rendering method to match the data method of mData.
|
|
|
9555 * @type function|int|string|null
|
|
|
9556 * @default null
|
|
|
9557 */
|
|
|
9558 "mRender": null,
|
|
|
9559
|
|
|
9560 /**
|
|
|
9561 * Unique header TH/TD element for this column - this is what the sorting
|
|
|
9562 * listener is attached to (if sorting is enabled.)
|
|
|
9563 * @type node
|
|
|
9564 * @default null
|
|
|
9565 */
|
|
|
9566 "nTh": null,
|
|
|
9567
|
|
|
9568 /**
|
|
|
9569 * Unique footer TH/TD element for this column (if there is one). Not used
|
|
|
9570 * in DataTables as such, but can be used for plug-ins to reference the
|
|
|
9571 * footer for each column.
|
|
|
9572 * @type node
|
|
|
9573 * @default null
|
|
|
9574 */
|
|
|
9575 "nTf": null,
|
|
|
9576
|
|
|
9577 /**
|
|
|
9578 * The class to apply to all TD elements in the table's TBODY for the column
|
|
|
9579 * @type string
|
|
|
9580 * @default null
|
|
|
9581 */
|
|
|
9582 "sClass": null,
|
|
|
9583
|
|
|
9584 /**
|
|
|
9585 * When DataTables calculates the column widths to assign to each column,
|
|
|
9586 * it finds the longest string in each column and then constructs a
|
|
|
9587 * temporary table and reads the widths from that. The problem with this
|
|
|
9588 * is that "mmm" is much wider then "iiii", but the latter is a longer
|
|
|
9589 * string - thus the calculation can go wrong (doing it properly and putting
|
|
|
9590 * it into an DOM object and measuring that is horribly(!) slow). Thus as
|
|
|
9591 * a "work around" we provide this option. It will append its value to the
|
|
|
9592 * text that is found to be the longest string for the column - i.e. padding.
|
|
|
9593 * @type string
|
|
|
9594 */
|
|
|
9595 "sContentPadding": null,
|
|
|
9596
|
|
|
9597 /**
|
|
|
9598 * Allows a default value to be given for a column's data, and will be used
|
|
|
9599 * whenever a null data source is encountered (this can be because mData
|
|
|
9600 * is set to null, or because the data source itself is null).
|
|
|
9601 * @type string
|
|
|
9602 * @default null
|
|
|
9603 */
|
|
|
9604 "sDefaultContent": null,
|
|
|
9605
|
|
|
9606 /**
|
|
|
9607 * Name for the column, allowing reference to the column by name as well as
|
|
|
9608 * by index (needs a lookup to work by name).
|
|
|
9609 * @type string
|
|
|
9610 */
|
|
|
9611 "sName": null,
|
|
|
9612
|
|
|
9613 /**
|
|
|
9614 * Custom sorting data type - defines which of the available plug-ins in
|
|
|
9615 * afnSortData the custom sorting will use - if any is defined.
|
|
|
9616 * @type string
|
|
|
9617 * @default std
|
|
|
9618 */
|
|
|
9619 "sSortDataType": 'std',
|
|
|
9620
|
|
|
9621 /**
|
|
|
9622 * Class to be applied to the header element when sorting on this column
|
|
|
9623 * @type string
|
|
|
9624 * @default null
|
|
|
9625 */
|
|
|
9626 "sSortingClass": null,
|
|
|
9627
|
|
|
9628 /**
|
|
|
9629 * Class to be applied to the header element when sorting on this column -
|
|
|
9630 * when jQuery UI theming is used.
|
|
|
9631 * @type string
|
|
|
9632 * @default null
|
|
|
9633 */
|
|
|
9634 "sSortingClassJUI": null,
|
|
|
9635
|
|
|
9636 /**
|
|
|
9637 * Title of the column - what is seen in the TH element (nTh).
|
|
|
9638 * @type string
|
|
|
9639 */
|
|
|
9640 "sTitle": null,
|
|
|
9641
|
|
|
9642 /**
|
|
|
9643 * Column sorting and filtering type
|
|
|
9644 * @type string
|
|
|
9645 * @default null
|
|
|
9646 */
|
|
|
9647 "sType": null,
|
|
|
9648
|
|
|
9649 /**
|
|
|
9650 * Width of the column
|
|
|
9651 * @type string
|
|
|
9652 * @default null
|
|
|
9653 */
|
|
|
9654 "sWidth": null,
|
|
|
9655
|
|
|
9656 /**
|
|
|
9657 * Width of the column when it was first "encountered"
|
|
|
9658 * @type string
|
|
|
9659 * @default null
|
|
|
9660 */
|
|
|
9661 "sWidthOrig": null
|
|
|
9662 };
|
|
|
9663
|
|
|
9664
|
|
|
9665 /*
|
|
|
9666 * Developer note: The properties of the object below are given in Hungarian
|
|
|
9667 * notation, that was used as the interface for DataTables prior to v1.10, however
|
|
|
9668 * from v1.10 onwards the primary interface is camel case. In order to avoid
|
|
|
9669 * breaking backwards compatibility utterly with this change, the Hungarian
|
|
|
9670 * version is still, internally the primary interface, but is is not documented
|
|
|
9671 * - hence the @name tags in each doc comment. This allows a Javascript function
|
|
|
9672 * to create a map from Hungarian notation to camel case (going the other direction
|
|
|
9673 * would require each property to be listed, which would at around 3K to the size
|
|
|
9674 * of DataTables, while this method is about a 0.5K hit.
|
|
|
9675 *
|
|
|
9676 * Ultimately this does pave the way for Hungarian notation to be dropped
|
|
|
9677 * completely, but that is a massive amount of work and will break current
|
|
|
9678 * installs (therefore is on-hold until v2).
|
|
|
9679 */
|
|
|
9680
|
|
|
9681 /**
|
|
|
9682 * Initialisation options that can be given to DataTables at initialisation
|
|
|
9683 * time.
|
|
|
9684 * @namespace
|
|
|
9685 */
|
|
|
9686 DataTable.defaults = {
|
|
|
9687 /**
|
|
|
9688 * An array of data to use for the table, passed in at initialisation which
|
|
|
9689 * will be used in preference to any data which is already in the DOM. This is
|
|
|
9690 * particularly useful for constructing tables purely in Javascript, for
|
|
|
9691 * example with a custom Ajax call.
|
|
|
9692 * @type array
|
|
|
9693 * @default null
|
|
|
9694 *
|
|
|
9695 * @dtopt Option
|
|
|
9696 * @name DataTable.defaults.data
|
|
|
9697 *
|
|
|
9698 * @example
|
|
|
9699 * // Using a 2D array data source
|
|
|
9700 * $(document).ready( function () {
|
|
|
9701 * $('#example').dataTable( {
|
|
|
9702 * "data": [
|
|
|
9703 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
|
|
|
9704 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
|
|
|
9705 * ],
|
|
|
9706 * "columns": [
|
|
|
9707 * { "title": "Engine" },
|
|
|
9708 * { "title": "Browser" },
|
|
|
9709 * { "title": "Platform" },
|
|
|
9710 * { "title": "Version" },
|
|
|
9711 * { "title": "Grade" }
|
|
|
9712 * ]
|
|
|
9713 * } );
|
|
|
9714 * } );
|
|
|
9715 *
|
|
|
9716 * @example
|
|
|
9717 * // Using an array of objects as a data source (`data`)
|
|
|
9718 * $(document).ready( function () {
|
|
|
9719 * $('#example').dataTable( {
|
|
|
9720 * "data": [
|
|
|
9721 * {
|
|
|
9722 * "engine": "Trident",
|
|
|
9723 * "browser": "Internet Explorer 4.0",
|
|
|
9724 * "platform": "Win 95+",
|
|
|
9725 * "version": 4,
|
|
|
9726 * "grade": "X"
|
|
|
9727 * },
|
|
|
9728 * {
|
|
|
9729 * "engine": "Trident",
|
|
|
9730 * "browser": "Internet Explorer 5.0",
|
|
|
9731 * "platform": "Win 95+",
|
|
|
9732 * "version": 5,
|
|
|
9733 * "grade": "C"
|
|
|
9734 * }
|
|
|
9735 * ],
|
|
|
9736 * "columns": [
|
|
|
9737 * { "title": "Engine", "data": "engine" },
|
|
|
9738 * { "title": "Browser", "data": "browser" },
|
|
|
9739 * { "title": "Platform", "data": "platform" },
|
|
|
9740 * { "title": "Version", "data": "version" },
|
|
|
9741 * { "title": "Grade", "data": "grade" }
|
|
|
9742 * ]
|
|
|
9743 * } );
|
|
|
9744 * } );
|
|
|
9745 */
|
|
|
9746 "aaData": null,
|
|
|
9747
|
|
|
9748
|
|
|
9749 /**
|
|
|
9750 * If ordering is enabled, then DataTables will perform a first pass sort on
|
|
|
9751 * initialisation. You can define which column(s) the sort is performed
|
|
|
9752 * upon, and the sorting direction, with this variable. The `sorting` array
|
|
|
9753 * should contain an array for each column to be sorted initially containing
|
|
|
9754 * the column's index and a direction string ('asc' or 'desc').
|
|
|
9755 * @type array
|
|
|
9756 * @default [[0,'asc']]
|
|
|
9757 *
|
|
|
9758 * @dtopt Option
|
|
|
9759 * @name DataTable.defaults.order
|
|
|
9760 *
|
|
|
9761 * @example
|
|
|
9762 * // Sort by 3rd column first, and then 4th column
|
|
|
9763 * $(document).ready( function() {
|
|
|
9764 * $('#example').dataTable( {
|
|
|
9765 * "order": [[2,'asc'], [3,'desc']]
|
|
|
9766 * } );
|
|
|
9767 * } );
|
|
|
9768 *
|
|
|
9769 * // No initial sorting
|
|
|
9770 * $(document).ready( function() {
|
|
|
9771 * $('#example').dataTable( {
|
|
|
9772 * "order": []
|
|
|
9773 * } );
|
|
|
9774 * } );
|
|
|
9775 */
|
|
|
9776 "aaSorting": [[0,'asc']],
|
|
|
9777
|
|
|
9778
|
|
|
9779 /**
|
|
|
9780 * This parameter is basically identical to the `sorting` parameter, but
|
|
|
9781 * cannot be overridden by user interaction with the table. What this means
|
|
|
9782 * is that you could have a column (visible or hidden) which the sorting
|
|
|
9783 * will always be forced on first - any sorting after that (from the user)
|
|
|
9784 * will then be performed as required. This can be useful for grouping rows
|
|
|
9785 * together.
|
|
|
9786 * @type array
|
|
|
9787 * @default null
|
|
|
9788 *
|
|
|
9789 * @dtopt Option
|
|
|
9790 * @name DataTable.defaults.orderFixed
|
|
|
9791 *
|
|
|
9792 * @example
|
|
|
9793 * $(document).ready( function() {
|
|
|
9794 * $('#example').dataTable( {
|
|
|
9795 * "orderFixed": [[0,'asc']]
|
|
|
9796 * } );
|
|
|
9797 * } )
|
|
|
9798 */
|
|
|
9799 "aaSortingFixed": [],
|
|
|
9800
|
|
|
9801
|
|
|
9802 /**
|
|
|
9803 * DataTables can be instructed to load data to display in the table from a
|
|
|
9804 * Ajax source. This option defines how that Ajax call is made and where to.
|
|
|
9805 *
|
|
|
9806 * The `ajax` property has three different modes of operation, depending on
|
|
|
9807 * how it is defined. These are:
|
|
|
9808 *
|
|
|
9809 * * `string` - Set the URL from where the data should be loaded from.
|
|
|
9810 * * `object` - Define properties for `jQuery.ajax`.
|
|
|
9811 * * `function` - Custom data get function
|
|
|
9812 *
|
|
|
9813 * `string`
|
|
|
9814 * --------
|
|
|
9815 *
|
|
|
9816 * As a string, the `ajax` property simply defines the URL from which
|
|
|
9817 * DataTables will load data.
|
|
|
9818 *
|
|
|
9819 * `object`
|
|
|
9820 * --------
|
|
|
9821 *
|
|
|
9822 * As an object, the parameters in the object are passed to
|
|
|
9823 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
|
|
|
9824 * of the Ajax request. DataTables has a number of default parameters which
|
|
|
9825 * you can override using this option. Please refer to the jQuery
|
|
|
9826 * documentation for a full description of the options available, although
|
|
|
9827 * the following parameters provide additional options in DataTables or
|
|
|
9828 * require special consideration:
|
|
|
9829 *
|
|
|
9830 * * `data` - As with jQuery, `data` can be provided as an object, but it
|
|
|
9831 * can also be used as a function to manipulate the data DataTables sends
|
|
|
9832 * to the server. The function takes a single parameter, an object of
|
|
|
9833 * parameters with the values that DataTables has readied for sending. An
|
|
|
9834 * object may be returned which will be merged into the DataTables
|
|
|
9835 * defaults, or you can add the items to the object that was passed in and
|
|
|
9836 * not return anything from the function. This supersedes `fnServerParams`
|
|
|
9837 * from DataTables 1.9-.
|
|
|
9838 *
|
|
|
9839 * * `dataSrc` - By default DataTables will look for the property `data` (or
|
|
|
9840 * `aaData` for compatibility with DataTables 1.9-) when obtaining data
|
|
|
9841 * from an Ajax source or for server-side processing - this parameter
|
|
|
9842 * allows that property to be changed. You can use Javascript dotted
|
|
|
9843 * object notation to get a data source for multiple levels of nesting, or
|
|
|
9844 * it my be used as a function. As a function it takes a single parameter,
|
|
|
9845 * the JSON returned from the server, which can be manipulated as
|
|
|
9846 * required, with the returned value being that used by DataTables as the
|
|
|
9847 * data source for the table. This supersedes `sAjaxDataProp` from
|
|
|
9848 * DataTables 1.9-.
|
|
|
9849 *
|
|
|
9850 * * `success` - Should not be overridden it is used internally in
|
|
|
9851 * DataTables. To manipulate / transform the data returned by the server
|
|
|
9852 * use `ajax.dataSrc`, or use `ajax` as a function (see below).
|
|
|
9853 *
|
|
|
9854 * `function`
|
|
|
9855 * ----------
|
|
|
9856 *
|
|
|
9857 * As a function, making the Ajax call is left up to yourself allowing
|
|
|
9858 * complete control of the Ajax request. Indeed, if desired, a method other
|
|
|
9859 * than Ajax could be used to obtain the required data, such as Web storage
|
|
|
9860 * or an AIR database.
|
|
|
9861 *
|
|
|
9862 * The function is given four parameters and no return is required. The
|
|
|
9863 * parameters are:
|
|
|
9864 *
|
|
|
9865 * 1. _object_ - Data to send to the server
|
|
|
9866 * 2. _function_ - Callback function that must be executed when the required
|
|
|
9867 * data has been obtained. That data should be passed into the callback
|
|
|
9868 * as the only parameter
|
|
|
9869 * 3. _object_ - DataTables settings object for the table
|
|
|
9870 *
|
|
|
9871 * Note that this supersedes `fnServerData` from DataTables 1.9-.
|
|
|
9872 *
|
|
|
9873 * @type string|object|function
|
|
|
9874 * @default null
|
|
|
9875 *
|
|
|
9876 * @dtopt Option
|
|
|
9877 * @name DataTable.defaults.ajax
|
|
|
9878 * @since 1.10.0
|
|
|
9879 *
|
|
|
9880 * @example
|
|
|
9881 * // Get JSON data from a file via Ajax.
|
|
|
9882 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
|
|
|
9883 * $('#example').dataTable( {
|
|
|
9884 * "ajax": "data.json"
|
|
|
9885 * } );
|
|
|
9886 *
|
|
|
9887 * @example
|
|
|
9888 * // Get JSON data from a file via Ajax, using `dataSrc` to change
|
|
|
9889 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
|
|
|
9890 * $('#example').dataTable( {
|
|
|
9891 * "ajax": {
|
|
|
9892 * "url": "data.json",
|
|
|
9893 * "dataSrc": "tableData"
|
|
|
9894 * }
|
|
|
9895 * } );
|
|
|
9896 *
|
|
|
9897 * @example
|
|
|
9898 * // Get JSON data from a file via Ajax, using `dataSrc` to read data
|
|
|
9899 * // from a plain array rather than an array in an object
|
|
|
9900 * $('#example').dataTable( {
|
|
|
9901 * "ajax": {
|
|
|
9902 * "url": "data.json",
|
|
|
9903 * "dataSrc": ""
|
|
|
9904 * }
|
|
|
9905 * } );
|
|
|
9906 *
|
|
|
9907 * @example
|
|
|
9908 * // Manipulate the data returned from the server - add a link to data
|
|
|
9909 * // (note this can, should, be done using `render` for the column - this
|
|
|
9910 * // is just a simple example of how the data can be manipulated).
|
|
|
9911 * $('#example').dataTable( {
|
|
|
9912 * "ajax": {
|
|
|
9913 * "url": "data.json",
|
|
|
9914 * "dataSrc": function ( json ) {
|
|
|
9915 * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
|
|
|
9916 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
|
|
|
9917 * }
|
|
|
9918 * return json;
|
|
|
9919 * }
|
|
|
9920 * }
|
|
|
9921 * } );
|
|
|
9922 *
|
|
|
9923 * @example
|
|
|
9924 * // Add data to the request
|
|
|
9925 * $('#example').dataTable( {
|
|
|
9926 * "ajax": {
|
|
|
9927 * "url": "data.json",
|
|
|
9928 * "data": function ( d ) {
|
|
|
9929 * return {
|
|
|
9930 * "extra_search": $('#extra').val()
|
|
|
9931 * };
|
|
|
9932 * }
|
|
|
9933 * }
|
|
|
9934 * } );
|
|
|
9935 *
|
|
|
9936 * @example
|
|
|
9937 * // Send request as POST
|
|
|
9938 * $('#example').dataTable( {
|
|
|
9939 * "ajax": {
|
|
|
9940 * "url": "data.json",
|
|
|
9941 * "type": "POST"
|
|
|
9942 * }
|
|
|
9943 * } );
|
|
|
9944 *
|
|
|
9945 * @example
|
|
|
9946 * // Get the data from localStorage (could interface with a form for
|
|
|
9947 * // adding, editing and removing rows).
|
|
|
9948 * $('#example').dataTable( {
|
|
|
9949 * "ajax": function (data, callback, settings) {
|
|
|
9950 * callback(
|
|
|
9951 * JSON.parse( localStorage.getItem('dataTablesData') )
|
|
|
9952 * );
|
|
|
9953 * }
|
|
|
9954 * } );
|
|
|
9955 */
|
|
|
9956 "ajax": null,
|
|
|
9957
|
|
|
9958
|
|
|
9959 /**
|
|
|
9960 * This parameter allows you to readily specify the entries in the length drop
|
|
|
9961 * down menu that DataTables shows when pagination is enabled. It can be
|
|
|
9962 * either a 1D array of options which will be used for both the displayed
|
|
|
9963 * option and the value, or a 2D array which will use the array in the first
|
|
|
9964 * position as the value, and the array in the second position as the
|
|
|
9965 * displayed options (useful for language strings such as 'All').
|
|
|
9966 *
|
|
|
9967 * Note that the `pageLength` property will be automatically set to the
|
|
|
9968 * first value given in this array, unless `pageLength` is also provided.
|
|
|
9969 * @type array
|
|
|
9970 * @default [ 10, 25, 50, 100 ]
|
|
|
9971 *
|
|
|
9972 * @dtopt Option
|
|
|
9973 * @name DataTable.defaults.lengthMenu
|
|
|
9974 *
|
|
|
9975 * @example
|
|
|
9976 * $(document).ready( function() {
|
|
|
9977 * $('#example').dataTable( {
|
|
|
9978 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
|
|
|
9979 * } );
|
|
|
9980 * } );
|
|
|
9981 */
|
|
|
9982 "aLengthMenu": [ 10, 25, 50, 100 ],
|
|
|
9983
|
|
|
9984
|
|
|
9985 /**
|
|
|
9986 * The `columns` option in the initialisation parameter allows you to define
|
|
|
9987 * details about the way individual columns behave. For a full list of
|
|
|
9988 * column options that can be set, please see
|
|
|
9989 * {@link DataTable.defaults.column}. Note that if you use `columns` to
|
|
|
9990 * define your columns, you must have an entry in the array for every single
|
|
|
9991 * column that you have in your table (these can be null if you don't which
|
|
|
9992 * to specify any options).
|
|
|
9993 * @member
|
|
|
9994 *
|
|
|
9995 * @name DataTable.defaults.column
|
|
|
9996 */
|
|
|
9997 "aoColumns": null,
|
|
|
9998
|
|
|
9999 /**
|
|
|
10000 * Very similar to `columns`, `columnDefs` allows you to target a specific
|
|
|
10001 * column, multiple columns, or all columns, using the `targets` property of
|
|
|
10002 * each object in the array. This allows great flexibility when creating
|
|
|
10003 * tables, as the `columnDefs` arrays can be of any length, targeting the
|
|
|
10004 * columns you specifically want. `columnDefs` may use any of the column
|
|
|
10005 * options available: {@link DataTable.defaults.column}, but it _must_
|
|
|
10006 * have `targets` defined in each object in the array. Values in the `targets`
|
|
|
10007 * array may be:
|
|
|
10008 * <ul>
|
|
|
10009 * <li>a string - class name will be matched on the TH for the column</li>
|
|
|
10010 * <li>0 or a positive integer - column index counting from the left</li>
|
|
|
10011 * <li>a negative integer - column index counting from the right</li>
|
|
|
10012 * <li>the string "_all" - all columns (i.e. assign a default)</li>
|
|
|
10013 * </ul>
|
|
|
10014 * @member
|
|
|
10015 *
|
|
|
10016 * @name DataTable.defaults.columnDefs
|
|
|
10017 */
|
|
|
10018 "aoColumnDefs": null,
|
|
|
10019
|
|
|
10020
|
|
|
10021 /**
|
|
|
10022 * Basically the same as `search`, this parameter defines the individual column
|
|
|
10023 * filtering state at initialisation time. The array must be of the same size
|
|
|
10024 * as the number of columns, and each element be an object with the parameters
|
|
|
10025 * `search` and `escapeRegex` (the latter is optional). 'null' is also
|
|
|
10026 * accepted and the default will be used.
|
|
|
10027 * @type array
|
|
|
10028 * @default []
|
|
|
10029 *
|
|
|
10030 * @dtopt Option
|
|
|
10031 * @name DataTable.defaults.searchCols
|
|
|
10032 *
|
|
|
10033 * @example
|
|
|
10034 * $(document).ready( function() {
|
|
|
10035 * $('#example').dataTable( {
|
|
|
10036 * "searchCols": [
|
|
|
10037 * null,
|
|
|
10038 * { "search": "My filter" },
|
|
|
10039 * null,
|
|
|
10040 * { "search": "^[0-9]", "escapeRegex": false }
|
|
|
10041 * ]
|
|
|
10042 * } );
|
|
|
10043 * } )
|
|
|
10044 */
|
|
|
10045 "aoSearchCols": [],
|
|
|
10046
|
|
|
10047
|
|
|
10048 /**
|
|
|
10049 * An array of CSS classes that should be applied to displayed rows. This
|
|
|
10050 * array may be of any length, and DataTables will apply each class
|
|
|
10051 * sequentially, looping when required.
|
|
|
10052 * @type array
|
|
|
10053 * @default null <i>Will take the values determined by the `oClasses.stripe*`
|
|
|
10054 * options</i>
|
|
|
10055 *
|
|
|
10056 * @dtopt Option
|
|
|
10057 * @name DataTable.defaults.stripeClasses
|
|
|
10058 *
|
|
|
10059 * @example
|
|
|
10060 * $(document).ready( function() {
|
|
|
10061 * $('#example').dataTable( {
|
|
|
10062 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
|
|
|
10063 * } );
|
|
|
10064 * } )
|
|
|
10065 */
|
|
|
10066 "asStripeClasses": null,
|
|
|
10067
|
|
|
10068
|
|
|
10069 /**
|
|
|
10070 * Enable or disable automatic column width calculation. This can be disabled
|
|
|
10071 * as an optimisation (it takes some time to calculate the widths) if the
|
|
|
10072 * tables widths are passed in using `columns`.
|
|
|
10073 * @type boolean
|
|
|
10074 * @default true
|
|
|
10075 *
|
|
|
10076 * @dtopt Features
|
|
|
10077 * @name DataTable.defaults.autoWidth
|
|
|
10078 *
|
|
|
10079 * @example
|
|
|
10080 * $(document).ready( function () {
|
|
|
10081 * $('#example').dataTable( {
|
|
|
10082 * "autoWidth": false
|
|
|
10083 * } );
|
|
|
10084 * } );
|
|
|
10085 */
|
|
|
10086 "bAutoWidth": true,
|
|
|
10087
|
|
|
10088
|
|
|
10089 /**
|
|
|
10090 * Deferred rendering can provide DataTables with a huge speed boost when you
|
|
|
10091 * are using an Ajax or JS data source for the table. This option, when set to
|
|
|
10092 * true, will cause DataTables to defer the creation of the table elements for
|
|
|
10093 * each row until they are needed for a draw - saving a significant amount of
|
|
|
10094 * time.
|
|
|
10095 * @type boolean
|
|
|
10096 * @default false
|
|
|
10097 *
|
|
|
10098 * @dtopt Features
|
|
|
10099 * @name DataTable.defaults.deferRender
|
|
|
10100 *
|
|
|
10101 * @example
|
|
|
10102 * $(document).ready( function() {
|
|
|
10103 * $('#example').dataTable( {
|
|
|
10104 * "ajax": "sources/arrays.txt",
|
|
|
10105 * "deferRender": true
|
|
|
10106 * } );
|
|
|
10107 * } );
|
|
|
10108 */
|
|
|
10109 "bDeferRender": false,
|
|
|
10110
|
|
|
10111
|
|
|
10112 /**
|
|
|
10113 * Replace a DataTable which matches the given selector and replace it with
|
|
|
10114 * one which has the properties of the new initialisation object passed. If no
|
|
|
10115 * table matches the selector, then the new DataTable will be constructed as
|
|
|
10116 * per normal.
|
|
|
10117 * @type boolean
|
|
|
10118 * @default false
|
|
|
10119 *
|
|
|
10120 * @dtopt Options
|
|
|
10121 * @name DataTable.defaults.destroy
|
|
|
10122 *
|
|
|
10123 * @example
|
|
|
10124 * $(document).ready( function() {
|
|
|
10125 * $('#example').dataTable( {
|
|
|
10126 * "srollY": "200px",
|
|
|
10127 * "paginate": false
|
|
|
10128 * } );
|
|
|
10129 *
|
|
|
10130 * // Some time later....
|
|
|
10131 * $('#example').dataTable( {
|
|
|
10132 * "filter": false,
|
|
|
10133 * "destroy": true
|
|
|
10134 * } );
|
|
|
10135 * } );
|
|
|
10136 */
|
|
|
10137 "bDestroy": false,
|
|
|
10138
|
|
|
10139
|
|
|
10140 /**
|
|
|
10141 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
|
|
|
10142 * that it allows the end user to input multiple words (space separated) and
|
|
|
10143 * will match a row containing those words, even if not in the order that was
|
|
|
10144 * specified (this allow matching across multiple columns). Note that if you
|
|
|
10145 * wish to use filtering in DataTables this must remain 'true' - to remove the
|
|
|
10146 * default filtering input box and retain filtering abilities, please use
|
|
|
10147 * {@link DataTable.defaults.dom}.
|
|
|
10148 * @type boolean
|
|
|
10149 * @default true
|
|
|
10150 *
|
|
|
10151 * @dtopt Features
|
|
|
10152 * @name DataTable.defaults.searching
|
|
|
10153 *
|
|
|
10154 * @example
|
|
|
10155 * $(document).ready( function () {
|
|
|
10156 * $('#example').dataTable( {
|
|
|
10157 * "searching": false
|
|
|
10158 * } );
|
|
|
10159 * } );
|
|
|
10160 */
|
|
|
10161 "bFilter": true,
|
|
|
10162
|
|
|
10163
|
|
|
10164 /**
|
|
|
10165 * Enable or disable the table information display. This shows information
|
|
|
10166 * about the data that is currently visible on the page, including information
|
|
|
10167 * about filtered data if that action is being performed.
|
|
|
10168 * @type boolean
|
|
|
10169 * @default true
|
|
|
10170 *
|
|
|
10171 * @dtopt Features
|
|
|
10172 * @name DataTable.defaults.info
|
|
|
10173 *
|
|
|
10174 * @example
|
|
|
10175 * $(document).ready( function () {
|
|
|
10176 * $('#example').dataTable( {
|
|
|
10177 * "info": false
|
|
|
10178 * } );
|
|
|
10179 * } );
|
|
|
10180 */
|
|
|
10181 "bInfo": true,
|
|
|
10182
|
|
|
10183
|
|
|
10184 /**
|
|
|
10185 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
|
|
|
10186 * slightly different and additional mark-up from what DataTables has
|
|
|
10187 * traditionally used).
|
|
|
10188 * @type boolean
|
|
|
10189 * @default false
|
|
|
10190 *
|
|
|
10191 * @dtopt Features
|
|
|
10192 * @name DataTable.defaults.jQueryUI
|
|
|
10193 *
|
|
|
10194 * @example
|
|
|
10195 * $(document).ready( function() {
|
|
|
10196 * $('#example').dataTable( {
|
|
|
10197 * "jQueryUI": true
|
|
|
10198 * } );
|
|
|
10199 * } );
|
|
|
10200 */
|
|
|
10201 "bJQueryUI": false,
|
|
|
10202
|
|
|
10203
|
|
|
10204 /**
|
|
|
10205 * Allows the end user to select the size of a formatted page from a select
|
|
|
10206 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
|
|
|
10207 * @type boolean
|
|
|
10208 * @default true
|
|
|
10209 *
|
|
|
10210 * @dtopt Features
|
|
|
10211 * @name DataTable.defaults.lengthChange
|
|
|
10212 *
|
|
|
10213 * @example
|
|
|
10214 * $(document).ready( function () {
|
|
|
10215 * $('#example').dataTable( {
|
|
|
10216 * "lengthChange": false
|
|
|
10217 * } );
|
|
|
10218 * } );
|
|
|
10219 */
|
|
|
10220 "bLengthChange": true,
|
|
|
10221
|
|
|
10222
|
|
|
10223 /**
|
|
|
10224 * Enable or disable pagination.
|
|
|
10225 * @type boolean
|
|
|
10226 * @default true
|
|
|
10227 *
|
|
|
10228 * @dtopt Features
|
|
|
10229 * @name DataTable.defaults.paging
|
|
|
10230 *
|
|
|
10231 * @example
|
|
|
10232 * $(document).ready( function () {
|
|
|
10233 * $('#example').dataTable( {
|
|
|
10234 * "paging": false
|
|
|
10235 * } );
|
|
|
10236 * } );
|
|
|
10237 */
|
|
|
10238 "bPaginate": true,
|
|
|
10239
|
|
|
10240
|
|
|
10241 /**
|
|
|
10242 * Enable or disable the display of a 'processing' indicator when the table is
|
|
|
10243 * being processed (e.g. a sort). This is particularly useful for tables with
|
|
|
10244 * large amounts of data where it can take a noticeable amount of time to sort
|
|
|
10245 * the entries.
|
|
|
10246 * @type boolean
|
|
|
10247 * @default false
|
|
|
10248 *
|
|
|
10249 * @dtopt Features
|
|
|
10250 * @name DataTable.defaults.processing
|
|
|
10251 *
|
|
|
10252 * @example
|
|
|
10253 * $(document).ready( function () {
|
|
|
10254 * $('#example').dataTable( {
|
|
|
10255 * "processing": true
|
|
|
10256 * } );
|
|
|
10257 * } );
|
|
|
10258 */
|
|
|
10259 "bProcessing": false,
|
|
|
10260
|
|
|
10261
|
|
|
10262 /**
|
|
|
10263 * Retrieve the DataTables object for the given selector. Note that if the
|
|
|
10264 * table has already been initialised, this parameter will cause DataTables
|
|
|
10265 * to simply return the object that has already been set up - it will not take
|
|
|
10266 * account of any changes you might have made to the initialisation object
|
|
|
10267 * passed to DataTables (setting this parameter to true is an acknowledgement
|
|
|
10268 * that you understand this). `destroy` can be used to reinitialise a table if
|
|
|
10269 * you need.
|
|
|
10270 * @type boolean
|
|
|
10271 * @default false
|
|
|
10272 *
|
|
|
10273 * @dtopt Options
|
|
|
10274 * @name DataTable.defaults.retrieve
|
|
|
10275 *
|
|
|
10276 * @example
|
|
|
10277 * $(document).ready( function() {
|
|
|
10278 * initTable();
|
|
|
10279 * tableActions();
|
|
|
10280 * } );
|
|
|
10281 *
|
|
|
10282 * function initTable ()
|
|
|
10283 * {
|
|
|
10284 * return $('#example').dataTable( {
|
|
|
10285 * "scrollY": "200px",
|
|
|
10286 * "paginate": false,
|
|
|
10287 * "retrieve": true
|
|
|
10288 * } );
|
|
|
10289 * }
|
|
|
10290 *
|
|
|
10291 * function tableActions ()
|
|
|
10292 * {
|
|
|
10293 * var table = initTable();
|
|
|
10294 * // perform API operations with oTable
|
|
|
10295 * }
|
|
|
10296 */
|
|
|
10297 "bRetrieve": false,
|
|
|
10298
|
|
|
10299
|
|
|
10300 /**
|
|
|
10301 * When vertical (y) scrolling is enabled, DataTables will force the height of
|
|
|
10302 * the table's viewport to the given height at all times (useful for layout).
|
|
|
10303 * However, this can look odd when filtering data down to a small data set,
|
|
|
10304 * and the footer is left "floating" further down. This parameter (when
|
|
|
10305 * enabled) will cause DataTables to collapse the table's viewport down when
|
|
|
10306 * the result set will fit within the given Y height.
|
|
|
10307 * @type boolean
|
|
|
10308 * @default false
|
|
|
10309 *
|
|
|
10310 * @dtopt Options
|
|
|
10311 * @name DataTable.defaults.scrollCollapse
|
|
|
10312 *
|
|
|
10313 * @example
|
|
|
10314 * $(document).ready( function() {
|
|
|
10315 * $('#example').dataTable( {
|
|
|
10316 * "scrollY": "200",
|
|
|
10317 * "scrollCollapse": true
|
|
|
10318 * } );
|
|
|
10319 * } );
|
|
|
10320 */
|
|
|
10321 "bScrollCollapse": false,
|
|
|
10322
|
|
|
10323
|
|
|
10324 /**
|
|
|
10325 * Configure DataTables to use server-side processing. Note that the
|
|
|
10326 * `ajax` parameter must also be given in order to give DataTables a
|
|
|
10327 * source to obtain the required data for each draw.
|
|
|
10328 * @type boolean
|
|
|
10329 * @default false
|
|
|
10330 *
|
|
|
10331 * @dtopt Features
|
|
|
10332 * @dtopt Server-side
|
|
|
10333 * @name DataTable.defaults.serverSide
|
|
|
10334 *
|
|
|
10335 * @example
|
|
|
10336 * $(document).ready( function () {
|
|
|
10337 * $('#example').dataTable( {
|
|
|
10338 * "serverSide": true,
|
|
|
10339 * "ajax": "xhr.php"
|
|
|
10340 * } );
|
|
|
10341 * } );
|
|
|
10342 */
|
|
|
10343 "bServerSide": false,
|
|
|
10344
|
|
|
10345
|
|
|
10346 /**
|
|
|
10347 * Enable or disable sorting of columns. Sorting of individual columns can be
|
|
|
10348 * disabled by the `sortable` option for each column.
|
|
|
10349 * @type boolean
|
|
|
10350 * @default true
|
|
|
10351 *
|
|
|
10352 * @dtopt Features
|
|
|
10353 * @name DataTable.defaults.ordering
|
|
|
10354 *
|
|
|
10355 * @example
|
|
|
10356 * $(document).ready( function () {
|
|
|
10357 * $('#example').dataTable( {
|
|
|
10358 * "ordering": false
|
|
|
10359 * } );
|
|
|
10360 * } );
|
|
|
10361 */
|
|
|
10362 "bSort": true,
|
|
|
10363
|
|
|
10364
|
|
|
10365 /**
|
|
|
10366 * Enable or display DataTables' ability to sort multiple columns at the
|
|
|
10367 * same time (activated by shift-click by the user).
|
|
|
10368 * @type boolean
|
|
|
10369 * @default true
|
|
|
10370 *
|
|
|
10371 * @dtopt Options
|
|
|
10372 * @name DataTable.defaults.orderMulti
|
|
|
10373 *
|
|
|
10374 * @example
|
|
|
10375 * // Disable multiple column sorting ability
|
|
|
10376 * $(document).ready( function () {
|
|
|
10377 * $('#example').dataTable( {
|
|
|
10378 * "orderMulti": false
|
|
|
10379 * } );
|
|
|
10380 * } );
|
|
|
10381 */
|
|
|
10382 "bSortMulti": true,
|
|
|
10383
|
|
|
10384
|
|
|
10385 /**
|
|
|
10386 * Allows control over whether DataTables should use the top (true) unique
|
|
|
10387 * cell that is found for a single column, or the bottom (false - default).
|
|
|
10388 * This is useful when using complex headers.
|
|
|
10389 * @type boolean
|
|
|
10390 * @default false
|
|
|
10391 *
|
|
|
10392 * @dtopt Options
|
|
|
10393 * @name DataTable.defaults.orderCellsTop
|
|
|
10394 *
|
|
|
10395 * @example
|
|
|
10396 * $(document).ready( function() {
|
|
|
10397 * $('#example').dataTable( {
|
|
|
10398 * "orderCellsTop": true
|
|
|
10399 * } );
|
|
|
10400 * } );
|
|
|
10401 */
|
|
|
10402 "bSortCellsTop": false,
|
|
|
10403
|
|
|
10404
|
|
|
10405 /**
|
|
|
10406 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
|
|
|
10407 * `sorting\_3` to the columns which are currently being sorted on. This is
|
|
|
10408 * presented as a feature switch as it can increase processing time (while
|
|
|
10409 * classes are removed and added) so for large data sets you might want to
|
|
|
10410 * turn this off.
|
|
|
10411 * @type boolean
|
|
|
10412 * @default true
|
|
|
10413 *
|
|
|
10414 * @dtopt Features
|
|
|
10415 * @name DataTable.defaults.orderClasses
|
|
|
10416 *
|
|
|
10417 * @example
|
|
|
10418 * $(document).ready( function () {
|
|
|
10419 * $('#example').dataTable( {
|
|
|
10420 * "orderClasses": false
|
|
|
10421 * } );
|
|
|
10422 * } );
|
|
|
10423 */
|
|
|
10424 "bSortClasses": true,
|
|
|
10425
|
|
|
10426
|
|
|
10427 /**
|
|
|
10428 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
|
|
|
10429 * used to save table display information such as pagination information,
|
|
|
10430 * display length, filtering and sorting. As such when the end user reloads
|
|
|
10431 * the page the display display will match what thy had previously set up.
|
|
|
10432 *
|
|
|
10433 * Due to the use of `localStorage` the default state saving is not supported
|
|
|
10434 * in IE6 or 7. If state saving is required in those browsers, use
|
|
|
10435 * `stateSaveCallback` to provide a storage solution such as cookies.
|
|
|
10436 * @type boolean
|
|
|
10437 * @default false
|
|
|
10438 *
|
|
|
10439 * @dtopt Features
|
|
|
10440 * @name DataTable.defaults.stateSave
|
|
|
10441 *
|
|
|
10442 * @example
|
|
|
10443 * $(document).ready( function () {
|
|
|
10444 * $('#example').dataTable( {
|
|
|
10445 * "stateSave": true
|
|
|
10446 * } );
|
|
|
10447 * } );
|
|
|
10448 */
|
|
|
10449 "bStateSave": false,
|
|
|
10450
|
|
|
10451
|
|
|
10452 /**
|
|
|
10453 * This function is called when a TR element is created (and all TD child
|
|
|
10454 * elements have been inserted), or registered if using a DOM source, allowing
|
|
|
10455 * manipulation of the TR element (adding classes etc).
|
|
|
10456 * @type function
|
|
|
10457 * @param {node} row "TR" element for the current row
|
|
|
10458 * @param {array} data Raw data array for this row
|
|
|
10459 * @param {int} dataIndex The index of this row in the internal aoData array
|
|
|
10460 *
|
|
|
10461 * @dtopt Callbacks
|
|
|
10462 * @name DataTable.defaults.createdRow
|
|
|
10463 *
|
|
|
10464 * @example
|
|
|
10465 * $(document).ready( function() {
|
|
|
10466 * $('#example').dataTable( {
|
|
|
10467 * "createdRow": function( row, data, dataIndex ) {
|
|
|
10468 * // Bold the grade for all 'A' grade browsers
|
|
|
10469 * if ( data[4] == "A" )
|
|
|
10470 * {
|
|
|
10471 * $('td:eq(4)', row).html( '<b>A</b>' );
|
|
|
10472 * }
|
|
|
10473 * }
|
|
|
10474 * } );
|
|
|
10475 * } );
|
|
|
10476 */
|
|
|
10477 "fnCreatedRow": null,
|
|
|
10478
|
|
|
10479
|
|
|
10480 /**
|
|
|
10481 * This function is called on every 'draw' event, and allows you to
|
|
|
10482 * dynamically modify any aspect you want about the created DOM.
|
|
|
10483 * @type function
|
|
|
10484 * @param {object} settings DataTables settings object
|
|
|
10485 *
|
|
|
10486 * @dtopt Callbacks
|
|
|
10487 * @name DataTable.defaults.drawCallback
|
|
|
10488 *
|
|
|
10489 * @example
|
|
|
10490 * $(document).ready( function() {
|
|
|
10491 * $('#example').dataTable( {
|
|
|
10492 * "drawCallback": function( settings ) {
|
|
|
10493 * alert( 'DataTables has redrawn the table' );
|
|
|
10494 * }
|
|
|
10495 * } );
|
|
|
10496 * } );
|
|
|
10497 */
|
|
|
10498 "fnDrawCallback": null,
|
|
|
10499
|
|
|
10500
|
|
|
10501 /**
|
|
|
10502 * Identical to fnHeaderCallback() but for the table footer this function
|
|
|
10503 * allows you to modify the table footer on every 'draw' event.
|
|
|
10504 * @type function
|
|
|
10505 * @param {node} foot "TR" element for the footer
|
|
|
10506 * @param {array} data Full table data (as derived from the original HTML)
|
|
|
10507 * @param {int} start Index for the current display starting point in the
|
|
|
10508 * display array
|
|
|
10509 * @param {int} end Index for the current display ending point in the
|
|
|
10510 * display array
|
|
|
10511 * @param {array int} display Index array to translate the visual position
|
|
|
10512 * to the full data array
|
|
|
10513 *
|
|
|
10514 * @dtopt Callbacks
|
|
|
10515 * @name DataTable.defaults.footerCallback
|
|
|
10516 *
|
|
|
10517 * @example
|
|
|
10518 * $(document).ready( function() {
|
|
|
10519 * $('#example').dataTable( {
|
|
|
10520 * "footerCallback": function( tfoot, data, start, end, display ) {
|
|
|
10521 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
|
|
|
10522 * }
|
|
|
10523 * } );
|
|
|
10524 * } )
|
|
|
10525 */
|
|
|
10526 "fnFooterCallback": null,
|
|
|
10527
|
|
|
10528
|
|
|
10529 /**
|
|
|
10530 * When rendering large numbers in the information element for the table
|
|
|
10531 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
|
|
|
10532 * to have a comma separator for the 'thousands' units (e.g. 1 million is
|
|
|
10533 * rendered as "1,000,000") to help readability for the end user. This
|
|
|
10534 * function will override the default method DataTables uses.
|
|
|
10535 * @type function
|
|
|
10536 * @member
|
|
|
10537 * @param {int} toFormat number to be formatted
|
|
|
10538 * @returns {string} formatted string for DataTables to show the number
|
|
|
10539 *
|
|
|
10540 * @dtopt Callbacks
|
|
|
10541 * @name DataTable.defaults.formatNumber
|
|
|
10542 *
|
|
|
10543 * @example
|
|
|
10544 * // Format a number using a single quote for the separator (note that
|
|
|
10545 * // this can also be done with the language.thousands option)
|
|
|
10546 * $(document).ready( function() {
|
|
|
10547 * $('#example').dataTable( {
|
|
|
10548 * "formatNumber": function ( toFormat ) {
|
|
|
10549 * return toFormat.toString().replace(
|
|
|
10550 * /\B(?=(\d{3})+(?!\d))/g, "'"
|
|
|
10551 * );
|
|
|
10552 * };
|
|
|
10553 * } );
|
|
|
10554 * } );
|
|
|
10555 */
|
|
|
10556 "fnFormatNumber": function ( toFormat ) {
|
|
|
10557 return toFormat.toString().replace(
|
|
|
10558 /\B(?=(\d{3})+(?!\d))/g,
|
|
|
10559 this.oLanguage.sThousands
|
|
|
10560 );
|
|
|
10561 },
|
|
|
10562
|
|
|
10563
|
|
|
10564 /**
|
|
|
10565 * This function is called on every 'draw' event, and allows you to
|
|
|
10566 * dynamically modify the header row. This can be used to calculate and
|
|
|
10567 * display useful information about the table.
|
|
|
10568 * @type function
|
|
|
10569 * @param {node} head "TR" element for the header
|
|
|
10570 * @param {array} data Full table data (as derived from the original HTML)
|
|
|
10571 * @param {int} start Index for the current display starting point in the
|
|
|
10572 * display array
|
|
|
10573 * @param {int} end Index for the current display ending point in the
|
|
|
10574 * display array
|
|
|
10575 * @param {array int} display Index array to translate the visual position
|
|
|
10576 * to the full data array
|
|
|
10577 *
|
|
|
10578 * @dtopt Callbacks
|
|
|
10579 * @name DataTable.defaults.headerCallback
|
|
|
10580 *
|
|
|
10581 * @example
|
|
|
10582 * $(document).ready( function() {
|
|
|
10583 * $('#example').dataTable( {
|
|
|
10584 * "fheaderCallback": function( head, data, start, end, display ) {
|
|
|
10585 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
|
|
|
10586 * }
|
|
|
10587 * } );
|
|
|
10588 * } )
|
|
|
10589 */
|
|
|
10590 "fnHeaderCallback": null,
|
|
|
10591
|
|
|
10592
|
|
|
10593 /**
|
|
|
10594 * The information element can be used to convey information about the current
|
|
|
10595 * state of the table. Although the internationalisation options presented by
|
|
|
10596 * DataTables are quite capable of dealing with most customisations, there may
|
|
|
10597 * be times where you wish to customise the string further. This callback
|
|
|
10598 * allows you to do exactly that.
|
|
|
10599 * @type function
|
|
|
10600 * @param {object} oSettings DataTables settings object
|
|
|
10601 * @param {int} start Starting position in data for the draw
|
|
|
10602 * @param {int} end End position in data for the draw
|
|
|
10603 * @param {int} max Total number of rows in the table (regardless of
|
|
|
10604 * filtering)
|
|
|
10605 * @param {int} total Total number of rows in the data set, after filtering
|
|
|
10606 * @param {string} pre The string that DataTables has formatted using it's
|
|
|
10607 * own rules
|
|
|
10608 * @returns {string} The string to be displayed in the information element.
|
|
|
10609 *
|
|
|
10610 * @dtopt Callbacks
|
|
|
10611 * @name DataTable.defaults.infoCallback
|
|
|
10612 *
|
|
|
10613 * @example
|
|
|
10614 * $('#example').dataTable( {
|
|
|
10615 * "infoCallback": function( settings, start, end, max, total, pre ) {
|
|
|
10616 * return start +" to "+ end;
|
|
|
10617 * }
|
|
|
10618 * } );
|
|
|
10619 */
|
|
|
10620 "fnInfoCallback": null,
|
|
|
10621
|
|
|
10622
|
|
|
10623 /**
|
|
|
10624 * Called when the table has been initialised. Normally DataTables will
|
|
|
10625 * initialise sequentially and there will be no need for this function,
|
|
|
10626 * however, this does not hold true when using external language information
|
|
|
10627 * since that is obtained using an async XHR call.
|
|
|
10628 * @type function
|
|
|
10629 * @param {object} settings DataTables settings object
|
|
|
10630 * @param {object} json The JSON object request from the server - only
|
|
|
10631 * present if client-side Ajax sourced data is used
|
|
|
10632 *
|
|
|
10633 * @dtopt Callbacks
|
|
|
10634 * @name DataTable.defaults.initComplete
|
|
|
10635 *
|
|
|
10636 * @example
|
|
|
10637 * $(document).ready( function() {
|
|
|
10638 * $('#example').dataTable( {
|
|
|
10639 * "initComplete": function(settings, json) {
|
|
|
10640 * alert( 'DataTables has finished its initialisation.' );
|
|
|
10641 * }
|
|
|
10642 * } );
|
|
|
10643 * } )
|
|
|
10644 */
|
|
|
10645 "fnInitComplete": null,
|
|
|
10646
|
|
|
10647
|
|
|
10648 /**
|
|
|
10649 * Called at the very start of each table draw and can be used to cancel the
|
|
|
10650 * draw by returning false, any other return (including undefined) results in
|
|
|
10651 * the full draw occurring).
|
|
|
10652 * @type function
|
|
|
10653 * @param {object} settings DataTables settings object
|
|
|
10654 * @returns {boolean} False will cancel the draw, anything else (including no
|
|
|
10655 * return) will allow it to complete.
|
|
|
10656 *
|
|
|
10657 * @dtopt Callbacks
|
|
|
10658 * @name DataTable.defaults.preDrawCallback
|
|
|
10659 *
|
|
|
10660 * @example
|
|
|
10661 * $(document).ready( function() {
|
|
|
10662 * $('#example').dataTable( {
|
|
|
10663 * "preDrawCallback": function( settings ) {
|
|
|
10664 * if ( $('#test').val() == 1 ) {
|
|
|
10665 * return false;
|
|
|
10666 * }
|
|
|
10667 * }
|
|
|
10668 * } );
|
|
|
10669 * } );
|
|
|
10670 */
|
|
|
10671 "fnPreDrawCallback": null,
|
|
|
10672
|
|
|
10673
|
|
|
10674 /**
|
|
|
10675 * This function allows you to 'post process' each row after it have been
|
|
|
10676 * generated for each table draw, but before it is rendered on screen. This
|
|
|
10677 * function might be used for setting the row class name etc.
|
|
|
10678 * @type function
|
|
|
10679 * @param {node} row "TR" element for the current row
|
|
|
10680 * @param {array} data Raw data array for this row
|
|
|
10681 * @param {int} displayIndex The display index for the current table draw
|
|
|
10682 * @param {int} displayIndexFull The index of the data in the full list of
|
|
|
10683 * rows (after filtering)
|
|
|
10684 *
|
|
|
10685 * @dtopt Callbacks
|
|
|
10686 * @name DataTable.defaults.rowCallback
|
|
|
10687 *
|
|
|
10688 * @example
|
|
|
10689 * $(document).ready( function() {
|
|
|
10690 * $('#example').dataTable( {
|
|
|
10691 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
|
|
|
10692 * // Bold the grade for all 'A' grade browsers
|
|
|
10693 * if ( data[4] == "A" ) {
|
|
|
10694 * $('td:eq(4)', row).html( '<b>A</b>' );
|
|
|
10695 * }
|
|
|
10696 * }
|
|
|
10697 * } );
|
|
|
10698 * } );
|
|
|
10699 */
|
|
|
10700 "fnRowCallback": null,
|
|
|
10701
|
|
|
10702
|
|
|
10703 /**
|
|
|
10704 * __Deprecated__ The functionality provided by this parameter has now been
|
|
|
10705 * superseded by that provided through `ajax`, which should be used instead.
|
|
|
10706 *
|
|
|
10707 * This parameter allows you to override the default function which obtains
|
|
|
10708 * the data from the server so something more suitable for your application.
|
|
|
10709 * For example you could use POST data, or pull information from a Gears or
|
|
|
10710 * AIR database.
|
|
|
10711 * @type function
|
|
|
10712 * @member
|
|
|
10713 * @param {string} source HTTP source to obtain the data from (`ajax`)
|
|
|
10714 * @param {array} data A key/value pair object containing the data to send
|
|
|
10715 * to the server
|
|
|
10716 * @param {function} callback to be called on completion of the data get
|
|
|
10717 * process that will draw the data on the page.
|
|
|
10718 * @param {object} settings DataTables settings object
|
|
|
10719 *
|
|
|
10720 * @dtopt Callbacks
|
|
|
10721 * @dtopt Server-side
|
|
|
10722 * @name DataTable.defaults.serverData
|
|
|
10723 *
|
|
|
10724 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
|
10725 */
|
|
|
10726 "fnServerData": null,
|
|
|
10727
|
|
|
10728
|
|
|
10729 /**
|
|
|
10730 * __Deprecated__ The functionality provided by this parameter has now been
|
|
|
10731 * superseded by that provided through `ajax`, which should be used instead.
|
|
|
10732 *
|
|
|
10733 * It is often useful to send extra data to the server when making an Ajax
|
|
|
10734 * request - for example custom filtering information, and this callback
|
|
|
10735 * function makes it trivial to send extra information to the server. The
|
|
|
10736 * passed in parameter is the data set that has been constructed by
|
|
|
10737 * DataTables, and you can add to this or modify it as you require.
|
|
|
10738 * @type function
|
|
|
10739 * @param {array} data Data array (array of objects which are name/value
|
|
|
10740 * pairs) that has been constructed by DataTables and will be sent to the
|
|
|
10741 * server. In the case of Ajax sourced data with server-side processing
|
|
|
10742 * this will be an empty array, for server-side processing there will be a
|
|
|
10743 * significant number of parameters!
|
|
|
10744 * @returns {undefined} Ensure that you modify the data array passed in,
|
|
|
10745 * as this is passed by reference.
|
|
|
10746 *
|
|
|
10747 * @dtopt Callbacks
|
|
|
10748 * @dtopt Server-side
|
|
|
10749 * @name DataTable.defaults.serverParams
|
|
|
10750 *
|
|
|
10751 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
|
10752 */
|
|
|
10753 "fnServerParams": null,
|
|
|
10754
|
|
|
10755
|
|
|
10756 /**
|
|
|
10757 * Load the table state. With this function you can define from where, and how, the
|
|
|
10758 * state of a table is loaded. By default DataTables will load from `localStorage`
|
|
|
10759 * but you might wish to use a server-side database or cookies.
|
|
|
10760 * @type function
|
|
|
10761 * @member
|
|
|
10762 * @param {object} settings DataTables settings object
|
|
|
10763 * @return {object} The DataTables state object to be loaded
|
|
|
10764 *
|
|
|
10765 * @dtopt Callbacks
|
|
|
10766 * @name DataTable.defaults.stateLoadCallback
|
|
|
10767 *
|
|
|
10768 * @example
|
|
|
10769 * $(document).ready( function() {
|
|
|
10770 * $('#example').dataTable( {
|
|
|
10771 * "stateSave": true,
|
|
|
10772 * "stateLoadCallback": function (settings) {
|
|
|
10773 * var o;
|
|
|
10774 *
|
|
|
10775 * // Send an Ajax request to the server to get the data. Note that
|
|
|
10776 * // this is a synchronous request.
|
|
|
10777 * $.ajax( {
|
|
|
10778 * "url": "/state_load",
|
|
|
10779 * "async": false,
|
|
|
10780 * "dataType": "json",
|
|
|
10781 * "success": function (json) {
|
|
|
10782 * o = json;
|
|
|
10783 * }
|
|
|
10784 * } );
|
|
|
10785 *
|
|
|
10786 * return o;
|
|
|
10787 * }
|
|
|
10788 * } );
|
|
|
10789 * } );
|
|
|
10790 */
|
|
|
10791 "fnStateLoadCallback": function ( settings ) {
|
|
|
10792 try {
|
|
|
10793 return JSON.parse(
|
|
|
10794 (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
|
|
|
10795 'DataTables_'+settings.sInstance+'_'+location.pathname
|
|
|
10796 )
|
|
|
10797 );
|
|
|
10798 } catch (e) {}
|
|
|
10799 },
|
|
|
10800
|
|
|
10801
|
|
|
10802 /**
|
|
|
10803 * Callback which allows modification of the saved state prior to loading that state.
|
|
|
10804 * This callback is called when the table is loading state from the stored data, but
|
|
|
10805 * prior to the settings object being modified by the saved state. Note that for
|
|
|
10806 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
|
|
|
10807 * a plug-in.
|
|
|
10808 * @type function
|
|
|
10809 * @param {object} settings DataTables settings object
|
|
|
10810 * @param {object} data The state object that is to be loaded
|
|
|
10811 *
|
|
|
10812 * @dtopt Callbacks
|
|
|
10813 * @name DataTable.defaults.stateLoadParams
|
|
|
10814 *
|
|
|
10815 * @example
|
|
|
10816 * // Remove a saved filter, so filtering is never loaded
|
|
|
10817 * $(document).ready( function() {
|
|
|
10818 * $('#example').dataTable( {
|
|
|
10819 * "stateSave": true,
|
|
|
10820 * "stateLoadParams": function (settings, data) {
|
|
|
10821 * data.oSearch.sSearch = "";
|
|
|
10822 * }
|
|
|
10823 * } );
|
|
|
10824 * } );
|
|
|
10825 *
|
|
|
10826 * @example
|
|
|
10827 * // Disallow state loading by returning false
|
|
|
10828 * $(document).ready( function() {
|
|
|
10829 * $('#example').dataTable( {
|
|
|
10830 * "stateSave": true,
|
|
|
10831 * "stateLoadParams": function (settings, data) {
|
|
|
10832 * return false;
|
|
|
10833 * }
|
|
|
10834 * } );
|
|
|
10835 * } );
|
|
|
10836 */
|
|
|
10837 "fnStateLoadParams": null,
|
|
|
10838
|
|
|
10839
|
|
|
10840 /**
|
|
|
10841 * Callback that is called when the state has been loaded from the state saving method
|
|
|
10842 * and the DataTables settings object has been modified as a result of the loaded state.
|
|
|
10843 * @type function
|
|
|
10844 * @param {object} settings DataTables settings object
|
|
|
10845 * @param {object} data The state object that was loaded
|
|
|
10846 *
|
|
|
10847 * @dtopt Callbacks
|
|
|
10848 * @name DataTable.defaults.stateLoaded
|
|
|
10849 *
|
|
|
10850 * @example
|
|
|
10851 * // Show an alert with the filtering value that was saved
|
|
|
10852 * $(document).ready( function() {
|
|
|
10853 * $('#example').dataTable( {
|
|
|
10854 * "stateSave": true,
|
|
|
10855 * "stateLoaded": function (settings, data) {
|
|
|
10856 * alert( 'Saved filter was: '+data.oSearch.sSearch );
|
|
|
10857 * }
|
|
|
10858 * } );
|
|
|
10859 * } );
|
|
|
10860 */
|
|
|
10861 "fnStateLoaded": null,
|
|
|
10862
|
|
|
10863
|
|
|
10864 /**
|
|
|
10865 * Save the table state. This function allows you to define where and how the state
|
|
|
10866 * information for the table is stored By default DataTables will use `localStorage`
|
|
|
10867 * but you might wish to use a server-side database or cookies.
|
|
|
10868 * @type function
|
|
|
10869 * @member
|
|
|
10870 * @param {object} settings DataTables settings object
|
|
|
10871 * @param {object} data The state object to be saved
|
|
|
10872 *
|
|
|
10873 * @dtopt Callbacks
|
|
|
10874 * @name DataTable.defaults.stateSaveCallback
|
|
|
10875 *
|
|
|
10876 * @example
|
|
|
10877 * $(document).ready( function() {
|
|
|
10878 * $('#example').dataTable( {
|
|
|
10879 * "stateSave": true,
|
|
|
10880 * "stateSaveCallback": function (settings, data) {
|
|
|
10881 * // Send an Ajax request to the server with the state object
|
|
|
10882 * $.ajax( {
|
|
|
10883 * "url": "/state_save",
|
|
|
10884 * "data": data,
|
|
|
10885 * "dataType": "json",
|
|
|
10886 * "method": "POST"
|
|
|
10887 * "success": function () {}
|
|
|
10888 * } );
|
|
|
10889 * }
|
|
|
10890 * } );
|
|
|
10891 * } );
|
|
|
10892 */
|
|
|
10893 "fnStateSaveCallback": function ( settings, data ) {
|
|
|
10894 try {
|
|
|
10895 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
|
|
|
10896 'DataTables_'+settings.sInstance+'_'+location.pathname,
|
|
|
10897 JSON.stringify( data )
|
|
|
10898 );
|
|
|
10899 } catch (e) {}
|
|
|
10900 },
|
|
|
10901
|
|
|
10902
|
|
|
10903 /**
|
|
|
10904 * Callback which allows modification of the state to be saved. Called when the table
|
|
|
10905 * has changed state a new state save is required. This method allows modification of
|
|
|
10906 * the state saving object prior to actually doing the save, including addition or
|
|
|
10907 * other state properties or modification. Note that for plug-in authors, you should
|
|
|
10908 * use the `stateSaveParams` event to save parameters for a plug-in.
|
|
|
10909 * @type function
|
|
|
10910 * @param {object} settings DataTables settings object
|
|
|
10911 * @param {object} data The state object to be saved
|
|
|
10912 *
|
|
|
10913 * @dtopt Callbacks
|
|
|
10914 * @name DataTable.defaults.stateSaveParams
|
|
|
10915 *
|
|
|
10916 * @example
|
|
|
10917 * // Remove a saved filter, so filtering is never saved
|
|
|
10918 * $(document).ready( function() {
|
|
|
10919 * $('#example').dataTable( {
|
|
|
10920 * "stateSave": true,
|
|
|
10921 * "stateSaveParams": function (settings, data) {
|
|
|
10922 * data.oSearch.sSearch = "";
|
|
|
10923 * }
|
|
|
10924 * } );
|
|
|
10925 * } );
|
|
|
10926 */
|
|
|
10927 "fnStateSaveParams": null,
|
|
|
10928
|
|
|
10929
|
|
|
10930 /**
|
|
|
10931 * Duration for which the saved state information is considered valid. After this period
|
|
|
10932 * has elapsed the state will be returned to the default.
|
|
|
10933 * Value is given in seconds.
|
|
|
10934 * @type int
|
|
|
10935 * @default 7200 <i>(2 hours)</i>
|
|
|
10936 *
|
|
|
10937 * @dtopt Options
|
|
|
10938 * @name DataTable.defaults.stateDuration
|
|
|
10939 *
|
|
|
10940 * @example
|
|
|
10941 * $(document).ready( function() {
|
|
|
10942 * $('#example').dataTable( {
|
|
|
10943 * "stateDuration": 60*60*24; // 1 day
|
|
|
10944 * } );
|
|
|
10945 * } )
|
|
|
10946 */
|
|
|
10947 "iStateDuration": 7200,
|
|
|
10948
|
|
|
10949
|
|
|
10950 /**
|
|
|
10951 * When enabled DataTables will not make a request to the server for the first
|
|
|
10952 * page draw - rather it will use the data already on the page (no sorting etc
|
|
|
10953 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
|
|
|
10954 * is used to indicate that deferred loading is required, but it is also used
|
|
|
10955 * to tell DataTables how many records there are in the full table (allowing
|
|
|
10956 * the information element and pagination to be displayed correctly). In the case
|
|
|
10957 * where a filtering is applied to the table on initial load, this can be
|
|
|
10958 * indicated by giving the parameter as an array, where the first element is
|
|
|
10959 * the number of records available after filtering and the second element is the
|
|
|
10960 * number of records without filtering (allowing the table information element
|
|
|
10961 * to be shown correctly).
|
|
|
10962 * @type int | array
|
|
|
10963 * @default null
|
|
|
10964 *
|
|
|
10965 * @dtopt Options
|
|
|
10966 * @name DataTable.defaults.deferLoading
|
|
|
10967 *
|
|
|
10968 * @example
|
|
|
10969 * // 57 records available in the table, no filtering applied
|
|
|
10970 * $(document).ready( function() {
|
|
|
10971 * $('#example').dataTable( {
|
|
|
10972 * "serverSide": true,
|
|
|
10973 * "ajax": "scripts/server_processing.php",
|
|
|
10974 * "deferLoading": 57
|
|
|
10975 * } );
|
|
|
10976 * } );
|
|
|
10977 *
|
|
|
10978 * @example
|
|
|
10979 * // 57 records after filtering, 100 without filtering (an initial filter applied)
|
|
|
10980 * $(document).ready( function() {
|
|
|
10981 * $('#example').dataTable( {
|
|
|
10982 * "serverSide": true,
|
|
|
10983 * "ajax": "scripts/server_processing.php",
|
|
|
10984 * "deferLoading": [ 57, 100 ],
|
|
|
10985 * "search": {
|
|
|
10986 * "search": "my_filter"
|
|
|
10987 * }
|
|
|
10988 * } );
|
|
|
10989 * } );
|
|
|
10990 */
|
|
|
10991 "iDeferLoading": null,
|
|
|
10992
|
|
|
10993
|
|
|
10994 /**
|
|
|
10995 * Number of rows to display on a single page when using pagination. If
|
|
|
10996 * feature enabled (`lengthChange`) then the end user will be able to override
|
|
|
10997 * this to a custom setting using a pop-up menu.
|
|
|
10998 * @type int
|
|
|
10999 * @default 10
|
|
|
11000 *
|
|
|
11001 * @dtopt Options
|
|
|
11002 * @name DataTable.defaults.pageLength
|
|
|
11003 *
|
|
|
11004 * @example
|
|
|
11005 * $(document).ready( function() {
|
|
|
11006 * $('#example').dataTable( {
|
|
|
11007 * "pageLength": 50
|
|
|
11008 * } );
|
|
|
11009 * } )
|
|
|
11010 */
|
|
|
11011 "iDisplayLength": 10,
|
|
|
11012
|
|
|
11013
|
|
|
11014 /**
|
|
|
11015 * Define the starting point for data display when using DataTables with
|
|
|
11016 * pagination. Note that this parameter is the number of records, rather than
|
|
|
11017 * the page number, so if you have 10 records per page and want to start on
|
|
|
11018 * the third page, it should be "20".
|
|
|
11019 * @type int
|
|
|
11020 * @default 0
|
|
|
11021 *
|
|
|
11022 * @dtopt Options
|
|
|
11023 * @name DataTable.defaults.displayStart
|
|
|
11024 *
|
|
|
11025 * @example
|
|
|
11026 * $(document).ready( function() {
|
|
|
11027 * $('#example').dataTable( {
|
|
|
11028 * "displayStart": 20
|
|
|
11029 * } );
|
|
|
11030 * } )
|
|
|
11031 */
|
|
|
11032 "iDisplayStart": 0,
|
|
|
11033
|
|
|
11034
|
|
|
11035 /**
|
|
|
11036 * By default DataTables allows keyboard navigation of the table (sorting, paging,
|
|
|
11037 * and filtering) by adding a `tabindex` attribute to the required elements. This
|
|
|
11038 * allows you to tab through the controls and press the enter key to activate them.
|
|
|
11039 * The tabindex is default 0, meaning that the tab follows the flow of the document.
|
|
|
11040 * You can overrule this using this parameter if you wish. Use a value of -1 to
|
|
|
11041 * disable built-in keyboard navigation.
|
|
|
11042 * @type int
|
|
|
11043 * @default 0
|
|
|
11044 *
|
|
|
11045 * @dtopt Options
|
|
|
11046 * @name DataTable.defaults.tabIndex
|
|
|
11047 *
|
|
|
11048 * @example
|
|
|
11049 * $(document).ready( function() {
|
|
|
11050 * $('#example').dataTable( {
|
|
|
11051 * "tabIndex": 1
|
|
|
11052 * } );
|
|
|
11053 * } );
|
|
|
11054 */
|
|
|
11055 "iTabIndex": 0,
|
|
|
11056
|
|
|
11057
|
|
|
11058 /**
|
|
|
11059 * Classes that DataTables assigns to the various components and features
|
|
|
11060 * that it adds to the HTML table. This allows classes to be configured
|
|
|
11061 * during initialisation in addition to through the static
|
|
|
11062 * {@link DataTable.ext.oStdClasses} object).
|
|
|
11063 * @namespace
|
|
|
11064 * @name DataTable.defaults.classes
|
|
|
11065 */
|
|
|
11066 "oClasses": {},
|
|
|
11067
|
|
|
11068
|
|
|
11069 /**
|
|
|
11070 * All strings that DataTables uses in the user interface that it creates
|
|
|
11071 * are defined in this object, allowing you to modified them individually or
|
|
|
11072 * completely replace them all as required.
|
|
|
11073 * @namespace
|
|
|
11074 * @name DataTable.defaults.language
|
|
|
11075 */
|
|
|
11076 "oLanguage": {
|
|
|
11077 /**
|
|
|
11078 * Strings that are used for WAI-ARIA labels and controls only (these are not
|
|
|
11079 * actually visible on the page, but will be read by screenreaders, and thus
|
|
|
11080 * must be internationalised as well).
|
|
|
11081 * @namespace
|
|
|
11082 * @name DataTable.defaults.language.aria
|
|
|
11083 */
|
|
|
11084 "oAria": {
|
|
|
11085 /**
|
|
|
11086 * ARIA label that is added to the table headers when the column may be
|
|
|
11087 * sorted ascending by activing the column (click or return when focused).
|
|
|
11088 * Note that the column header is prefixed to this string.
|
|
|
11089 * @type string
|
|
|
11090 * @default : activate to sort column ascending
|
|
|
11091 *
|
|
|
11092 * @dtopt Language
|
|
|
11093 * @name DataTable.defaults.language.aria.sortAscending
|
|
|
11094 *
|
|
|
11095 * @example
|
|
|
11096 * $(document).ready( function() {
|
|
|
11097 * $('#example').dataTable( {
|
|
|
11098 * "language": {
|
|
|
11099 * "aria": {
|
|
|
11100 * "sortAscending": " - click/return to sort ascending"
|
|
|
11101 * }
|
|
|
11102 * }
|
|
|
11103 * } );
|
|
|
11104 * } );
|
|
|
11105 */
|
|
|
11106 "sSortAscending": ": activate to sort column ascending",
|
|
|
11107
|
|
|
11108 /**
|
|
|
11109 * ARIA label that is added to the table headers when the column may be
|
|
|
11110 * sorted descending by activing the column (click or return when focused).
|
|
|
11111 * Note that the column header is prefixed to this string.
|
|
|
11112 * @type string
|
|
|
11113 * @default : activate to sort column ascending
|
|
|
11114 *
|
|
|
11115 * @dtopt Language
|
|
|
11116 * @name DataTable.defaults.language.aria.sortDescending
|
|
|
11117 *
|
|
|
11118 * @example
|
|
|
11119 * $(document).ready( function() {
|
|
|
11120 * $('#example').dataTable( {
|
|
|
11121 * "language": {
|
|
|
11122 * "aria": {
|
|
|
11123 * "sortDescending": " - click/return to sort descending"
|
|
|
11124 * }
|
|
|
11125 * }
|
|
|
11126 * } );
|
|
|
11127 * } );
|
|
|
11128 */
|
|
|
11129 "sSortDescending": ": activate to sort column descending"
|
|
|
11130 },
|
|
|
11131
|
|
|
11132 /**
|
|
|
11133 * Pagination string used by DataTables for the built-in pagination
|
|
|
11134 * control types.
|
|
|
11135 * @namespace
|
|
|
11136 * @name DataTable.defaults.language.paginate
|
|
|
11137 */
|
|
|
11138 "oPaginate": {
|
|
|
11139 /**
|
|
|
11140 * Text to use when using the 'full_numbers' type of pagination for the
|
|
|
11141 * button to take the user to the first page.
|
|
|
11142 * @type string
|
|
|
11143 * @default First
|
|
|
11144 *
|
|
|
11145 * @dtopt Language
|
|
|
11146 * @name DataTable.defaults.language.paginate.first
|
|
|
11147 *
|
|
|
11148 * @example
|
|
|
11149 * $(document).ready( function() {
|
|
|
11150 * $('#example').dataTable( {
|
|
|
11151 * "language": {
|
|
|
11152 * "paginate": {
|
|
|
11153 * "first": "First page"
|
|
|
11154 * }
|
|
|
11155 * }
|
|
|
11156 * } );
|
|
|
11157 * } );
|
|
|
11158 */
|
|
|
11159 "sFirst": "First",
|
|
|
11160
|
|
|
11161
|
|
|
11162 /**
|
|
|
11163 * Text to use when using the 'full_numbers' type of pagination for the
|
|
|
11164 * button to take the user to the last page.
|
|
|
11165 * @type string
|
|
|
11166 * @default Last
|
|
|
11167 *
|
|
|
11168 * @dtopt Language
|
|
|
11169 * @name DataTable.defaults.language.paginate.last
|
|
|
11170 *
|
|
|
11171 * @example
|
|
|
11172 * $(document).ready( function() {
|
|
|
11173 * $('#example').dataTable( {
|
|
|
11174 * "language": {
|
|
|
11175 * "paginate": {
|
|
|
11176 * "last": "Last page"
|
|
|
11177 * }
|
|
|
11178 * }
|
|
|
11179 * } );
|
|
|
11180 * } );
|
|
|
11181 */
|
|
|
11182 "sLast": "Last",
|
|
|
11183
|
|
|
11184
|
|
|
11185 /**
|
|
|
11186 * Text to use for the 'next' pagination button (to take the user to the
|
|
|
11187 * next page).
|
|
|
11188 * @type string
|
|
|
11189 * @default Next
|
|
|
11190 *
|
|
|
11191 * @dtopt Language
|
|
|
11192 * @name DataTable.defaults.language.paginate.next
|
|
|
11193 *
|
|
|
11194 * @example
|
|
|
11195 * $(document).ready( function() {
|
|
|
11196 * $('#example').dataTable( {
|
|
|
11197 * "language": {
|
|
|
11198 * "paginate": {
|
|
|
11199 * "next": "Next page"
|
|
|
11200 * }
|
|
|
11201 * }
|
|
|
11202 * } );
|
|
|
11203 * } );
|
|
|
11204 */
|
|
|
11205 "sNext": "Next",
|
|
|
11206
|
|
|
11207
|
|
|
11208 /**
|
|
|
11209 * Text to use for the 'previous' pagination button (to take the user to
|
|
|
11210 * the previous page).
|
|
|
11211 * @type string
|
|
|
11212 * @default Previous
|
|
|
11213 *
|
|
|
11214 * @dtopt Language
|
|
|
11215 * @name DataTable.defaults.language.paginate.previous
|
|
|
11216 *
|
|
|
11217 * @example
|
|
|
11218 * $(document).ready( function() {
|
|
|
11219 * $('#example').dataTable( {
|
|
|
11220 * "language": {
|
|
|
11221 * "paginate": {
|
|
|
11222 * "previous": "Previous page"
|
|
|
11223 * }
|
|
|
11224 * }
|
|
|
11225 * } );
|
|
|
11226 * } );
|
|
|
11227 */
|
|
|
11228 "sPrevious": "Previous"
|
|
|
11229 },
|
|
|
11230
|
|
|
11231 /**
|
|
|
11232 * This string is shown in preference to `zeroRecords` when the table is
|
|
|
11233 * empty of data (regardless of filtering). Note that this is an optional
|
|
|
11234 * parameter - if it is not given, the value of `zeroRecords` will be used
|
|
|
11235 * instead (either the default or given value).
|
|
|
11236 * @type string
|
|
|
11237 * @default No data available in table
|
|
|
11238 *
|
|
|
11239 * @dtopt Language
|
|
|
11240 * @name DataTable.defaults.language.emptyTable
|
|
|
11241 *
|
|
|
11242 * @example
|
|
|
11243 * $(document).ready( function() {
|
|
|
11244 * $('#example').dataTable( {
|
|
|
11245 * "language": {
|
|
|
11246 * "emptyTable": "No data available in table"
|
|
|
11247 * }
|
|
|
11248 * } );
|
|
|
11249 * } );
|
|
|
11250 */
|
|
|
11251 "sEmptyTable": "No data available in table",
|
|
|
11252
|
|
|
11253
|
|
|
11254 /**
|
|
|
11255 * This string gives information to the end user about the information
|
|
|
11256 * that is current on display on the page. The following tokens can be
|
|
|
11257 * used in the string and will be dynamically replaced as the table
|
|
|
11258 * display updates. This tokens can be placed anywhere in the string, or
|
|
|
11259 * removed as needed by the language requires:
|
|
|
11260 *
|
|
|
11261 * * `\_START\_` - Display index of the first record on the current page
|
|
|
11262 * * `\_END\_` - Display index of the last record on the current page
|
|
|
11263 * * `\_TOTAL\_` - Number of records in the table after filtering
|
|
|
11264 * * `\_MAX\_` - Number of records in the table without filtering
|
|
|
11265 * * `\_PAGE\_` - Current page number
|
|
|
11266 * * `\_PAGES\_` - Total number of pages of data in the table
|
|
|
11267 *
|
|
|
11268 * @type string
|
|
|
11269 * @default Showing _START_ to _END_ of _TOTAL_ entries
|
|
|
11270 *
|
|
|
11271 * @dtopt Language
|
|
|
11272 * @name DataTable.defaults.language.info
|
|
|
11273 *
|
|
|
11274 * @example
|
|
|
11275 * $(document).ready( function() {
|
|
|
11276 * $('#example').dataTable( {
|
|
|
11277 * "language": {
|
|
|
11278 * "info": "Showing page _PAGE_ of _PAGES_"
|
|
|
11279 * }
|
|
|
11280 * } );
|
|
|
11281 * } );
|
|
|
11282 */
|
|
|
11283 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
|
|
|
11284
|
|
|
11285
|
|
|
11286 /**
|
|
|
11287 * Display information string for when the table is empty. Typically the
|
|
|
11288 * format of this string should match `info`.
|
|
|
11289 * @type string
|
|
|
11290 * @default Showing 0 to 0 of 0 entries
|
|
|
11291 *
|
|
|
11292 * @dtopt Language
|
|
|
11293 * @name DataTable.defaults.language.infoEmpty
|
|
|
11294 *
|
|
|
11295 * @example
|
|
|
11296 * $(document).ready( function() {
|
|
|
11297 * $('#example').dataTable( {
|
|
|
11298 * "language": {
|
|
|
11299 * "infoEmpty": "No entries to show"
|
|
|
11300 * }
|
|
|
11301 * } );
|
|
|
11302 * } );
|
|
|
11303 */
|
|
|
11304 "sInfoEmpty": "Showing 0 to 0 of 0 entries",
|
|
|
11305
|
|
|
11306
|
|
|
11307 /**
|
|
|
11308 * When a user filters the information in a table, this string is appended
|
|
|
11309 * to the information (`info`) to give an idea of how strong the filtering
|
|
|
11310 * is. The variable _MAX_ is dynamically updated.
|
|
|
11311 * @type string
|
|
|
11312 * @default (filtered from _MAX_ total entries)
|
|
|
11313 *
|
|
|
11314 * @dtopt Language
|
|
|
11315 * @name DataTable.defaults.language.infoFiltered
|
|
|
11316 *
|
|
|
11317 * @example
|
|
|
11318 * $(document).ready( function() {
|
|
|
11319 * $('#example').dataTable( {
|
|
|
11320 * "language": {
|
|
|
11321 * "infoFiltered": " - filtering from _MAX_ records"
|
|
|
11322 * }
|
|
|
11323 * } );
|
|
|
11324 * } );
|
|
|
11325 */
|
|
|
11326 "sInfoFiltered": "(filtered from _MAX_ total entries)",
|
|
|
11327
|
|
|
11328
|
|
|
11329 /**
|
|
|
11330 * If can be useful to append extra information to the info string at times,
|
|
|
11331 * and this variable does exactly that. This information will be appended to
|
|
|
11332 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
|
|
|
11333 * being used) at all times.
|
|
|
11334 * @type string
|
|
|
11335 * @default <i>Empty string</i>
|
|
|
11336 *
|
|
|
11337 * @dtopt Language
|
|
|
11338 * @name DataTable.defaults.language.infoPostFix
|
|
|
11339 *
|
|
|
11340 * @example
|
|
|
11341 * $(document).ready( function() {
|
|
|
11342 * $('#example').dataTable( {
|
|
|
11343 * "language": {
|
|
|
11344 * "infoPostFix": "All records shown are derived from real information."
|
|
|
11345 * }
|
|
|
11346 * } );
|
|
|
11347 * } );
|
|
|
11348 */
|
|
|
11349 "sInfoPostFix": "",
|
|
|
11350
|
|
|
11351
|
|
|
11352 /**
|
|
|
11353 * This decimal place operator is a little different from the other
|
|
|
11354 * language options since DataTables doesn't output floating point
|
|
|
11355 * numbers, so it won't ever use this for display of a number. Rather,
|
|
|
11356 * what this parameter does is modify the sort methods of the table so
|
|
|
11357 * that numbers which are in a format which has a character other than
|
|
|
11358 * a period (`.`) as a decimal place will be sorted numerically.
|
|
|
11359 *
|
|
|
11360 * Note that numbers with different decimal places cannot be shown in
|
|
|
11361 * the same table and still be sortable, the table must be consistent.
|
|
|
11362 * However, multiple different tables on the page can use different
|
|
|
11363 * decimal place characters.
|
|
|
11364 * @type string
|
|
|
11365 * @default
|
|
|
11366 *
|
|
|
11367 * @dtopt Language
|
|
|
11368 * @name DataTable.defaults.language.decimal
|
|
|
11369 *
|
|
|
11370 * @example
|
|
|
11371 * $(document).ready( function() {
|
|
|
11372 * $('#example').dataTable( {
|
|
|
11373 * "language": {
|
|
|
11374 * "decimal": ","
|
|
|
11375 * "thousands": "."
|
|
|
11376 * }
|
|
|
11377 * } );
|
|
|
11378 * } );
|
|
|
11379 */
|
|
|
11380 "sDecimal": "",
|
|
|
11381
|
|
|
11382
|
|
|
11383 /**
|
|
|
11384 * DataTables has a build in number formatter (`formatNumber`) which is
|
|
|
11385 * used to format large numbers that are used in the table information.
|
|
|
11386 * By default a comma is used, but this can be trivially changed to any
|
|
|
11387 * character you wish with this parameter.
|
|
|
11388 * @type string
|
|
|
11389 * @default ,
|
|
|
11390 *
|
|
|
11391 * @dtopt Language
|
|
|
11392 * @name DataTable.defaults.language.thousands
|
|
|
11393 *
|
|
|
11394 * @example
|
|
|
11395 * $(document).ready( function() {
|
|
|
11396 * $('#example').dataTable( {
|
|
|
11397 * "language": {
|
|
|
11398 * "thousands": "'"
|
|
|
11399 * }
|
|
|
11400 * } );
|
|
|
11401 * } );
|
|
|
11402 */
|
|
|
11403 "sThousands": ",",
|
|
|
11404
|
|
|
11405
|
|
|
11406 /**
|
|
|
11407 * Detail the action that will be taken when the drop down menu for the
|
|
|
11408 * pagination length option is changed. The '_MENU_' variable is replaced
|
|
|
11409 * with a default select list of 10, 25, 50 and 100, and can be replaced
|
|
|
11410 * with a custom select box if required.
|
|
|
11411 * @type string
|
|
|
11412 * @default Show _MENU_ entries
|
|
|
11413 *
|
|
|
11414 * @dtopt Language
|
|
|
11415 * @name DataTable.defaults.language.lengthMenu
|
|
|
11416 *
|
|
|
11417 * @example
|
|
|
11418 * // Language change only
|
|
|
11419 * $(document).ready( function() {
|
|
|
11420 * $('#example').dataTable( {
|
|
|
11421 * "language": {
|
|
|
11422 * "lengthMenu": "Display _MENU_ records"
|
|
|
11423 * }
|
|
|
11424 * } );
|
|
|
11425 * } );
|
|
|
11426 *
|
|
|
11427 * @example
|
|
|
11428 * // Language and options change
|
|
|
11429 * $(document).ready( function() {
|
|
|
11430 * $('#example').dataTable( {
|
|
|
11431 * "language": {
|
|
|
11432 * "lengthMenu": 'Display <select>'+
|
|
|
11433 * '<option value="10">10</option>'+
|
|
|
11434 * '<option value="20">20</option>'+
|
|
|
11435 * '<option value="30">30</option>'+
|
|
|
11436 * '<option value="40">40</option>'+
|
|
|
11437 * '<option value="50">50</option>'+
|
|
|
11438 * '<option value="-1">All</option>'+
|
|
|
11439 * '</select> records'
|
|
|
11440 * }
|
|
|
11441 * } );
|
|
|
11442 * } );
|
|
|
11443 */
|
|
|
11444 "sLengthMenu": "Show _MENU_ entries",
|
|
|
11445
|
|
|
11446
|
|
|
11447 /**
|
|
|
11448 * When using Ajax sourced data and during the first draw when DataTables is
|
|
|
11449 * gathering the data, this message is shown in an empty row in the table to
|
|
|
11450 * indicate to the end user the the data is being loaded. Note that this
|
|
|
11451 * parameter is not used when loading data by server-side processing, just
|
|
|
11452 * Ajax sourced data with client-side processing.
|
|
|
11453 * @type string
|
|
|
11454 * @default Loading...
|
|
|
11455 *
|
|
|
11456 * @dtopt Language
|
|
|
11457 * @name DataTable.defaults.language.loadingRecords
|
|
|
11458 *
|
|
|
11459 * @example
|
|
|
11460 * $(document).ready( function() {
|
|
|
11461 * $('#example').dataTable( {
|
|
|
11462 * "language": {
|
|
|
11463 * "loadingRecords": "Please wait - loading..."
|
|
|
11464 * }
|
|
|
11465 * } );
|
|
|
11466 * } );
|
|
|
11467 */
|
|
|
11468 "sLoadingRecords": "Loading...",
|
|
|
11469
|
|
|
11470
|
|
|
11471 /**
|
|
|
11472 * Text which is displayed when the table is processing a user action
|
|
|
11473 * (usually a sort command or similar).
|
|
|
11474 * @type string
|
|
|
11475 * @default Processing...
|
|
|
11476 *
|
|
|
11477 * @dtopt Language
|
|
|
11478 * @name DataTable.defaults.language.processing
|
|
|
11479 *
|
|
|
11480 * @example
|
|
|
11481 * $(document).ready( function() {
|
|
|
11482 * $('#example').dataTable( {
|
|
|
11483 * "language": {
|
|
|
11484 * "processing": "DataTables is currently busy"
|
|
|
11485 * }
|
|
|
11486 * } );
|
|
|
11487 * } );
|
|
|
11488 */
|
|
|
11489 "sProcessing": "Processing...",
|
|
|
11490
|
|
|
11491
|
|
|
11492 /**
|
|
|
11493 * Details the actions that will be taken when the user types into the
|
|
|
11494 * filtering input text box. The variable "_INPUT_", if used in the string,
|
|
|
11495 * is replaced with the HTML text box for the filtering input allowing
|
|
|
11496 * control over where it appears in the string. If "_INPUT_" is not given
|
|
|
11497 * then the input box is appended to the string automatically.
|
|
|
11498 * @type string
|
|
|
11499 * @default Search:
|
|
|
11500 *
|
|
|
11501 * @dtopt Language
|
|
|
11502 * @name DataTable.defaults.language.search
|
|
|
11503 *
|
|
|
11504 * @example
|
|
|
11505 * // Input text box will be appended at the end automatically
|
|
|
11506 * $(document).ready( function() {
|
|
|
11507 * $('#example').dataTable( {
|
|
|
11508 * "language": {
|
|
|
11509 * "search": "Filter records:"
|
|
|
11510 * }
|
|
|
11511 * } );
|
|
|
11512 * } );
|
|
|
11513 *
|
|
|
11514 * @example
|
|
|
11515 * // Specify where the filter should appear
|
|
|
11516 * $(document).ready( function() {
|
|
|
11517 * $('#example').dataTable( {
|
|
|
11518 * "language": {
|
|
|
11519 * "search": "Apply filter _INPUT_ to table"
|
|
|
11520 * }
|
|
|
11521 * } );
|
|
|
11522 * } );
|
|
|
11523 */
|
|
|
11524 "sSearch": "Search:",
|
|
|
11525
|
|
|
11526
|
|
|
11527 /**
|
|
|
11528 * Assign a `placeholder` attribute to the search `input` element
|
|
|
11529 * @type string
|
|
|
11530 * @default
|
|
|
11531 *
|
|
|
11532 * @dtopt Language
|
|
|
11533 * @name DataTable.defaults.language.searchPlaceholder
|
|
|
11534 */
|
|
|
11535 "sSearchPlaceholder": "",
|
|
|
11536
|
|
|
11537
|
|
|
11538 /**
|
|
|
11539 * All of the language information can be stored in a file on the
|
|
|
11540 * server-side, which DataTables will look up if this parameter is passed.
|
|
|
11541 * It must store the URL of the language file, which is in a JSON format,
|
|
|
11542 * and the object has the same properties as the oLanguage object in the
|
|
|
11543 * initialiser object (i.e. the above parameters). Please refer to one of
|
|
|
11544 * the example language files to see how this works in action.
|
|
|
11545 * @type string
|
|
|
11546 * @default <i>Empty string - i.e. disabled</i>
|
|
|
11547 *
|
|
|
11548 * @dtopt Language
|
|
|
11549 * @name DataTable.defaults.language.url
|
|
|
11550 *
|
|
|
11551 * @example
|
|
|
11552 * $(document).ready( function() {
|
|
|
11553 * $('#example').dataTable( {
|
|
|
11554 * "language": {
|
|
|
11555 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
|
|
|
11556 * }
|
|
|
11557 * } );
|
|
|
11558 * } );
|
|
|
11559 */
|
|
|
11560 "sUrl": "",
|
|
|
11561
|
|
|
11562
|
|
|
11563 /**
|
|
|
11564 * Text shown inside the table records when the is no information to be
|
|
|
11565 * displayed after filtering. `emptyTable` is shown when there is simply no
|
|
|
11566 * information in the table at all (regardless of filtering).
|
|
|
11567 * @type string
|
|
|
11568 * @default No matching records found
|
|
|
11569 *
|
|
|
11570 * @dtopt Language
|
|
|
11571 * @name DataTable.defaults.language.zeroRecords
|
|
|
11572 *
|
|
|
11573 * @example
|
|
|
11574 * $(document).ready( function() {
|
|
|
11575 * $('#example').dataTable( {
|
|
|
11576 * "language": {
|
|
|
11577 * "zeroRecords": "No records to display"
|
|
|
11578 * }
|
|
|
11579 * } );
|
|
|
11580 * } );
|
|
|
11581 */
|
|
|
11582 "sZeroRecords": "No matching records found"
|
|
|
11583 },
|
|
|
11584
|
|
|
11585
|
|
|
11586 /**
|
|
|
11587 * This parameter allows you to have define the global filtering state at
|
|
|
11588 * initialisation time. As an object the `search` parameter must be
|
|
|
11589 * defined, but all other parameters are optional. When `regex` is true,
|
|
|
11590 * the search string will be treated as a regular expression, when false
|
|
|
11591 * (default) it will be treated as a straight string. When `smart`
|
|
|
11592 * DataTables will use it's smart filtering methods (to word match at
|
|
|
11593 * any point in the data), when false this will not be done.
|
|
|
11594 * @namespace
|
|
|
11595 * @extends DataTable.models.oSearch
|
|
|
11596 *
|
|
|
11597 * @dtopt Options
|
|
|
11598 * @name DataTable.defaults.search
|
|
|
11599 *
|
|
|
11600 * @example
|
|
|
11601 * $(document).ready( function() {
|
|
|
11602 * $('#example').dataTable( {
|
|
|
11603 * "search": {"search": "Initial search"}
|
|
|
11604 * } );
|
|
|
11605 * } )
|
|
|
11606 */
|
|
|
11607 "oSearch": $.extend( {}, DataTable.models.oSearch ),
|
|
|
11608
|
|
|
11609
|
|
|
11610 /**
|
|
|
11611 * __Deprecated__ The functionality provided by this parameter has now been
|
|
|
11612 * superseded by that provided through `ajax`, which should be used instead.
|
|
|
11613 *
|
|
|
11614 * By default DataTables will look for the property `data` (or `aaData` for
|
|
|
11615 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
|
|
|
11616 * source or for server-side processing - this parameter allows that
|
|
|
11617 * property to be changed. You can use Javascript dotted object notation to
|
|
|
11618 * get a data source for multiple levels of nesting.
|
|
|
11619 * @type string
|
|
|
11620 * @default data
|
|
|
11621 *
|
|
|
11622 * @dtopt Options
|
|
|
11623 * @dtopt Server-side
|
|
|
11624 * @name DataTable.defaults.ajaxDataProp
|
|
|
11625 *
|
|
|
11626 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
|
11627 */
|
|
|
11628 "sAjaxDataProp": "data",
|
|
|
11629
|
|
|
11630
|
|
|
11631 /**
|
|
|
11632 * __Deprecated__ The functionality provided by this parameter has now been
|
|
|
11633 * superseded by that provided through `ajax`, which should be used instead.
|
|
|
11634 *
|
|
|
11635 * You can instruct DataTables to load data from an external
|
|
|
11636 * source using this parameter (use aData if you want to pass data in you
|
|
|
11637 * already have). Simply provide a url a JSON object can be obtained from.
|
|
|
11638 * @type string
|
|
|
11639 * @default null
|
|
|
11640 *
|
|
|
11641 * @dtopt Options
|
|
|
11642 * @dtopt Server-side
|
|
|
11643 * @name DataTable.defaults.ajaxSource
|
|
|
11644 *
|
|
|
11645 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
|
11646 */
|
|
|
11647 "sAjaxSource": null,
|
|
|
11648
|
|
|
11649
|
|
|
11650 /**
|
|
|
11651 * This initialisation variable allows you to specify exactly where in the
|
|
|
11652 * DOM you want DataTables to inject the various controls it adds to the page
|
|
|
11653 * (for example you might want the pagination controls at the top of the
|
|
|
11654 * table). DIV elements (with or without a custom class) can also be added to
|
|
|
11655 * aid styling. The follow syntax is used:
|
|
|
11656 * <ul>
|
|
|
11657 * <li>The following options are allowed:
|
|
|
11658 * <ul>
|
|
|
11659 * <li>'l' - Length changing</li>
|
|
|
11660 * <li>'f' - Filtering input</li>
|
|
|
11661 * <li>'t' - The table!</li>
|
|
|
11662 * <li>'i' - Information</li>
|
|
|
11663 * <li>'p' - Pagination</li>
|
|
|
11664 * <li>'r' - pRocessing</li>
|
|
|
11665 * </ul>
|
|
|
11666 * </li>
|
|
|
11667 * <li>The following constants are allowed:
|
|
|
11668 * <ul>
|
|
|
11669 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
|
|
|
11670 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
|
|
|
11671 * </ul>
|
|
|
11672 * </li>
|
|
|
11673 * <li>The following syntax is expected:
|
|
|
11674 * <ul>
|
|
|
11675 * <li>'<' and '>' - div elements</li>
|
|
|
11676 * <li>'<"class" and '>' - div with a class</li>
|
|
|
11677 * <li>'<"#id" and '>' - div with an ID</li>
|
|
|
11678 * </ul>
|
|
|
11679 * </li>
|
|
|
11680 * <li>Examples:
|
|
|
11681 * <ul>
|
|
|
11682 * <li>'<"wrapper"flipt>'</li>
|
|
|
11683 * <li>'<lf<t>ip>'</li>
|
|
|
11684 * </ul>
|
|
|
11685 * </li>
|
|
|
11686 * </ul>
|
|
|
11687 * @type string
|
|
|
11688 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
|
|
|
11689 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
|
|
|
11690 *
|
|
|
11691 * @dtopt Options
|
|
|
11692 * @name DataTable.defaults.dom
|
|
|
11693 *
|
|
|
11694 * @example
|
|
|
11695 * $(document).ready( function() {
|
|
|
11696 * $('#example').dataTable( {
|
|
|
11697 * "dom": '<"top"i>rt<"bottom"flp><"clear">'
|
|
|
11698 * } );
|
|
|
11699 * } );
|
|
|
11700 */
|
|
|
11701 "sDom": "lfrtip",
|
|
|
11702
|
|
|
11703
|
|
|
11704 /**
|
|
|
11705 * Search delay option. This will throttle full table searches that use the
|
|
|
11706 * DataTables provided search input element (it does not effect calls to
|
|
|
11707 * `dt-api search()`, providing a delay before the search is made.
|
|
|
11708 * @type integer
|
|
|
11709 * @default 0
|
|
|
11710 *
|
|
|
11711 * @dtopt Options
|
|
|
11712 * @name DataTable.defaults.searchDelay
|
|
|
11713 *
|
|
|
11714 * @example
|
|
|
11715 * $(document).ready( function() {
|
|
|
11716 * $('#example').dataTable( {
|
|
|
11717 * "searchDelay": 200
|
|
|
11718 * } );
|
|
|
11719 * } )
|
|
|
11720 */
|
|
|
11721 "searchDelay": null,
|
|
|
11722
|
|
|
11723
|
|
|
11724 /**
|
|
|
11725 * DataTables features four different built-in options for the buttons to
|
|
|
11726 * display for pagination control:
|
|
|
11727 *
|
|
|
11728 * * `simple` - 'Previous' and 'Next' buttons only
|
|
|
11729 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
|
|
|
11730 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
|
|
|
11731 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
|
|
|
11732 * page numbers
|
|
|
11733 *
|
|
|
11734 * Further methods can be added using {@link DataTable.ext.oPagination}.
|
|
|
11735 * @type string
|
|
|
11736 * @default simple_numbers
|
|
|
11737 *
|
|
|
11738 * @dtopt Options
|
|
|
11739 * @name DataTable.defaults.pagingType
|
|
|
11740 *
|
|
|
11741 * @example
|
|
|
11742 * $(document).ready( function() {
|
|
|
11743 * $('#example').dataTable( {
|
|
|
11744 * "pagingType": "full_numbers"
|
|
|
11745 * } );
|
|
|
11746 * } )
|
|
|
11747 */
|
|
|
11748 "sPaginationType": "simple_numbers",
|
|
|
11749
|
|
|
11750
|
|
|
11751 /**
|
|
|
11752 * Enable horizontal scrolling. When a table is too wide to fit into a
|
|
|
11753 * certain layout, or you have a large number of columns in the table, you
|
|
|
11754 * can enable x-scrolling to show the table in a viewport, which can be
|
|
|
11755 * scrolled. This property can be `true` which will allow the table to
|
|
|
11756 * scroll horizontally when needed, or any CSS unit, or a number (in which
|
|
|
11757 * case it will be treated as a pixel measurement). Setting as simply `true`
|
|
|
11758 * is recommended.
|
|
|
11759 * @type boolean|string
|
|
|
11760 * @default <i>blank string - i.e. disabled</i>
|
|
|
11761 *
|
|
|
11762 * @dtopt Features
|
|
|
11763 * @name DataTable.defaults.scrollX
|
|
|
11764 *
|
|
|
11765 * @example
|
|
|
11766 * $(document).ready( function() {
|
|
|
11767 * $('#example').dataTable( {
|
|
|
11768 * "scrollX": true,
|
|
|
11769 * "scrollCollapse": true
|
|
|
11770 * } );
|
|
|
11771 * } );
|
|
|
11772 */
|
|
|
11773 "sScrollX": "",
|
|
|
11774
|
|
|
11775
|
|
|
11776 /**
|
|
|
11777 * This property can be used to force a DataTable to use more width than it
|
|
|
11778 * might otherwise do when x-scrolling is enabled. For example if you have a
|
|
|
11779 * table which requires to be well spaced, this parameter is useful for
|
|
|
11780 * "over-sizing" the table, and thus forcing scrolling. This property can by
|
|
|
11781 * any CSS unit, or a number (in which case it will be treated as a pixel
|
|
|
11782 * measurement).
|
|
|
11783 * @type string
|
|
|
11784 * @default <i>blank string - i.e. disabled</i>
|
|
|
11785 *
|
|
|
11786 * @dtopt Options
|
|
|
11787 * @name DataTable.defaults.scrollXInner
|
|
|
11788 *
|
|
|
11789 * @example
|
|
|
11790 * $(document).ready( function() {
|
|
|
11791 * $('#example').dataTable( {
|
|
|
11792 * "scrollX": "100%",
|
|
|
11793 * "scrollXInner": "110%"
|
|
|
11794 * } );
|
|
|
11795 * } );
|
|
|
11796 */
|
|
|
11797 "sScrollXInner": "",
|
|
|
11798
|
|
|
11799
|
|
|
11800 /**
|
|
|
11801 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
|
|
|
11802 * to the given height, and enable scrolling for any data which overflows the
|
|
|
11803 * current viewport. This can be used as an alternative to paging to display
|
|
|
11804 * a lot of data in a small area (although paging and scrolling can both be
|
|
|
11805 * enabled at the same time). This property can be any CSS unit, or a number
|
|
|
11806 * (in which case it will be treated as a pixel measurement).
|
|
|
11807 * @type string
|
|
|
11808 * @default <i>blank string - i.e. disabled</i>
|
|
|
11809 *
|
|
|
11810 * @dtopt Features
|
|
|
11811 * @name DataTable.defaults.scrollY
|
|
|
11812 *
|
|
|
11813 * @example
|
|
|
11814 * $(document).ready( function() {
|
|
|
11815 * $('#example').dataTable( {
|
|
|
11816 * "scrollY": "200px",
|
|
|
11817 * "paginate": false
|
|
|
11818 * } );
|
|
|
11819 * } );
|
|
|
11820 */
|
|
|
11821 "sScrollY": "",
|
|
|
11822
|
|
|
11823
|
|
|
11824 /**
|
|
|
11825 * __Deprecated__ The functionality provided by this parameter has now been
|
|
|
11826 * superseded by that provided through `ajax`, which should be used instead.
|
|
|
11827 *
|
|
|
11828 * Set the HTTP method that is used to make the Ajax call for server-side
|
|
|
11829 * processing or Ajax sourced data.
|
|
|
11830 * @type string
|
|
|
11831 * @default GET
|
|
|
11832 *
|
|
|
11833 * @dtopt Options
|
|
|
11834 * @dtopt Server-side
|
|
|
11835 * @name DataTable.defaults.serverMethod
|
|
|
11836 *
|
|
|
11837 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
|
11838 */
|
|
|
11839 "sServerMethod": "GET",
|
|
|
11840
|
|
|
11841
|
|
|
11842 /**
|
|
|
11843 * DataTables makes use of renderers when displaying HTML elements for
|
|
|
11844 * a table. These renderers can be added or modified by plug-ins to
|
|
|
11845 * generate suitable mark-up for a site. For example the Bootstrap
|
|
|
11846 * integration plug-in for DataTables uses a paging button renderer to
|
|
|
11847 * display pagination buttons in the mark-up required by Bootstrap.
|
|
|
11848 *
|
|
|
11849 * For further information about the renderers available see
|
|
|
11850 * DataTable.ext.renderer
|
|
|
11851 * @type string|object
|
|
|
11852 * @default null
|
|
|
11853 *
|
|
|
11854 * @name DataTable.defaults.renderer
|
|
|
11855 *
|
|
|
11856 */
|
|
|
11857 "renderer": null,
|
|
|
11858
|
|
|
11859
|
|
|
11860 /**
|
|
|
11861 * Set the data property name that DataTables should use to get a row's id
|
|
|
11862 * to set as the `id` property in the node.
|
|
|
11863 * @type string
|
|
|
11864 * @default DT_RowId
|
|
|
11865 *
|
|
|
11866 * @name DataTable.defaults.rowId
|
|
|
11867 */
|
|
|
11868 "rowId": "DT_RowId"
|
|
|
11869 };
|
|
|
11870
|
|
|
11871 _fnHungarianMap( DataTable.defaults );
|
|
|
11872
|
|
|
11873
|
|
|
11874
|
|
|
11875 /*
|
|
|
11876 * Developer note - See note in model.defaults.js about the use of Hungarian
|
|
|
11877 * notation and camel case.
|
|
|
11878 */
|
|
|
11879
|
|
|
11880 /**
|
|
|
11881 * Column options that can be given to DataTables at initialisation time.
|
|
|
11882 * @namespace
|
|
|
11883 */
|
|
|
11884 DataTable.defaults.column = {
|
|
|
11885 /**
|
|
|
11886 * Define which column(s) an order will occur on for this column. This
|
|
|
11887 * allows a column's ordering to take multiple columns into account when
|
|
|
11888 * doing a sort or use the data from a different column. For example first
|
|
|
11889 * name / last name columns make sense to do a multi-column sort over the
|
|
|
11890 * two columns.
|
|
|
11891 * @type array|int
|
|
|
11892 * @default null <i>Takes the value of the column index automatically</i>
|
|
|
11893 *
|
|
|
11894 * @name DataTable.defaults.column.orderData
|
|
|
11895 * @dtopt Columns
|
|
|
11896 *
|
|
|
11897 * @example
|
|
|
11898 * // Using `columnDefs`
|
|
|
11899 * $(document).ready( function() {
|
|
|
11900 * $('#example').dataTable( {
|
|
|
11901 * "columnDefs": [
|
|
|
11902 * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
|
|
|
11903 * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
|
|
|
11904 * { "orderData": 2, "targets": [ 2 ] }
|
|
|
11905 * ]
|
|
|
11906 * } );
|
|
|
11907 * } );
|
|
|
11908 *
|
|
|
11909 * @example
|
|
|
11910 * // Using `columns`
|
|
|
11911 * $(document).ready( function() {
|
|
|
11912 * $('#example').dataTable( {
|
|
|
11913 * "columns": [
|
|
|
11914 * { "orderData": [ 0, 1 ] },
|
|
|
11915 * { "orderData": [ 1, 0 ] },
|
|
|
11916 * { "orderData": 2 },
|
|
|
11917 * null,
|
|
|
11918 * null
|
|
|
11919 * ]
|
|
|
11920 * } );
|
|
|
11921 * } );
|
|
|
11922 */
|
|
|
11923 "aDataSort": null,
|
|
|
11924 "iDataSort": -1,
|
|
|
11925
|
|
|
11926
|
|
|
11927 /**
|
|
|
11928 * You can control the default ordering direction, and even alter the
|
|
|
11929 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
|
|
|
11930 * using this parameter.
|
|
|
11931 * @type array
|
|
|
11932 * @default [ 'asc', 'desc' ]
|
|
|
11933 *
|
|
|
11934 * @name DataTable.defaults.column.orderSequence
|
|
|
11935 * @dtopt Columns
|
|
|
11936 *
|
|
|
11937 * @example
|
|
|
11938 * // Using `columnDefs`
|
|
|
11939 * $(document).ready( function() {
|
|
|
11940 * $('#example').dataTable( {
|
|
|
11941 * "columnDefs": [
|
|
|
11942 * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
|
|
|
11943 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
|
|
|
11944 * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
|
|
|
11945 * ]
|
|
|
11946 * } );
|
|
|
11947 * } );
|
|
|
11948 *
|
|
|
11949 * @example
|
|
|
11950 * // Using `columns`
|
|
|
11951 * $(document).ready( function() {
|
|
|
11952 * $('#example').dataTable( {
|
|
|
11953 * "columns": [
|
|
|
11954 * null,
|
|
|
11955 * { "orderSequence": [ "asc" ] },
|
|
|
11956 * { "orderSequence": [ "desc", "asc", "asc" ] },
|
|
|
11957 * { "orderSequence": [ "desc" ] },
|
|
|
11958 * null
|
|
|
11959 * ]
|
|
|
11960 * } );
|
|
|
11961 * } );
|
|
|
11962 */
|
|
|
11963 "asSorting": [ 'asc', 'desc' ],
|
|
|
11964
|
|
|
11965
|
|
|
11966 /**
|
|
|
11967 * Enable or disable filtering on the data in this column.
|
|
|
11968 * @type boolean
|
|
|
11969 * @default true
|
|
|
11970 *
|
|
|
11971 * @name DataTable.defaults.column.searchable
|
|
|
11972 * @dtopt Columns
|
|
|
11973 *
|
|
|
11974 * @example
|
|
|
11975 * // Using `columnDefs`
|
|
|
11976 * $(document).ready( function() {
|
|
|
11977 * $('#example').dataTable( {
|
|
|
11978 * "columnDefs": [
|
|
|
11979 * { "searchable": false, "targets": [ 0 ] }
|
|
|
11980 * ] } );
|
|
|
11981 * } );
|
|
|
11982 *
|
|
|
11983 * @example
|
|
|
11984 * // Using `columns`
|
|
|
11985 * $(document).ready( function() {
|
|
|
11986 * $('#example').dataTable( {
|
|
|
11987 * "columns": [
|
|
|
11988 * { "searchable": false },
|
|
|
11989 * null,
|
|
|
11990 * null,
|
|
|
11991 * null,
|
|
|
11992 * null
|
|
|
11993 * ] } );
|
|
|
11994 * } );
|
|
|
11995 */
|
|
|
11996 "bSearchable": true,
|
|
|
11997
|
|
|
11998
|
|
|
11999 /**
|
|
|
12000 * Enable or disable ordering on this column.
|
|
|
12001 * @type boolean
|
|
|
12002 * @default true
|
|
|
12003 *
|
|
|
12004 * @name DataTable.defaults.column.orderable
|
|
|
12005 * @dtopt Columns
|
|
|
12006 *
|
|
|
12007 * @example
|
|
|
12008 * // Using `columnDefs`
|
|
|
12009 * $(document).ready( function() {
|
|
|
12010 * $('#example').dataTable( {
|
|
|
12011 * "columnDefs": [
|
|
|
12012 * { "orderable": false, "targets": [ 0 ] }
|
|
|
12013 * ] } );
|
|
|
12014 * } );
|
|
|
12015 *
|
|
|
12016 * @example
|
|
|
12017 * // Using `columns`
|
|
|
12018 * $(document).ready( function() {
|
|
|
12019 * $('#example').dataTable( {
|
|
|
12020 * "columns": [
|
|
|
12021 * { "orderable": false },
|
|
|
12022 * null,
|
|
|
12023 * null,
|
|
|
12024 * null,
|
|
|
12025 * null
|
|
|
12026 * ] } );
|
|
|
12027 * } );
|
|
|
12028 */
|
|
|
12029 "bSortable": true,
|
|
|
12030
|
|
|
12031
|
|
|
12032 /**
|
|
|
12033 * Enable or disable the display of this column.
|
|
|
12034 * @type boolean
|
|
|
12035 * @default true
|
|
|
12036 *
|
|
|
12037 * @name DataTable.defaults.column.visible
|
|
|
12038 * @dtopt Columns
|
|
|
12039 *
|
|
|
12040 * @example
|
|
|
12041 * // Using `columnDefs`
|
|
|
12042 * $(document).ready( function() {
|
|
|
12043 * $('#example').dataTable( {
|
|
|
12044 * "columnDefs": [
|
|
|
12045 * { "visible": false, "targets": [ 0 ] }
|
|
|
12046 * ] } );
|
|
|
12047 * } );
|
|
|
12048 *
|
|
|
12049 * @example
|
|
|
12050 * // Using `columns`
|
|
|
12051 * $(document).ready( function() {
|
|
|
12052 * $('#example').dataTable( {
|
|
|
12053 * "columns": [
|
|
|
12054 * { "visible": false },
|
|
|
12055 * null,
|
|
|
12056 * null,
|
|
|
12057 * null,
|
|
|
12058 * null
|
|
|
12059 * ] } );
|
|
|
12060 * } );
|
|
|
12061 */
|
|
|
12062 "bVisible": true,
|
|
|
12063
|
|
|
12064
|
|
|
12065 /**
|
|
|
12066 * Developer definable function that is called whenever a cell is created (Ajax source,
|
|
|
12067 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
|
|
|
12068 * allowing you to modify the DOM element (add background colour for example) when the
|
|
|
12069 * element is available.
|
|
|
12070 * @type function
|
|
|
12071 * @param {element} td The TD node that has been created
|
|
|
12072 * @param {*} cellData The Data for the cell
|
|
|
12073 * @param {array|object} rowData The data for the whole row
|
|
|
12074 * @param {int} row The row index for the aoData data store
|
|
|
12075 * @param {int} col The column index for aoColumns
|
|
|
12076 *
|
|
|
12077 * @name DataTable.defaults.column.createdCell
|
|
|
12078 * @dtopt Columns
|
|
|
12079 *
|
|
|
12080 * @example
|
|
|
12081 * $(document).ready( function() {
|
|
|
12082 * $('#example').dataTable( {
|
|
|
12083 * "columnDefs": [ {
|
|
|
12084 * "targets": [3],
|
|
|
12085 * "createdCell": function (td, cellData, rowData, row, col) {
|
|
|
12086 * if ( cellData == "1.7" ) {
|
|
|
12087 * $(td).css('color', 'blue')
|
|
|
12088 * }
|
|
|
12089 * }
|
|
|
12090 * } ]
|
|
|
12091 * });
|
|
|
12092 * } );
|
|
|
12093 */
|
|
|
12094 "fnCreatedCell": null,
|
|
|
12095
|
|
|
12096
|
|
|
12097 /**
|
|
|
12098 * This parameter has been replaced by `data` in DataTables to ensure naming
|
|
|
12099 * consistency. `dataProp` can still be used, as there is backwards
|
|
|
12100 * compatibility in DataTables for this option, but it is strongly
|
|
|
12101 * recommended that you use `data` in preference to `dataProp`.
|
|
|
12102 * @name DataTable.defaults.column.dataProp
|
|
|
12103 */
|
|
|
12104
|
|
|
12105
|
|
|
12106 /**
|
|
|
12107 * This property can be used to read data from any data source property,
|
|
|
12108 * including deeply nested objects / properties. `data` can be given in a
|
|
|
12109 * number of different ways which effect its behaviour:
|
|
|
12110 *
|
|
|
12111 * * `integer` - treated as an array index for the data source. This is the
|
|
|
12112 * default that DataTables uses (incrementally increased for each column).
|
|
|
12113 * * `string` - read an object property from the data source. There are
|
|
|
12114 * three 'special' options that can be used in the string to alter how
|
|
|
12115 * DataTables reads the data from the source object:
|
|
|
12116 * * `.` - Dotted Javascript notation. Just as you use a `.` in
|
|
|
12117 * Javascript to read from nested objects, so to can the options
|
|
|
12118 * specified in `data`. For example: `browser.version` or
|
|
|
12119 * `browser.name`. If your object parameter name contains a period, use
|
|
|
12120 * `\\` to escape it - i.e. `first\\.name`.
|
|
|
12121 * * `[]` - Array notation. DataTables can automatically combine data
|
|
|
12122 * from and array source, joining the data with the characters provided
|
|
|
12123 * between the two brackets. For example: `name[, ]` would provide a
|
|
|
12124 * comma-space separated list from the source array. If no characters
|
|
|
12125 * are provided between the brackets, the original array source is
|
|
|
12126 * returned.
|
|
|
12127 * * `()` - Function notation. Adding `()` to the end of a parameter will
|
|
|
12128 * execute a function of the name given. For example: `browser()` for a
|
|
|
12129 * simple function on the data source, `browser.version()` for a
|
|
|
12130 * function in a nested property or even `browser().version` to get an
|
|
|
12131 * object property if the function called returns an object. Note that
|
|
|
12132 * function notation is recommended for use in `render` rather than
|
|
|
12133 * `data` as it is much simpler to use as a renderer.
|
|
|
12134 * * `null` - use the original data source for the row rather than plucking
|
|
|
12135 * data directly from it. This action has effects on two other
|
|
|
12136 * initialisation options:
|
|
|
12137 * * `defaultContent` - When null is given as the `data` option and
|
|
|
12138 * `defaultContent` is specified for the column, the value defined by
|
|
|
12139 * `defaultContent` will be used for the cell.
|
|
|
12140 * * `render` - When null is used for the `data` option and the `render`
|
|
|
12141 * option is specified for the column, the whole data source for the
|
|
|
12142 * row is used for the renderer.
|
|
|
12143 * * `function` - the function given will be executed whenever DataTables
|
|
|
12144 * needs to set or get the data for a cell in the column. The function
|
|
|
12145 * takes three parameters:
|
|
|
12146 * * Parameters:
|
|
|
12147 * * `{array|object}` The data source for the row
|
|
|
12148 * * `{string}` The type call data requested - this will be 'set' when
|
|
|
12149 * setting data or 'filter', 'display', 'type', 'sort' or undefined
|
|
|
12150 * when gathering data. Note that when `undefined` is given for the
|
|
|
12151 * type DataTables expects to get the raw data for the object back<
|
|
|
12152 * * `{*}` Data to set when the second parameter is 'set'.
|
|
|
12153 * * Return:
|
|
|
12154 * * The return value from the function is not required when 'set' is
|
|
|
12155 * the type of call, but otherwise the return is what will be used
|
|
|
12156 * for the data requested.
|
|
|
12157 *
|
|
|
12158 * Note that `data` is a getter and setter option. If you just require
|
|
|
12159 * formatting of data for output, you will likely want to use `render` which
|
|
|
12160 * is simply a getter and thus simpler to use.
|
|
|
12161 *
|
|
|
12162 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
|
|
|
12163 * name change reflects the flexibility of this property and is consistent
|
|
|
12164 * with the naming of mRender. If 'mDataProp' is given, then it will still
|
|
|
12165 * be used by DataTables, as it automatically maps the old name to the new
|
|
|
12166 * if required.
|
|
|
12167 *
|
|
|
12168 * @type string|int|function|null
|
|
|
12169 * @default null <i>Use automatically calculated column index</i>
|
|
|
12170 *
|
|
|
12171 * @name DataTable.defaults.column.data
|
|
|
12172 * @dtopt Columns
|
|
|
12173 *
|
|
|
12174 * @example
|
|
|
12175 * // Read table data from objects
|
|
|
12176 * // JSON structure for each row:
|
|
|
12177 * // {
|
|
|
12178 * // "engine": {value},
|
|
|
12179 * // "browser": {value},
|
|
|
12180 * // "platform": {value},
|
|
|
12181 * // "version": {value},
|
|
|
12182 * // "grade": {value}
|
|
|
12183 * // }
|
|
|
12184 * $(document).ready( function() {
|
|
|
12185 * $('#example').dataTable( {
|
|
|
12186 * "ajaxSource": "sources/objects.txt",
|
|
|
12187 * "columns": [
|
|
|
12188 * { "data": "engine" },
|
|
|
12189 * { "data": "browser" },
|
|
|
12190 * { "data": "platform" },
|
|
|
12191 * { "data": "version" },
|
|
|
12192 * { "data": "grade" }
|
|
|
12193 * ]
|
|
|
12194 * } );
|
|
|
12195 * } );
|
|
|
12196 *
|
|
|
12197 * @example
|
|
|
12198 * // Read information from deeply nested objects
|
|
|
12199 * // JSON structure for each row:
|
|
|
12200 * // {
|
|
|
12201 * // "engine": {value},
|
|
|
12202 * // "browser": {value},
|
|
|
12203 * // "platform": {
|
|
|
12204 * // "inner": {value}
|
|
|
12205 * // },
|
|
|
12206 * // "details": [
|
|
|
12207 * // {value}, {value}
|
|
|
12208 * // ]
|
|
|
12209 * // }
|
|
|
12210 * $(document).ready( function() {
|
|
|
12211 * $('#example').dataTable( {
|
|
|
12212 * "ajaxSource": "sources/deep.txt",
|
|
|
12213 * "columns": [
|
|
|
12214 * { "data": "engine" },
|
|
|
12215 * { "data": "browser" },
|
|
|
12216 * { "data": "platform.inner" },
|
|
|
12217 * { "data": "platform.details.0" },
|
|
|
12218 * { "data": "platform.details.1" }
|
|
|
12219 * ]
|
|
|
12220 * } );
|
|
|
12221 * } );
|
|
|
12222 *
|
|
|
12223 * @example
|
|
|
12224 * // Using `data` as a function to provide different information for
|
|
|
12225 * // sorting, filtering and display. In this case, currency (price)
|
|
|
12226 * $(document).ready( function() {
|
|
|
12227 * $('#example').dataTable( {
|
|
|
12228 * "columnDefs": [ {
|
|
|
12229 * "targets": [ 0 ],
|
|
|
12230 * "data": function ( source, type, val ) {
|
|
|
12231 * if (type === 'set') {
|
|
|
12232 * source.price = val;
|
|
|
12233 * // Store the computed dislay and filter values for efficiency
|
|
|
12234 * source.price_display = val=="" ? "" : "$"+numberFormat(val);
|
|
|
12235 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
|
|
|
12236 * return;
|
|
|
12237 * }
|
|
|
12238 * else if (type === 'display') {
|
|
|
12239 * return source.price_display;
|
|
|
12240 * }
|
|
|
12241 * else if (type === 'filter') {
|
|
|
12242 * return source.price_filter;
|
|
|
12243 * }
|
|
|
12244 * // 'sort', 'type' and undefined all just use the integer
|
|
|
12245 * return source.price;
|
|
|
12246 * }
|
|
|
12247 * } ]
|
|
|
12248 * } );
|
|
|
12249 * } );
|
|
|
12250 *
|
|
|
12251 * @example
|
|
|
12252 * // Using default content
|
|
|
12253 * $(document).ready( function() {
|
|
|
12254 * $('#example').dataTable( {
|
|
|
12255 * "columnDefs": [ {
|
|
|
12256 * "targets": [ 0 ],
|
|
|
12257 * "data": null,
|
|
|
12258 * "defaultContent": "Click to edit"
|
|
|
12259 * } ]
|
|
|
12260 * } );
|
|
|
12261 * } );
|
|
|
12262 *
|
|
|
12263 * @example
|
|
|
12264 * // Using array notation - outputting a list from an array
|
|
|
12265 * $(document).ready( function() {
|
|
|
12266 * $('#example').dataTable( {
|
|
|
12267 * "columnDefs": [ {
|
|
|
12268 * "targets": [ 0 ],
|
|
|
12269 * "data": "name[, ]"
|
|
|
12270 * } ]
|
|
|
12271 * } );
|
|
|
12272 * } );
|
|
|
12273 *
|
|
|
12274 */
|
|
|
12275 "mData": null,
|
|
|
12276
|
|
|
12277
|
|
|
12278 /**
|
|
|
12279 * This property is the rendering partner to `data` and it is suggested that
|
|
|
12280 * when you want to manipulate data for display (including filtering,
|
|
|
12281 * sorting etc) without altering the underlying data for the table, use this
|
|
|
12282 * property. `render` can be considered to be the the read only companion to
|
|
|
12283 * `data` which is read / write (then as such more complex). Like `data`
|
|
|
12284 * this option can be given in a number of different ways to effect its
|
|
|
12285 * behaviour:
|
|
|
12286 *
|
|
|
12287 * * `integer` - treated as an array index for the data source. This is the
|
|
|
12288 * default that DataTables uses (incrementally increased for each column).
|
|
|
12289 * * `string` - read an object property from the data source. There are
|
|
|
12290 * three 'special' options that can be used in the string to alter how
|
|
|
12291 * DataTables reads the data from the source object:
|
|
|
12292 * * `.` - Dotted Javascript notation. Just as you use a `.` in
|
|
|
12293 * Javascript to read from nested objects, so to can the options
|
|
|
12294 * specified in `data`. For example: `browser.version` or
|
|
|
12295 * `browser.name`. If your object parameter name contains a period, use
|
|
|
12296 * `\\` to escape it - i.e. `first\\.name`.
|
|
|
12297 * * `[]` - Array notation. DataTables can automatically combine data
|
|
|
12298 * from and array source, joining the data with the characters provided
|
|
|
12299 * between the two brackets. For example: `name[, ]` would provide a
|
|
|
12300 * comma-space separated list from the source array. If no characters
|
|
|
12301 * are provided between the brackets, the original array source is
|
|
|
12302 * returned.
|
|
|
12303 * * `()` - Function notation. Adding `()` to the end of a parameter will
|
|
|
12304 * execute a function of the name given. For example: `browser()` for a
|
|
|
12305 * simple function on the data source, `browser.version()` for a
|
|
|
12306 * function in a nested property or even `browser().version` to get an
|
|
|
12307 * object property if the function called returns an object.
|
|
|
12308 * * `object` - use different data for the different data types requested by
|
|
|
12309 * DataTables ('filter', 'display', 'type' or 'sort'). The property names
|
|
|
12310 * of the object is the data type the property refers to and the value can
|
|
|
12311 * defined using an integer, string or function using the same rules as
|
|
|
12312 * `render` normally does. Note that an `_` option _must_ be specified.
|
|
|
12313 * This is the default value to use if you haven't specified a value for
|
|
|
12314 * the data type requested by DataTables.
|
|
|
12315 * * `function` - the function given will be executed whenever DataTables
|
|
|
12316 * needs to set or get the data for a cell in the column. The function
|
|
|
12317 * takes three parameters:
|
|
|
12318 * * Parameters:
|
|
|
12319 * * {array|object} The data source for the row (based on `data`)
|
|
|
12320 * * {string} The type call data requested - this will be 'filter',
|
|
|
12321 * 'display', 'type' or 'sort'.
|
|
|
12322 * * {array|object} The full data source for the row (not based on
|
|
|
12323 * `data`)
|
|
|
12324 * * Return:
|
|
|
12325 * * The return value from the function is what will be used for the
|
|
|
12326 * data requested.
|
|
|
12327 *
|
|
|
12328 * @type string|int|function|object|null
|
|
|
12329 * @default null Use the data source value.
|
|
|
12330 *
|
|
|
12331 * @name DataTable.defaults.column.render
|
|
|
12332 * @dtopt Columns
|
|
|
12333 *
|
|
|
12334 * @example
|
|
|
12335 * // Create a comma separated list from an array of objects
|
|
|
12336 * $(document).ready( function() {
|
|
|
12337 * $('#example').dataTable( {
|
|
|
12338 * "ajaxSource": "sources/deep.txt",
|
|
|
12339 * "columns": [
|
|
|
12340 * { "data": "engine" },
|
|
|
12341 * { "data": "browser" },
|
|
|
12342 * {
|
|
|
12343 * "data": "platform",
|
|
|
12344 * "render": "[, ].name"
|
|
|
12345 * }
|
|
|
12346 * ]
|
|
|
12347 * } );
|
|
|
12348 * } );
|
|
|
12349 *
|
|
|
12350 * @example
|
|
|
12351 * // Execute a function to obtain data
|
|
|
12352 * $(document).ready( function() {
|
|
|
12353 * $('#example').dataTable( {
|
|
|
12354 * "columnDefs": [ {
|
|
|
12355 * "targets": [ 0 ],
|
|
|
12356 * "data": null, // Use the full data source object for the renderer's source
|
|
|
12357 * "render": "browserName()"
|
|
|
12358 * } ]
|
|
|
12359 * } );
|
|
|
12360 * } );
|
|
|
12361 *
|
|
|
12362 * @example
|
|
|
12363 * // As an object, extracting different data for the different types
|
|
|
12364 * // This would be used with a data source such as:
|
|
|
12365 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
|
|
|
12366 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
|
|
|
12367 * // (which has both forms) is used for filtering for if a user inputs either format, while
|
|
|
12368 * // the formatted phone number is the one that is shown in the table.
|
|
|
12369 * $(document).ready( function() {
|
|
|
12370 * $('#example').dataTable( {
|
|
|
12371 * "columnDefs": [ {
|
|
|
12372 * "targets": [ 0 ],
|
|
|
12373 * "data": null, // Use the full data source object for the renderer's source
|
|
|
12374 * "render": {
|
|
|
12375 * "_": "phone",
|
|
|
12376 * "filter": "phone_filter",
|
|
|
12377 * "display": "phone_display"
|
|
|
12378 * }
|
|
|
12379 * } ]
|
|
|
12380 * } );
|
|
|
12381 * } );
|
|
|
12382 *
|
|
|
12383 * @example
|
|
|
12384 * // Use as a function to create a link from the data source
|
|
|
12385 * $(document).ready( function() {
|
|
|
12386 * $('#example').dataTable( {
|
|
|
12387 * "columnDefs": [ {
|
|
|
12388 * "targets": [ 0 ],
|
|
|
12389 * "data": "download_link",
|
|
|
12390 * "render": function ( data, type, full ) {
|
|
|
12391 * return '<a href="'+data+'">Download</a>';
|
|
|
12392 * }
|
|
|
12393 * } ]
|
|
|
12394 * } );
|
|
|
12395 * } );
|
|
|
12396 */
|
|
|
12397 "mRender": null,
|
|
|
12398
|
|
|
12399
|
|
|
12400 /**
|
|
|
12401 * Change the cell type created for the column - either TD cells or TH cells. This
|
|
|
12402 * can be useful as TH cells have semantic meaning in the table body, allowing them
|
|
|
12403 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
|
|
|
12404 * @type string
|
|
|
12405 * @default td
|
|
|
12406 *
|
|
|
12407 * @name DataTable.defaults.column.cellType
|
|
|
12408 * @dtopt Columns
|
|
|
12409 *
|
|
|
12410 * @example
|
|
|
12411 * // Make the first column use TH cells
|
|
|
12412 * $(document).ready( function() {
|
|
|
12413 * $('#example').dataTable( {
|
|
|
12414 * "columnDefs": [ {
|
|
|
12415 * "targets": [ 0 ],
|
|
|
12416 * "cellType": "th"
|
|
|
12417 * } ]
|
|
|
12418 * } );
|
|
|
12419 * } );
|
|
|
12420 */
|
|
|
12421 "sCellType": "td",
|
|
|
12422
|
|
|
12423
|
|
|
12424 /**
|
|
|
12425 * Class to give to each cell in this column.
|
|
|
12426 * @type string
|
|
|
12427 * @default <i>Empty string</i>
|
|
|
12428 *
|
|
|
12429 * @name DataTable.defaults.column.class
|
|
|
12430 * @dtopt Columns
|
|
|
12431 *
|
|
|
12432 * @example
|
|
|
12433 * // Using `columnDefs`
|
|
|
12434 * $(document).ready( function() {
|
|
|
12435 * $('#example').dataTable( {
|
|
|
12436 * "columnDefs": [
|
|
|
12437 * { "class": "my_class", "targets": [ 0 ] }
|
|
|
12438 * ]
|
|
|
12439 * } );
|
|
|
12440 * } );
|
|
|
12441 *
|
|
|
12442 * @example
|
|
|
12443 * // Using `columns`
|
|
|
12444 * $(document).ready( function() {
|
|
|
12445 * $('#example').dataTable( {
|
|
|
12446 * "columns": [
|
|
|
12447 * { "class": "my_class" },
|
|
|
12448 * null,
|
|
|
12449 * null,
|
|
|
12450 * null,
|
|
|
12451 * null
|
|
|
12452 * ]
|
|
|
12453 * } );
|
|
|
12454 * } );
|
|
|
12455 */
|
|
|
12456 "sClass": "",
|
|
|
12457
|
|
|
12458 /**
|
|
|
12459 * When DataTables calculates the column widths to assign to each column,
|
|
|
12460 * it finds the longest string in each column and then constructs a
|
|
|
12461 * temporary table and reads the widths from that. The problem with this
|
|
|
12462 * is that "mmm" is much wider then "iiii", but the latter is a longer
|
|
|
12463 * string - thus the calculation can go wrong (doing it properly and putting
|
|
|
12464 * it into an DOM object and measuring that is horribly(!) slow). Thus as
|
|
|
12465 * a "work around" we provide this option. It will append its value to the
|
|
|
12466 * text that is found to be the longest string for the column - i.e. padding.
|
|
|
12467 * Generally you shouldn't need this!
|
|
|
12468 * @type string
|
|
|
12469 * @default <i>Empty string<i>
|
|
|
12470 *
|
|
|
12471 * @name DataTable.defaults.column.contentPadding
|
|
|
12472 * @dtopt Columns
|
|
|
12473 *
|
|
|
12474 * @example
|
|
|
12475 * // Using `columns`
|
|
|
12476 * $(document).ready( function() {
|
|
|
12477 * $('#example').dataTable( {
|
|
|
12478 * "columns": [
|
|
|
12479 * null,
|
|
|
12480 * null,
|
|
|
12481 * null,
|
|
|
12482 * {
|
|
|
12483 * "contentPadding": "mmm"
|
|
|
12484 * }
|
|
|
12485 * ]
|
|
|
12486 * } );
|
|
|
12487 * } );
|
|
|
12488 */
|
|
|
12489 "sContentPadding": "",
|
|
|
12490
|
|
|
12491
|
|
|
12492 /**
|
|
|
12493 * Allows a default value to be given for a column's data, and will be used
|
|
|
12494 * whenever a null data source is encountered (this can be because `data`
|
|
|
12495 * is set to null, or because the data source itself is null).
|
|
|
12496 * @type string
|
|
|
12497 * @default null
|
|
|
12498 *
|
|
|
12499 * @name DataTable.defaults.column.defaultContent
|
|
|
12500 * @dtopt Columns
|
|
|
12501 *
|
|
|
12502 * @example
|
|
|
12503 * // Using `columnDefs`
|
|
|
12504 * $(document).ready( function() {
|
|
|
12505 * $('#example').dataTable( {
|
|
|
12506 * "columnDefs": [
|
|
|
12507 * {
|
|
|
12508 * "data": null,
|
|
|
12509 * "defaultContent": "Edit",
|
|
|
12510 * "targets": [ -1 ]
|
|
|
12511 * }
|
|
|
12512 * ]
|
|
|
12513 * } );
|
|
|
12514 * } );
|
|
|
12515 *
|
|
|
12516 * @example
|
|
|
12517 * // Using `columns`
|
|
|
12518 * $(document).ready( function() {
|
|
|
12519 * $('#example').dataTable( {
|
|
|
12520 * "columns": [
|
|
|
12521 * null,
|
|
|
12522 * null,
|
|
|
12523 * null,
|
|
|
12524 * {
|
|
|
12525 * "data": null,
|
|
|
12526 * "defaultContent": "Edit"
|
|
|
12527 * }
|
|
|
12528 * ]
|
|
|
12529 * } );
|
|
|
12530 * } );
|
|
|
12531 */
|
|
|
12532 "sDefaultContent": null,
|
|
|
12533
|
|
|
12534
|
|
|
12535 /**
|
|
|
12536 * This parameter is only used in DataTables' server-side processing. It can
|
|
|
12537 * be exceptionally useful to know what columns are being displayed on the
|
|
|
12538 * client side, and to map these to database fields. When defined, the names
|
|
|
12539 * also allow DataTables to reorder information from the server if it comes
|
|
|
12540 * back in an unexpected order (i.e. if you switch your columns around on the
|
|
|
12541 * client-side, your server-side code does not also need updating).
|
|
|
12542 * @type string
|
|
|
12543 * @default <i>Empty string</i>
|
|
|
12544 *
|
|
|
12545 * @name DataTable.defaults.column.name
|
|
|
12546 * @dtopt Columns
|
|
|
12547 *
|
|
|
12548 * @example
|
|
|
12549 * // Using `columnDefs`
|
|
|
12550 * $(document).ready( function() {
|
|
|
12551 * $('#example').dataTable( {
|
|
|
12552 * "columnDefs": [
|
|
|
12553 * { "name": "engine", "targets": [ 0 ] },
|
|
|
12554 * { "name": "browser", "targets": [ 1 ] },
|
|
|
12555 * { "name": "platform", "targets": [ 2 ] },
|
|
|
12556 * { "name": "version", "targets": [ 3 ] },
|
|
|
12557 * { "name": "grade", "targets": [ 4 ] }
|
|
|
12558 * ]
|
|
|
12559 * } );
|
|
|
12560 * } );
|
|
|
12561 *
|
|
|
12562 * @example
|
|
|
12563 * // Using `columns`
|
|
|
12564 * $(document).ready( function() {
|
|
|
12565 * $('#example').dataTable( {
|
|
|
12566 * "columns": [
|
|
|
12567 * { "name": "engine" },
|
|
|
12568 * { "name": "browser" },
|
|
|
12569 * { "name": "platform" },
|
|
|
12570 * { "name": "version" },
|
|
|
12571 * { "name": "grade" }
|
|
|
12572 * ]
|
|
|
12573 * } );
|
|
|
12574 * } );
|
|
|
12575 */
|
|
|
12576 "sName": "",
|
|
|
12577
|
|
|
12578
|
|
|
12579 /**
|
|
|
12580 * Defines a data source type for the ordering which can be used to read
|
|
|
12581 * real-time information from the table (updating the internally cached
|
|
|
12582 * version) prior to ordering. This allows ordering to occur on user
|
|
|
12583 * editable elements such as form inputs.
|
|
|
12584 * @type string
|
|
|
12585 * @default std
|
|
|
12586 *
|
|
|
12587 * @name DataTable.defaults.column.orderDataType
|
|
|
12588 * @dtopt Columns
|
|
|
12589 *
|
|
|
12590 * @example
|
|
|
12591 * // Using `columnDefs`
|
|
|
12592 * $(document).ready( function() {
|
|
|
12593 * $('#example').dataTable( {
|
|
|
12594 * "columnDefs": [
|
|
|
12595 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
|
|
|
12596 * { "type": "numeric", "targets": [ 3 ] },
|
|
|
12597 * { "orderDataType": "dom-select", "targets": [ 4 ] },
|
|
|
12598 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
|
|
|
12599 * ]
|
|
|
12600 * } );
|
|
|
12601 * } );
|
|
|
12602 *
|
|
|
12603 * @example
|
|
|
12604 * // Using `columns`
|
|
|
12605 * $(document).ready( function() {
|
|
|
12606 * $('#example').dataTable( {
|
|
|
12607 * "columns": [
|
|
|
12608 * null,
|
|
|
12609 * null,
|
|
|
12610 * { "orderDataType": "dom-text" },
|
|
|
12611 * { "orderDataType": "dom-text", "type": "numeric" },
|
|
|
12612 * { "orderDataType": "dom-select" },
|
|
|
12613 * { "orderDataType": "dom-checkbox" }
|
|
|
12614 * ]
|
|
|
12615 * } );
|
|
|
12616 * } );
|
|
|
12617 */
|
|
|
12618 "sSortDataType": "std",
|
|
|
12619
|
|
|
12620
|
|
|
12621 /**
|
|
|
12622 * The title of this column.
|
|
|
12623 * @type string
|
|
|
12624 * @default null <i>Derived from the 'TH' value for this column in the
|
|
|
12625 * original HTML table.</i>
|
|
|
12626 *
|
|
|
12627 * @name DataTable.defaults.column.title
|
|
|
12628 * @dtopt Columns
|
|
|
12629 *
|
|
|
12630 * @example
|
|
|
12631 * // Using `columnDefs`
|
|
|
12632 * $(document).ready( function() {
|
|
|
12633 * $('#example').dataTable( {
|
|
|
12634 * "columnDefs": [
|
|
|
12635 * { "title": "My column title", "targets": [ 0 ] }
|
|
|
12636 * ]
|
|
|
12637 * } );
|
|
|
12638 * } );
|
|
|
12639 *
|
|
|
12640 * @example
|
|
|
12641 * // Using `columns`
|
|
|
12642 * $(document).ready( function() {
|
|
|
12643 * $('#example').dataTable( {
|
|
|
12644 * "columns": [
|
|
|
12645 * { "title": "My column title" },
|
|
|
12646 * null,
|
|
|
12647 * null,
|
|
|
12648 * null,
|
|
|
12649 * null
|
|
|
12650 * ]
|
|
|
12651 * } );
|
|
|
12652 * } );
|
|
|
12653 */
|
|
|
12654 "sTitle": null,
|
|
|
12655
|
|
|
12656
|
|
|
12657 /**
|
|
|
12658 * The type allows you to specify how the data for this column will be
|
|
|
12659 * ordered. Four types (string, numeric, date and html (which will strip
|
|
|
12660 * HTML tags before ordering)) are currently available. Note that only date
|
|
|
12661 * formats understood by Javascript's Date() object will be accepted as type
|
|
|
12662 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
|
|
|
12663 * 'numeric', 'date' or 'html' (by default). Further types can be adding
|
|
|
12664 * through plug-ins.
|
|
|
12665 * @type string
|
|
|
12666 * @default null <i>Auto-detected from raw data</i>
|
|
|
12667 *
|
|
|
12668 * @name DataTable.defaults.column.type
|
|
|
12669 * @dtopt Columns
|
|
|
12670 *
|
|
|
12671 * @example
|
|
|
12672 * // Using `columnDefs`
|
|
|
12673 * $(document).ready( function() {
|
|
|
12674 * $('#example').dataTable( {
|
|
|
12675 * "columnDefs": [
|
|
|
12676 * { "type": "html", "targets": [ 0 ] }
|
|
|
12677 * ]
|
|
|
12678 * } );
|
|
|
12679 * } );
|
|
|
12680 *
|
|
|
12681 * @example
|
|
|
12682 * // Using `columns`
|
|
|
12683 * $(document).ready( function() {
|
|
|
12684 * $('#example').dataTable( {
|
|
|
12685 * "columns": [
|
|
|
12686 * { "type": "html" },
|
|
|
12687 * null,
|
|
|
12688 * null,
|
|
|
12689 * null,
|
|
|
12690 * null
|
|
|
12691 * ]
|
|
|
12692 * } );
|
|
|
12693 * } );
|
|
|
12694 */
|
|
|
12695 "sType": null,
|
|
|
12696
|
|
|
12697
|
|
|
12698 /**
|
|
|
12699 * Defining the width of the column, this parameter may take any CSS value
|
|
|
12700 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
|
|
|
12701 * been given a specific width through this interface ensuring that the table
|
|
|
12702 * remains readable.
|
|
|
12703 * @type string
|
|
|
12704 * @default null <i>Automatic</i>
|
|
|
12705 *
|
|
|
12706 * @name DataTable.defaults.column.width
|
|
|
12707 * @dtopt Columns
|
|
|
12708 *
|
|
|
12709 * @example
|
|
|
12710 * // Using `columnDefs`
|
|
|
12711 * $(document).ready( function() {
|
|
|
12712 * $('#example').dataTable( {
|
|
|
12713 * "columnDefs": [
|
|
|
12714 * { "width": "20%", "targets": [ 0 ] }
|
|
|
12715 * ]
|
|
|
12716 * } );
|
|
|
12717 * } );
|
|
|
12718 *
|
|
|
12719 * @example
|
|
|
12720 * // Using `columns`
|
|
|
12721 * $(document).ready( function() {
|
|
|
12722 * $('#example').dataTable( {
|
|
|
12723 * "columns": [
|
|
|
12724 * { "width": "20%" },
|
|
|
12725 * null,
|
|
|
12726 * null,
|
|
|
12727 * null,
|
|
|
12728 * null
|
|
|
12729 * ]
|
|
|
12730 * } );
|
|
|
12731 * } );
|
|
|
12732 */
|
|
|
12733 "sWidth": null
|
|
|
12734 };
|
|
|
12735
|
|
|
12736 _fnHungarianMap( DataTable.defaults.column );
|
|
|
12737
|
|
|
12738
|
|
|
12739
|
|
|
12740 /**
|
|
|
12741 * DataTables settings object - this holds all the information needed for a
|
|
|
12742 * given table, including configuration, data and current application of the
|
|
|
12743 * table options. DataTables does not have a single instance for each DataTable
|
|
|
12744 * with the settings attached to that instance, but rather instances of the
|
|
|
12745 * DataTable "class" are created on-the-fly as needed (typically by a
|
|
|
12746 * $().dataTable() call) and the settings object is then applied to that
|
|
|
12747 * instance.
|
|
|
12748 *
|
|
|
12749 * Note that this object is related to {@link DataTable.defaults} but this
|
|
|
12750 * one is the internal data store for DataTables's cache of columns. It should
|
|
|
12751 * NOT be manipulated outside of DataTables. Any configuration should be done
|
|
|
12752 * through the initialisation options.
|
|
|
12753 * @namespace
|
|
|
12754 * @todo Really should attach the settings object to individual instances so we
|
|
|
12755 * don't need to create new instances on each $().dataTable() call (if the
|
|
|
12756 * table already exists). It would also save passing oSettings around and
|
|
|
12757 * into every single function. However, this is a very significant
|
|
|
12758 * architecture change for DataTables and will almost certainly break
|
|
|
12759 * backwards compatibility with older installations. This is something that
|
|
|
12760 * will be done in 2.0.
|
|
|
12761 */
|
|
|
12762 DataTable.models.oSettings = {
|
|
|
12763 /**
|
|
|
12764 * Primary features of DataTables and their enablement state.
|
|
|
12765 * @namespace
|
|
|
12766 */
|
|
|
12767 "oFeatures": {
|
|
|
12768
|
|
|
12769 /**
|
|
|
12770 * Flag to say if DataTables should automatically try to calculate the
|
|
|
12771 * optimum table and columns widths (true) or not (false).
|
|
|
12772 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12773 * set a default use {@link DataTable.defaults}.
|
|
|
12774 * @type boolean
|
|
|
12775 */
|
|
|
12776 "bAutoWidth": null,
|
|
|
12777
|
|
|
12778 /**
|
|
|
12779 * Delay the creation of TR and TD elements until they are actually
|
|
|
12780 * needed by a driven page draw. This can give a significant speed
|
|
|
12781 * increase for Ajax source and Javascript source data, but makes no
|
|
|
12782 * difference at all fro DOM and server-side processing tables.
|
|
|
12783 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12784 * set a default use {@link DataTable.defaults}.
|
|
|
12785 * @type boolean
|
|
|
12786 */
|
|
|
12787 "bDeferRender": null,
|
|
|
12788
|
|
|
12789 /**
|
|
|
12790 * Enable filtering on the table or not. Note that if this is disabled
|
|
|
12791 * then there is no filtering at all on the table, including fnFilter.
|
|
|
12792 * To just remove the filtering input use sDom and remove the 'f' option.
|
|
|
12793 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12794 * set a default use {@link DataTable.defaults}.
|
|
|
12795 * @type boolean
|
|
|
12796 */
|
|
|
12797 "bFilter": null,
|
|
|
12798
|
|
|
12799 /**
|
|
|
12800 * Table information element (the 'Showing x of y records' div) enable
|
|
|
12801 * flag.
|
|
|
12802 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12803 * set a default use {@link DataTable.defaults}.
|
|
|
12804 * @type boolean
|
|
|
12805 */
|
|
|
12806 "bInfo": null,
|
|
|
12807
|
|
|
12808 /**
|
|
|
12809 * Present a user control allowing the end user to change the page size
|
|
|
12810 * when pagination is enabled.
|
|
|
12811 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12812 * set a default use {@link DataTable.defaults}.
|
|
|
12813 * @type boolean
|
|
|
12814 */
|
|
|
12815 "bLengthChange": null,
|
|
|
12816
|
|
|
12817 /**
|
|
|
12818 * Pagination enabled or not. Note that if this is disabled then length
|
|
|
12819 * changing must also be disabled.
|
|
|
12820 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12821 * set a default use {@link DataTable.defaults}.
|
|
|
12822 * @type boolean
|
|
|
12823 */
|
|
|
12824 "bPaginate": null,
|
|
|
12825
|
|
|
12826 /**
|
|
|
12827 * Processing indicator enable flag whenever DataTables is enacting a
|
|
|
12828 * user request - typically an Ajax request for server-side processing.
|
|
|
12829 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12830 * set a default use {@link DataTable.defaults}.
|
|
|
12831 * @type boolean
|
|
|
12832 */
|
|
|
12833 "bProcessing": null,
|
|
|
12834
|
|
|
12835 /**
|
|
|
12836 * Server-side processing enabled flag - when enabled DataTables will
|
|
|
12837 * get all data from the server for every draw - there is no filtering,
|
|
|
12838 * sorting or paging done on the client-side.
|
|
|
12839 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12840 * set a default use {@link DataTable.defaults}.
|
|
|
12841 * @type boolean
|
|
|
12842 */
|
|
|
12843 "bServerSide": null,
|
|
|
12844
|
|
|
12845 /**
|
|
|
12846 * Sorting enablement flag.
|
|
|
12847 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12848 * set a default use {@link DataTable.defaults}.
|
|
|
12849 * @type boolean
|
|
|
12850 */
|
|
|
12851 "bSort": null,
|
|
|
12852
|
|
|
12853 /**
|
|
|
12854 * Multi-column sorting
|
|
|
12855 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12856 * set a default use {@link DataTable.defaults}.
|
|
|
12857 * @type boolean
|
|
|
12858 */
|
|
|
12859 "bSortMulti": null,
|
|
|
12860
|
|
|
12861 /**
|
|
|
12862 * Apply a class to the columns which are being sorted to provide a
|
|
|
12863 * visual highlight or not. This can slow things down when enabled since
|
|
|
12864 * there is a lot of DOM interaction.
|
|
|
12865 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12866 * set a default use {@link DataTable.defaults}.
|
|
|
12867 * @type boolean
|
|
|
12868 */
|
|
|
12869 "bSortClasses": null,
|
|
|
12870
|
|
|
12871 /**
|
|
|
12872 * State saving enablement flag.
|
|
|
12873 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12874 * set a default use {@link DataTable.defaults}.
|
|
|
12875 * @type boolean
|
|
|
12876 */
|
|
|
12877 "bStateSave": null
|
|
|
12878 },
|
|
|
12879
|
|
|
12880
|
|
|
12881 /**
|
|
|
12882 * Scrolling settings for a table.
|
|
|
12883 * @namespace
|
|
|
12884 */
|
|
|
12885 "oScroll": {
|
|
|
12886 /**
|
|
|
12887 * When the table is shorter in height than sScrollY, collapse the
|
|
|
12888 * table container down to the height of the table (when true).
|
|
|
12889 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12890 * set a default use {@link DataTable.defaults}.
|
|
|
12891 * @type boolean
|
|
|
12892 */
|
|
|
12893 "bCollapse": null,
|
|
|
12894
|
|
|
12895 /**
|
|
|
12896 * Width of the scrollbar for the web-browser's platform. Calculated
|
|
|
12897 * during table initialisation.
|
|
|
12898 * @type int
|
|
|
12899 * @default 0
|
|
|
12900 */
|
|
|
12901 "iBarWidth": 0,
|
|
|
12902
|
|
|
12903 /**
|
|
|
12904 * Viewport width for horizontal scrolling. Horizontal scrolling is
|
|
|
12905 * disabled if an empty string.
|
|
|
12906 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12907 * set a default use {@link DataTable.defaults}.
|
|
|
12908 * @type string
|
|
|
12909 */
|
|
|
12910 "sX": null,
|
|
|
12911
|
|
|
12912 /**
|
|
|
12913 * Width to expand the table to when using x-scrolling. Typically you
|
|
|
12914 * should not need to use this.
|
|
|
12915 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12916 * set a default use {@link DataTable.defaults}.
|
|
|
12917 * @type string
|
|
|
12918 * @deprecated
|
|
|
12919 */
|
|
|
12920 "sXInner": null,
|
|
|
12921
|
|
|
12922 /**
|
|
|
12923 * Viewport height for vertical scrolling. Vertical scrolling is disabled
|
|
|
12924 * if an empty string.
|
|
|
12925 * Note that this parameter will be set by the initialisation routine. To
|
|
|
12926 * set a default use {@link DataTable.defaults}.
|
|
|
12927 * @type string
|
|
|
12928 */
|
|
|
12929 "sY": null
|
|
|
12930 },
|
|
|
12931
|
|
|
12932 /**
|
|
|
12933 * Language information for the table.
|
|
|
12934 * @namespace
|
|
|
12935 * @extends DataTable.defaults.oLanguage
|
|
|
12936 */
|
|
|
12937 "oLanguage": {
|
|
|
12938 /**
|
|
|
12939 * Information callback function. See
|
|
|
12940 * {@link DataTable.defaults.fnInfoCallback}
|
|
|
12941 * @type function
|
|
|
12942 * @default null
|
|
|
12943 */
|
|
|
12944 "fnInfoCallback": null
|
|
|
12945 },
|
|
|
12946
|
|
|
12947 /**
|
|
|
12948 * Browser support parameters
|
|
|
12949 * @namespace
|
|
|
12950 */
|
|
|
12951 "oBrowser": {
|
|
|
12952 /**
|
|
|
12953 * Indicate if the browser incorrectly calculates width:100% inside a
|
|
|
12954 * scrolling element (IE6/7)
|
|
|
12955 * @type boolean
|
|
|
12956 * @default false
|
|
|
12957 */
|
|
|
12958 "bScrollOversize": false,
|
|
|
12959
|
|
|
12960 /**
|
|
|
12961 * Determine if the vertical scrollbar is on the right or left of the
|
|
|
12962 * scrolling container - needed for rtl language layout, although not
|
|
|
12963 * all browsers move the scrollbar (Safari).
|
|
|
12964 * @type boolean
|
|
|
12965 * @default false
|
|
|
12966 */
|
|
|
12967 "bScrollbarLeft": false,
|
|
|
12968
|
|
|
12969 /**
|
|
|
12970 * Flag for if `getBoundingClientRect` is fully supported or not
|
|
|
12971 * @type boolean
|
|
|
12972 * @default false
|
|
|
12973 */
|
|
|
12974 "bBounding": false,
|
|
|
12975
|
|
|
12976 /**
|
|
|
12977 * Browser scrollbar width
|
|
|
12978 * @type integer
|
|
|
12979 * @default 0
|
|
|
12980 */
|
|
|
12981 "barWidth": 0
|
|
|
12982 },
|
|
|
12983
|
|
|
12984
|
|
|
12985 "ajax": null,
|
|
|
12986
|
|
|
12987
|
|
|
12988 /**
|
|
|
12989 * Array referencing the nodes which are used for the features. The
|
|
|
12990 * parameters of this object match what is allowed by sDom - i.e.
|
|
|
12991 * <ul>
|
|
|
12992 * <li>'l' - Length changing</li>
|
|
|
12993 * <li>'f' - Filtering input</li>
|
|
|
12994 * <li>'t' - The table!</li>
|
|
|
12995 * <li>'i' - Information</li>
|
|
|
12996 * <li>'p' - Pagination</li>
|
|
|
12997 * <li>'r' - pRocessing</li>
|
|
|
12998 * </ul>
|
|
|
12999 * @type array
|
|
|
13000 * @default []
|
|
|
13001 */
|
|
|
13002 "aanFeatures": [],
|
|
|
13003
|
|
|
13004 /**
|
|
|
13005 * Store data information - see {@link DataTable.models.oRow} for detailed
|
|
|
13006 * information.
|
|
|
13007 * @type array
|
|
|
13008 * @default []
|
|
|
13009 */
|
|
|
13010 "aoData": [],
|
|
|
13011
|
|
|
13012 /**
|
|
|
13013 * Array of indexes which are in the current display (after filtering etc)
|
|
|
13014 * @type array
|
|
|
13015 * @default []
|
|
|
13016 */
|
|
|
13017 "aiDisplay": [],
|
|
|
13018
|
|
|
13019 /**
|
|
|
13020 * Array of indexes for display - no filtering
|
|
|
13021 * @type array
|
|
|
13022 * @default []
|
|
|
13023 */
|
|
|
13024 "aiDisplayMaster": [],
|
|
|
13025
|
|
|
13026 /**
|
|
|
13027 * Map of row ids to data indexes
|
|
|
13028 * @type object
|
|
|
13029 * @default {}
|
|
|
13030 */
|
|
|
13031 "aIds": {},
|
|
|
13032
|
|
|
13033 /**
|
|
|
13034 * Store information about each column that is in use
|
|
|
13035 * @type array
|
|
|
13036 * @default []
|
|
|
13037 */
|
|
|
13038 "aoColumns": [],
|
|
|
13039
|
|
|
13040 /**
|
|
|
13041 * Store information about the table's header
|
|
|
13042 * @type array
|
|
|
13043 * @default []
|
|
|
13044 */
|
|
|
13045 "aoHeader": [],
|
|
|
13046
|
|
|
13047 /**
|
|
|
13048 * Store information about the table's footer
|
|
|
13049 * @type array
|
|
|
13050 * @default []
|
|
|
13051 */
|
|
|
13052 "aoFooter": [],
|
|
|
13053
|
|
|
13054 /**
|
|
|
13055 * Store the applied global search information in case we want to force a
|
|
|
13056 * research or compare the old search to a new one.
|
|
|
13057 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13058 * set a default use {@link DataTable.defaults}.
|
|
|
13059 * @namespace
|
|
|
13060 * @extends DataTable.models.oSearch
|
|
|
13061 */
|
|
|
13062 "oPreviousSearch": {},
|
|
|
13063
|
|
|
13064 /**
|
|
|
13065 * Store the applied search for each column - see
|
|
|
13066 * {@link DataTable.models.oSearch} for the format that is used for the
|
|
|
13067 * filtering information for each column.
|
|
|
13068 * @type array
|
|
|
13069 * @default []
|
|
|
13070 */
|
|
|
13071 "aoPreSearchCols": [],
|
|
|
13072
|
|
|
13073 /**
|
|
|
13074 * Sorting that is applied to the table. Note that the inner arrays are
|
|
|
13075 * used in the following manner:
|
|
|
13076 * <ul>
|
|
|
13077 * <li>Index 0 - column number</li>
|
|
|
13078 * <li>Index 1 - current sorting direction</li>
|
|
|
13079 * </ul>
|
|
|
13080 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13081 * set a default use {@link DataTable.defaults}.
|
|
|
13082 * @type array
|
|
|
13083 * @todo These inner arrays should really be objects
|
|
|
13084 */
|
|
|
13085 "aaSorting": null,
|
|
|
13086
|
|
|
13087 /**
|
|
|
13088 * Sorting that is always applied to the table (i.e. prefixed in front of
|
|
|
13089 * aaSorting).
|
|
|
13090 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13091 * set a default use {@link DataTable.defaults}.
|
|
|
13092 * @type array
|
|
|
13093 * @default []
|
|
|
13094 */
|
|
|
13095 "aaSortingFixed": [],
|
|
|
13096
|
|
|
13097 /**
|
|
|
13098 * Classes to use for the striping of a table.
|
|
|
13099 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13100 * set a default use {@link DataTable.defaults}.
|
|
|
13101 * @type array
|
|
|
13102 * @default []
|
|
|
13103 */
|
|
|
13104 "asStripeClasses": null,
|
|
|
13105
|
|
|
13106 /**
|
|
|
13107 * If restoring a table - we should restore its striping classes as well
|
|
|
13108 * @type array
|
|
|
13109 * @default []
|
|
|
13110 */
|
|
|
13111 "asDestroyStripes": [],
|
|
|
13112
|
|
|
13113 /**
|
|
|
13114 * If restoring a table - we should restore its width
|
|
|
13115 * @type int
|
|
|
13116 * @default 0
|
|
|
13117 */
|
|
|
13118 "sDestroyWidth": 0,
|
|
|
13119
|
|
|
13120 /**
|
|
|
13121 * Callback functions array for every time a row is inserted (i.e. on a draw).
|
|
|
13122 * @type array
|
|
|
13123 * @default []
|
|
|
13124 */
|
|
|
13125 "aoRowCallback": [],
|
|
|
13126
|
|
|
13127 /**
|
|
|
13128 * Callback functions for the header on each draw.
|
|
|
13129 * @type array
|
|
|
13130 * @default []
|
|
|
13131 */
|
|
|
13132 "aoHeaderCallback": [],
|
|
|
13133
|
|
|
13134 /**
|
|
|
13135 * Callback function for the footer on each draw.
|
|
|
13136 * @type array
|
|
|
13137 * @default []
|
|
|
13138 */
|
|
|
13139 "aoFooterCallback": [],
|
|
|
13140
|
|
|
13141 /**
|
|
|
13142 * Array of callback functions for draw callback functions
|
|
|
13143 * @type array
|
|
|
13144 * @default []
|
|
|
13145 */
|
|
|
13146 "aoDrawCallback": [],
|
|
|
13147
|
|
|
13148 /**
|
|
|
13149 * Array of callback functions for row created function
|
|
|
13150 * @type array
|
|
|
13151 * @default []
|
|
|
13152 */
|
|
|
13153 "aoRowCreatedCallback": [],
|
|
|
13154
|
|
|
13155 /**
|
|
|
13156 * Callback functions for just before the table is redrawn. A return of
|
|
|
13157 * false will be used to cancel the draw.
|
|
|
13158 * @type array
|
|
|
13159 * @default []
|
|
|
13160 */
|
|
|
13161 "aoPreDrawCallback": [],
|
|
|
13162
|
|
|
13163 /**
|
|
|
13164 * Callback functions for when the table has been initialised.
|
|
|
13165 * @type array
|
|
|
13166 * @default []
|
|
|
13167 */
|
|
|
13168 "aoInitComplete": [],
|
|
|
13169
|
|
|
13170
|
|
|
13171 /**
|
|
|
13172 * Callbacks for modifying the settings to be stored for state saving, prior to
|
|
|
13173 * saving state.
|
|
|
13174 * @type array
|
|
|
13175 * @default []
|
|
|
13176 */
|
|
|
13177 "aoStateSaveParams": [],
|
|
|
13178
|
|
|
13179 /**
|
|
|
13180 * Callbacks for modifying the settings that have been stored for state saving
|
|
|
13181 * prior to using the stored values to restore the state.
|
|
|
13182 * @type array
|
|
|
13183 * @default []
|
|
|
13184 */
|
|
|
13185 "aoStateLoadParams": [],
|
|
|
13186
|
|
|
13187 /**
|
|
|
13188 * Callbacks for operating on the settings object once the saved state has been
|
|
|
13189 * loaded
|
|
|
13190 * @type array
|
|
|
13191 * @default []
|
|
|
13192 */
|
|
|
13193 "aoStateLoaded": [],
|
|
|
13194
|
|
|
13195 /**
|
|
|
13196 * Cache the table ID for quick access
|
|
|
13197 * @type string
|
|
|
13198 * @default <i>Empty string</i>
|
|
|
13199 */
|
|
|
13200 "sTableId": "",
|
|
|
13201
|
|
|
13202 /**
|
|
|
13203 * The TABLE node for the main table
|
|
|
13204 * @type node
|
|
|
13205 * @default null
|
|
|
13206 */
|
|
|
13207 "nTable": null,
|
|
|
13208
|
|
|
13209 /**
|
|
|
13210 * Permanent ref to the thead element
|
|
|
13211 * @type node
|
|
|
13212 * @default null
|
|
|
13213 */
|
|
|
13214 "nTHead": null,
|
|
|
13215
|
|
|
13216 /**
|
|
|
13217 * Permanent ref to the tfoot element - if it exists
|
|
|
13218 * @type node
|
|
|
13219 * @default null
|
|
|
13220 */
|
|
|
13221 "nTFoot": null,
|
|
|
13222
|
|
|
13223 /**
|
|
|
13224 * Permanent ref to the tbody element
|
|
|
13225 * @type node
|
|
|
13226 * @default null
|
|
|
13227 */
|
|
|
13228 "nTBody": null,
|
|
|
13229
|
|
|
13230 /**
|
|
|
13231 * Cache the wrapper node (contains all DataTables controlled elements)
|
|
|
13232 * @type node
|
|
|
13233 * @default null
|
|
|
13234 */
|
|
|
13235 "nTableWrapper": null,
|
|
|
13236
|
|
|
13237 /**
|
|
|
13238 * Indicate if when using server-side processing the loading of data
|
|
|
13239 * should be deferred until the second draw.
|
|
|
13240 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13241 * set a default use {@link DataTable.defaults}.
|
|
|
13242 * @type boolean
|
|
|
13243 * @default false
|
|
|
13244 */
|
|
|
13245 "bDeferLoading": false,
|
|
|
13246
|
|
|
13247 /**
|
|
|
13248 * Indicate if all required information has been read in
|
|
|
13249 * @type boolean
|
|
|
13250 * @default false
|
|
|
13251 */
|
|
|
13252 "bInitialised": false,
|
|
|
13253
|
|
|
13254 /**
|
|
|
13255 * Information about open rows. Each object in the array has the parameters
|
|
|
13256 * 'nTr' and 'nParent'
|
|
|
13257 * @type array
|
|
|
13258 * @default []
|
|
|
13259 */
|
|
|
13260 "aoOpenRows": [],
|
|
|
13261
|
|
|
13262 /**
|
|
|
13263 * Dictate the positioning of DataTables' control elements - see
|
|
|
13264 * {@link DataTable.model.oInit.sDom}.
|
|
|
13265 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13266 * set a default use {@link DataTable.defaults}.
|
|
|
13267 * @type string
|
|
|
13268 * @default null
|
|
|
13269 */
|
|
|
13270 "sDom": null,
|
|
|
13271
|
|
|
13272 /**
|
|
|
13273 * Search delay (in mS)
|
|
|
13274 * @type integer
|
|
|
13275 * @default null
|
|
|
13276 */
|
|
|
13277 "searchDelay": null,
|
|
|
13278
|
|
|
13279 /**
|
|
|
13280 * Which type of pagination should be used.
|
|
|
13281 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13282 * set a default use {@link DataTable.defaults}.
|
|
|
13283 * @type string
|
|
|
13284 * @default two_button
|
|
|
13285 */
|
|
|
13286 "sPaginationType": "two_button",
|
|
|
13287
|
|
|
13288 /**
|
|
|
13289 * The state duration (for `stateSave`) in seconds.
|
|
|
13290 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13291 * set a default use {@link DataTable.defaults}.
|
|
|
13292 * @type int
|
|
|
13293 * @default 0
|
|
|
13294 */
|
|
|
13295 "iStateDuration": 0,
|
|
|
13296
|
|
|
13297 /**
|
|
|
13298 * Array of callback functions for state saving. Each array element is an
|
|
|
13299 * object with the following parameters:
|
|
|
13300 * <ul>
|
|
|
13301 * <li>function:fn - function to call. Takes two parameters, oSettings
|
|
|
13302 * and the JSON string to save that has been thus far created. Returns
|
|
|
13303 * a JSON string to be inserted into a json object
|
|
|
13304 * (i.e. '"param": [ 0, 1, 2]')</li>
|
|
|
13305 * <li>string:sName - name of callback</li>
|
|
|
13306 * </ul>
|
|
|
13307 * @type array
|
|
|
13308 * @default []
|
|
|
13309 */
|
|
|
13310 "aoStateSave": [],
|
|
|
13311
|
|
|
13312 /**
|
|
|
13313 * Array of callback functions for state loading. Each array element is an
|
|
|
13314 * object with the following parameters:
|
|
|
13315 * <ul>
|
|
|
13316 * <li>function:fn - function to call. Takes two parameters, oSettings
|
|
|
13317 * and the object stored. May return false to cancel state loading</li>
|
|
|
13318 * <li>string:sName - name of callback</li>
|
|
|
13319 * </ul>
|
|
|
13320 * @type array
|
|
|
13321 * @default []
|
|
|
13322 */
|
|
|
13323 "aoStateLoad": [],
|
|
|
13324
|
|
|
13325 /**
|
|
|
13326 * State that was saved. Useful for back reference
|
|
|
13327 * @type object
|
|
|
13328 * @default null
|
|
|
13329 */
|
|
|
13330 "oSavedState": null,
|
|
|
13331
|
|
|
13332 /**
|
|
|
13333 * State that was loaded. Useful for back reference
|
|
|
13334 * @type object
|
|
|
13335 * @default null
|
|
|
13336 */
|
|
|
13337 "oLoadedState": null,
|
|
|
13338
|
|
|
13339 /**
|
|
|
13340 * Source url for AJAX data for the table.
|
|
|
13341 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13342 * set a default use {@link DataTable.defaults}.
|
|
|
13343 * @type string
|
|
|
13344 * @default null
|
|
|
13345 */
|
|
|
13346 "sAjaxSource": null,
|
|
|
13347
|
|
|
13348 /**
|
|
|
13349 * Property from a given object from which to read the table data from. This
|
|
|
13350 * can be an empty string (when not server-side processing), in which case
|
|
|
13351 * it is assumed an an array is given directly.
|
|
|
13352 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13353 * set a default use {@link DataTable.defaults}.
|
|
|
13354 * @type string
|
|
|
13355 */
|
|
|
13356 "sAjaxDataProp": null,
|
|
|
13357
|
|
|
13358 /**
|
|
|
13359 * Note if draw should be blocked while getting data
|
|
|
13360 * @type boolean
|
|
|
13361 * @default true
|
|
|
13362 */
|
|
|
13363 "bAjaxDataGet": true,
|
|
|
13364
|
|
|
13365 /**
|
|
|
13366 * The last jQuery XHR object that was used for server-side data gathering.
|
|
|
13367 * This can be used for working with the XHR information in one of the
|
|
|
13368 * callbacks
|
|
|
13369 * @type object
|
|
|
13370 * @default null
|
|
|
13371 */
|
|
|
13372 "jqXHR": null,
|
|
|
13373
|
|
|
13374 /**
|
|
|
13375 * JSON returned from the server in the last Ajax request
|
|
|
13376 * @type object
|
|
|
13377 * @default undefined
|
|
|
13378 */
|
|
|
13379 "json": undefined,
|
|
|
13380
|
|
|
13381 /**
|
|
|
13382 * Data submitted as part of the last Ajax request
|
|
|
13383 * @type object
|
|
|
13384 * @default undefined
|
|
|
13385 */
|
|
|
13386 "oAjaxData": undefined,
|
|
|
13387
|
|
|
13388 /**
|
|
|
13389 * Function to get the server-side data.
|
|
|
13390 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13391 * set a default use {@link DataTable.defaults}.
|
|
|
13392 * @type function
|
|
|
13393 */
|
|
|
13394 "fnServerData": null,
|
|
|
13395
|
|
|
13396 /**
|
|
|
13397 * Functions which are called prior to sending an Ajax request so extra
|
|
|
13398 * parameters can easily be sent to the server
|
|
|
13399 * @type array
|
|
|
13400 * @default []
|
|
|
13401 */
|
|
|
13402 "aoServerParams": [],
|
|
|
13403
|
|
|
13404 /**
|
|
|
13405 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
|
|
|
13406 * required).
|
|
|
13407 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13408 * set a default use {@link DataTable.defaults}.
|
|
|
13409 * @type string
|
|
|
13410 */
|
|
|
13411 "sServerMethod": null,
|
|
|
13412
|
|
|
13413 /**
|
|
|
13414 * Format numbers for display.
|
|
|
13415 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13416 * set a default use {@link DataTable.defaults}.
|
|
|
13417 * @type function
|
|
|
13418 */
|
|
|
13419 "fnFormatNumber": null,
|
|
|
13420
|
|
|
13421 /**
|
|
|
13422 * List of options that can be used for the user selectable length menu.
|
|
|
13423 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13424 * set a default use {@link DataTable.defaults}.
|
|
|
13425 * @type array
|
|
|
13426 * @default []
|
|
|
13427 */
|
|
|
13428 "aLengthMenu": null,
|
|
|
13429
|
|
|
13430 /**
|
|
|
13431 * Counter for the draws that the table does. Also used as a tracker for
|
|
|
13432 * server-side processing
|
|
|
13433 * @type int
|
|
|
13434 * @default 0
|
|
|
13435 */
|
|
|
13436 "iDraw": 0,
|
|
|
13437
|
|
|
13438 /**
|
|
|
13439 * Indicate if a redraw is being done - useful for Ajax
|
|
|
13440 * @type boolean
|
|
|
13441 * @default false
|
|
|
13442 */
|
|
|
13443 "bDrawing": false,
|
|
|
13444
|
|
|
13445 /**
|
|
|
13446 * Draw index (iDraw) of the last error when parsing the returned data
|
|
|
13447 * @type int
|
|
|
13448 * @default -1
|
|
|
13449 */
|
|
|
13450 "iDrawError": -1,
|
|
|
13451
|
|
|
13452 /**
|
|
|
13453 * Paging display length
|
|
|
13454 * @type int
|
|
|
13455 * @default 10
|
|
|
13456 */
|
|
|
13457 "_iDisplayLength": 10,
|
|
|
13458
|
|
|
13459 /**
|
|
|
13460 * Paging start point - aiDisplay index
|
|
|
13461 * @type int
|
|
|
13462 * @default 0
|
|
|
13463 */
|
|
|
13464 "_iDisplayStart": 0,
|
|
|
13465
|
|
|
13466 /**
|
|
|
13467 * Server-side processing - number of records in the result set
|
|
|
13468 * (i.e. before filtering), Use fnRecordsTotal rather than
|
|
|
13469 * this property to get the value of the number of records, regardless of
|
|
|
13470 * the server-side processing setting.
|
|
|
13471 * @type int
|
|
|
13472 * @default 0
|
|
|
13473 * @private
|
|
|
13474 */
|
|
|
13475 "_iRecordsTotal": 0,
|
|
|
13476
|
|
|
13477 /**
|
|
|
13478 * Server-side processing - number of records in the current display set
|
|
|
13479 * (i.e. after filtering). Use fnRecordsDisplay rather than
|
|
|
13480 * this property to get the value of the number of records, regardless of
|
|
|
13481 * the server-side processing setting.
|
|
|
13482 * @type boolean
|
|
|
13483 * @default 0
|
|
|
13484 * @private
|
|
|
13485 */
|
|
|
13486 "_iRecordsDisplay": 0,
|
|
|
13487
|
|
|
13488 /**
|
|
|
13489 * Flag to indicate if jQuery UI marking and classes should be used.
|
|
|
13490 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13491 * set a default use {@link DataTable.defaults}.
|
|
|
13492 * @type boolean
|
|
|
13493 */
|
|
|
13494 "bJUI": null,
|
|
|
13495
|
|
|
13496 /**
|
|
|
13497 * The classes to use for the table
|
|
|
13498 * @type object
|
|
|
13499 * @default {}
|
|
|
13500 */
|
|
|
13501 "oClasses": {},
|
|
|
13502
|
|
|
13503 /**
|
|
|
13504 * Flag attached to the settings object so you can check in the draw
|
|
|
13505 * callback if filtering has been done in the draw. Deprecated in favour of
|
|
|
13506 * events.
|
|
|
13507 * @type boolean
|
|
|
13508 * @default false
|
|
|
13509 * @deprecated
|
|
|
13510 */
|
|
|
13511 "bFiltered": false,
|
|
|
13512
|
|
|
13513 /**
|
|
|
13514 * Flag attached to the settings object so you can check in the draw
|
|
|
13515 * callback if sorting has been done in the draw. Deprecated in favour of
|
|
|
13516 * events.
|
|
|
13517 * @type boolean
|
|
|
13518 * @default false
|
|
|
13519 * @deprecated
|
|
|
13520 */
|
|
|
13521 "bSorted": false,
|
|
|
13522
|
|
|
13523 /**
|
|
|
13524 * Indicate that if multiple rows are in the header and there is more than
|
|
|
13525 * one unique cell per column, if the top one (true) or bottom one (false)
|
|
|
13526 * should be used for sorting / title by DataTables.
|
|
|
13527 * Note that this parameter will be set by the initialisation routine. To
|
|
|
13528 * set a default use {@link DataTable.defaults}.
|
|
|
13529 * @type boolean
|
|
|
13530 */
|
|
|
13531 "bSortCellsTop": null,
|
|
|
13532
|
|
|
13533 /**
|
|
|
13534 * Initialisation object that is used for the table
|
|
|
13535 * @type object
|
|
|
13536 * @default null
|
|
|
13537 */
|
|
|
13538 "oInit": null,
|
|
|
13539
|
|
|
13540 /**
|
|
|
13541 * Destroy callback functions - for plug-ins to attach themselves to the
|
|
|
13542 * destroy so they can clean up markup and events.
|
|
|
13543 * @type array
|
|
|
13544 * @default []
|
|
|
13545 */
|
|
|
13546 "aoDestroyCallback": [],
|
|
|
13547
|
|
|
13548
|
|
|
13549 /**
|
|
|
13550 * Get the number of records in the current record set, before filtering
|
|
|
13551 * @type function
|
|
|
13552 */
|
|
|
13553 "fnRecordsTotal": function ()
|
|
|
13554 {
|
|
|
13555 return _fnDataSource( this ) == 'ssp' ?
|
|
|
13556 this._iRecordsTotal * 1 :
|
|
|
13557 this.aiDisplayMaster.length;
|
|
|
13558 },
|
|
|
13559
|
|
|
13560 /**
|
|
|
13561 * Get the number of records in the current record set, after filtering
|
|
|
13562 * @type function
|
|
|
13563 */
|
|
|
13564 "fnRecordsDisplay": function ()
|
|
|
13565 {
|
|
|
13566 return _fnDataSource( this ) == 'ssp' ?
|
|
|
13567 this._iRecordsDisplay * 1 :
|
|
|
13568 this.aiDisplay.length;
|
|
|
13569 },
|
|
|
13570
|
|
|
13571 /**
|
|
|
13572 * Get the display end point - aiDisplay index
|
|
|
13573 * @type function
|
|
|
13574 */
|
|
|
13575 "fnDisplayEnd": function ()
|
|
|
13576 {
|
|
|
13577 var
|
|
|
13578 len = this._iDisplayLength,
|
|
|
13579 start = this._iDisplayStart,
|
|
|
13580 calc = start + len,
|
|
|
13581 records = this.aiDisplay.length,
|
|
|
13582 features = this.oFeatures,
|
|
|
13583 paginate = features.bPaginate;
|
|
|
13584
|
|
|
13585 if ( features.bServerSide ) {
|
|
|
13586 return paginate === false || len === -1 ?
|
|
|
13587 start + records :
|
|
|
13588 Math.min( start+len, this._iRecordsDisplay );
|
|
|
13589 }
|
|
|
13590 else {
|
|
|
13591 return ! paginate || calc>records || len===-1 ?
|
|
|
13592 records :
|
|
|
13593 calc;
|
|
|
13594 }
|
|
|
13595 },
|
|
|
13596
|
|
|
13597 /**
|
|
|
13598 * The DataTables object for this table
|
|
|
13599 * @type object
|
|
|
13600 * @default null
|
|
|
13601 */
|
|
|
13602 "oInstance": null,
|
|
|
13603
|
|
|
13604 /**
|
|
|
13605 * Unique identifier for each instance of the DataTables object. If there
|
|
|
13606 * is an ID on the table node, then it takes that value, otherwise an
|
|
|
13607 * incrementing internal counter is used.
|
|
|
13608 * @type string
|
|
|
13609 * @default null
|
|
|
13610 */
|
|
|
13611 "sInstance": null,
|
|
|
13612
|
|
|
13613 /**
|
|
|
13614 * tabindex attribute value that is added to DataTables control elements, allowing
|
|
|
13615 * keyboard navigation of the table and its controls.
|
|
|
13616 */
|
|
|
13617 "iTabIndex": 0,
|
|
|
13618
|
|
|
13619 /**
|
|
|
13620 * DIV container for the footer scrolling table if scrolling
|
|
|
13621 */
|
|
|
13622 "nScrollHead": null,
|
|
|
13623
|
|
|
13624 /**
|
|
|
13625 * DIV container for the footer scrolling table if scrolling
|
|
|
13626 */
|
|
|
13627 "nScrollFoot": null,
|
|
|
13628
|
|
|
13629 /**
|
|
|
13630 * Last applied sort
|
|
|
13631 * @type array
|
|
|
13632 * @default []
|
|
|
13633 */
|
|
|
13634 "aLastSort": [],
|
|
|
13635
|
|
|
13636 /**
|
|
|
13637 * Stored plug-in instances
|
|
|
13638 * @type object
|
|
|
13639 * @default {}
|
|
|
13640 */
|
|
|
13641 "oPlugins": {},
|
|
|
13642
|
|
|
13643 /**
|
|
|
13644 * Function used to get a row's id from the row's data
|
|
|
13645 * @type function
|
|
|
13646 * @default null
|
|
|
13647 */
|
|
|
13648 "rowIdFn": null,
|
|
|
13649
|
|
|
13650 /**
|
|
|
13651 * Data location where to store a row's id
|
|
|
13652 * @type string
|
|
|
13653 * @default null
|
|
|
13654 */
|
|
|
13655 "rowId": null
|
|
|
13656 };
|
|
|
13657
|
|
|
13658 /**
|
|
|
13659 * Extension object for DataTables that is used to provide all extension
|
|
|
13660 * options.
|
|
|
13661 *
|
|
|
13662 * Note that the `DataTable.ext` object is available through
|
|
|
13663 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
|
|
|
13664 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
|
|
|
13665 * @namespace
|
|
|
13666 * @extends DataTable.models.ext
|
|
|
13667 */
|
|
|
13668
|
|
|
13669
|
|
|
13670 /**
|
|
|
13671 * DataTables extensions
|
|
|
13672 *
|
|
|
13673 * This namespace acts as a collection area for plug-ins that can be used to
|
|
|
13674 * extend DataTables capabilities. Indeed many of the build in methods
|
|
|
13675 * use this method to provide their own capabilities (sorting methods for
|
|
|
13676 * example).
|
|
|
13677 *
|
|
|
13678 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
|
|
|
13679 * reasons
|
|
|
13680 *
|
|
|
13681 * @namespace
|
|
|
13682 */
|
|
|
13683 DataTable.ext = _ext = {
|
|
|
13684 /**
|
|
|
13685 * Buttons. For use with the Buttons extension for DataTables. This is
|
|
|
13686 * defined here so other extensions can define buttons regardless of load
|
|
|
13687 * order. It is _not_ used by DataTables core.
|
|
|
13688 *
|
|
|
13689 * @type object
|
|
|
13690 * @default {}
|
|
|
13691 */
|
|
|
13692 buttons: {},
|
|
|
13693
|
|
|
13694
|
|
|
13695 /**
|
|
|
13696 * Element class names
|
|
|
13697 *
|
|
|
13698 * @type object
|
|
|
13699 * @default {}
|
|
|
13700 */
|
|
|
13701 classes: {},
|
|
|
13702
|
|
|
13703
|
|
|
13704 /**
|
|
|
13705 * Error reporting.
|
|
|
13706 *
|
|
|
13707 * How should DataTables report an error. Can take the value 'alert',
|
|
|
13708 * 'throw', 'none' or a function.
|
|
|
13709 *
|
|
|
13710 * @type string|function
|
|
|
13711 * @default alert
|
|
|
13712 */
|
|
|
13713 errMode: "alert",
|
|
|
13714
|
|
|
13715
|
|
|
13716 /**
|
|
|
13717 * Feature plug-ins.
|
|
|
13718 *
|
|
|
13719 * This is an array of objects which describe the feature plug-ins that are
|
|
|
13720 * available to DataTables. These feature plug-ins are then available for
|
|
|
13721 * use through the `dom` initialisation option.
|
|
|
13722 *
|
|
|
13723 * Each feature plug-in is described by an object which must have the
|
|
|
13724 * following properties:
|
|
|
13725 *
|
|
|
13726 * * `fnInit` - function that is used to initialise the plug-in,
|
|
|
13727 * * `cFeature` - a character so the feature can be enabled by the `dom`
|
|
|
13728 * instillation option. This is case sensitive.
|
|
|
13729 *
|
|
|
13730 * The `fnInit` function has the following input parameters:
|
|
|
13731 *
|
|
|
13732 * 1. `{object}` DataTables settings object: see
|
|
|
13733 * {@link DataTable.models.oSettings}
|
|
|
13734 *
|
|
|
13735 * And the following return is expected:
|
|
|
13736 *
|
|
|
13737 * * {node|null} The element which contains your feature. Note that the
|
|
|
13738 * return may also be void if your plug-in does not require to inject any
|
|
|
13739 * DOM elements into DataTables control (`dom`) - for example this might
|
|
|
13740 * be useful when developing a plug-in which allows table control via
|
|
|
13741 * keyboard entry
|
|
|
13742 *
|
|
|
13743 * @type array
|
|
|
13744 *
|
|
|
13745 * @example
|
|
|
13746 * $.fn.dataTable.ext.features.push( {
|
|
|
13747 * "fnInit": function( oSettings ) {
|
|
|
13748 * return new TableTools( { "oDTSettings": oSettings } );
|
|
|
13749 * },
|
|
|
13750 * "cFeature": "T"
|
|
|
13751 * } );
|
|
|
13752 */
|
|
|
13753 feature: [],
|
|
|
13754
|
|
|
13755
|
|
|
13756 /**
|
|
|
13757 * Row searching.
|
|
|
13758 *
|
|
|
13759 * This method of searching is complimentary to the default type based
|
|
|
13760 * searching, and a lot more comprehensive as it allows you complete control
|
|
|
13761 * over the searching logic. Each element in this array is a function
|
|
|
13762 * (parameters described below) that is called for every row in the table,
|
|
|
13763 * and your logic decides if it should be included in the searching data set
|
|
|
13764 * or not.
|
|
|
13765 *
|
|
|
13766 * Searching functions have the following input parameters:
|
|
|
13767 *
|
|
|
13768 * 1. `{object}` DataTables settings object: see
|
|
|
13769 * {@link DataTable.models.oSettings}
|
|
|
13770 * 2. `{array|object}` Data for the row to be processed (same as the
|
|
|
13771 * original format that was passed in as the data source, or an array
|
|
|
13772 * from a DOM data source
|
|
|
13773 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
|
|
|
13774 * can be useful to retrieve the `TR` element if you need DOM interaction.
|
|
|
13775 *
|
|
|
13776 * And the following return is expected:
|
|
|
13777 *
|
|
|
13778 * * {boolean} Include the row in the searched result set (true) or not
|
|
|
13779 * (false)
|
|
|
13780 *
|
|
|
13781 * Note that as with the main search ability in DataTables, technically this
|
|
|
13782 * is "filtering", since it is subtractive. However, for consistency in
|
|
|
13783 * naming we call it searching here.
|
|
|
13784 *
|
|
|
13785 * @type array
|
|
|
13786 * @default []
|
|
|
13787 *
|
|
|
13788 * @example
|
|
|
13789 * // The following example shows custom search being applied to the
|
|
|
13790 * // fourth column (i.e. the data[3] index) based on two input values
|
|
|
13791 * // from the end-user, matching the data in a certain range.
|
|
|
13792 * $.fn.dataTable.ext.search.push(
|
|
|
13793 * function( settings, data, dataIndex ) {
|
|
|
13794 * var min = document.getElementById('min').value * 1;
|
|
|
13795 * var max = document.getElementById('max').value * 1;
|
|
|
13796 * var version = data[3] == "-" ? 0 : data[3]*1;
|
|
|
13797 *
|
|
|
13798 * if ( min == "" && max == "" ) {
|
|
|
13799 * return true;
|
|
|
13800 * }
|
|
|
13801 * else if ( min == "" && version < max ) {
|
|
|
13802 * return true;
|
|
|
13803 * }
|
|
|
13804 * else if ( min < version && "" == max ) {
|
|
|
13805 * return true;
|
|
|
13806 * }
|
|
|
13807 * else if ( min < version && version < max ) {
|
|
|
13808 * return true;
|
|
|
13809 * }
|
|
|
13810 * return false;
|
|
|
13811 * }
|
|
|
13812 * );
|
|
|
13813 */
|
|
|
13814 search: [],
|
|
|
13815
|
|
|
13816
|
|
|
13817 /**
|
|
|
13818 * Selector extensions
|
|
|
13819 *
|
|
|
13820 * The `selector` option can be used to extend the options available for the
|
|
|
13821 * selector modifier options (`selector-modifier` object data type) that
|
|
|
13822 * each of the three built in selector types offer (row, column and cell +
|
|
|
13823 * their plural counterparts). For example the Select extension uses this
|
|
|
13824 * mechanism to provide an option to select only rows, columns and cells
|
|
|
13825 * that have been marked as selected by the end user (`{selected: true}`),
|
|
|
13826 * which can be used in conjunction with the existing built in selector
|
|
|
13827 * options.
|
|
|
13828 *
|
|
|
13829 * Each property is an array to which functions can be pushed. The functions
|
|
|
13830 * take three attributes:
|
|
|
13831 *
|
|
|
13832 * * Settings object for the host table
|
|
|
13833 * * Options object (`selector-modifier` object type)
|
|
|
13834 * * Array of selected item indexes
|
|
|
13835 *
|
|
|
13836 * The return is an array of the resulting item indexes after the custom
|
|
|
13837 * selector has been applied.
|
|
|
13838 *
|
|
|
13839 * @type object
|
|
|
13840 */
|
|
|
13841 selector: {
|
|
|
13842 cell: [],
|
|
|
13843 column: [],
|
|
|
13844 row: []
|
|
|
13845 },
|
|
|
13846
|
|
|
13847
|
|
|
13848 /**
|
|
|
13849 * Internal functions, exposed for used in plug-ins.
|
|
|
13850 *
|
|
|
13851 * Please note that you should not need to use the internal methods for
|
|
|
13852 * anything other than a plug-in (and even then, try to avoid if possible).
|
|
|
13853 * The internal function may change between releases.
|
|
|
13854 *
|
|
|
13855 * @type object
|
|
|
13856 * @default {}
|
|
|
13857 */
|
|
|
13858 internal: {},
|
|
|
13859
|
|
|
13860
|
|
|
13861 /**
|
|
|
13862 * Legacy configuration options. Enable and disable legacy options that
|
|
|
13863 * are available in DataTables.
|
|
|
13864 *
|
|
|
13865 * @type object
|
|
|
13866 */
|
|
|
13867 legacy: {
|
|
|
13868 /**
|
|
|
13869 * Enable / disable DataTables 1.9 compatible server-side processing
|
|
|
13870 * requests
|
|
|
13871 *
|
|
|
13872 * @type boolean
|
|
|
13873 * @default null
|
|
|
13874 */
|
|
|
13875 ajax: null
|
|
|
13876 },
|
|
|
13877
|
|
|
13878
|
|
|
13879 /**
|
|
|
13880 * Pagination plug-in methods.
|
|
|
13881 *
|
|
|
13882 * Each entry in this object is a function and defines which buttons should
|
|
|
13883 * be shown by the pagination rendering method that is used for the table:
|
|
|
13884 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
|
|
|
13885 * buttons are displayed in the document, while the functions here tell it
|
|
|
13886 * what buttons to display. This is done by returning an array of button
|
|
|
13887 * descriptions (what each button will do).
|
|
|
13888 *
|
|
|
13889 * Pagination types (the four built in options and any additional plug-in
|
|
|
13890 * options defined here) can be used through the `paginationType`
|
|
|
13891 * initialisation parameter.
|
|
|
13892 *
|
|
|
13893 * The functions defined take two parameters:
|
|
|
13894 *
|
|
|
13895 * 1. `{int} page` The current page index
|
|
|
13896 * 2. `{int} pages` The number of pages in the table
|
|
|
13897 *
|
|
|
13898 * Each function is expected to return an array where each element of the
|
|
|
13899 * array can be one of:
|
|
|
13900 *
|
|
|
13901 * * `first` - Jump to first page when activated
|
|
|
13902 * * `last` - Jump to last page when activated
|
|
|
13903 * * `previous` - Show previous page when activated
|
|
|
13904 * * `next` - Show next page when activated
|
|
|
13905 * * `{int}` - Show page of the index given
|
|
|
13906 * * `{array}` - A nested array containing the above elements to add a
|
|
|
13907 * containing 'DIV' element (might be useful for styling).
|
|
|
13908 *
|
|
|
13909 * Note that DataTables v1.9- used this object slightly differently whereby
|
|
|
13910 * an object with two functions would be defined for each plug-in. That
|
|
|
13911 * ability is still supported by DataTables 1.10+ to provide backwards
|
|
|
13912 * compatibility, but this option of use is now decremented and no longer
|
|
|
13913 * documented in DataTables 1.10+.
|
|
|
13914 *
|
|
|
13915 * @type object
|
|
|
13916 * @default {}
|
|
|
13917 *
|
|
|
13918 * @example
|
|
|
13919 * // Show previous, next and current page buttons only
|
|
|
13920 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
|
|
|
13921 * return [ 'previous', page, 'next' ];
|
|
|
13922 * };
|
|
|
13923 */
|
|
|
13924 pager: {},
|
|
|
13925
|
|
|
13926
|
|
|
13927 renderer: {
|
|
|
13928 pageButton: {},
|
|
|
13929 header: {}
|
|
|
13930 },
|
|
|
13931
|
|
|
13932
|
|
|
13933 /**
|
|
|
13934 * Ordering plug-ins - custom data source
|
|
|
13935 *
|
|
|
13936 * The extension options for ordering of data available here is complimentary
|
|
|
13937 * to the default type based ordering that DataTables typically uses. It
|
|
|
13938 * allows much greater control over the the data that is being used to
|
|
|
13939 * order a column, but is necessarily therefore more complex.
|
|
|
13940 *
|
|
|
13941 * This type of ordering is useful if you want to do ordering based on data
|
|
|
13942 * live from the DOM (for example the contents of an 'input' element) rather
|
|
|
13943 * than just the static string that DataTables knows of.
|
|
|
13944 *
|
|
|
13945 * The way these plug-ins work is that you create an array of the values you
|
|
|
13946 * wish to be ordering for the column in question and then return that
|
|
|
13947 * array. The data in the array much be in the index order of the rows in
|
|
|
13948 * the table (not the currently ordering order!). Which order data gathering
|
|
|
13949 * function is run here depends on the `dt-init columns.orderDataType`
|
|
|
13950 * parameter that is used for the column (if any).
|
|
|
13951 *
|
|
|
13952 * The functions defined take two parameters:
|
|
|
13953 *
|
|
|
13954 * 1. `{object}` DataTables settings object: see
|
|
|
13955 * {@link DataTable.models.oSettings}
|
|
|
13956 * 2. `{int}` Target column index
|
|
|
13957 *
|
|
|
13958 * Each function is expected to return an array:
|
|
|
13959 *
|
|
|
13960 * * `{array}` Data for the column to be ordering upon
|
|
|
13961 *
|
|
|
13962 * @type array
|
|
|
13963 *
|
|
|
13964 * @example
|
|
|
13965 * // Ordering using `input` node values
|
|
|
13966 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
|
|
|
13967 * {
|
|
|
13968 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
|
|
|
13969 * return $('input', td).val();
|
|
|
13970 * } );
|
|
|
13971 * }
|
|
|
13972 */
|
|
|
13973 order: {},
|
|
|
13974
|
|
|
13975
|
|
|
13976 /**
|
|
|
13977 * Type based plug-ins.
|
|
|
13978 *
|
|
|
13979 * Each column in DataTables has a type assigned to it, either by automatic
|
|
|
13980 * detection or by direct assignment using the `type` option for the column.
|
|
|
13981 * The type of a column will effect how it is ordering and search (plug-ins
|
|
|
13982 * can also make use of the column type if required).
|
|
|
13983 *
|
|
|
13984 * @namespace
|
|
|
13985 */
|
|
|
13986 type: {
|
|
|
13987 /**
|
|
|
13988 * Type detection functions.
|
|
|
13989 *
|
|
|
13990 * The functions defined in this object are used to automatically detect
|
|
|
13991 * a column's type, making initialisation of DataTables super easy, even
|
|
|
13992 * when complex data is in the table.
|
|
|
13993 *
|
|
|
13994 * The functions defined take two parameters:
|
|
|
13995 *
|
|
|
13996 * 1. `{*}` Data from the column cell to be analysed
|
|
|
13997 * 2. `{settings}` DataTables settings object. This can be used to
|
|
|
13998 * perform context specific type detection - for example detection
|
|
|
13999 * based on language settings such as using a comma for a decimal
|
|
|
14000 * place. Generally speaking the options from the settings will not
|
|
|
14001 * be required
|
|
|
14002 *
|
|
|
14003 * Each function is expected to return:
|
|
|
14004 *
|
|
|
14005 * * `{string|null}` Data type detected, or null if unknown (and thus
|
|
|
14006 * pass it on to the other type detection functions.
|
|
|
14007 *
|
|
|
14008 * @type array
|
|
|
14009 *
|
|
|
14010 * @example
|
|
|
14011 * // Currency type detection plug-in:
|
|
|
14012 * $.fn.dataTable.ext.type.detect.push(
|
|
|
14013 * function ( data, settings ) {
|
|
|
14014 * // Check the numeric part
|
|
|
14015 * if ( ! $.isNumeric( data.substring(1) ) ) {
|
|
|
14016 * return null;
|
|
|
14017 * }
|
|
|
14018 *
|
|
|
14019 * // Check prefixed by currency
|
|
|
14020 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) {
|
|
|
14021 * return 'currency';
|
|
|
14022 * }
|
|
|
14023 * return null;
|
|
|
14024 * }
|
|
|
14025 * );
|
|
|
14026 */
|
|
|
14027 detect: [],
|
|
|
14028
|
|
|
14029
|
|
|
14030 /**
|
|
|
14031 * Type based search formatting.
|
|
|
14032 *
|
|
|
14033 * The type based searching functions can be used to pre-format the
|
|
|
14034 * data to be search on. For example, it can be used to strip HTML
|
|
|
14035 * tags or to de-format telephone numbers for numeric only searching.
|
|
|
14036 *
|
|
|
14037 * Note that is a search is not defined for a column of a given type,
|
|
|
14038 * no search formatting will be performed.
|
|
|
14039 *
|
|
|
14040 * Pre-processing of searching data plug-ins - When you assign the sType
|
|
|
14041 * for a column (or have it automatically detected for you by DataTables
|
|
|
14042 * or a type detection plug-in), you will typically be using this for
|
|
|
14043 * custom sorting, but it can also be used to provide custom searching
|
|
|
14044 * by allowing you to pre-processing the data and returning the data in
|
|
|
14045 * the format that should be searched upon. This is done by adding
|
|
|
14046 * functions this object with a parameter name which matches the sType
|
|
|
14047 * for that target column. This is the corollary of <i>afnSortData</i>
|
|
|
14048 * for searching data.
|
|
|
14049 *
|
|
|
14050 * The functions defined take a single parameter:
|
|
|
14051 *
|
|
|
14052 * 1. `{*}` Data from the column cell to be prepared for searching
|
|
|
14053 *
|
|
|
14054 * Each function is expected to return:
|
|
|
14055 *
|
|
|
14056 * * `{string|null}` Formatted string that will be used for the searching.
|
|
|
14057 *
|
|
|
14058 * @type object
|
|
|
14059 * @default {}
|
|
|
14060 *
|
|
|
14061 * @example
|
|
|
14062 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
|
|
|
14063 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
|
|
|
14064 * }
|
|
|
14065 */
|
|
|
14066 search: {},
|
|
|
14067
|
|
|
14068
|
|
|
14069 /**
|
|
|
14070 * Type based ordering.
|
|
|
14071 *
|
|
|
14072 * The column type tells DataTables what ordering to apply to the table
|
|
|
14073 * when a column is sorted upon. The order for each type that is defined,
|
|
|
14074 * is defined by the functions available in this object.
|
|
|
14075 *
|
|
|
14076 * Each ordering option can be described by three properties added to
|
|
|
14077 * this object:
|
|
|
14078 *
|
|
|
14079 * * `{type}-pre` - Pre-formatting function
|
|
|
14080 * * `{type}-asc` - Ascending order function
|
|
|
14081 * * `{type}-desc` - Descending order function
|
|
|
14082 *
|
|
|
14083 * All three can be used together, only `{type}-pre` or only
|
|
|
14084 * `{type}-asc` and `{type}-desc` together. It is generally recommended
|
|
|
14085 * that only `{type}-pre` is used, as this provides the optimal
|
|
|
14086 * implementation in terms of speed, although the others are provided
|
|
|
14087 * for compatibility with existing Javascript sort functions.
|
|
|
14088 *
|
|
|
14089 * `{type}-pre`: Functions defined take a single parameter:
|
|
|
14090 *
|
|
|
14091 * 1. `{*}` Data from the column cell to be prepared for ordering
|
|
|
14092 *
|
|
|
14093 * And return:
|
|
|
14094 *
|
|
|
14095 * * `{*}` Data to be sorted upon
|
|
|
14096 *
|
|
|
14097 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
|
|
|
14098 * functions, taking two parameters:
|
|
|
14099 *
|
|
|
14100 * 1. `{*}` Data to compare to the second parameter
|
|
|
14101 * 2. `{*}` Data to compare to the first parameter
|
|
|
14102 *
|
|
|
14103 * And returning:
|
|
|
14104 *
|
|
|
14105 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
|
|
|
14106 * than the second parameter, ===0 if the two parameters are equal and
|
|
|
14107 * >0 if the first parameter should be sorted height than the second
|
|
|
14108 * parameter.
|
|
|
14109 *
|
|
|
14110 * @type object
|
|
|
14111 * @default {}
|
|
|
14112 *
|
|
|
14113 * @example
|
|
|
14114 * // Numeric ordering of formatted numbers with a pre-formatter
|
|
|
14115 * $.extend( $.fn.dataTable.ext.type.order, {
|
|
|
14116 * "string-pre": function(x) {
|
|
|
14117 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
|
|
|
14118 * return parseFloat( a );
|
|
|
14119 * }
|
|
|
14120 * } );
|
|
|
14121 *
|
|
|
14122 * @example
|
|
|
14123 * // Case-sensitive string ordering, with no pre-formatting method
|
|
|
14124 * $.extend( $.fn.dataTable.ext.order, {
|
|
|
14125 * "string-case-asc": function(x,y) {
|
|
|
14126 * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
|
|
14127 * },
|
|
|
14128 * "string-case-desc": function(x,y) {
|
|
|
14129 * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
|
|
|
14130 * }
|
|
|
14131 * } );
|
|
|
14132 */
|
|
|
14133 order: {}
|
|
|
14134 },
|
|
|
14135
|
|
|
14136 /**
|
|
|
14137 * Unique DataTables instance counter
|
|
|
14138 *
|
|
|
14139 * @type int
|
|
|
14140 * @private
|
|
|
14141 */
|
|
|
14142 _unique: 0,
|
|
|
14143
|
|
|
14144
|
|
|
14145 //
|
|
|
14146 // Depreciated
|
|
|
14147 // The following properties are retained for backwards compatiblity only.
|
|
|
14148 // The should not be used in new projects and will be removed in a future
|
|
|
14149 // version
|
|
|
14150 //
|
|
|
14151
|
|
|
14152 /**
|
|
|
14153 * Version check function.
|
|
|
14154 * @type function
|
|
|
14155 * @depreciated Since 1.10
|
|
|
14156 */
|
|
|
14157 fnVersionCheck: DataTable.fnVersionCheck,
|
|
|
14158
|
|
|
14159
|
|
|
14160 /**
|
|
|
14161 * Index for what 'this' index API functions should use
|
|
|
14162 * @type int
|
|
|
14163 * @deprecated Since v1.10
|
|
|
14164 */
|
|
|
14165 iApiIndex: 0,
|
|
|
14166
|
|
|
14167
|
|
|
14168 /**
|
|
|
14169 * jQuery UI class container
|
|
|
14170 * @type object
|
|
|
14171 * @deprecated Since v1.10
|
|
|
14172 */
|
|
|
14173 oJUIClasses: {},
|
|
|
14174
|
|
|
14175
|
|
|
14176 /**
|
|
|
14177 * Software version
|
|
|
14178 * @type string
|
|
|
14179 * @deprecated Since v1.10
|
|
|
14180 */
|
|
|
14181 sVersion: DataTable.version
|
|
|
14182 };
|
|
|
14183
|
|
|
14184
|
|
|
14185 //
|
|
|
14186 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
|
|
|
14187 //
|
|
|
14188 $.extend( _ext, {
|
|
|
14189 afnFiltering: _ext.search,
|
|
|
14190 aTypes: _ext.type.detect,
|
|
|
14191 ofnSearch: _ext.type.search,
|
|
|
14192 oSort: _ext.type.order,
|
|
|
14193 afnSortData: _ext.order,
|
|
|
14194 aoFeatures: _ext.feature,
|
|
|
14195 oApi: _ext.internal,
|
|
|
14196 oStdClasses: _ext.classes,
|
|
|
14197 oPagination: _ext.pager
|
|
|
14198 } );
|
|
|
14199
|
|
|
14200
|
|
|
14201 $.extend( DataTable.ext.classes, {
|
|
|
14202 "sTable": "dataTable",
|
|
|
14203 "sNoFooter": "no-footer",
|
|
|
14204
|
|
|
14205 /* Paging buttons */
|
|
|
14206 "sPageButton": "paginate_button",
|
|
|
14207 "sPageButtonActive": "current",
|
|
|
14208 "sPageButtonDisabled": "disabled",
|
|
|
14209
|
|
|
14210 /* Striping classes */
|
|
|
14211 "sStripeOdd": "odd",
|
|
|
14212 "sStripeEven": "even",
|
|
|
14213
|
|
|
14214 /* Empty row */
|
|
|
14215 "sRowEmpty": "dataTables_empty",
|
|
|
14216
|
|
|
14217 /* Features */
|
|
|
14218 "sWrapper": "dataTables_wrapper",
|
|
|
14219 "sFilter": "dataTables_filter",
|
|
|
14220 "sInfo": "dataTables_info",
|
|
|
14221 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
|
|
|
14222 "sLength": "dataTables_length",
|
|
|
14223 "sProcessing": "dataTables_processing",
|
|
|
14224
|
|
|
14225 /* Sorting */
|
|
|
14226 "sSortAsc": "sorting_asc",
|
|
|
14227 "sSortDesc": "sorting_desc",
|
|
|
14228 "sSortable": "sorting", /* Sortable in both directions */
|
|
|
14229 "sSortableAsc": "sorting_asc_disabled",
|
|
|
14230 "sSortableDesc": "sorting_desc_disabled",
|
|
|
14231 "sSortableNone": "sorting_disabled",
|
|
|
14232 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
|
|
|
14233
|
|
|
14234 /* Filtering */
|
|
|
14235 "sFilterInput": "",
|
|
|
14236
|
|
|
14237 /* Page length */
|
|
|
14238 "sLengthSelect": "",
|
|
|
14239
|
|
|
14240 /* Scrolling */
|
|
|
14241 "sScrollWrapper": "dataTables_scroll",
|
|
|
14242 "sScrollHead": "dataTables_scrollHead",
|
|
|
14243 "sScrollHeadInner": "dataTables_scrollHeadInner",
|
|
|
14244 "sScrollBody": "dataTables_scrollBody",
|
|
|
14245 "sScrollFoot": "dataTables_scrollFoot",
|
|
|
14246 "sScrollFootInner": "dataTables_scrollFootInner",
|
|
|
14247
|
|
|
14248 /* Misc */
|
|
|
14249 "sHeaderTH": "",
|
|
|
14250 "sFooterTH": "",
|
|
|
14251
|
|
|
14252 // Deprecated
|
|
|
14253 "sSortJUIAsc": "",
|
|
|
14254 "sSortJUIDesc": "",
|
|
|
14255 "sSortJUI": "",
|
|
|
14256 "sSortJUIAscAllowed": "",
|
|
|
14257 "sSortJUIDescAllowed": "",
|
|
|
14258 "sSortJUIWrapper": "",
|
|
|
14259 "sSortIcon": "",
|
|
|
14260 "sJUIHeader": "",
|
|
|
14261 "sJUIFooter": ""
|
|
|
14262 } );
|
|
|
14263
|
|
|
14264
|
|
|
14265 (function() {
|
|
|
14266
|
|
|
14267 // Reused strings for better compression. Closure compiler appears to have a
|
|
|
14268 // weird edge case where it is trying to expand strings rather than use the
|
|
|
14269 // variable version. This results in about 200 bytes being added, for very
|
|
|
14270 // little preference benefit since it this run on script load only.
|
|
|
14271 var _empty = '';
|
|
|
14272 _empty = '';
|
|
|
14273
|
|
|
14274 var _stateDefault = _empty + 'ui-state-default';
|
|
|
14275 var _sortIcon = _empty + 'css_right ui-icon ui-icon-';
|
|
|
14276 var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
|
|
|
14277
|
|
|
14278 $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
|
|
|
14279 /* Full numbers paging buttons */
|
|
|
14280 "sPageButton": "fg-button ui-button "+_stateDefault,
|
|
|
14281 "sPageButtonActive": "ui-state-disabled",
|
|
|
14282 "sPageButtonDisabled": "ui-state-disabled",
|
|
|
14283
|
|
|
14284 /* Features */
|
|
|
14285 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
|
|
|
14286 "ui-buttonset-multi paging_", /* Note that the type is postfixed */
|
|
|
14287
|
|
|
14288 /* Sorting */
|
|
|
14289 "sSortAsc": _stateDefault+" sorting_asc",
|
|
|
14290 "sSortDesc": _stateDefault+" sorting_desc",
|
|
|
14291 "sSortable": _stateDefault+" sorting",
|
|
|
14292 "sSortableAsc": _stateDefault+" sorting_asc_disabled",
|
|
|
14293 "sSortableDesc": _stateDefault+" sorting_desc_disabled",
|
|
|
14294 "sSortableNone": _stateDefault+" sorting_disabled",
|
|
|
14295 "sSortJUIAsc": _sortIcon+"triangle-1-n",
|
|
|
14296 "sSortJUIDesc": _sortIcon+"triangle-1-s",
|
|
|
14297 "sSortJUI": _sortIcon+"carat-2-n-s",
|
|
|
14298 "sSortJUIAscAllowed": _sortIcon+"carat-1-n",
|
|
|
14299 "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
|
|
|
14300 "sSortJUIWrapper": "DataTables_sort_wrapper",
|
|
|
14301 "sSortIcon": "DataTables_sort_icon",
|
|
|
14302
|
|
|
14303 /* Scrolling */
|
|
|
14304 "sScrollHead": "dataTables_scrollHead "+_stateDefault,
|
|
|
14305 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
|
|
|
14306
|
|
|
14307 /* Misc */
|
|
|
14308 "sHeaderTH": _stateDefault,
|
|
|
14309 "sFooterTH": _stateDefault,
|
|
|
14310 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
|
|
|
14311 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
|
|
|
14312 } );
|
|
|
14313
|
|
|
14314 }());
|
|
|
14315
|
|
|
14316
|
|
|
14317
|
|
|
14318 var extPagination = DataTable.ext.pager;
|
|
|
14319
|
|
|
14320 function _numbers ( page, pages ) {
|
|
|
14321 var
|
|
|
14322 numbers = [],
|
|
|
14323 buttons = extPagination.numbers_length,
|
|
|
14324 half = Math.floor( buttons / 2 ),
|
|
|
14325 i = 1;
|
|
|
14326
|
|
|
14327 if ( pages <= buttons ) {
|
|
|
14328 numbers = _range( 0, pages );
|
|
|
14329 }
|
|
|
14330 else if ( page <= half ) {
|
|
|
14331 numbers = _range( 0, buttons-2 );
|
|
|
14332 numbers.push( 'ellipsis' );
|
|
|
14333 numbers.push( pages-1 );
|
|
|
14334 }
|
|
|
14335 else if ( page >= pages - 1 - half ) {
|
|
|
14336 numbers = _range( pages-(buttons-2), pages );
|
|
|
14337 numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
|
|
|
14338 numbers.splice( 0, 0, 0 );
|
|
|
14339 }
|
|
|
14340 else {
|
|
|
14341 numbers = _range( page-half+2, page+half-1 );
|
|
|
14342 numbers.push( 'ellipsis' );
|
|
|
14343 numbers.push( pages-1 );
|
|
|
14344 numbers.splice( 0, 0, 'ellipsis' );
|
|
|
14345 numbers.splice( 0, 0, 0 );
|
|
|
14346 }
|
|
|
14347
|
|
|
14348 numbers.DT_el = 'span';
|
|
|
14349 return numbers;
|
|
|
14350 }
|
|
|
14351
|
|
|
14352
|
|
|
14353 $.extend( extPagination, {
|
|
|
14354 simple: function ( page, pages ) {
|
|
|
14355 return [ 'previous', 'next' ];
|
|
|
14356 },
|
|
|
14357
|
|
|
14358 full: function ( page, pages ) {
|
|
|
14359 return [ 'first', 'previous', 'next', 'last' ];
|
|
|
14360 },
|
|
|
14361
|
|
|
14362 numbers: function ( page, pages ) {
|
|
|
14363 return [ _numbers(page, pages) ];
|
|
|
14364 },
|
|
|
14365
|
|
|
14366 simple_numbers: function ( page, pages ) {
|
|
|
14367 return [ 'previous', _numbers(page, pages), 'next' ];
|
|
|
14368 },
|
|
|
14369
|
|
|
14370 full_numbers: function ( page, pages ) {
|
|
|
14371 return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
|
|
|
14372 },
|
|
|
14373
|
|
|
14374 // For testing and plug-ins to use
|
|
|
14375 _numbers: _numbers,
|
|
|
14376
|
|
|
14377 // Number of number buttons (including ellipsis) to show. _Must be odd!_
|
|
|
14378 numbers_length: 7
|
|
|
14379 } );
|
|
|
14380
|
|
|
14381
|
|
|
14382 $.extend( true, DataTable.ext.renderer, {
|
|
|
14383 pageButton: {
|
|
|
14384 _: function ( settings, host, idx, buttons, page, pages ) {
|
|
|
14385 var classes = settings.oClasses;
|
|
|
14386 var lang = settings.oLanguage.oPaginate;
|
|
|
14387 var btnDisplay, btnClass, counter=0;
|
|
|
14388
|
|
|
14389 var attach = function( container, buttons ) {
|
|
|
14390 var i, ien, node, button;
|
|
|
14391 var clickHandler = function ( e ) {
|
|
|
14392 _fnPageChange( settings, e.data.action, true );
|
|
|
14393 };
|
|
|
14394
|
|
|
14395 for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
|
|
|
14396 button = buttons[i];
|
|
|
14397
|
|
|
14398 if ( $.isArray( button ) ) {
|
|
|
14399 var inner = $( '<'+(button.DT_el || 'div')+'/>' )
|
|
|
14400 .appendTo( container );
|
|
|
14401 attach( inner, button );
|
|
|
14402 }
|
|
|
14403 else {
|
|
|
14404 btnDisplay = null;
|
|
|
14405 btnClass = '';
|
|
|
14406
|
|
|
14407 switch ( button ) {
|
|
|
14408 case 'ellipsis':
|
|
|
14409 container.append('<span class="ellipsis">…</span>');
|
|
|
14410 break;
|
|
|
14411
|
|
|
14412 case 'first':
|
|
|
14413 btnDisplay = lang.sFirst;
|
|
|
14414 btnClass = button + (page > 0 ?
|
|
|
14415 '' : ' '+classes.sPageButtonDisabled);
|
|
|
14416 break;
|
|
|
14417
|
|
|
14418 case 'previous':
|
|
|
14419 btnDisplay = lang.sPrevious;
|
|
|
14420 btnClass = button + (page > 0 ?
|
|
|
14421 '' : ' '+classes.sPageButtonDisabled);
|
|
|
14422 break;
|
|
|
14423
|
|
|
14424 case 'next':
|
|
|
14425 btnDisplay = lang.sNext;
|
|
|
14426 btnClass = button + (page < pages-1 ?
|
|
|
14427 '' : ' '+classes.sPageButtonDisabled);
|
|
|
14428 break;
|
|
|
14429
|
|
|
14430 case 'last':
|
|
|
14431 btnDisplay = lang.sLast;
|
|
|
14432 btnClass = button + (page < pages-1 ?
|
|
|
14433 '' : ' '+classes.sPageButtonDisabled);
|
|
|
14434 break;
|
|
|
14435
|
|
|
14436 default:
|
|
|
14437 btnDisplay = button + 1;
|
|
|
14438 btnClass = page === button ?
|
|
|
14439 classes.sPageButtonActive : '';
|
|
|
14440 break;
|
|
|
14441 }
|
|
|
14442
|
|
|
14443 if ( btnDisplay !== null ) {
|
|
|
14444 node = $('<a>', {
|
|
|
14445 'class': classes.sPageButton+' '+btnClass,
|
|
|
14446 'aria-controls': settings.sTableId,
|
|
|
14447 'data-dt-idx': counter,
|
|
|
14448 'tabindex': settings.iTabIndex,
|
|
|
14449 'id': idx === 0 && typeof button === 'string' ?
|
|
|
14450 settings.sTableId +'_'+ button :
|
|
|
14451 null
|
|
|
14452 } )
|
|
|
14453 .html( btnDisplay )
|
|
|
14454 .appendTo( container );
|
|
|
14455
|
|
|
14456 _fnBindAction(
|
|
|
14457 node, {action: button}, clickHandler
|
|
|
14458 );
|
|
|
14459
|
|
|
14460 counter++;
|
|
|
14461 }
|
|
|
14462 }
|
|
|
14463 }
|
|
|
14464 };
|
|
|
14465
|
|
|
14466 // IE9 throws an 'unknown error' if document.activeElement is used
|
|
|
14467 // inside an iframe or frame. Try / catch the error. Not good for
|
|
|
14468 // accessibility, but neither are frames.
|
|
|
14469 var activeEl;
|
|
|
14470
|
|
|
14471 try {
|
|
|
14472 // Because this approach is destroying and recreating the paging
|
|
|
14473 // elements, focus is lost on the select button which is bad for
|
|
|
14474 // accessibility. So we want to restore focus once the draw has
|
|
|
14475 // completed
|
|
|
14476 activeEl = $(host).find(document.activeElement).data('dt-idx');
|
|
|
14477 }
|
|
|
14478 catch (e) {}
|
|
|
14479
|
|
|
14480 attach( $(host).empty(), buttons );
|
|
|
14481
|
|
|
14482 if ( activeEl ) {
|
|
|
14483 $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
|
|
|
14484 }
|
|
|
14485 }
|
|
|
14486 }
|
|
|
14487 } );
|
|
|
14488
|
|
|
14489
|
|
|
14490
|
|
|
14491 // Built in type detection. See model.ext.aTypes for information about
|
|
|
14492 // what is required from this methods.
|
|
|
14493 $.extend( DataTable.ext.type.detect, [
|
|
|
14494 // Plain numbers - first since V8 detects some plain numbers as dates
|
|
|
14495 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
|
|
|
14496 function ( d, settings )
|
|
|
14497 {
|
|
|
14498 var decimal = settings.oLanguage.sDecimal;
|
|
|
14499 return _isNumber( d, decimal ) ? 'num'+decimal : null;
|
|
|
14500 },
|
|
|
14501
|
|
|
14502 // Dates (only those recognised by the browser's Date.parse)
|
|
|
14503 function ( d, settings )
|
|
|
14504 {
|
|
|
14505 // V8 will remove any unknown characters at the start and end of the
|
|
|
14506 // expression, leading to false matches such as `$245.12` or `10%` being
|
|
|
14507 // a valid date. See forum thread 18941 for detail.
|
|
|
14508 if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
|
|
|
14509 return null;
|
|
|
14510 }
|
|
|
14511 var parsed = Date.parse(d);
|
|
|
14512 return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
|
|
|
14513 },
|
|
|
14514
|
|
|
14515 // Formatted numbers
|
|
|
14516 function ( d, settings )
|
|
|
14517 {
|
|
|
14518 var decimal = settings.oLanguage.sDecimal;
|
|
|
14519 return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
|
|
|
14520 },
|
|
|
14521
|
|
|
14522 // HTML numeric
|
|
|
14523 function ( d, settings )
|
|
|
14524 {
|
|
|
14525 var decimal = settings.oLanguage.sDecimal;
|
|
|
14526 return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
|
|
|
14527 },
|
|
|
14528
|
|
|
14529 // HTML numeric, formatted
|
|
|
14530 function ( d, settings )
|
|
|
14531 {
|
|
|
14532 var decimal = settings.oLanguage.sDecimal;
|
|
|
14533 return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
|
|
|
14534 },
|
|
|
14535
|
|
|
14536 // HTML (this is strict checking - there must be html)
|
|
|
14537 function ( d, settings )
|
|
|
14538 {
|
|
|
14539 return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
|
|
|
14540 'html' : null;
|
|
|
14541 }
|
|
|
14542 ] );
|
|
|
14543
|
|
|
14544
|
|
|
14545
|
|
|
14546 // Filter formatting functions. See model.ext.ofnSearch for information about
|
|
|
14547 // what is required from these methods.
|
|
|
14548 //
|
|
|
14549 // Note that additional search methods are added for the html numbers and
|
|
|
14550 // html formatted numbers by `_addNumericSort()` when we know what the decimal
|
|
|
14551 // place is
|
|
|
14552
|
|
|
14553
|
|
|
14554 $.extend( DataTable.ext.type.search, {
|
|
|
14555 html: function ( data ) {
|
|
|
14556 return _empty(data) ?
|
|
|
14557 data :
|
|
|
14558 typeof data === 'string' ?
|
|
|
14559 data
|
|
|
14560 .replace( _re_new_lines, " " )
|
|
|
14561 .replace( _re_html, "" ) :
|
|
|
14562 '';
|
|
|
14563 },
|
|
|
14564
|
|
|
14565 string: function ( data ) {
|
|
|
14566 return _empty(data) ?
|
|
|
14567 data :
|
|
|
14568 typeof data === 'string' ?
|
|
|
14569 data.replace( _re_new_lines, " " ) :
|
|
|
14570 data;
|
|
|
14571 }
|
|
|
14572 } );
|
|
|
14573
|
|
|
14574
|
|
|
14575
|
|
|
14576 var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
|
|
|
14577 if ( d !== 0 && (!d || d === '-') ) {
|
|
|
14578 return -Infinity;
|
|
|
14579 }
|
|
|
14580
|
|
|
14581 // If a decimal place other than `.` is used, it needs to be given to the
|
|
|
14582 // function so we can detect it and replace with a `.` which is the only
|
|
|
14583 // decimal place Javascript recognises - it is not locale aware.
|
|
|
14584 if ( decimalPlace ) {
|
|
|
14585 d = _numToDecimal( d, decimalPlace );
|
|
|
14586 }
|
|
|
14587
|
|
|
14588 if ( d.replace ) {
|
|
|
14589 if ( re1 ) {
|
|
|
14590 d = d.replace( re1, '' );
|
|
|
14591 }
|
|
|
14592
|
|
|
14593 if ( re2 ) {
|
|
|
14594 d = d.replace( re2, '' );
|
|
|
14595 }
|
|
|
14596 }
|
|
|
14597
|
|
|
14598 return d * 1;
|
|
|
14599 };
|
|
|
14600
|
|
|
14601
|
|
|
14602 // Add the numeric 'deformatting' functions for sorting and search. This is done
|
|
|
14603 // in a function to provide an easy ability for the language options to add
|
|
|
14604 // additional methods if a non-period decimal place is used.
|
|
|
14605 function _addNumericSort ( decimalPlace ) {
|
|
|
14606 $.each(
|
|
|
14607 {
|
|
|
14608 // Plain numbers
|
|
|
14609 "num": function ( d ) {
|
|
|
14610 return __numericReplace( d, decimalPlace );
|
|
|
14611 },
|
|
|
14612
|
|
|
14613 // Formatted numbers
|
|
|
14614 "num-fmt": function ( d ) {
|
|
|
14615 return __numericReplace( d, decimalPlace, _re_formatted_numeric );
|
|
|
14616 },
|
|
|
14617
|
|
|
14618 // HTML numeric
|
|
|
14619 "html-num": function ( d ) {
|
|
|
14620 return __numericReplace( d, decimalPlace, _re_html );
|
|
|
14621 },
|
|
|
14622
|
|
|
14623 // HTML numeric, formatted
|
|
|
14624 "html-num-fmt": function ( d ) {
|
|
|
14625 return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
|
|
|
14626 }
|
|
|
14627 },
|
|
|
14628 function ( key, fn ) {
|
|
|
14629 // Add the ordering method
|
|
|
14630 _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
|
|
|
14631
|
|
|
14632 // For HTML types add a search formatter that will strip the HTML
|
|
|
14633 if ( key.match(/^html\-/) ) {
|
|
|
14634 _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
|
|
|
14635 }
|
|
|
14636 }
|
|
|
14637 );
|
|
|
14638 }
|
|
|
14639
|
|
|
14640
|
|
|
14641 // Default sort methods
|
|
|
14642 $.extend( _ext.type.order, {
|
|
|
14643 // Dates
|
|
|
14644 "date-pre": function ( d ) {
|
|
|
14645 return Date.parse( d ) || 0;
|
|
|
14646 },
|
|
|
14647
|
|
|
14648 // html
|
|
|
14649 "html-pre": function ( a ) {
|
|
|
14650 return _empty(a) ?
|
|
|
14651 '' :
|
|
|
14652 a.replace ?
|
|
|
14653 a.replace( /<.*?>/g, "" ).toLowerCase() :
|
|
|
14654 a+'';
|
|
|
14655 },
|
|
|
14656
|
|
|
14657 // string
|
|
|
14658 "string-pre": function ( a ) {
|
|
|
14659 // This is a little complex, but faster than always calling toString,
|
|
|
14660 // http://jsperf.com/tostring-v-check
|
|
|
14661 return _empty(a) ?
|
|
|
14662 '' :
|
|
|
14663 typeof a === 'string' ?
|
|
|
14664 a.toLowerCase() :
|
|
|
14665 ! a.toString ?
|
|
|
14666 '' :
|
|
|
14667 a.toString();
|
|
|
14668 },
|
|
|
14669
|
|
|
14670 // string-asc and -desc are retained only for compatibility with the old
|
|
|
14671 // sort methods
|
|
|
14672 "string-asc": function ( x, y ) {
|
|
|
14673 return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
|
|
14674 },
|
|
|
14675
|
|
|
14676 "string-desc": function ( x, y ) {
|
|
|
14677 return ((x < y) ? 1 : ((x > y) ? -1 : 0));
|
|
|
14678 }
|
|
|
14679 } );
|
|
|
14680
|
|
|
14681
|
|
|
14682 // Numeric sorting types - order doesn't matter here
|
|
|
14683 _addNumericSort( '' );
|
|
|
14684
|
|
|
14685
|
|
|
14686 $.extend( true, DataTable.ext.renderer, {
|
|
|
14687 header: {
|
|
|
14688 _: function ( settings, cell, column, classes ) {
|
|
|
14689 // No additional mark-up required
|
|
|
14690 // Attach a sort listener to update on sort - note that using the
|
|
|
14691 // `DT` namespace will allow the event to be removed automatically
|
|
|
14692 // on destroy, while the `dt` namespaced event is the one we are
|
|
|
14693 // listening for
|
|
|
14694 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
|
|
|
14695 if ( settings !== ctx ) { // need to check this this is the host
|
|
|
14696 return; // table, not a nested one
|
|
|
14697 }
|
|
|
14698
|
|
|
14699 var colIdx = column.idx;
|
|
|
14700
|
|
|
14701 cell
|
|
|
14702 .removeClass(
|
|
|
14703 column.sSortingClass +' '+
|
|
|
14704 classes.sSortAsc +' '+
|
|
|
14705 classes.sSortDesc
|
|
|
14706 )
|
|
|
14707 .addClass( columns[ colIdx ] == 'asc' ?
|
|
|
14708 classes.sSortAsc : columns[ colIdx ] == 'desc' ?
|
|
|
14709 classes.sSortDesc :
|
|
|
14710 column.sSortingClass
|
|
|
14711 );
|
|
|
14712 } );
|
|
|
14713 },
|
|
|
14714
|
|
|
14715 jqueryui: function ( settings, cell, column, classes ) {
|
|
|
14716 $('<div/>')
|
|
|
14717 .addClass( classes.sSortJUIWrapper )
|
|
|
14718 .append( cell.contents() )
|
|
|
14719 .append( $('<span/>')
|
|
|
14720 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
|
|
|
14721 )
|
|
|
14722 .appendTo( cell );
|
|
|
14723
|
|
|
14724 // Attach a sort listener to update on sort
|
|
|
14725 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
|
|
|
14726 if ( settings !== ctx ) {
|
|
|
14727 return;
|
|
|
14728 }
|
|
|
14729
|
|
|
14730 var colIdx = column.idx;
|
|
|
14731
|
|
|
14732 cell
|
|
|
14733 .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
|
|
|
14734 .addClass( columns[ colIdx ] == 'asc' ?
|
|
|
14735 classes.sSortAsc : columns[ colIdx ] == 'desc' ?
|
|
|
14736 classes.sSortDesc :
|
|
|
14737 column.sSortingClass
|
|
|
14738 );
|
|
|
14739
|
|
|
14740 cell
|
|
|
14741 .find( 'span.'+classes.sSortIcon )
|
|
|
14742 .removeClass(
|
|
|
14743 classes.sSortJUIAsc +" "+
|
|
|
14744 classes.sSortJUIDesc +" "+
|
|
|
14745 classes.sSortJUI +" "+
|
|
|
14746 classes.sSortJUIAscAllowed +" "+
|
|
|
14747 classes.sSortJUIDescAllowed
|
|
|
14748 )
|
|
|
14749 .addClass( columns[ colIdx ] == 'asc' ?
|
|
|
14750 classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
|
|
|
14751 classes.sSortJUIDesc :
|
|
|
14752 column.sSortingClassJUI
|
|
|
14753 );
|
|
|
14754 } );
|
|
|
14755 }
|
|
|
14756 }
|
|
|
14757 } );
|
|
|
14758
|
|
|
14759 /*
|
|
|
14760 * Public helper functions. These aren't used internally by DataTables, or
|
|
|
14761 * called by any of the options passed into DataTables, but they can be used
|
|
|
14762 * externally by developers working with DataTables. They are helper functions
|
|
|
14763 * to make working with DataTables a little bit easier.
|
|
|
14764 */
|
|
|
14765
|
|
|
14766 /**
|
|
|
14767 * Helpers for `columns.render`.
|
|
|
14768 *
|
|
|
14769 * The options defined here can be used with the `columns.render` initialisation
|
|
|
14770 * option to provide a display renderer. The following functions are defined:
|
|
|
14771 *
|
|
|
14772 * * `number` - Will format numeric data (defined by `columns.data`) for
|
|
|
14773 * display, retaining the original unformatted data for sorting and filtering.
|
|
|
14774 * It takes 5 parameters:
|
|
|
14775 * * `string` - Thousands grouping separator
|
|
|
14776 * * `string` - Decimal point indicator
|
|
|
14777 * * `integer` - Number of decimal points to show
|
|
|
14778 * * `string` (optional) - Prefix.
|
|
|
14779 * * `string` (optional) - Postfix (/suffix).
|
|
|
14780 *
|
|
|
14781 * @example
|
|
|
14782 * // Column definition using the number renderer
|
|
|
14783 * {
|
|
|
14784 * data: "salary",
|
|
|
14785 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
|
|
|
14786 * }
|
|
|
14787 *
|
|
|
14788 * @namespace
|
|
|
14789 */
|
|
|
14790 DataTable.render = {
|
|
|
14791 number: function ( thousands, decimal, precision, prefix, postfix ) {
|
|
|
14792 return {
|
|
|
14793 display: function ( d ) {
|
|
|
14794 if ( typeof d !== 'number' && typeof d !== 'string' ) {
|
|
|
14795 return d;
|
|
|
14796 }
|
|
|
14797
|
|
|
14798 var negative = d < 0 ? '-' : '';
|
|
|
14799 d = Math.abs( parseFloat( d ) );
|
|
|
14800
|
|
|
14801 var intPart = parseInt( d, 10 );
|
|
|
14802 var floatPart = precision ?
|
|
|
14803 decimal+(d - intPart).toFixed( precision ).substring( 2 ):
|
|
|
14804 '';
|
|
|
14805
|
|
|
14806 return negative + (prefix||'') +
|
|
|
14807 intPart.toString().replace(
|
|
|
14808 /\B(?=(\d{3})+(?!\d))/g, thousands
|
|
|
14809 ) +
|
|
|
14810 floatPart +
|
|
|
14811 (postfix||'');
|
|
|
14812 }
|
|
|
14813 };
|
|
|
14814 }
|
|
|
14815 };
|
|
|
14816
|
|
|
14817
|
|
|
14818 /*
|
|
|
14819 * This is really a good bit rubbish this method of exposing the internal methods
|
|
|
14820 * publicly... - To be fixed in 2.0 using methods on the prototype
|
|
|
14821 */
|
|
|
14822
|
|
|
14823
|
|
|
14824 /**
|
|
|
14825 * Create a wrapper function for exporting an internal functions to an external API.
|
|
|
14826 * @param {string} fn API function name
|
|
|
14827 * @returns {function} wrapped function
|
|
|
14828 * @memberof DataTable#internal
|
|
|
14829 */
|
|
|
14830 function _fnExternApiFunc (fn)
|
|
|
14831 {
|
|
|
14832 return function() {
|
|
|
14833 var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
|
|
|
14834 Array.prototype.slice.call(arguments)
|
|
|
14835 );
|
|
|
14836 return DataTable.ext.internal[fn].apply( this, args );
|
|
|
14837 };
|
|
|
14838 }
|
|
|
14839
|
|
|
14840
|
|
|
14841 /**
|
|
|
14842 * Reference to internal functions for use by plug-in developers. Note that
|
|
|
14843 * these methods are references to internal functions and are considered to be
|
|
|
14844 * private. If you use these methods, be aware that they are liable to change
|
|
|
14845 * between versions.
|
|
|
14846 * @namespace
|
|
|
14847 */
|
|
|
14848 $.extend( DataTable.ext.internal, {
|
|
|
14849 _fnExternApiFunc: _fnExternApiFunc,
|
|
|
14850 _fnBuildAjax: _fnBuildAjax,
|
|
|
14851 _fnAjaxUpdate: _fnAjaxUpdate,
|
|
|
14852 _fnAjaxParameters: _fnAjaxParameters,
|
|
|
14853 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
|
|
|
14854 _fnAjaxDataSrc: _fnAjaxDataSrc,
|
|
|
14855 _fnAddColumn: _fnAddColumn,
|
|
|
14856 _fnColumnOptions: _fnColumnOptions,
|
|
|
14857 _fnAdjustColumnSizing: _fnAdjustColumnSizing,
|
|
|
14858 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
|
|
|
14859 _fnColumnIndexToVisible: _fnColumnIndexToVisible,
|
|
|
14860 _fnVisbleColumns: _fnVisbleColumns,
|
|
|
14861 _fnGetColumns: _fnGetColumns,
|
|
|
14862 _fnColumnTypes: _fnColumnTypes,
|
|
|
14863 _fnApplyColumnDefs: _fnApplyColumnDefs,
|
|
|
14864 _fnHungarianMap: _fnHungarianMap,
|
|
|
14865 _fnCamelToHungarian: _fnCamelToHungarian,
|
|
|
14866 _fnLanguageCompat: _fnLanguageCompat,
|
|
|
14867 _fnBrowserDetect: _fnBrowserDetect,
|
|
|
14868 _fnAddData: _fnAddData,
|
|
|
14869 _fnAddTr: _fnAddTr,
|
|
|
14870 _fnNodeToDataIndex: _fnNodeToDataIndex,
|
|
|
14871 _fnNodeToColumnIndex: _fnNodeToColumnIndex,
|
|
|
14872 _fnGetCellData: _fnGetCellData,
|
|
|
14873 _fnSetCellData: _fnSetCellData,
|
|
|
14874 _fnSplitObjNotation: _fnSplitObjNotation,
|
|
|
14875 _fnGetObjectDataFn: _fnGetObjectDataFn,
|
|
|
14876 _fnSetObjectDataFn: _fnSetObjectDataFn,
|
|
|
14877 _fnGetDataMaster: _fnGetDataMaster,
|
|
|
14878 _fnClearTable: _fnClearTable,
|
|
|
14879 _fnDeleteIndex: _fnDeleteIndex,
|
|
|
14880 _fnInvalidate: _fnInvalidate,
|
|
|
14881 _fnGetRowElements: _fnGetRowElements,
|
|
|
14882 _fnCreateTr: _fnCreateTr,
|
|
|
14883 _fnBuildHead: _fnBuildHead,
|
|
|
14884 _fnDrawHead: _fnDrawHead,
|
|
|
14885 _fnDraw: _fnDraw,
|
|
|
14886 _fnReDraw: _fnReDraw,
|
|
|
14887 _fnAddOptionsHtml: _fnAddOptionsHtml,
|
|
|
14888 _fnDetectHeader: _fnDetectHeader,
|
|
|
14889 _fnGetUniqueThs: _fnGetUniqueThs,
|
|
|
14890 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
|
|
|
14891 _fnFilterComplete: _fnFilterComplete,
|
|
|
14892 _fnFilterCustom: _fnFilterCustom,
|
|
|
14893 _fnFilterColumn: _fnFilterColumn,
|
|
|
14894 _fnFilter: _fnFilter,
|
|
|
14895 _fnFilterCreateSearch: _fnFilterCreateSearch,
|
|
|
14896 _fnEscapeRegex: _fnEscapeRegex,
|
|
|
14897 _fnFilterData: _fnFilterData,
|
|
|
14898 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
|
|
|
14899 _fnUpdateInfo: _fnUpdateInfo,
|
|
|
14900 _fnInfoMacros: _fnInfoMacros,
|
|
|
14901 _fnInitialise: _fnInitialise,
|
|
|
14902 _fnInitComplete: _fnInitComplete,
|
|
|
14903 _fnLengthChange: _fnLengthChange,
|
|
|
14904 _fnFeatureHtmlLength: _fnFeatureHtmlLength,
|
|
|
14905 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
|
|
|
14906 _fnPageChange: _fnPageChange,
|
|
|
14907 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
|
|
|
14908 _fnProcessingDisplay: _fnProcessingDisplay,
|
|
|
14909 _fnFeatureHtmlTable: _fnFeatureHtmlTable,
|
|
|
14910 _fnScrollDraw: _fnScrollDraw,
|
|
|
14911 _fnApplyToChildren: _fnApplyToChildren,
|
|
|
14912 _fnCalculateColumnWidths: _fnCalculateColumnWidths,
|
|
|
14913 _fnThrottle: _fnThrottle,
|
|
|
14914 _fnConvertToWidth: _fnConvertToWidth,
|
|
|
14915 _fnGetWidestNode: _fnGetWidestNode,
|
|
|
14916 _fnGetMaxLenString: _fnGetMaxLenString,
|
|
|
14917 _fnStringToCss: _fnStringToCss,
|
|
|
14918 _fnSortFlatten: _fnSortFlatten,
|
|
|
14919 _fnSort: _fnSort,
|
|
|
14920 _fnSortAria: _fnSortAria,
|
|
|
14921 _fnSortListener: _fnSortListener,
|
|
|
14922 _fnSortAttachListener: _fnSortAttachListener,
|
|
|
14923 _fnSortingClasses: _fnSortingClasses,
|
|
|
14924 _fnSortData: _fnSortData,
|
|
|
14925 _fnSaveState: _fnSaveState,
|
|
|
14926 _fnLoadState: _fnLoadState,
|
|
|
14927 _fnSettingsFromNode: _fnSettingsFromNode,
|
|
|
14928 _fnLog: _fnLog,
|
|
|
14929 _fnMap: _fnMap,
|
|
|
14930 _fnBindAction: _fnBindAction,
|
|
|
14931 _fnCallbackReg: _fnCallbackReg,
|
|
|
14932 _fnCallbackFire: _fnCallbackFire,
|
|
|
14933 _fnLengthOverflow: _fnLengthOverflow,
|
|
|
14934 _fnRenderer: _fnRenderer,
|
|
|
14935 _fnDataSource: _fnDataSource,
|
|
|
14936 _fnRowAttributes: _fnRowAttributes,
|
|
|
14937 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
|
|
|
14938 // in 1.10, so this dead-end function is
|
|
|
14939 // added to prevent errors
|
|
|
14940 } );
|
|
|
14941
|
|
|
14942
|
|
|
14943 // jQuery access
|
|
|
14944 $.fn.dataTable = DataTable;
|
|
|
14945
|
|
|
14946 // Legacy aliases
|
|
|
14947 $.fn.dataTableSettings = DataTable.settings;
|
|
|
14948 $.fn.dataTableExt = DataTable.ext;
|
|
|
14949
|
|
|
14950 // With a capital `D` we return a DataTables API instance rather than a
|
|
|
14951 // jQuery object
|
|
|
14952 $.fn.DataTable = function ( opts ) {
|
|
|
14953 return $(this).dataTable( opts ).api();
|
|
|
14954 };
|
|
|
14955
|
|
|
14956 // All properties that are available to $.fn.dataTable should also be
|
|
|
14957 // available on $.fn.DataTable
|
|
|
14958 $.each( DataTable, function ( prop, val ) {
|
|
|
14959 $.fn.DataTable[ prop ] = val;
|
|
|
14960 } );
|
|
|
14961
|
|
|
14962
|
|
|
14963 // Information about events fired by DataTables - for documentation.
|
|
|
14964 /**
|
|
|
14965 * Draw event, fired whenever the table is redrawn on the page, at the same
|
|
|
14966 * point as fnDrawCallback. This may be useful for binding events or
|
|
|
14967 * performing calculations when the table is altered at all.
|
|
|
14968 * @name DataTable#draw.dt
|
|
|
14969 * @event
|
|
|
14970 * @param {event} e jQuery event object
|
|
|
14971 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
14972 */
|
|
|
14973
|
|
|
14974 /**
|
|
|
14975 * Search event, fired when the searching applied to the table (using the
|
|
|
14976 * built-in global search, or column filters) is altered.
|
|
|
14977 * @name DataTable#search.dt
|
|
|
14978 * @event
|
|
|
14979 * @param {event} e jQuery event object
|
|
|
14980 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
14981 */
|
|
|
14982
|
|
|
14983 /**
|
|
|
14984 * Page change event, fired when the paging of the table is altered.
|
|
|
14985 * @name DataTable#page.dt
|
|
|
14986 * @event
|
|
|
14987 * @param {event} e jQuery event object
|
|
|
14988 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
14989 */
|
|
|
14990
|
|
|
14991 /**
|
|
|
14992 * Order event, fired when the ordering applied to the table is altered.
|
|
|
14993 * @name DataTable#order.dt
|
|
|
14994 * @event
|
|
|
14995 * @param {event} e jQuery event object
|
|
|
14996 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
14997 */
|
|
|
14998
|
|
|
14999 /**
|
|
|
15000 * DataTables initialisation complete event, fired when the table is fully
|
|
|
15001 * drawn, including Ajax data loaded, if Ajax data is required.
|
|
|
15002 * @name DataTable#init.dt
|
|
|
15003 * @event
|
|
|
15004 * @param {event} e jQuery event object
|
|
|
15005 * @param {object} oSettings DataTables settings object
|
|
|
15006 * @param {object} json The JSON object request from the server - only
|
|
|
15007 * present if client-side Ajax sourced data is used</li></ol>
|
|
|
15008 */
|
|
|
15009
|
|
|
15010 /**
|
|
|
15011 * State save event, fired when the table has changed state a new state save
|
|
|
15012 * is required. This event allows modification of the state saving object
|
|
|
15013 * prior to actually doing the save, including addition or other state
|
|
|
15014 * properties (for plug-ins) or modification of a DataTables core property.
|
|
|
15015 * @name DataTable#stateSaveParams.dt
|
|
|
15016 * @event
|
|
|
15017 * @param {event} e jQuery event object
|
|
|
15018 * @param {object} oSettings DataTables settings object
|
|
|
15019 * @param {object} json The state information to be saved
|
|
|
15020 */
|
|
|
15021
|
|
|
15022 /**
|
|
|
15023 * State load event, fired when the table is loading state from the stored
|
|
|
15024 * data, but prior to the settings object being modified by the saved state
|
|
|
15025 * - allowing modification of the saved state is required or loading of
|
|
|
15026 * state for a plug-in.
|
|
|
15027 * @name DataTable#stateLoadParams.dt
|
|
|
15028 * @event
|
|
|
15029 * @param {event} e jQuery event object
|
|
|
15030 * @param {object} oSettings DataTables settings object
|
|
|
15031 * @param {object} json The saved state information
|
|
|
15032 */
|
|
|
15033
|
|
|
15034 /**
|
|
|
15035 * State loaded event, fired when state has been loaded from stored data and
|
|
|
15036 * the settings object has been modified by the loaded data.
|
|
|
15037 * @name DataTable#stateLoaded.dt
|
|
|
15038 * @event
|
|
|
15039 * @param {event} e jQuery event object
|
|
|
15040 * @param {object} oSettings DataTables settings object
|
|
|
15041 * @param {object} json The saved state information
|
|
|
15042 */
|
|
|
15043
|
|
|
15044 /**
|
|
|
15045 * Processing event, fired when DataTables is doing some kind of processing
|
|
|
15046 * (be it, order, searcg or anything else). It can be used to indicate to
|
|
|
15047 * the end user that there is something happening, or that something has
|
|
|
15048 * finished.
|
|
|
15049 * @name DataTable#processing.dt
|
|
|
15050 * @event
|
|
|
15051 * @param {event} e jQuery event object
|
|
|
15052 * @param {object} oSettings DataTables settings object
|
|
|
15053 * @param {boolean} bShow Flag for if DataTables is doing processing or not
|
|
|
15054 */
|
|
|
15055
|
|
|
15056 /**
|
|
|
15057 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
|
|
|
15058 * request to made to the server for new data. This event is called before
|
|
|
15059 * DataTables processed the returned data, so it can also be used to pre-
|
|
|
15060 * process the data returned from the server, if needed.
|
|
|
15061 *
|
|
|
15062 * Note that this trigger is called in `fnServerData`, if you override
|
|
|
15063 * `fnServerData` and which to use this event, you need to trigger it in you
|
|
|
15064 * success function.
|
|
|
15065 * @name DataTable#xhr.dt
|
|
|
15066 * @event
|
|
|
15067 * @param {event} e jQuery event object
|
|
|
15068 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
15069 * @param {object} json JSON returned from the server
|
|
|
15070 *
|
|
|
15071 * @example
|
|
|
15072 * // Use a custom property returned from the server in another DOM element
|
|
|
15073 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
|
|
|
15074 * $('#status').html( json.status );
|
|
|
15075 * } );
|
|
|
15076 *
|
|
|
15077 * @example
|
|
|
15078 * // Pre-process the data returned from the server
|
|
|
15079 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
|
|
|
15080 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
|
|
|
15081 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
|
|
|
15082 * }
|
|
|
15083 * // Note no return - manipulate the data directly in the JSON object.
|
|
|
15084 * } );
|
|
|
15085 */
|
|
|
15086
|
|
|
15087 /**
|
|
|
15088 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
|
|
|
15089 * or passing the bDestroy:true parameter in the initialisation object. This
|
|
|
15090 * can be used to remove bound events, added DOM nodes, etc.
|
|
|
15091 * @name DataTable#destroy.dt
|
|
|
15092 * @event
|
|
|
15093 * @param {event} e jQuery event object
|
|
|
15094 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
15095 */
|
|
|
15096
|
|
|
15097 /**
|
|
|
15098 * Page length change event, fired when number of records to show on each
|
|
|
15099 * page (the length) is changed.
|
|
|
15100 * @name DataTable#length.dt
|
|
|
15101 * @event
|
|
|
15102 * @param {event} e jQuery event object
|
|
|
15103 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
15104 * @param {integer} len New length
|
|
|
15105 */
|
|
|
15106
|
|
|
15107 /**
|
|
|
15108 * Column sizing has changed.
|
|
|
15109 * @name DataTable#column-sizing.dt
|
|
|
15110 * @event
|
|
|
15111 * @param {event} e jQuery event object
|
|
|
15112 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
15113 */
|
|
|
15114
|
|
|
15115 /**
|
|
|
15116 * Column visibility has changed.
|
|
|
15117 * @name DataTable#column-visibility.dt
|
|
|
15118 * @event
|
|
|
15119 * @param {event} e jQuery event object
|
|
|
15120 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
|
15121 * @param {int} column Column index
|
|
|
15122 * @param {bool} vis `false` if column now hidden, or `true` if visible
|
|
|
15123 */
|
|
|
15124
|
|
|
15125 return $.fn.dataTable;
|
|
|
15126 }));
|
|
|
15127
|
|
|
15128 }(window, document));
|
|
|
15129
|