0
|
1 /*! DataTables 1.10.4
|
|
2 * ©2008-2014 SpryMedia Ltd - datatables.net/license
|
|
3 */
|
|
4
|
|
5 /**
|
|
6 * @summary DataTables
|
|
7 * @description Paginate, search and order HTML tables
|
|
8 * @version 1.10.4
|
|
9 * @file jquery.dataTables.js
|
|
10 * @author SpryMedia Ltd (www.sprymedia.co.uk)
|
|
11 * @contact www.sprymedia.co.uk/contact
|
|
12 * @copyright Copyright 2008-2014 SpryMedia Ltd.
|
|
13 *
|
|
14 * This source file is free software, available under the following license:
|
|
15 * MIT license - http://datatables.net/license
|
|
16 *
|
|
17 * This source file is distributed in the hope that it will be useful, but
|
|
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
|
|
20 *
|
|
21 * For details please refer to: http://www.datatables.net
|
|
22 */
|
|
23
|
|
24 /*jslint evil: true, undef: true, browser: true */
|
|
25 /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
|
|
26
|
|
27 (/** @lends <global> */function( window, document, undefined ) {
|
|
28
|
|
29 (function( factory ) {
|
|
30 "use strict";
|
|
31
|
|
32 if ( typeof define === 'function' && define.amd ) {
|
|
33 // Define as an AMD module if possible
|
|
34 define( 'datatables', ['jquery'], factory );
|
|
35 }
|
|
36 else if ( typeof exports === 'object' ) {
|
|
37 // Node/CommonJS
|
|
38 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 // U+2009 is thin space and U+202F is narrow no-break space, both used in many
|
|
115 // standards as thousands separators
|
|
116 var _re_formatted_numeric = /[',$£€¥%\u2009\u202F]/g;
|
|
117
|
|
118
|
|
119 var _empty = function ( d ) {
|
|
120 return !d || d === true || d === '-' ? true : false;
|
|
121 };
|
|
122
|
|
123
|
|
124 var _intVal = function ( s ) {
|
|
125 var integer = parseInt( s, 10 );
|
|
126 return !isNaN(integer) && isFinite(s) ? integer : null;
|
|
127 };
|
|
128
|
|
129 // Convert from a formatted number with characters other than `.` as the
|
|
130 // decimal place, to a Javascript number
|
|
131 var _numToDecimal = function ( num, decimalPoint ) {
|
|
132 // Cache created regular expressions for speed as this function is called often
|
|
133 if ( ! _re_dic[ decimalPoint ] ) {
|
|
134 _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
|
|
135 }
|
|
136 return typeof num === 'string' && decimalPoint !== '.' ?
|
|
137 num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
|
|
138 num;
|
|
139 };
|
|
140
|
|
141
|
|
142 var _isNumber = function ( d, decimalPoint, formatted ) {
|
|
143 var strType = typeof d === 'string';
|
|
144
|
|
145 if ( decimalPoint && strType ) {
|
|
146 d = _numToDecimal( d, decimalPoint );
|
|
147 }
|
|
148
|
|
149 if ( formatted && strType ) {
|
|
150 d = d.replace( _re_formatted_numeric, '' );
|
|
151 }
|
|
152
|
|
153 return _empty( d ) || (!isNaN( parseFloat(d) ) && isFinite( d ));
|
|
154 };
|
|
155
|
|
156
|
|
157 // A string without HTML in it can be considered to be HTML still
|
|
158 var _isHtml = function ( d ) {
|
|
159 return _empty( d ) || typeof d === 'string';
|
|
160 };
|
|
161
|
|
162
|
|
163 var _htmlNumeric = function ( d, decimalPoint, formatted ) {
|
|
164 if ( _empty( d ) ) {
|
|
165 return true;
|
|
166 }
|
|
167
|
|
168 var html = _isHtml( d );
|
|
169 return ! html ?
|
|
170 null :
|
|
171 _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
|
|
172 true :
|
|
173 null;
|
|
174 };
|
|
175
|
|
176
|
|
177 var _pluck = function ( a, prop, prop2 ) {
|
|
178 var out = [];
|
|
179 var i=0, ien=a.length;
|
|
180
|
|
181 // Could have the test in the loop for slightly smaller code, but speed
|
|
182 // is essential here
|
|
183 if ( prop2 !== undefined ) {
|
|
184 for ( ; i<ien ; i++ ) {
|
|
185 if ( a[i] && a[i][ prop ] ) {
|
|
186 out.push( a[i][ prop ][ prop2 ] );
|
|
187 }
|
|
188 }
|
|
189 }
|
|
190 else {
|
|
191 for ( ; i<ien ; i++ ) {
|
|
192 if ( a[i] ) {
|
|
193 out.push( a[i][ prop ] );
|
|
194 }
|
|
195 }
|
|
196 }
|
|
197
|
|
198 return out;
|
|
199 };
|
|
200
|
|
201
|
|
202 // Basically the same as _pluck, but rather than looping over `a` we use `order`
|
|
203 // as the indexes to pick from `a`
|
|
204 var _pluck_order = function ( a, order, prop, prop2 )
|
|
205 {
|
|
206 var out = [];
|
|
207 var i=0, ien=order.length;
|
|
208
|
|
209 // Could have the test in the loop for slightly smaller code, but speed
|
|
210 // is essential here
|
|
211 if ( prop2 !== undefined ) {
|
|
212 for ( ; i<ien ; i++ ) {
|
|
213 if ( a[ order[i] ][ prop ] ) {
|
|
214 out.push( a[ order[i] ][ prop ][ prop2 ] );
|
|
215 }
|
|
216 }
|
|
217 }
|
|
218 else {
|
|
219 for ( ; i<ien ; i++ ) {
|
|
220 out.push( a[ order[i] ][ prop ] );
|
|
221 }
|
|
222 }
|
|
223
|
|
224 return out;
|
|
225 };
|
|
226
|
|
227
|
|
228 var _range = function ( len, start )
|
|
229 {
|
|
230 var out = [];
|
|
231 var end;
|
|
232
|
|
233 if ( start === undefined ) {
|
|
234 start = 0;
|
|
235 end = len;
|
|
236 }
|
|
237 else {
|
|
238 end = start;
|
|
239 start = len;
|
|
240 }
|
|
241
|
|
242 for ( var i=start ; i<end ; i++ ) {
|
|
243 out.push( i );
|
|
244 }
|
|
245
|
|
246 return out;
|
|
247 };
|
|
248
|
|
249
|
|
250 var _removeEmpty = function ( a )
|
|
251 {
|
|
252 var out = [];
|
|
253
|
|
254 for ( var i=0, ien=a.length ; i<ien ; i++ ) {
|
|
255 if ( a[i] ) { // careful - will remove all falsy values!
|
|
256 out.push( a[i] );
|
|
257 }
|
|
258 }
|
|
259
|
|
260 return out;
|
|
261 };
|
|
262
|
|
263
|
|
264 var _stripHtml = function ( d ) {
|
|
265 return d.replace( _re_html, '' );
|
|
266 };
|
|
267
|
|
268
|
|
269 /**
|
|
270 * Find the unique elements in a source array.
|
|
271 *
|
|
272 * @param {array} src Source array
|
|
273 * @return {array} Array of unique items
|
|
274 * @ignore
|
|
275 */
|
|
276 var _unique = function ( src )
|
|
277 {
|
|
278 // A faster unique method is to use object keys to identify used values,
|
|
279 // but this doesn't work with arrays or objects, which we must also
|
|
280 // consider. See jsperf.com/compare-array-unique-versions/4 for more
|
|
281 // information.
|
|
282 var
|
|
283 out = [],
|
|
284 val,
|
|
285 i, ien=src.length,
|
|
286 j, k=0;
|
|
287
|
|
288 again: for ( i=0 ; i<ien ; i++ ) {
|
|
289 val = src[i];
|
|
290
|
|
291 for ( j=0 ; j<k ; j++ ) {
|
|
292 if ( out[j] === val ) {
|
|
293 continue again;
|
|
294 }
|
|
295 }
|
|
296
|
|
297 out.push( val );
|
|
298 k++;
|
|
299 }
|
|
300
|
|
301 return out;
|
|
302 };
|
|
303
|
|
304
|
|
305
|
|
306 /**
|
|
307 * Create a mapping object that allows camel case parameters to be looked up
|
|
308 * for their Hungarian counterparts. The mapping is stored in a private
|
|
309 * parameter called `_hungarianMap` which can be accessed on the source object.
|
|
310 * @param {object} o
|
|
311 * @memberof DataTable#oApi
|
|
312 */
|
|
313 function _fnHungarianMap ( o )
|
|
314 {
|
|
315 var
|
|
316 hungarian = 'a aa ai ao as b fn i m o s ',
|
|
317 match,
|
|
318 newKey,
|
|
319 map = {};
|
|
320
|
|
321 $.each( o, function (key, val) {
|
|
322 match = key.match(/^([^A-Z]+?)([A-Z])/);
|
|
323
|
|
324 if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
|
|
325 {
|
|
326 newKey = key.replace( match[0], match[2].toLowerCase() );
|
|
327 map[ newKey ] = key;
|
|
328
|
|
329 if ( match[1] === 'o' )
|
|
330 {
|
|
331 _fnHungarianMap( o[key] );
|
|
332 }
|
|
333 }
|
|
334 } );
|
|
335
|
|
336 o._hungarianMap = map;
|
|
337 }
|
|
338
|
|
339
|
|
340 /**
|
|
341 * Convert from camel case parameters to Hungarian, based on a Hungarian map
|
|
342 * created by _fnHungarianMap.
|
|
343 * @param {object} src The model object which holds all parameters that can be
|
|
344 * mapped.
|
|
345 * @param {object} user The object to convert from camel case to Hungarian.
|
|
346 * @param {boolean} force When set to `true`, properties which already have a
|
|
347 * Hungarian value in the `user` object will be overwritten. Otherwise they
|
|
348 * won't be.
|
|
349 * @memberof DataTable#oApi
|
|
350 */
|
|
351 function _fnCamelToHungarian ( src, user, force )
|
|
352 {
|
|
353 if ( ! src._hungarianMap ) {
|
|
354 _fnHungarianMap( src );
|
|
355 }
|
|
356
|
|
357 var hungarianKey;
|
|
358
|
|
359 $.each( user, function (key, val) {
|
|
360 hungarianKey = src._hungarianMap[ key ];
|
|
361
|
|
362 if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
|
|
363 {
|
|
364 // For objects, we need to buzz down into the object to copy parameters
|
|
365 if ( hungarianKey.charAt(0) === 'o' )
|
|
366 {
|
|
367 // Copy the camelCase options over to the hungarian
|
|
368 if ( ! user[ hungarianKey ] ) {
|
|
369 user[ hungarianKey ] = {};
|
|
370 }
|
|
371 $.extend( true, user[hungarianKey], user[key] );
|
|
372
|
|
373 _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
|
|
374 }
|
|
375 else {
|
|
376 user[hungarianKey] = user[ key ];
|
|
377 }
|
|
378 }
|
|
379 } );
|
|
380 }
|
|
381
|
|
382
|
|
383 /**
|
|
384 * Language compatibility - when certain options are given, and others aren't, we
|
|
385 * need to duplicate the values over, in order to provide backwards compatibility
|
|
386 * with older language files.
|
|
387 * @param {object} oSettings dataTables settings object
|
|
388 * @memberof DataTable#oApi
|
|
389 */
|
|
390 function _fnLanguageCompat( lang )
|
|
391 {
|
|
392 var defaults = DataTable.defaults.oLanguage;
|
|
393 var zeroRecords = lang.sZeroRecords;
|
|
394
|
|
395 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
|
|
396 * sZeroRecords - assuming that is given.
|
|
397 */
|
|
398 if ( ! lang.sEmptyTable && zeroRecords &&
|
|
399 defaults.sEmptyTable === "No data available in table" )
|
|
400 {
|
|
401 _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
|
|
402 }
|
|
403
|
|
404 /* Likewise with loading records */
|
|
405 if ( ! lang.sLoadingRecords && zeroRecords &&
|
|
406 defaults.sLoadingRecords === "Loading..." )
|
|
407 {
|
|
408 _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
|
|
409 }
|
|
410
|
|
411 // Old parameter name of the thousands separator mapped onto the new
|
|
412 if ( lang.sInfoThousands ) {
|
|
413 lang.sThousands = lang.sInfoThousands;
|
|
414 }
|
|
415
|
|
416 var decimal = lang.sDecimal;
|
|
417 if ( decimal ) {
|
|
418 _addNumericSort( decimal );
|
|
419 }
|
|
420 }
|
|
421
|
|
422
|
|
423 /**
|
|
424 * Map one parameter onto another
|
|
425 * @param {object} o Object to map
|
|
426 * @param {*} knew The new parameter name
|
|
427 * @param {*} old The old parameter name
|
|
428 */
|
|
429 var _fnCompatMap = function ( o, knew, old ) {
|
|
430 if ( o[ knew ] !== undefined ) {
|
|
431 o[ old ] = o[ knew ];
|
|
432 }
|
|
433 };
|
|
434
|
|
435
|
|
436 /**
|
|
437 * Provide backwards compatibility for the main DT options. Note that the new
|
|
438 * options are mapped onto the old parameters, so this is an external interface
|
|
439 * change only.
|
|
440 * @param {object} init Object to map
|
|
441 */
|
|
442 function _fnCompatOpts ( init )
|
|
443 {
|
|
444 _fnCompatMap( init, 'ordering', 'bSort' );
|
|
445 _fnCompatMap( init, 'orderMulti', 'bSortMulti' );
|
|
446 _fnCompatMap( init, 'orderClasses', 'bSortClasses' );
|
|
447 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
|
|
448 _fnCompatMap( init, 'order', 'aaSorting' );
|
|
449 _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' );
|
|
450 _fnCompatMap( init, 'paging', 'bPaginate' );
|
|
451 _fnCompatMap( init, 'pagingType', 'sPaginationType' );
|
|
452 _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
|
|
453 _fnCompatMap( init, 'searching', 'bFilter' );
|
|
454
|
|
455 // Column search objects are in an array, so it needs to be converted
|
|
456 // element by element
|
|
457 var searchCols = init.aoSearchCols;
|
|
458
|
|
459 if ( searchCols ) {
|
|
460 for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
|
|
461 if ( searchCols[i] ) {
|
|
462 _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
|
|
463 }
|
|
464 }
|
|
465 }
|
|
466 }
|
|
467
|
|
468
|
|
469 /**
|
|
470 * Provide backwards compatibility for column options. Note that the new options
|
|
471 * are mapped onto the old parameters, so this is an external interface change
|
|
472 * only.
|
|
473 * @param {object} init Object to map
|
|
474 */
|
|
475 function _fnCompatCols ( init )
|
|
476 {
|
|
477 _fnCompatMap( init, 'orderable', 'bSortable' );
|
|
478 _fnCompatMap( init, 'orderData', 'aDataSort' );
|
|
479 _fnCompatMap( init, 'orderSequence', 'asSorting' );
|
|
480 _fnCompatMap( init, 'orderDataType', 'sortDataType' );
|
|
481 }
|
|
482
|
|
483
|
|
484 /**
|
|
485 * Browser feature detection for capabilities, quirks
|
|
486 * @param {object} settings dataTables settings object
|
|
487 * @memberof DataTable#oApi
|
|
488 */
|
|
489 function _fnBrowserDetect( settings )
|
|
490 {
|
|
491 var browser = settings.oBrowser;
|
|
492
|
|
493 // Scrolling feature / quirks detection
|
|
494 var n = $('<div/>')
|
|
495 .css( {
|
|
496 position: 'absolute',
|
|
497 top: 0,
|
|
498 left: 0,
|
|
499 height: 1,
|
|
500 width: 1,
|
|
501 overflow: 'hidden'
|
|
502 } )
|
|
503 .append(
|
|
504 $('<div/>')
|
|
505 .css( {
|
|
506 position: 'absolute',
|
|
507 top: 1,
|
|
508 left: 1,
|
|
509 width: 100,
|
|
510 overflow: 'scroll'
|
|
511 } )
|
|
512 .append(
|
|
513 $('<div class="test"/>')
|
|
514 .css( {
|
|
515 width: '100%',
|
|
516 height: 10
|
|
517 } )
|
|
518 )
|
|
519 )
|
|
520 .appendTo( 'body' );
|
|
521
|
|
522 var test = n.find('.test');
|
|
523
|
|
524 // IE6/7 will oversize a width 100% element inside a scrolling element, to
|
|
525 // include the width of the scrollbar, while other browsers ensure the inner
|
|
526 // element is contained without forcing scrolling
|
|
527 browser.bScrollOversize = test[0].offsetWidth === 100;
|
|
528
|
|
529 // In rtl text layout, some browsers (most, but not all) will place the
|
|
530 // scrollbar on the left, rather than the right.
|
|
531 browser.bScrollbarLeft = test.offset().left !== 1;
|
|
532
|
|
533 n.remove();
|
|
534 }
|
|
535
|
|
536
|
|
537 /**
|
|
538 * Array.prototype reduce[Right] method, used for browsers which don't support
|
|
539 * JS 1.6. Done this way to reduce code size, since we iterate either way
|
|
540 * @param {object} settings dataTables settings object
|
|
541 * @memberof DataTable#oApi
|
|
542 */
|
|
543 function _fnReduce ( that, fn, init, start, end, inc )
|
|
544 {
|
|
545 var
|
|
546 i = start,
|
|
547 value,
|
|
548 isSet = false;
|
|
549
|
|
550 if ( init !== undefined ) {
|
|
551 value = init;
|
|
552 isSet = true;
|
|
553 }
|
|
554
|
|
555 while ( i !== end ) {
|
|
556 if ( ! that.hasOwnProperty(i) ) {
|
|
557 continue;
|
|
558 }
|
|
559
|
|
560 value = isSet ?
|
|
561 fn( value, that[i], i, that ) :
|
|
562 that[i];
|
|
563
|
|
564 isSet = true;
|
|
565 i += inc;
|
|
566 }
|
|
567
|
|
568 return value;
|
|
569 }
|
|
570
|
|
571 /**
|
|
572 * Add a column to the list used for the table with default values
|
|
573 * @param {object} oSettings dataTables settings object
|
|
574 * @param {node} nTh The th element for this column
|
|
575 * @memberof DataTable#oApi
|
|
576 */
|
|
577 function _fnAddColumn( oSettings, nTh )
|
|
578 {
|
|
579 // Add column to aoColumns array
|
|
580 var oDefaults = DataTable.defaults.column;
|
|
581 var iCol = oSettings.aoColumns.length;
|
|
582 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
|
|
583 "nTh": nTh ? nTh : document.createElement('th'),
|
|
584 "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
|
|
585 "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
|
|
586 "mData": oDefaults.mData ? oDefaults.mData : iCol,
|
|
587 idx: iCol
|
|
588 } );
|
|
589 oSettings.aoColumns.push( oCol );
|
|
590
|
|
591 // Add search object for column specific search. Note that the `searchCols[ iCol ]`
|
|
592 // passed into extend can be undefined. This allows the user to give a default
|
|
593 // with only some of the parameters defined, and also not give a default
|
|
594 var searchCols = oSettings.aoPreSearchCols;
|
|
595 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
|
|
596
|
|
597 // Use the default column options function to initialise classes etc
|
|
598 _fnColumnOptions( oSettings, iCol, null );
|
|
599 }
|
|
600
|
|
601
|
|
602 /**
|
|
603 * Apply options for a column
|
|
604 * @param {object} oSettings dataTables settings object
|
|
605 * @param {int} iCol column index to consider
|
|
606 * @param {object} oOptions object with sType, bVisible and bSearchable etc
|
|
607 * @memberof DataTable#oApi
|
|
608 */
|
|
609 function _fnColumnOptions( oSettings, iCol, oOptions )
|
|
610 {
|
|
611 var oCol = oSettings.aoColumns[ iCol ];
|
|
612 var oClasses = oSettings.oClasses;
|
|
613 var th = $(oCol.nTh);
|
|
614
|
|
615 // Try to get width information from the DOM. We can't get it from CSS
|
|
616 // as we'd need to parse the CSS stylesheet. `width` option can override
|
|
617 if ( ! oCol.sWidthOrig ) {
|
|
618 // Width attribute
|
|
619 oCol.sWidthOrig = th.attr('width') || null;
|
|
620
|
|
621 // Style attribute
|
|
622 var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
|
|
623 if ( t ) {
|
|
624 oCol.sWidthOrig = t[1];
|
|
625 }
|
|
626 }
|
|
627
|
|
628 /* User specified column options */
|
|
629 if ( oOptions !== undefined && oOptions !== null )
|
|
630 {
|
|
631 // Backwards compatibility
|
|
632 _fnCompatCols( oOptions );
|
|
633
|
|
634 // Map camel case parameters to their Hungarian counterparts
|
|
635 _fnCamelToHungarian( DataTable.defaults.column, oOptions );
|
|
636
|
|
637 /* Backwards compatibility for mDataProp */
|
|
638 if ( oOptions.mDataProp !== undefined && !oOptions.mData )
|
|
639 {
|
|
640 oOptions.mData = oOptions.mDataProp;
|
|
641 }
|
|
642
|
|
643 if ( oOptions.sType )
|
|
644 {
|
|
645 oCol._sManualType = oOptions.sType;
|
|
646 }
|
|
647
|
|
648 // `class` is a reserved word in Javascript, so we need to provide
|
|
649 // the ability to use a valid name for the camel case input
|
|
650 if ( oOptions.className && ! oOptions.sClass )
|
|
651 {
|
|
652 oOptions.sClass = oOptions.className;
|
|
653 }
|
|
654
|
|
655 $.extend( oCol, oOptions );
|
|
656 _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
|
|
657
|
|
658 /* iDataSort to be applied (backwards compatibility), but aDataSort will take
|
|
659 * priority if defined
|
|
660 */
|
|
661 if ( typeof oOptions.iDataSort === 'number' )
|
|
662 {
|
|
663 oCol.aDataSort = [ oOptions.iDataSort ];
|
|
664 }
|
|
665 _fnMap( oCol, oOptions, "aDataSort" );
|
|
666 }
|
|
667
|
|
668 /* Cache the data get and set functions for speed */
|
|
669 var mDataSrc = oCol.mData;
|
|
670 var mData = _fnGetObjectDataFn( mDataSrc );
|
|
671 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
|
|
672
|
|
673 var attrTest = function( src ) {
|
|
674 return typeof src === 'string' && src.indexOf('@') !== -1;
|
|
675 };
|
|
676 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
|
|
677 attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
|
|
678 );
|
|
679
|
|
680 oCol.fnGetData = function (rowData, type, meta) {
|
|
681 var innerData = mData( rowData, type, undefined, meta );
|
|
682
|
|
683 return mRender && type ?
|
|
684 mRender( innerData, type, rowData, meta ) :
|
|
685 innerData;
|
|
686 };
|
|
687 oCol.fnSetData = function ( rowData, val, meta ) {
|
|
688 return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
|
|
689 };
|
|
690
|
|
691 // Indicate if DataTables should read DOM data as an object or array
|
|
692 // Used in _fnGetRowElements
|
|
693 if ( typeof mDataSrc !== 'number' ) {
|
|
694 oSettings._rowReadObject = true;
|
|
695 }
|
|
696
|
|
697 /* Feature sorting overrides column specific when off */
|
|
698 if ( !oSettings.oFeatures.bSort )
|
|
699 {
|
|
700 oCol.bSortable = false;
|
|
701 th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
|
|
702 }
|
|
703
|
|
704 /* Check that the class assignment is correct for sorting */
|
|
705 var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
|
|
706 var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
|
|
707 if ( !oCol.bSortable || (!bAsc && !bDesc) )
|
|
708 {
|
|
709 oCol.sSortingClass = oClasses.sSortableNone;
|
|
710 oCol.sSortingClassJUI = "";
|
|
711 }
|
|
712 else if ( bAsc && !bDesc )
|
|
713 {
|
|
714 oCol.sSortingClass = oClasses.sSortableAsc;
|
|
715 oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
|
|
716 }
|
|
717 else if ( !bAsc && bDesc )
|
|
718 {
|
|
719 oCol.sSortingClass = oClasses.sSortableDesc;
|
|
720 oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
|
|
721 }
|
|
722 else
|
|
723 {
|
|
724 oCol.sSortingClass = oClasses.sSortable;
|
|
725 oCol.sSortingClassJUI = oClasses.sSortJUI;
|
|
726 }
|
|
727 }
|
|
728
|
|
729
|
|
730 /**
|
|
731 * Adjust the table column widths for new data. Note: you would probably want to
|
|
732 * do a redraw after calling this function!
|
|
733 * @param {object} settings dataTables settings object
|
|
734 * @memberof DataTable#oApi
|
|
735 */
|
|
736 function _fnAdjustColumnSizing ( settings )
|
|
737 {
|
|
738 /* Not interested in doing column width calculation if auto-width is disabled */
|
|
739 if ( settings.oFeatures.bAutoWidth !== false )
|
|
740 {
|
|
741 var columns = settings.aoColumns;
|
|
742
|
|
743 _fnCalculateColumnWidths( settings );
|
|
744 for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
|
|
745 {
|
|
746 columns[i].nTh.style.width = columns[i].sWidth;
|
|
747 }
|
|
748 }
|
|
749
|
|
750 var scroll = settings.oScroll;
|
|
751 if ( scroll.sY !== '' || scroll.sX !== '')
|
|
752 {
|
|
753 _fnScrollDraw( settings );
|
|
754 }
|
|
755
|
|
756 _fnCallbackFire( settings, null, 'column-sizing', [settings] );
|
|
757 }
|
|
758
|
|
759
|
|
760 /**
|
|
761 * Covert the index of a visible column to the index in the data array (take account
|
|
762 * of hidden columns)
|
|
763 * @param {object} oSettings dataTables settings object
|
|
764 * @param {int} iMatch Visible column index to lookup
|
|
765 * @returns {int} i the data index
|
|
766 * @memberof DataTable#oApi
|
|
767 */
|
|
768 function _fnVisibleToColumnIndex( oSettings, iMatch )
|
|
769 {
|
|
770 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
|
|
771
|
|
772 return typeof aiVis[iMatch] === 'number' ?
|
|
773 aiVis[iMatch] :
|
|
774 null;
|
|
775 }
|
|
776
|
|
777
|
|
778 /**
|
|
779 * Covert the index of an index in the data array and convert it to the visible
|
|
780 * column index (take account of hidden columns)
|
|
781 * @param {int} iMatch Column index to lookup
|
|
782 * @param {object} oSettings dataTables settings object
|
|
783 * @returns {int} i the data index
|
|
784 * @memberof DataTable#oApi
|
|
785 */
|
|
786 function _fnColumnIndexToVisible( oSettings, iMatch )
|
|
787 {
|
|
788 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
|
|
789 var iPos = $.inArray( iMatch, aiVis );
|
|
790
|
|
791 return iPos !== -1 ? iPos : null;
|
|
792 }
|
|
793
|
|
794
|
|
795 /**
|
|
796 * Get the number of visible columns
|
|
797 * @param {object} oSettings dataTables settings object
|
|
798 * @returns {int} i the number of visible columns
|
|
799 * @memberof DataTable#oApi
|
|
800 */
|
|
801 function _fnVisbleColumns( oSettings )
|
|
802 {
|
|
803 return _fnGetColumns( oSettings, 'bVisible' ).length;
|
|
804 }
|
|
805
|
|
806
|
|
807 /**
|
|
808 * Get an array of column indexes that match a given property
|
|
809 * @param {object} oSettings dataTables settings object
|
|
810 * @param {string} sParam Parameter in aoColumns to look for - typically
|
|
811 * bVisible or bSearchable
|
|
812 * @returns {array} Array of indexes with matched properties
|
|
813 * @memberof DataTable#oApi
|
|
814 */
|
|
815 function _fnGetColumns( oSettings, sParam )
|
|
816 {
|
|
817 var a = [];
|
|
818
|
|
819 $.map( oSettings.aoColumns, function(val, i) {
|
|
820 if ( val[sParam] ) {
|
|
821 a.push( i );
|
|
822 }
|
|
823 } );
|
|
824
|
|
825 return a;
|
|
826 }
|
|
827
|
|
828
|
|
829 /**
|
|
830 * Calculate the 'type' of a column
|
|
831 * @param {object} settings dataTables settings object
|
|
832 * @memberof DataTable#oApi
|
|
833 */
|
|
834 function _fnColumnTypes ( settings )
|
|
835 {
|
|
836 var columns = settings.aoColumns;
|
|
837 var data = settings.aoData;
|
|
838 var types = DataTable.ext.type.detect;
|
|
839 var i, ien, j, jen, k, ken;
|
|
840 var col, cell, detectedType, cache;
|
|
841
|
|
842 // For each column, spin over the
|
|
843 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
|
844 col = columns[i];
|
|
845 cache = [];
|
|
846
|
|
847 if ( ! col.sType && col._sManualType ) {
|
|
848 col.sType = col._sManualType;
|
|
849 }
|
|
850 else if ( ! col.sType ) {
|
|
851 for ( j=0, jen=types.length ; j<jen ; j++ ) {
|
|
852 for ( k=0, ken=data.length ; k<ken ; k++ ) {
|
|
853 // Use a cache array so we only need to get the type data
|
|
854 // from the formatter once (when using multiple detectors)
|
|
855 if ( cache[k] === undefined ) {
|
|
856 cache[k] = _fnGetCellData( settings, k, i, 'type' );
|
|
857 }
|
|
858
|
|
859 detectedType = types[j]( cache[k], settings );
|
|
860
|
|
861 // If null, then this type can't apply to this column, so
|
|
862 // rather than testing all cells, break out. There is an
|
|
863 // exception for the last type which is `html`. We need to
|
|
864 // scan all rows since it is possible to mix string and HTML
|
|
865 // types
|
|
866 if ( ! detectedType && j !== types.length-1 ) {
|
|
867 break;
|
|
868 }
|
|
869
|
|
870 // Only a single match is needed for html type since it is
|
|
871 // bottom of the pile and very similar to string
|
|
872 if ( detectedType === 'html' ) {
|
|
873 break;
|
|
874 }
|
|
875 }
|
|
876
|
|
877 // Type is valid for all data points in the column - use this
|
|
878 // type
|
|
879 if ( detectedType ) {
|
|
880 col.sType = detectedType;
|
|
881 break;
|
|
882 }
|
|
883 }
|
|
884
|
|
885 // Fall back - if no type was detected, always use string
|
|
886 if ( ! col.sType ) {
|
|
887 col.sType = 'string';
|
|
888 }
|
|
889 }
|
|
890 }
|
|
891 }
|
|
892
|
|
893
|
|
894 /**
|
|
895 * Take the column definitions and static columns arrays and calculate how
|
|
896 * they relate to column indexes. The callback function will then apply the
|
|
897 * definition found for a column to a suitable configuration object.
|
|
898 * @param {object} oSettings dataTables settings object
|
|
899 * @param {array} aoColDefs The aoColumnDefs array that is to be applied
|
|
900 * @param {array} aoCols The aoColumns array that defines columns individually
|
|
901 * @param {function} fn Callback function - takes two parameters, the calculated
|
|
902 * column index and the definition for that column.
|
|
903 * @memberof DataTable#oApi
|
|
904 */
|
|
905 function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
|
|
906 {
|
|
907 var i, iLen, j, jLen, k, kLen, def;
|
|
908 var columns = oSettings.aoColumns;
|
|
909
|
|
910 // Column definitions with aTargets
|
|
911 if ( aoColDefs )
|
|
912 {
|
|
913 /* Loop over the definitions array - loop in reverse so first instance has priority */
|
|
914 for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
|
|
915 {
|
|
916 def = aoColDefs[i];
|
|
917
|
|
918 /* Each definition can target multiple columns, as it is an array */
|
|
919 var aTargets = def.targets !== undefined ?
|
|
920 def.targets :
|
|
921 def.aTargets;
|
|
922
|
|
923 if ( ! $.isArray( aTargets ) )
|
|
924 {
|
|
925 aTargets = [ aTargets ];
|
|
926 }
|
|
927
|
|
928 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
|
|
929 {
|
|
930 if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
|
|
931 {
|
|
932 /* Add columns that we don't yet know about */
|
|
933 while( columns.length <= aTargets[j] )
|
|
934 {
|
|
935 _fnAddColumn( oSettings );
|
|
936 }
|
|
937
|
|
938 /* Integer, basic index */
|
|
939 fn( aTargets[j], def );
|
|
940 }
|
|
941 else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
|
|
942 {
|
|
943 /* Negative integer, right to left column counting */
|
|
944 fn( columns.length+aTargets[j], def );
|
|
945 }
|
|
946 else if ( typeof aTargets[j] === 'string' )
|
|
947 {
|
|
948 /* Class name matching on TH element */
|
|
949 for ( k=0, kLen=columns.length ; k<kLen ; k++ )
|
|
950 {
|
|
951 if ( aTargets[j] == "_all" ||
|
|
952 $(columns[k].nTh).hasClass( aTargets[j] ) )
|
|
953 {
|
|
954 fn( k, def );
|
|
955 }
|
|
956 }
|
|
957 }
|
|
958 }
|
|
959 }
|
|
960 }
|
|
961
|
|
962 // Statically defined columns array
|
|
963 if ( aoCols )
|
|
964 {
|
|
965 for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
|
|
966 {
|
|
967 fn( i, aoCols[i] );
|
|
968 }
|
|
969 }
|
|
970 }
|
|
971
|
|
972 /**
|
|
973 * Add a data array to the table, creating DOM node etc. This is the parallel to
|
|
974 * _fnGatherData, but for adding rows from a Javascript source, rather than a
|
|
975 * DOM source.
|
|
976 * @param {object} oSettings dataTables settings object
|
|
977 * @param {array} aData data array to be added
|
|
978 * @param {node} [nTr] TR element to add to the table - optional. If not given,
|
|
979 * DataTables will create a row automatically
|
|
980 * @param {array} [anTds] Array of TD|TH elements for the row - must be given
|
|
981 * if nTr is.
|
|
982 * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
|
|
983 * @memberof DataTable#oApi
|
|
984 */
|
|
985 function _fnAddData ( oSettings, aDataIn, nTr, anTds )
|
|
986 {
|
|
987 /* Create the object for storing information about this new row */
|
|
988 var iRow = oSettings.aoData.length;
|
|
989 var oData = $.extend( true, {}, DataTable.models.oRow, {
|
|
990 src: nTr ? 'dom' : 'data'
|
|
991 } );
|
|
992
|
|
993 oData._aData = aDataIn;
|
|
994 oSettings.aoData.push( oData );
|
|
995
|
|
996 /* Create the cells */
|
|
997 var nTd, sThisType;
|
|
998 var columns = oSettings.aoColumns;
|
|
999 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
|
|
1000 {
|
|
1001 // When working with a row, the data source object must be populated. In
|
|
1002 // all other cases, the data source object is already populated, so we
|
|
1003 // don't overwrite it, which might break bindings etc
|
|
1004 if ( nTr ) {
|
|
1005 _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
|
|
1006 }
|
|
1007 columns[i].sType = null;
|
|
1008 }
|
|
1009
|
|
1010 /* Add to the display array */
|
|
1011 oSettings.aiDisplayMaster.push( iRow );
|
|
1012
|
|
1013 /* Create the DOM information, or register it if already present */
|
|
1014 if ( nTr || ! oSettings.oFeatures.bDeferRender )
|
|
1015 {
|
|
1016 _fnCreateTr( oSettings, iRow, nTr, anTds );
|
|
1017 }
|
|
1018
|
|
1019 return iRow;
|
|
1020 }
|
|
1021
|
|
1022
|
|
1023 /**
|
|
1024 * Add one or more TR elements to the table. Generally we'd expect to
|
|
1025 * use this for reading data from a DOM sourced table, but it could be
|
|
1026 * used for an TR element. Note that if a TR is given, it is used (i.e.
|
|
1027 * it is not cloned).
|
|
1028 * @param {object} settings dataTables settings object
|
|
1029 * @param {array|node|jQuery} trs The TR element(s) to add to the table
|
|
1030 * @returns {array} Array of indexes for the added rows
|
|
1031 * @memberof DataTable#oApi
|
|
1032 */
|
|
1033 function _fnAddTr( settings, trs )
|
|
1034 {
|
|
1035 var row;
|
|
1036
|
|
1037 // Allow an individual node to be passed in
|
|
1038 if ( ! (trs instanceof $) ) {
|
|
1039 trs = $(trs);
|
|
1040 }
|
|
1041
|
|
1042 return trs.map( function (i, el) {
|
|
1043 row = _fnGetRowElements( settings, el );
|
|
1044 return _fnAddData( settings, row.data, el, row.cells );
|
|
1045 } );
|
|
1046 }
|
|
1047
|
|
1048
|
|
1049 /**
|
|
1050 * Take a TR element and convert it to an index in aoData
|
|
1051 * @param {object} oSettings dataTables settings object
|
|
1052 * @param {node} n the TR element to find
|
|
1053 * @returns {int} index if the node is found, null if not
|
|
1054 * @memberof DataTable#oApi
|
|
1055 */
|
|
1056 function _fnNodeToDataIndex( oSettings, n )
|
|
1057 {
|
|
1058 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
|
|
1059 }
|
|
1060
|
|
1061
|
|
1062 /**
|
|
1063 * Take a TD element and convert it into a column data index (not the visible index)
|
|
1064 * @param {object} oSettings dataTables settings object
|
|
1065 * @param {int} iRow The row number the TD/TH can be found in
|
|
1066 * @param {node} n The TD/TH element to find
|
|
1067 * @returns {int} index if the node is found, -1 if not
|
|
1068 * @memberof DataTable#oApi
|
|
1069 */
|
|
1070 function _fnNodeToColumnIndex( oSettings, iRow, n )
|
|
1071 {
|
|
1072 return $.inArray( n, oSettings.aoData[ iRow ].anCells );
|
|
1073 }
|
|
1074
|
|
1075
|
|
1076 /**
|
|
1077 * Get the data for a given cell from the internal cache, taking into account data mapping
|
|
1078 * @param {object} settings dataTables settings object
|
|
1079 * @param {int} rowIdx aoData row id
|
|
1080 * @param {int} colIdx Column index
|
|
1081 * @param {string} type data get type ('display', 'type' 'filter' 'sort')
|
|
1082 * @returns {*} Cell data
|
|
1083 * @memberof DataTable#oApi
|
|
1084 */
|
|
1085 function _fnGetCellData( settings, rowIdx, colIdx, type )
|
|
1086 {
|
|
1087 var draw = settings.iDraw;
|
|
1088 var col = settings.aoColumns[colIdx];
|
|
1089 var rowData = settings.aoData[rowIdx]._aData;
|
|
1090 var defaultContent = col.sDefaultContent;
|
|
1091 var cellData = col.fnGetData( rowData, type, {
|
|
1092 settings: settings,
|
|
1093 row: rowIdx,
|
|
1094 col: colIdx
|
|
1095 } );
|
|
1096
|
|
1097 if ( cellData === undefined ) {
|
|
1098 if ( settings.iDrawError != draw && defaultContent === null ) {
|
|
1099 _fnLog( settings, 0, "Requested unknown parameter "+
|
|
1100 (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
|
|
1101 " for row "+rowIdx, 4 );
|
|
1102 settings.iDrawError = draw;
|
|
1103 }
|
|
1104 return defaultContent;
|
|
1105 }
|
|
1106
|
|
1107 /* When the data source is null, we can use default column data */
|
|
1108 if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
|
|
1109 cellData = defaultContent;
|
|
1110 }
|
|
1111 else if ( typeof cellData === 'function' ) {
|
|
1112 // If the data source is a function, then we run it and use the return,
|
|
1113 // executing in the scope of the data object (for instances)
|
|
1114 return cellData.call( rowData );
|
|
1115 }
|
|
1116
|
|
1117 if ( cellData === null && type == 'display' ) {
|
|
1118 return '';
|
|
1119 }
|
|
1120 return cellData;
|
|
1121 }
|
|
1122
|
|
1123
|
|
1124 /**
|
|
1125 * Set the value for a specific cell, into the internal data cache
|
|
1126 * @param {object} settings dataTables settings object
|
|
1127 * @param {int} rowIdx aoData row id
|
|
1128 * @param {int} colIdx Column index
|
|
1129 * @param {*} val Value to set
|
|
1130 * @memberof DataTable#oApi
|
|
1131 */
|
|
1132 function _fnSetCellData( settings, rowIdx, colIdx, val )
|
|
1133 {
|
|
1134 var col = settings.aoColumns[colIdx];
|
|
1135 var rowData = settings.aoData[rowIdx]._aData;
|
|
1136
|
|
1137 col.fnSetData( rowData, val, {
|
|
1138 settings: settings,
|
|
1139 row: rowIdx,
|
|
1140 col: colIdx
|
|
1141 } );
|
|
1142 }
|
|
1143
|
|
1144
|
|
1145 // Private variable that is used to match action syntax in the data property object
|
|
1146 var __reArray = /\[.*?\]$/;
|
|
1147 var __reFn = /\(\)$/;
|
|
1148
|
|
1149 /**
|
|
1150 * Split string on periods, taking into account escaped periods
|
|
1151 * @param {string} str String to split
|
|
1152 * @return {array} Split string
|
|
1153 */
|
|
1154 function _fnSplitObjNotation( str )
|
|
1155 {
|
|
1156 return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
|
|
1157 return s.replace(/\\./g, '.');
|
|
1158 } );
|
|
1159 }
|
|
1160
|
|
1161
|
|
1162 /**
|
|
1163 * Return a function that can be used to get data from a source object, taking
|
|
1164 * into account the ability to use nested objects as a source
|
|
1165 * @param {string|int|function} mSource The data source for the object
|
|
1166 * @returns {function} Data get function
|
|
1167 * @memberof DataTable#oApi
|
|
1168 */
|
|
1169 function _fnGetObjectDataFn( mSource )
|
|
1170 {
|
|
1171 if ( $.isPlainObject( mSource ) )
|
|
1172 {
|
|
1173 /* Build an object of get functions, and wrap them in a single call */
|
|
1174 var o = {};
|
|
1175 $.each( mSource, function (key, val) {
|
|
1176 if ( val ) {
|
|
1177 o[key] = _fnGetObjectDataFn( val );
|
|
1178 }
|
|
1179 } );
|
|
1180
|
|
1181 return function (data, type, row, meta) {
|
|
1182 var t = o[type] || o._;
|
|
1183 return t !== undefined ?
|
|
1184 t(data, type, row, meta) :
|
|
1185 data;
|
|
1186 };
|
|
1187 }
|
|
1188 else if ( mSource === null )
|
|
1189 {
|
|
1190 /* Give an empty string for rendering / sorting etc */
|
|
1191 return function (data) { // type, row and meta also passed, but not used
|
|
1192 return data;
|
|
1193 };
|
|
1194 }
|
|
1195 else if ( typeof mSource === 'function' )
|
|
1196 {
|
|
1197 return function (data, type, row, meta) {
|
|
1198 return mSource( data, type, row, meta );
|
|
1199 };
|
|
1200 }
|
|
1201 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
|
|
1202 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
|
|
1203 {
|
|
1204 /* If there is a . in the source string then the data source is in a
|
|
1205 * nested object so we loop over the data for each level to get the next
|
|
1206 * level down. On each loop we test for undefined, and if found immediately
|
|
1207 * return. This allows entire objects to be missing and sDefaultContent to
|
|
1208 * be used if defined, rather than throwing an error
|
|
1209 */
|
|
1210 var fetchData = function (data, type, src) {
|
|
1211 var arrayNotation, funcNotation, out, innerSrc;
|
|
1212
|
|
1213 if ( src !== "" )
|
|
1214 {
|
|
1215 var a = _fnSplitObjNotation( src );
|
|
1216
|
|
1217 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
|
|
1218 {
|
|
1219 // Check if we are dealing with special notation
|
|
1220 arrayNotation = a[i].match(__reArray);
|
|
1221 funcNotation = a[i].match(__reFn);
|
|
1222
|
|
1223 if ( arrayNotation )
|
|
1224 {
|
|
1225 // Array notation
|
|
1226 a[i] = a[i].replace(__reArray, '');
|
|
1227
|
|
1228 // Condition allows simply [] to be passed in
|
|
1229 if ( a[i] !== "" ) {
|
|
1230 data = data[ a[i] ];
|
|
1231 }
|
|
1232 out = [];
|
|
1233
|
|
1234 // Get the remainder of the nested object to get
|
|
1235 a.splice( 0, i+1 );
|
|
1236 innerSrc = a.join('.');
|
|
1237
|
|
1238 // Traverse each entry in the array getting the properties requested
|
|
1239 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
|
|
1240 out.push( fetchData( data[j], type, innerSrc ) );
|
|
1241 }
|
|
1242
|
|
1243 // If a string is given in between the array notation indicators, that
|
|
1244 // is used to join the strings together, otherwise an array is returned
|
|
1245 var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
|
|
1246 data = (join==="") ? out : out.join(join);
|
|
1247
|
|
1248 // The inner call to fetchData has already traversed through the remainder
|
|
1249 // of the source requested, so we exit from the loop
|
|
1250 break;
|
|
1251 }
|
|
1252 else if ( funcNotation )
|
|
1253 {
|
|
1254 // Function call
|
|
1255 a[i] = a[i].replace(__reFn, '');
|
|
1256 data = data[ a[i] ]();
|
|
1257 continue;
|
|
1258 }
|
|
1259
|
|
1260 if ( data === null || data[ a[i] ] === undefined )
|
|
1261 {
|
|
1262 return undefined;
|
|
1263 }
|
|
1264 data = data[ a[i] ];
|
|
1265 }
|
|
1266 }
|
|
1267
|
|
1268 return data;
|
|
1269 };
|
|
1270
|
|
1271 return function (data, type) { // row and meta also passed, but not used
|
|
1272 return fetchData( data, type, mSource );
|
|
1273 };
|
|
1274 }
|
|
1275 else
|
|
1276 {
|
|
1277 /* Array or flat object mapping */
|
|
1278 return function (data, type) { // row and meta also passed, but not used
|
|
1279 return data[mSource];
|
|
1280 };
|
|
1281 }
|
|
1282 }
|
|
1283
|
|
1284
|
|
1285 /**
|
|
1286 * Return a function that can be used to set data from a source object, taking
|
|
1287 * into account the ability to use nested objects as a source
|
|
1288 * @param {string|int|function} mSource The data source for the object
|
|
1289 * @returns {function} Data set function
|
|
1290 * @memberof DataTable#oApi
|
|
1291 */
|
|
1292 function _fnSetObjectDataFn( mSource )
|
|
1293 {
|
|
1294 if ( $.isPlainObject( mSource ) )
|
|
1295 {
|
|
1296 /* Unlike get, only the underscore (global) option is used for for
|
|
1297 * setting data since we don't know the type here. This is why an object
|
|
1298 * option is not documented for `mData` (which is read/write), but it is
|
|
1299 * for `mRender` which is read only.
|
|
1300 */
|
|
1301 return _fnSetObjectDataFn( mSource._ );
|
|
1302 }
|
|
1303 else if ( mSource === null )
|
|
1304 {
|
|
1305 /* Nothing to do when the data source is null */
|
|
1306 return function () {};
|
|
1307 }
|
|
1308 else if ( typeof mSource === 'function' )
|
|
1309 {
|
|
1310 return function (data, val, meta) {
|
|
1311 mSource( data, 'set', val, meta );
|
|
1312 };
|
|
1313 }
|
|
1314 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
|
|
1315 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
|
|
1316 {
|
|
1317 /* Like the get, we need to get data from a nested object */
|
|
1318 var setData = function (data, val, src) {
|
|
1319 var a = _fnSplitObjNotation( src ), b;
|
|
1320 var aLast = a[a.length-1];
|
|
1321 var arrayNotation, funcNotation, o, innerSrc;
|
|
1322
|
|
1323 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
|
|
1324 {
|
|
1325 // Check if we are dealing with an array notation request
|
|
1326 arrayNotation = a[i].match(__reArray);
|
|
1327 funcNotation = a[i].match(__reFn);
|
|
1328
|
|
1329 if ( arrayNotation )
|
|
1330 {
|
|
1331 a[i] = a[i].replace(__reArray, '');
|
|
1332 data[ a[i] ] = [];
|
|
1333
|
|
1334 // Get the remainder of the nested object to set so we can recurse
|
|
1335 b = a.slice();
|
|
1336 b.splice( 0, i+1 );
|
|
1337 innerSrc = b.join('.');
|
|
1338
|
|
1339 // Traverse each entry in the array setting the properties requested
|
|
1340 for ( var j=0, jLen=val.length ; j<jLen ; j++ )
|
|
1341 {
|
|
1342 o = {};
|
|
1343 setData( o, val[j], innerSrc );
|
|
1344 data[ a[i] ].push( o );
|
|
1345 }
|
|
1346
|
|
1347 // The inner call to setData has already traversed through the remainder
|
|
1348 // of the source and has set the data, thus we can exit here
|
|
1349 return;
|
|
1350 }
|
|
1351 else if ( funcNotation )
|
|
1352 {
|
|
1353 // Function call
|
|
1354 a[i] = a[i].replace(__reFn, '');
|
|
1355 data = data[ a[i] ]( val );
|
|
1356 }
|
|
1357
|
|
1358 // If the nested object doesn't currently exist - since we are
|
|
1359 // trying to set the value - create it
|
|
1360 if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
|
|
1361 {
|
|
1362 data[ a[i] ] = {};
|
|
1363 }
|
|
1364 data = data[ a[i] ];
|
|
1365 }
|
|
1366
|
|
1367 // Last item in the input - i.e, the actual set
|
|
1368 if ( aLast.match(__reFn ) )
|
|
1369 {
|
|
1370 // Function call
|
|
1371 data = data[ aLast.replace(__reFn, '') ]( val );
|
|
1372 }
|
|
1373 else
|
|
1374 {
|
|
1375 // If array notation is used, we just want to strip it and use the property name
|
|
1376 // and assign the value. If it isn't used, then we get the result we want anyway
|
|
1377 data[ aLast.replace(__reArray, '') ] = val;
|
|
1378 }
|
|
1379 };
|
|
1380
|
|
1381 return function (data, val) { // meta is also passed in, but not used
|
|
1382 return setData( data, val, mSource );
|
|
1383 };
|
|
1384 }
|
|
1385 else
|
|
1386 {
|
|
1387 /* Array or flat object mapping */
|
|
1388 return function (data, val) { // meta is also passed in, but not used
|
|
1389 data[mSource] = val;
|
|
1390 };
|
|
1391 }
|
|
1392 }
|
|
1393
|
|
1394
|
|
1395 /**
|
|
1396 * Return an array with the full table data
|
|
1397 * @param {object} oSettings dataTables settings object
|
|
1398 * @returns array {array} aData Master data array
|
|
1399 * @memberof DataTable#oApi
|
|
1400 */
|
|
1401 function _fnGetDataMaster ( settings )
|
|
1402 {
|
|
1403 return _pluck( settings.aoData, '_aData' );
|
|
1404 }
|
|
1405
|
|
1406
|
|
1407 /**
|
|
1408 * Nuke the table
|
|
1409 * @param {object} oSettings dataTables settings object
|
|
1410 * @memberof DataTable#oApi
|
|
1411 */
|
|
1412 function _fnClearTable( settings )
|
|
1413 {
|
|
1414 settings.aoData.length = 0;
|
|
1415 settings.aiDisplayMaster.length = 0;
|
|
1416 settings.aiDisplay.length = 0;
|
|
1417 }
|
|
1418
|
|
1419
|
|
1420 /**
|
|
1421 * Take an array of integers (index array) and remove a target integer (value - not
|
|
1422 * the key!)
|
|
1423 * @param {array} a Index array to target
|
|
1424 * @param {int} iTarget value to find
|
|
1425 * @memberof DataTable#oApi
|
|
1426 */
|
|
1427 function _fnDeleteIndex( a, iTarget, splice )
|
|
1428 {
|
|
1429 var iTargetIndex = -1;
|
|
1430
|
|
1431 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
|
|
1432 {
|
|
1433 if ( a[i] == iTarget )
|
|
1434 {
|
|
1435 iTargetIndex = i;
|
|
1436 }
|
|
1437 else if ( a[i] > iTarget )
|
|
1438 {
|
|
1439 a[i]--;
|
|
1440 }
|
|
1441 }
|
|
1442
|
|
1443 if ( iTargetIndex != -1 && splice === undefined )
|
|
1444 {
|
|
1445 a.splice( iTargetIndex, 1 );
|
|
1446 }
|
|
1447 }
|
|
1448
|
|
1449
|
|
1450 /**
|
|
1451 * Mark cached data as invalid such that a re-read of the data will occur when
|
|
1452 * the cached data is next requested. Also update from the data source object.
|
|
1453 *
|
|
1454 * @param {object} settings DataTables settings object
|
|
1455 * @param {int} rowIdx Row index to invalidate
|
|
1456 * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
|
|
1457 * or 'data'
|
|
1458 * @param {int} [colIdx] Column index to invalidate. If undefined the whole
|
|
1459 * row will be invalidated
|
|
1460 * @memberof DataTable#oApi
|
|
1461 *
|
|
1462 * @todo For the modularisation of v1.11 this will need to become a callback, so
|
|
1463 * the sort and filter methods can subscribe to it. That will required
|
|
1464 * initialisation options for sorting, which is why it is not already baked in
|
|
1465 */
|
|
1466 function _fnInvalidate( settings, rowIdx, src, colIdx )
|
|
1467 {
|
|
1468 var row = settings.aoData[ rowIdx ];
|
|
1469 var i, ien;
|
|
1470 var cellWrite = function ( cell, col ) {
|
|
1471 // This is very frustrating, but in IE if you just write directly
|
|
1472 // to innerHTML, and elements that are overwritten are GC'ed,
|
|
1473 // even if there is a reference to them elsewhere
|
|
1474 while ( cell.childNodes.length ) {
|
|
1475 cell.removeChild( cell.firstChild );
|
|
1476 }
|
|
1477
|
|
1478 cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
|
|
1479 };
|
|
1480
|
|
1481 // Are we reading last data from DOM or the data object?
|
|
1482 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
|
|
1483 // Read the data from the DOM
|
|
1484 row._aData = _fnGetRowElements(
|
|
1485 settings, row, colIdx, colIdx === undefined ? undefined : row._aData
|
|
1486 )
|
|
1487 .data;
|
|
1488 }
|
|
1489 else {
|
|
1490 // Reading from data object, update the DOM
|
|
1491 var cells = row.anCells;
|
|
1492
|
|
1493 if ( cells ) {
|
|
1494 if ( colIdx !== undefined ) {
|
|
1495 cellWrite( cells[colIdx], colIdx );
|
|
1496 }
|
|
1497 else {
|
|
1498 for ( i=0, ien=cells.length ; i<ien ; i++ ) {
|
|
1499 cellWrite( cells[i], i );
|
|
1500 }
|
|
1501 }
|
|
1502 }
|
|
1503 }
|
|
1504
|
|
1505 // For both row and cell invalidation, the cached data for sorting and
|
|
1506 // filtering is nulled out
|
|
1507 row._aSortData = null;
|
|
1508 row._aFilterData = null;
|
|
1509
|
|
1510 // Invalidate the type for a specific column (if given) or all columns since
|
|
1511 // the data might have changed
|
|
1512 var cols = settings.aoColumns;
|
|
1513 if ( colIdx !== undefined ) {
|
|
1514 cols[ colIdx ].sType = null;
|
|
1515 }
|
|
1516 else {
|
|
1517 for ( i=0, ien=cols.length ; i<ien ; i++ ) {
|
|
1518 cols[i].sType = null;
|
|
1519 }
|
|
1520
|
|
1521 // Update DataTables special `DT_*` attributes for the row
|
|
1522 _fnRowAttributes( row );
|
|
1523 }
|
|
1524 }
|
|
1525
|
|
1526
|
|
1527 /**
|
|
1528 * Build a data source object from an HTML row, reading the contents of the
|
|
1529 * cells that are in the row.
|
|
1530 *
|
|
1531 * @param {object} settings DataTables settings object
|
|
1532 * @param {node|object} TR element from which to read data or existing row
|
|
1533 * object from which to re-read the data from the cells
|
|
1534 * @param {int} [colIdx] Optional column index
|
|
1535 * @param {array|object} [d] Data source object. If `colIdx` is given then this
|
|
1536 * parameter should also be given and will be used to write the data into.
|
|
1537 * Only the column in question will be written
|
|
1538 * @returns {object} Object with two parameters: `data` the data read, in
|
|
1539 * document order, and `cells` and array of nodes (they can be useful to the
|
|
1540 * caller, so rather than needing a second traversal to get them, just return
|
|
1541 * them from here).
|
|
1542 * @memberof DataTable#oApi
|
|
1543 */
|
|
1544 function _fnGetRowElements( settings, row, colIdx, d )
|
|
1545 {
|
|
1546 var
|
|
1547 tds = [],
|
|
1548 td = row.firstChild,
|
|
1549 name, col, o, i=0, contents,
|
|
1550 columns = settings.aoColumns,
|
|
1551 objectRead = settings._rowReadObject;
|
|
1552
|
|
1553 // Allow the data object to be passed in, or construct
|
|
1554 d = d || objectRead ? {} : [];
|
|
1555
|
|
1556 var attr = function ( str, td ) {
|
|
1557 if ( typeof str === 'string' ) {
|
|
1558 var idx = str.indexOf('@');
|
|
1559
|
|
1560 if ( idx !== -1 ) {
|
|
1561 var attr = str.substring( idx+1 );
|
|
1562 var setter = _fnSetObjectDataFn( str );
|
|
1563 setter( d, td.getAttribute( attr ) );
|
|
1564 }
|
|
1565 }
|
|
1566 };
|
|
1567
|
|
1568 // Read data from a cell and store into the data object
|
|
1569 var cellProcess = function ( cell ) {
|
|
1570 if ( colIdx === undefined || colIdx === i ) {
|
|
1571 col = columns[i];
|
|
1572 contents = $.trim(cell.innerHTML);
|
|
1573
|
|
1574 if ( col && col._bAttrSrc ) {
|
|
1575 var setter = _fnSetObjectDataFn( col.mData._ );
|
|
1576 setter( d, contents );
|
|
1577
|
|
1578 attr( col.mData.sort, cell );
|
|
1579 attr( col.mData.type, cell );
|
|
1580 attr( col.mData.filter, cell );
|
|
1581 }
|
|
1582 else {
|
|
1583 // Depending on the `data` option for the columns the data can
|
|
1584 // be read to either an object or an array.
|
|
1585 if ( objectRead ) {
|
|
1586 if ( ! col._setter ) {
|
|
1587 // Cache the setter function
|
|
1588 col._setter = _fnSetObjectDataFn( col.mData );
|
|
1589 }
|
|
1590 col._setter( d, contents );
|
|
1591 }
|
|
1592 else {
|
|
1593 d[i] = contents;
|
|
1594 }
|
|
1595 }
|
|
1596 }
|
|
1597
|
|
1598 i++;
|
|
1599 };
|
|
1600
|
|
1601 if ( td ) {
|
|
1602 // `tr` element was passed in
|
|
1603 while ( td ) {
|
|
1604 name = td.nodeName.toUpperCase();
|
|
1605
|
|
1606 if ( name == "TD" || name == "TH" ) {
|
|
1607 cellProcess( td );
|
|
1608 tds.push( td );
|
|
1609 }
|
|
1610
|
|
1611 td = td.nextSibling;
|
|
1612 }
|
|
1613 }
|
|
1614 else {
|
|
1615 // Existing row object passed in
|
|
1616 tds = row.anCells;
|
|
1617
|
|
1618 for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
|
|
1619 cellProcess( tds[j] );
|
|
1620 }
|
|
1621 }
|
|
1622
|
|
1623 return {
|
|
1624 data: d,
|
|
1625 cells: tds
|
|
1626 };
|
|
1627 }
|
|
1628 /**
|
|
1629 * Create a new TR element (and it's TD children) for a row
|
|
1630 * @param {object} oSettings dataTables settings object
|
|
1631 * @param {int} iRow Row to consider
|
|
1632 * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
|
|
1633 * DataTables will create a row automatically
|
|
1634 * @param {array} [anTds] Array of TD|TH elements for the row - must be given
|
|
1635 * if nTr is.
|
|
1636 * @memberof DataTable#oApi
|
|
1637 */
|
|
1638 function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
|
|
1639 {
|
|
1640 var
|
|
1641 row = oSettings.aoData[iRow],
|
|
1642 rowData = row._aData,
|
|
1643 cells = [],
|
|
1644 nTr, nTd, oCol,
|
|
1645 i, iLen;
|
|
1646
|
|
1647 if ( row.nTr === null )
|
|
1648 {
|
|
1649 nTr = nTrIn || document.createElement('tr');
|
|
1650
|
|
1651 row.nTr = nTr;
|
|
1652 row.anCells = cells;
|
|
1653
|
|
1654 /* Use a private property on the node to allow reserve mapping from the node
|
|
1655 * to the aoData array for fast look up
|
|
1656 */
|
|
1657 nTr._DT_RowIndex = iRow;
|
|
1658
|
|
1659 /* Special parameters can be given by the data source to be used on the row */
|
|
1660 _fnRowAttributes( row );
|
|
1661
|
|
1662 /* Process each column */
|
|
1663 for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
|
|
1664 {
|
|
1665 oCol = oSettings.aoColumns[i];
|
|
1666
|
|
1667 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
|
|
1668 cells.push( nTd );
|
|
1669
|
|
1670 // Need to create the HTML if new, or if a rendering function is defined
|
|
1671 if ( !nTrIn || oCol.mRender || oCol.mData !== i )
|
|
1672 {
|
|
1673 nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
|
|
1674 }
|
|
1675
|
|
1676 /* Add user defined class */
|
|
1677 if ( oCol.sClass )
|
|
1678 {
|
|
1679 nTd.className += ' '+oCol.sClass;
|
|
1680 }
|
|
1681
|
|
1682 // Visibility - add or remove as required
|
|
1683 if ( oCol.bVisible && ! nTrIn )
|
|
1684 {
|
|
1685 nTr.appendChild( nTd );
|
|
1686 }
|
|
1687 else if ( ! oCol.bVisible && nTrIn )
|
|
1688 {
|
|
1689 nTd.parentNode.removeChild( nTd );
|
|
1690 }
|
|
1691
|
|
1692 if ( oCol.fnCreatedCell )
|
|
1693 {
|
|
1694 oCol.fnCreatedCell.call( oSettings.oInstance,
|
|
1695 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
|
|
1696 );
|
|
1697 }
|
|
1698 }
|
|
1699
|
|
1700 _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
|
|
1701 }
|
|
1702
|
|
1703 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
|
|
1704 // and deployed
|
|
1705 row.nTr.setAttribute( 'role', 'row' );
|
|
1706 }
|
|
1707
|
|
1708
|
|
1709 /**
|
|
1710 * Add attributes to a row based on the special `DT_*` parameters in a data
|
|
1711 * source object.
|
|
1712 * @param {object} DataTables row object for the row to be modified
|
|
1713 * @memberof DataTable#oApi
|
|
1714 */
|
|
1715 function _fnRowAttributes( row )
|
|
1716 {
|
|
1717 var tr = row.nTr;
|
|
1718 var data = row._aData;
|
|
1719
|
|
1720 if ( tr ) {
|
|
1721 if ( data.DT_RowId ) {
|
|
1722 tr.id = data.DT_RowId;
|
|
1723 }
|
|
1724
|
|
1725 if ( data.DT_RowClass ) {
|
|
1726 // Remove any classes added by DT_RowClass before
|
|
1727 var a = data.DT_RowClass.split(' ');
|
|
1728 row.__rowc = row.__rowc ?
|
|
1729 _unique( row.__rowc.concat( a ) ) :
|
|
1730 a;
|
|
1731
|
|
1732 $(tr)
|
|
1733 .removeClass( row.__rowc.join(' ') )
|
|
1734 .addClass( data.DT_RowClass );
|
|
1735 }
|
|
1736
|
|
1737 if ( data.DT_RowData ) {
|
|
1738 $(tr).data( data.DT_RowData );
|
|
1739 }
|
|
1740 }
|
|
1741 }
|
|
1742
|
|
1743
|
|
1744 /**
|
|
1745 * Create the HTML header for the table
|
|
1746 * @param {object} oSettings dataTables settings object
|
|
1747 * @memberof DataTable#oApi
|
|
1748 */
|
|
1749 function _fnBuildHead( oSettings )
|
|
1750 {
|
|
1751 var i, ien, cell, row, column;
|
|
1752 var thead = oSettings.nTHead;
|
|
1753 var tfoot = oSettings.nTFoot;
|
|
1754 var createHeader = $('th, td', thead).length === 0;
|
|
1755 var classes = oSettings.oClasses;
|
|
1756 var columns = oSettings.aoColumns;
|
|
1757
|
|
1758 if ( createHeader ) {
|
|
1759 row = $('<tr/>').appendTo( thead );
|
|
1760 }
|
|
1761
|
|
1762 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
|
1763 column = columns[i];
|
|
1764 cell = $( column.nTh ).addClass( column.sClass );
|
|
1765
|
|
1766 if ( createHeader ) {
|
|
1767 cell.appendTo( row );
|
|
1768 }
|
|
1769
|
|
1770 // 1.11 move into sorting
|
|
1771 if ( oSettings.oFeatures.bSort ) {
|
|
1772 cell.addClass( column.sSortingClass );
|
|
1773
|
|
1774 if ( column.bSortable !== false ) {
|
|
1775 cell
|
|
1776 .attr( 'tabindex', oSettings.iTabIndex )
|
|
1777 .attr( 'aria-controls', oSettings.sTableId );
|
|
1778
|
|
1779 _fnSortAttachListener( oSettings, column.nTh, i );
|
|
1780 }
|
|
1781 }
|
|
1782
|
|
1783 if ( column.sTitle != cell.html() ) {
|
|
1784 cell.html( column.sTitle );
|
|
1785 }
|
|
1786
|
|
1787 _fnRenderer( oSettings, 'header' )(
|
|
1788 oSettings, cell, column, classes
|
|
1789 );
|
|
1790 }
|
|
1791
|
|
1792 if ( createHeader ) {
|
|
1793 _fnDetectHeader( oSettings.aoHeader, thead );
|
|
1794 }
|
|
1795
|
|
1796 /* ARIA role for the rows */
|
|
1797 $(thead).find('>tr').attr('role', 'row');
|
|
1798
|
|
1799 /* Deal with the footer - add classes if required */
|
|
1800 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
|
|
1801 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
|
|
1802
|
|
1803 // Cache the footer cells. Note that we only take the cells from the first
|
|
1804 // row in the footer. If there is more than one row the user wants to
|
|
1805 // interact with, they need to use the table().foot() method. Note also this
|
|
1806 // allows cells to be used for multiple columns using colspan
|
|
1807 if ( tfoot !== null ) {
|
|
1808 var cells = oSettings.aoFooter[0];
|
|
1809
|
|
1810 for ( i=0, ien=cells.length ; i<ien ; i++ ) {
|
|
1811 column = columns[i];
|
|
1812 column.nTf = cells[i].cell;
|
|
1813
|
|
1814 if ( column.sClass ) {
|
|
1815 $(column.nTf).addClass( column.sClass );
|
|
1816 }
|
|
1817 }
|
|
1818 }
|
|
1819 }
|
|
1820
|
|
1821
|
|
1822 /**
|
|
1823 * Draw the header (or footer) element based on the column visibility states. The
|
|
1824 * methodology here is to use the layout array from _fnDetectHeader, modified for
|
|
1825 * the instantaneous column visibility, to construct the new layout. The grid is
|
|
1826 * traversed over cell at a time in a rows x columns grid fashion, although each
|
|
1827 * cell insert can cover multiple elements in the grid - which is tracks using the
|
|
1828 * aApplied array. Cell inserts in the grid will only occur where there isn't
|
|
1829 * already a cell in that position.
|
|
1830 * @param {object} oSettings dataTables settings object
|
|
1831 * @param array {objects} aoSource Layout array from _fnDetectHeader
|
|
1832 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
|
|
1833 * @memberof DataTable#oApi
|
|
1834 */
|
|
1835 function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
|
|
1836 {
|
|
1837 var i, iLen, j, jLen, k, kLen, n, nLocalTr;
|
|
1838 var aoLocal = [];
|
|
1839 var aApplied = [];
|
|
1840 var iColumns = oSettings.aoColumns.length;
|
|
1841 var iRowspan, iColspan;
|
|
1842
|
|
1843 if ( ! aoSource )
|
|
1844 {
|
|
1845 return;
|
|
1846 }
|
|
1847
|
|
1848 if ( bIncludeHidden === undefined )
|
|
1849 {
|
|
1850 bIncludeHidden = false;
|
|
1851 }
|
|
1852
|
|
1853 /* Make a copy of the master layout array, but without the visible columns in it */
|
|
1854 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
|
|
1855 {
|
|
1856 aoLocal[i] = aoSource[i].slice();
|
|
1857 aoLocal[i].nTr = aoSource[i].nTr;
|
|
1858
|
|
1859 /* Remove any columns which are currently hidden */
|
|
1860 for ( j=iColumns-1 ; j>=0 ; j-- )
|
|
1861 {
|
|
1862 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
|
|
1863 {
|
|
1864 aoLocal[i].splice( j, 1 );
|
|
1865 }
|
|
1866 }
|
|
1867
|
|
1868 /* Prep the applied array - it needs an element for each row */
|
|
1869 aApplied.push( [] );
|
|
1870 }
|
|
1871
|
|
1872 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
|
|
1873 {
|
|
1874 nLocalTr = aoLocal[i].nTr;
|
|
1875
|
|
1876 /* All cells are going to be replaced, so empty out the row */
|
|
1877 if ( nLocalTr )
|
|
1878 {
|
|
1879 while( (n = nLocalTr.firstChild) )
|
|
1880 {
|
|
1881 nLocalTr.removeChild( n );
|
|
1882 }
|
|
1883 }
|
|
1884
|
|
1885 for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
|
|
1886 {
|
|
1887 iRowspan = 1;
|
|
1888 iColspan = 1;
|
|
1889
|
|
1890 /* Check to see if there is already a cell (row/colspan) covering our target
|
|
1891 * insert point. If there is, then there is nothing to do.
|
|
1892 */
|
|
1893 if ( aApplied[i][j] === undefined )
|
|
1894 {
|
|
1895 nLocalTr.appendChild( aoLocal[i][j].cell );
|
|
1896 aApplied[i][j] = 1;
|
|
1897
|
|
1898 /* Expand the cell to cover as many rows as needed */
|
|
1899 while ( aoLocal[i+iRowspan] !== undefined &&
|
|
1900 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
|
|
1901 {
|
|
1902 aApplied[i+iRowspan][j] = 1;
|
|
1903 iRowspan++;
|
|
1904 }
|
|
1905
|
|
1906 /* Expand the cell to cover as many columns as needed */
|
|
1907 while ( aoLocal[i][j+iColspan] !== undefined &&
|
|
1908 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
|
|
1909 {
|
|
1910 /* Must update the applied array over the rows for the columns */
|
|
1911 for ( k=0 ; k<iRowspan ; k++ )
|
|
1912 {
|
|
1913 aApplied[i+k][j+iColspan] = 1;
|
|
1914 }
|
|
1915 iColspan++;
|
|
1916 }
|
|
1917
|
|
1918 /* Do the actual expansion in the DOM */
|
|
1919 $(aoLocal[i][j].cell)
|
|
1920 .attr('rowspan', iRowspan)
|
|
1921 .attr('colspan', iColspan);
|
|
1922 }
|
|
1923 }
|
|
1924 }
|
|
1925 }
|
|
1926
|
|
1927
|
|
1928 /**
|
|
1929 * Insert the required TR nodes into the table for display
|
|
1930 * @param {object} oSettings dataTables settings object
|
|
1931 * @memberof DataTable#oApi
|
|
1932 */
|
|
1933 function _fnDraw( oSettings )
|
|
1934 {
|
|
1935 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
|
|
1936 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
|
|
1937 if ( $.inArray( false, aPreDraw ) !== -1 )
|
|
1938 {
|
|
1939 _fnProcessingDisplay( oSettings, false );
|
|
1940 return;
|
|
1941 }
|
|
1942
|
|
1943 var i, iLen, n;
|
|
1944 var anRows = [];
|
|
1945 var iRowCount = 0;
|
|
1946 var asStripeClasses = oSettings.asStripeClasses;
|
|
1947 var iStripes = asStripeClasses.length;
|
|
1948 var iOpenRows = oSettings.aoOpenRows.length;
|
|
1949 var oLang = oSettings.oLanguage;
|
|
1950 var iInitDisplayStart = oSettings.iInitDisplayStart;
|
|
1951 var bServerSide = _fnDataSource( oSettings ) == 'ssp';
|
|
1952 var aiDisplay = oSettings.aiDisplay;
|
|
1953
|
|
1954 oSettings.bDrawing = true;
|
|
1955
|
|
1956 /* Check and see if we have an initial draw position from state saving */
|
|
1957 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
|
|
1958 {
|
|
1959 oSettings._iDisplayStart = bServerSide ?
|
|
1960 iInitDisplayStart :
|
|
1961 iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
|
|
1962 0 :
|
|
1963 iInitDisplayStart;
|
|
1964
|
|
1965 oSettings.iInitDisplayStart = -1;
|
|
1966 }
|
|
1967
|
|
1968 var iDisplayStart = oSettings._iDisplayStart;
|
|
1969 var iDisplayEnd = oSettings.fnDisplayEnd();
|
|
1970
|
|
1971 /* Server-side processing draw intercept */
|
|
1972 if ( oSettings.bDeferLoading )
|
|
1973 {
|
|
1974 oSettings.bDeferLoading = false;
|
|
1975 oSettings.iDraw++;
|
|
1976 _fnProcessingDisplay( oSettings, false );
|
|
1977 }
|
|
1978 else if ( !bServerSide )
|
|
1979 {
|
|
1980 oSettings.iDraw++;
|
|
1981 }
|
|
1982 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
|
|
1983 {
|
|
1984 return;
|
|
1985 }
|
|
1986
|
|
1987 if ( aiDisplay.length !== 0 )
|
|
1988 {
|
|
1989 var iStart = bServerSide ? 0 : iDisplayStart;
|
|
1990 var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
|
|
1991
|
|
1992 for ( var j=iStart ; j<iEnd ; j++ )
|
|
1993 {
|
|
1994 var iDataIndex = aiDisplay[j];
|
|
1995 var aoData = oSettings.aoData[ iDataIndex ];
|
|
1996 if ( aoData.nTr === null )
|
|
1997 {
|
|
1998 _fnCreateTr( oSettings, iDataIndex );
|
|
1999 }
|
|
2000
|
|
2001 var nRow = aoData.nTr;
|
|
2002
|
|
2003 /* Remove the old striping classes and then add the new one */
|
|
2004 if ( iStripes !== 0 )
|
|
2005 {
|
|
2006 var sStripe = asStripeClasses[ iRowCount % iStripes ];
|
|
2007 if ( aoData._sRowStripe != sStripe )
|
|
2008 {
|
|
2009 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
|
|
2010 aoData._sRowStripe = sStripe;
|
|
2011 }
|
|
2012 }
|
|
2013
|
|
2014 // Row callback functions - might want to manipulate the row
|
|
2015 // iRowCount and j are not currently documented. Are they at all
|
|
2016 // useful?
|
|
2017 _fnCallbackFire( oSettings, 'aoRowCallback', null,
|
|
2018 [nRow, aoData._aData, iRowCount, j] );
|
|
2019
|
|
2020 anRows.push( nRow );
|
|
2021 iRowCount++;
|
|
2022 }
|
|
2023 }
|
|
2024 else
|
|
2025 {
|
|
2026 /* Table is empty - create a row with an empty message in it */
|
|
2027 var sZero = oLang.sZeroRecords;
|
|
2028 if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' )
|
|
2029 {
|
|
2030 sZero = oLang.sLoadingRecords;
|
|
2031 }
|
|
2032 else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
|
|
2033 {
|
|
2034 sZero = oLang.sEmptyTable;
|
|
2035 }
|
|
2036
|
|
2037 anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
|
|
2038 .append( $('<td />', {
|
|
2039 'valign': 'top',
|
|
2040 'colSpan': _fnVisbleColumns( oSettings ),
|
|
2041 'class': oSettings.oClasses.sRowEmpty
|
|
2042 } ).html( sZero ) )[0];
|
|
2043 }
|
|
2044
|
|
2045 /* Header and footer callbacks */
|
|
2046 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
|
|
2047 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
|
|
2048
|
|
2049 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
|
|
2050 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
|
|
2051
|
|
2052 var body = $(oSettings.nTBody);
|
|
2053
|
|
2054 body.children().detach();
|
|
2055 body.append( $(anRows) );
|
|
2056
|
|
2057 /* Call all required callback functions for the end of a draw */
|
|
2058 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
|
|
2059
|
|
2060 /* Draw is complete, sorting and filtering must be as well */
|
|
2061 oSettings.bSorted = false;
|
|
2062 oSettings.bFiltered = false;
|
|
2063 oSettings.bDrawing = false;
|
|
2064 }
|
|
2065
|
|
2066
|
|
2067 /**
|
|
2068 * Redraw the table - taking account of the various features which are enabled
|
|
2069 * @param {object} oSettings dataTables settings object
|
|
2070 * @param {boolean} [holdPosition] Keep the current paging position. By default
|
|
2071 * the paging is reset to the first page
|
|
2072 * @memberof DataTable#oApi
|
|
2073 */
|
|
2074 function _fnReDraw( settings, holdPosition )
|
|
2075 {
|
|
2076 var
|
|
2077 features = settings.oFeatures,
|
|
2078 sort = features.bSort,
|
|
2079 filter = features.bFilter;
|
|
2080
|
|
2081 if ( sort ) {
|
|
2082 _fnSort( settings );
|
|
2083 }
|
|
2084
|
|
2085 if ( filter ) {
|
|
2086 _fnFilterComplete( settings, settings.oPreviousSearch );
|
|
2087 }
|
|
2088 else {
|
|
2089 // No filtering, so we want to just use the display master
|
|
2090 settings.aiDisplay = settings.aiDisplayMaster.slice();
|
|
2091 }
|
|
2092
|
|
2093 if ( holdPosition !== true ) {
|
|
2094 settings._iDisplayStart = 0;
|
|
2095 }
|
|
2096
|
|
2097 // Let any modules know about the draw hold position state (used by
|
|
2098 // scrolling internally)
|
|
2099 settings._drawHold = holdPosition;
|
|
2100
|
|
2101 _fnDraw( settings );
|
|
2102
|
|
2103 settings._drawHold = false;
|
|
2104 }
|
|
2105
|
|
2106
|
|
2107 /**
|
|
2108 * Add the options to the page HTML for the table
|
|
2109 * @param {object} oSettings dataTables settings object
|
|
2110 * @memberof DataTable#oApi
|
|
2111 */
|
|
2112 function _fnAddOptionsHtml ( oSettings )
|
|
2113 {
|
|
2114 var classes = oSettings.oClasses;
|
|
2115 var table = $(oSettings.nTable);
|
|
2116 var holding = $('<div/>').insertBefore( table ); // Holding element for speed
|
|
2117 var features = oSettings.oFeatures;
|
|
2118
|
|
2119 // All DataTables are wrapped in a div
|
|
2120 var insert = $('<div/>', {
|
|
2121 id: oSettings.sTableId+'_wrapper',
|
|
2122 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
|
|
2123 } );
|
|
2124
|
|
2125 oSettings.nHolding = holding[0];
|
|
2126 oSettings.nTableWrapper = insert[0];
|
|
2127 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
|
|
2128
|
|
2129 /* Loop over the user set positioning and place the elements as needed */
|
|
2130 var aDom = oSettings.sDom.split('');
|
|
2131 var featureNode, cOption, nNewNode, cNext, sAttr, j;
|
|
2132 for ( var i=0 ; i<aDom.length ; i++ )
|
|
2133 {
|
|
2134 featureNode = null;
|
|
2135 cOption = aDom[i];
|
|
2136
|
|
2137 if ( cOption == '<' )
|
|
2138 {
|
|
2139 /* New container div */
|
|
2140 nNewNode = $('<div/>')[0];
|
|
2141
|
|
2142 /* Check to see if we should append an id and/or a class name to the container */
|
|
2143 cNext = aDom[i+1];
|
|
2144 if ( cNext == "'" || cNext == '"' )
|
|
2145 {
|
|
2146 sAttr = "";
|
|
2147 j = 2;
|
|
2148 while ( aDom[i+j] != cNext )
|
|
2149 {
|
|
2150 sAttr += aDom[i+j];
|
|
2151 j++;
|
|
2152 }
|
|
2153
|
|
2154 /* Replace jQuery UI constants @todo depreciated */
|
|
2155 if ( sAttr == "H" )
|
|
2156 {
|
|
2157 sAttr = classes.sJUIHeader;
|
|
2158 }
|
|
2159 else if ( sAttr == "F" )
|
|
2160 {
|
|
2161 sAttr = classes.sJUIFooter;
|
|
2162 }
|
|
2163
|
|
2164 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
|
|
2165 * breaks the string into parts and applies them as needed
|
|
2166 */
|
|
2167 if ( sAttr.indexOf('.') != -1 )
|
|
2168 {
|
|
2169 var aSplit = sAttr.split('.');
|
|
2170 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
|
|
2171 nNewNode.className = aSplit[1];
|
|
2172 }
|
|
2173 else if ( sAttr.charAt(0) == "#" )
|
|
2174 {
|
|
2175 nNewNode.id = sAttr.substr(1, sAttr.length-1);
|
|
2176 }
|
|
2177 else
|
|
2178 {
|
|
2179 nNewNode.className = sAttr;
|
|
2180 }
|
|
2181
|
|
2182 i += j; /* Move along the position array */
|
|
2183 }
|
|
2184
|
|
2185 insert.append( nNewNode );
|
|
2186 insert = $(nNewNode);
|
|
2187 }
|
|
2188 else if ( cOption == '>' )
|
|
2189 {
|
|
2190 /* End container div */
|
|
2191 insert = insert.parent();
|
|
2192 }
|
|
2193 // @todo Move options into their own plugins?
|
|
2194 else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
|
|
2195 {
|
|
2196 /* Length */
|
|
2197 featureNode = _fnFeatureHtmlLength( oSettings );
|
|
2198 }
|
|
2199 else if ( cOption == 'f' && features.bFilter )
|
|
2200 {
|
|
2201 /* Filter */
|
|
2202 featureNode = _fnFeatureHtmlFilter( oSettings );
|
|
2203 }
|
|
2204 else if ( cOption == 'r' && features.bProcessing )
|
|
2205 {
|
|
2206 /* pRocessing */
|
|
2207 featureNode = _fnFeatureHtmlProcessing( oSettings );
|
|
2208 }
|
|
2209 else if ( cOption == 't' )
|
|
2210 {
|
|
2211 /* Table */
|
|
2212 featureNode = _fnFeatureHtmlTable( oSettings );
|
|
2213 }
|
|
2214 else if ( cOption == 'i' && features.bInfo )
|
|
2215 {
|
|
2216 /* Info */
|
|
2217 featureNode = _fnFeatureHtmlInfo( oSettings );
|
|
2218 }
|
|
2219 else if ( cOption == 'p' && features.bPaginate )
|
|
2220 {
|
|
2221 /* Pagination */
|
|
2222 featureNode = _fnFeatureHtmlPaginate( oSettings );
|
|
2223 }
|
|
2224 else if ( DataTable.ext.feature.length !== 0 )
|
|
2225 {
|
|
2226 /* Plug-in features */
|
|
2227 var aoFeatures = DataTable.ext.feature;
|
|
2228 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
|
|
2229 {
|
|
2230 if ( cOption == aoFeatures[k].cFeature )
|
|
2231 {
|
|
2232 featureNode = aoFeatures[k].fnInit( oSettings );
|
|
2233 break;
|
|
2234 }
|
|
2235 }
|
|
2236 }
|
|
2237
|
|
2238 /* Add to the 2D features array */
|
|
2239 if ( featureNode )
|
|
2240 {
|
|
2241 var aanFeatures = oSettings.aanFeatures;
|
|
2242
|
|
2243 if ( ! aanFeatures[cOption] )
|
|
2244 {
|
|
2245 aanFeatures[cOption] = [];
|
|
2246 }
|
|
2247
|
|
2248 aanFeatures[cOption].push( featureNode );
|
|
2249 insert.append( featureNode );
|
|
2250 }
|
|
2251 }
|
|
2252
|
|
2253 /* Built our DOM structure - replace the holding div with what we want */
|
|
2254 holding.replaceWith( insert );
|
|
2255 }
|
|
2256
|
|
2257
|
|
2258 /**
|
|
2259 * Use the DOM source to create up an array of header cells. The idea here is to
|
|
2260 * create a layout grid (array) of rows x columns, which contains a reference
|
|
2261 * to the cell that that point in the grid (regardless of col/rowspan), such that
|
|
2262 * any column / row could be removed and the new grid constructed
|
|
2263 * @param array {object} aLayout Array to store the calculated layout in
|
|
2264 * @param {node} nThead The header/footer element for the table
|
|
2265 * @memberof DataTable#oApi
|
|
2266 */
|
|
2267 function _fnDetectHeader ( aLayout, nThead )
|
|
2268 {
|
|
2269 var nTrs = $(nThead).children('tr');
|
|
2270 var nTr, nCell;
|
|
2271 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
|
|
2272 var bUnique;
|
|
2273 var fnShiftCol = function ( a, i, j ) {
|
|
2274 var k = a[i];
|
|
2275 while ( k[j] ) {
|
|
2276 j++;
|
|
2277 }
|
|
2278 return j;
|
|
2279 };
|
|
2280
|
|
2281 aLayout.splice( 0, aLayout.length );
|
|
2282
|
|
2283 /* We know how many rows there are in the layout - so prep it */
|
|
2284 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
|
|
2285 {
|
|
2286 aLayout.push( [] );
|
|
2287 }
|
|
2288
|
|
2289 /* Calculate a layout array */
|
|
2290 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
|
|
2291 {
|
|
2292 nTr = nTrs[i];
|
|
2293 iColumn = 0;
|
|
2294
|
|
2295 /* For every cell in the row... */
|
|
2296 nCell = nTr.firstChild;
|
|
2297 while ( nCell ) {
|
|
2298 if ( nCell.nodeName.toUpperCase() == "TD" ||
|
|
2299 nCell.nodeName.toUpperCase() == "TH" )
|
|
2300 {
|
|
2301 /* Get the col and rowspan attributes from the DOM and sanitise them */
|
|
2302 iColspan = nCell.getAttribute('colspan') * 1;
|
|
2303 iRowspan = nCell.getAttribute('rowspan') * 1;
|
|
2304 iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
|
|
2305 iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
|
|
2306
|
|
2307 /* There might be colspan cells already in this row, so shift our target
|
|
2308 * accordingly
|
|
2309 */
|
|
2310 iColShifted = fnShiftCol( aLayout, i, iColumn );
|
|
2311
|
|
2312 /* Cache calculation for unique columns */
|
|
2313 bUnique = iColspan === 1 ? true : false;
|
|
2314
|
|
2315 /* If there is col / rowspan, copy the information into the layout grid */
|
|
2316 for ( l=0 ; l<iColspan ; l++ )
|
|
2317 {
|
|
2318 for ( k=0 ; k<iRowspan ; k++ )
|
|
2319 {
|
|
2320 aLayout[i+k][iColShifted+l] = {
|
|
2321 "cell": nCell,
|
|
2322 "unique": bUnique
|
|
2323 };
|
|
2324 aLayout[i+k].nTr = nTr;
|
|
2325 }
|
|
2326 }
|
|
2327 }
|
|
2328 nCell = nCell.nextSibling;
|
|
2329 }
|
|
2330 }
|
|
2331 }
|
|
2332
|
|
2333
|
|
2334 /**
|
|
2335 * Get an array of unique th elements, one for each column
|
|
2336 * @param {object} oSettings dataTables settings object
|
|
2337 * @param {node} nHeader automatically detect the layout from this node - optional
|
|
2338 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
|
|
2339 * @returns array {node} aReturn list of unique th's
|
|
2340 * @memberof DataTable#oApi
|
|
2341 */
|
|
2342 function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
|
|
2343 {
|
|
2344 var aReturn = [];
|
|
2345 if ( !aLayout )
|
|
2346 {
|
|
2347 aLayout = oSettings.aoHeader;
|
|
2348 if ( nHeader )
|
|
2349 {
|
|
2350 aLayout = [];
|
|
2351 _fnDetectHeader( aLayout, nHeader );
|
|
2352 }
|
|
2353 }
|
|
2354
|
|
2355 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
|
|
2356 {
|
|
2357 for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
|
|
2358 {
|
|
2359 if ( aLayout[i][j].unique &&
|
|
2360 (!aReturn[j] || !oSettings.bSortCellsTop) )
|
|
2361 {
|
|
2362 aReturn[j] = aLayout[i][j].cell;
|
|
2363 }
|
|
2364 }
|
|
2365 }
|
|
2366
|
|
2367 return aReturn;
|
|
2368 }
|
|
2369
|
|
2370
|
|
2371
|
|
2372 /**
|
|
2373 * Create an Ajax call based on the table's settings, taking into account that
|
|
2374 * parameters can have multiple forms, and backwards compatibility.
|
|
2375 *
|
|
2376 * @param {object} oSettings dataTables settings object
|
|
2377 * @param {array} data Data to send to the server, required by
|
|
2378 * DataTables - may be augmented by developer callbacks
|
|
2379 * @param {function} fn Callback function to run when data is obtained
|
|
2380 */
|
|
2381 function _fnBuildAjax( oSettings, data, fn )
|
|
2382 {
|
|
2383 // Compatibility with 1.9-, allow fnServerData and event to manipulate
|
|
2384 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
|
|
2385
|
|
2386 // Convert to object based for 1.10+ if using the old array scheme which can
|
|
2387 // come from server-side processing or serverParams
|
|
2388 if ( data && $.isArray(data) ) {
|
|
2389 var tmp = {};
|
|
2390 var rbracket = /(.*?)\[\]$/;
|
|
2391
|
|
2392 $.each( data, function (key, val) {
|
|
2393 var match = val.name.match(rbracket);
|
|
2394
|
|
2395 if ( match ) {
|
|
2396 // Support for arrays
|
|
2397 var name = match[0];
|
|
2398
|
|
2399 if ( ! tmp[ name ] ) {
|
|
2400 tmp[ name ] = [];
|
|
2401 }
|
|
2402 tmp[ name ].push( val.value );
|
|
2403 }
|
|
2404 else {
|
|
2405 tmp[val.name] = val.value;
|
|
2406 }
|
|
2407 } );
|
|
2408 data = tmp;
|
|
2409 }
|
|
2410
|
|
2411 var ajaxData;
|
|
2412 var ajax = oSettings.ajax;
|
|
2413 var instance = oSettings.oInstance;
|
|
2414
|
|
2415 if ( $.isPlainObject( ajax ) && ajax.data )
|
|
2416 {
|
|
2417 ajaxData = ajax.data;
|
|
2418
|
|
2419 var newData = $.isFunction( ajaxData ) ?
|
|
2420 ajaxData( data ) : // fn can manipulate data or return an object
|
|
2421 ajaxData; // object or array to merge
|
|
2422
|
|
2423 // If the function returned an object, use that alone
|
|
2424 data = $.isFunction( ajaxData ) && newData ?
|
|
2425 newData :
|
|
2426 $.extend( true, data, newData );
|
|
2427
|
|
2428 // Remove the data property as we've resolved it already and don't want
|
|
2429 // jQuery to do it again (it is restored at the end of the function)
|
|
2430 delete ajax.data;
|
|
2431 }
|
|
2432
|
|
2433 var baseAjax = {
|
|
2434 "data": data,
|
|
2435 "success": function (json) {
|
|
2436 var error = json.error || json.sError;
|
|
2437 if ( error ) {
|
|
2438 oSettings.oApi._fnLog( oSettings, 0, error );
|
|
2439 }
|
|
2440
|
|
2441 oSettings.json = json;
|
|
2442 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
|
|
2443 fn( json );
|
|
2444 },
|
|
2445 "dataType": "json",
|
|
2446 "cache": false,
|
|
2447 "type": oSettings.sServerMethod,
|
|
2448 "error": function (xhr, error, thrown) {
|
|
2449 var log = oSettings.oApi._fnLog;
|
|
2450
|
|
2451 if ( error == "parsererror" ) {
|
|
2452 log( oSettings, 0, 'Invalid JSON response', 1 );
|
|
2453 }
|
|
2454 else if ( xhr.readyState === 4 ) {
|
|
2455 log( oSettings, 0, 'Ajax error', 7 );
|
|
2456 }
|
|
2457
|
|
2458 _fnProcessingDisplay( oSettings, false );
|
|
2459 }
|
|
2460 };
|
|
2461
|
|
2462 // Store the data submitted for the API
|
|
2463 oSettings.oAjaxData = data;
|
|
2464
|
|
2465 // Allow plug-ins and external processes to modify the data
|
|
2466 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
|
|
2467
|
|
2468 if ( oSettings.fnServerData )
|
|
2469 {
|
|
2470 // DataTables 1.9- compatibility
|
|
2471 oSettings.fnServerData.call( instance,
|
|
2472 oSettings.sAjaxSource,
|
|
2473 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
|
|
2474 return { name: key, value: val };
|
|
2475 } ),
|
|
2476 fn,
|
|
2477 oSettings
|
|
2478 );
|
|
2479 }
|
|
2480 else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
|
|
2481 {
|
|
2482 // DataTables 1.9- compatibility
|
|
2483 oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
|
|
2484 url: ajax || oSettings.sAjaxSource
|
|
2485 } ) );
|
|
2486 }
|
|
2487 else if ( $.isFunction( ajax ) )
|
|
2488 {
|
|
2489 // Is a function - let the caller define what needs to be done
|
|
2490 oSettings.jqXHR = ajax.call( instance, data, fn, oSettings );
|
|
2491 }
|
|
2492 else
|
|
2493 {
|
|
2494 // Object to extend the base settings
|
|
2495 oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
|
|
2496
|
|
2497 // Restore for next time around
|
|
2498 ajax.data = ajaxData;
|
|
2499 }
|
|
2500 }
|
|
2501
|
|
2502
|
|
2503 /**
|
|
2504 * Update the table using an Ajax call
|
|
2505 * @param {object} settings dataTables settings object
|
|
2506 * @returns {boolean} Block the table drawing or not
|
|
2507 * @memberof DataTable#oApi
|
|
2508 */
|
|
2509 function _fnAjaxUpdate( settings )
|
|
2510 {
|
|
2511 if ( settings.bAjaxDataGet ) {
|
|
2512 settings.iDraw++;
|
|
2513 _fnProcessingDisplay( settings, true );
|
|
2514
|
|
2515 _fnBuildAjax(
|
|
2516 settings,
|
|
2517 _fnAjaxParameters( settings ),
|
|
2518 function(json) {
|
|
2519 _fnAjaxUpdateDraw( settings, json );
|
|
2520 }
|
|
2521 );
|
|
2522
|
|
2523 return false;
|
|
2524 }
|
|
2525 return true;
|
|
2526 }
|
|
2527
|
|
2528
|
|
2529 /**
|
|
2530 * Build up the parameters in an object needed for a server-side processing
|
|
2531 * request. Note that this is basically done twice, is different ways - a modern
|
|
2532 * method which is used by default in DataTables 1.10 which uses objects and
|
|
2533 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
|
|
2534 * the sAjaxSource option is used in the initialisation, or the legacyAjax
|
|
2535 * option is set.
|
|
2536 * @param {object} oSettings dataTables settings object
|
|
2537 * @returns {bool} block the table drawing or not
|
|
2538 * @memberof DataTable#oApi
|
|
2539 */
|
|
2540 function _fnAjaxParameters( settings )
|
|
2541 {
|
|
2542 var
|
|
2543 columns = settings.aoColumns,
|
|
2544 columnCount = columns.length,
|
|
2545 features = settings.oFeatures,
|
|
2546 preSearch = settings.oPreviousSearch,
|
|
2547 preColSearch = settings.aoPreSearchCols,
|
|
2548 i, data = [], dataProp, column, columnSearch,
|
|
2549 sort = _fnSortFlatten( settings ),
|
|
2550 displayStart = settings._iDisplayStart,
|
|
2551 displayLength = features.bPaginate !== false ?
|
|
2552 settings._iDisplayLength :
|
|
2553 -1;
|
|
2554
|
|
2555 var param = function ( name, value ) {
|
|
2556 data.push( { 'name': name, 'value': value } );
|
|
2557 };
|
|
2558
|
|
2559 // DataTables 1.9- compatible method
|
|
2560 param( 'sEcho', settings.iDraw );
|
|
2561 param( 'iColumns', columnCount );
|
|
2562 param( 'sColumns', _pluck( columns, 'sName' ).join(',') );
|
|
2563 param( 'iDisplayStart', displayStart );
|
|
2564 param( 'iDisplayLength', displayLength );
|
|
2565
|
|
2566 // DataTables 1.10+ method
|
|
2567 var d = {
|
|
2568 draw: settings.iDraw,
|
|
2569 columns: [],
|
|
2570 order: [],
|
|
2571 start: displayStart,
|
|
2572 length: displayLength,
|
|
2573 search: {
|
|
2574 value: preSearch.sSearch,
|
|
2575 regex: preSearch.bRegex
|
|
2576 }
|
|
2577 };
|
|
2578
|
|
2579 for ( i=0 ; i<columnCount ; i++ ) {
|
|
2580 column = columns[i];
|
|
2581 columnSearch = preColSearch[i];
|
|
2582 dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
|
|
2583
|
|
2584 d.columns.push( {
|
|
2585 data: dataProp,
|
|
2586 name: column.sName,
|
|
2587 searchable: column.bSearchable,
|
|
2588 orderable: column.bSortable,
|
|
2589 search: {
|
|
2590 value: columnSearch.sSearch,
|
|
2591 regex: columnSearch.bRegex
|
|
2592 }
|
|
2593 } );
|
|
2594
|
|
2595 param( "mDataProp_"+i, dataProp );
|
|
2596
|
|
2597 if ( features.bFilter ) {
|
|
2598 param( 'sSearch_'+i, columnSearch.sSearch );
|
|
2599 param( 'bRegex_'+i, columnSearch.bRegex );
|
|
2600 param( 'bSearchable_'+i, column.bSearchable );
|
|
2601 }
|
|
2602
|
|
2603 if ( features.bSort ) {
|
|
2604 param( 'bSortable_'+i, column.bSortable );
|
|
2605 }
|
|
2606 }
|
|
2607
|
|
2608 if ( features.bFilter ) {
|
|
2609 param( 'sSearch', preSearch.sSearch );
|
|
2610 param( 'bRegex', preSearch.bRegex );
|
|
2611 }
|
|
2612
|
|
2613 if ( features.bSort ) {
|
|
2614 $.each( sort, function ( i, val ) {
|
|
2615 d.order.push( { column: val.col, dir: val.dir } );
|
|
2616
|
|
2617 param( 'iSortCol_'+i, val.col );
|
|
2618 param( 'sSortDir_'+i, val.dir );
|
|
2619 } );
|
|
2620
|
|
2621 param( 'iSortingCols', sort.length );
|
|
2622 }
|
|
2623
|
|
2624 // If the legacy.ajax parameter is null, then we automatically decide which
|
|
2625 // form to use, based on sAjaxSource
|
|
2626 var legacy = DataTable.ext.legacy.ajax;
|
|
2627 if ( legacy === null ) {
|
|
2628 return settings.sAjaxSource ? data : d;
|
|
2629 }
|
|
2630
|
|
2631 // Otherwise, if legacy has been specified then we use that to decide on the
|
|
2632 // form
|
|
2633 return legacy ? data : d;
|
|
2634 }
|
|
2635
|
|
2636
|
|
2637 /**
|
|
2638 * Data the data from the server (nuking the old) and redraw the table
|
|
2639 * @param {object} oSettings dataTables settings object
|
|
2640 * @param {object} json json data return from the server.
|
|
2641 * @param {string} json.sEcho Tracking flag for DataTables to match requests
|
|
2642 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
|
|
2643 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
|
|
2644 * @param {array} json.aaData The data to display on this page
|
|
2645 * @param {string} [json.sColumns] Column ordering (sName, comma separated)
|
|
2646 * @memberof DataTable#oApi
|
|
2647 */
|
|
2648 function _fnAjaxUpdateDraw ( settings, json )
|
|
2649 {
|
|
2650 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
|
|
2651 // Support both
|
|
2652 var compat = function ( old, modern ) {
|
|
2653 return json[old] !== undefined ? json[old] : json[modern];
|
|
2654 };
|
|
2655
|
|
2656 var draw = compat( 'sEcho', 'draw' );
|
|
2657 var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );
|
|
2658 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
|
|
2659
|
|
2660 if ( draw ) {
|
|
2661 // Protect against out of sequence returns
|
|
2662 if ( draw*1 < settings.iDraw ) {
|
|
2663 return;
|
|
2664 }
|
|
2665 settings.iDraw = draw * 1;
|
|
2666 }
|
|
2667
|
|
2668 _fnClearTable( settings );
|
|
2669 settings._iRecordsTotal = parseInt(recordsTotal, 10);
|
|
2670 settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
|
|
2671
|
|
2672 var data = _fnAjaxDataSrc( settings, json );
|
|
2673 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
2674 _fnAddData( settings, data[i] );
|
|
2675 }
|
|
2676 settings.aiDisplay = settings.aiDisplayMaster.slice();
|
|
2677
|
|
2678 settings.bAjaxDataGet = false;
|
|
2679 _fnDraw( settings );
|
|
2680
|
|
2681 if ( ! settings._bInitComplete ) {
|
|
2682 _fnInitComplete( settings, json );
|
|
2683 }
|
|
2684
|
|
2685 settings.bAjaxDataGet = true;
|
|
2686 _fnProcessingDisplay( settings, false );
|
|
2687 }
|
|
2688
|
|
2689
|
|
2690 /**
|
|
2691 * Get the data from the JSON data source to use for drawing a table. Using
|
|
2692 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
|
|
2693 * source object, or from a processing function.
|
|
2694 * @param {object} oSettings dataTables settings object
|
|
2695 * @param {object} json Data source object / array from the server
|
|
2696 * @return {array} Array of data to use
|
|
2697 */
|
|
2698 function _fnAjaxDataSrc ( oSettings, json )
|
|
2699 {
|
|
2700 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
|
|
2701 oSettings.ajax.dataSrc :
|
|
2702 oSettings.sAjaxDataProp; // Compatibility with 1.9-.
|
|
2703
|
|
2704 // Compatibility with 1.9-. In order to read from aaData, check if the
|
|
2705 // default has been changed, if not, check for aaData
|
|
2706 if ( dataSrc === 'data' ) {
|
|
2707 return json.aaData || json[dataSrc];
|
|
2708 }
|
|
2709
|
|
2710 return dataSrc !== "" ?
|
|
2711 _fnGetObjectDataFn( dataSrc )( json ) :
|
|
2712 json;
|
|
2713 }
|
|
2714
|
|
2715
|
|
2716 /**
|
|
2717 * Generate the node required for filtering text
|
|
2718 * @returns {node} Filter control element
|
|
2719 * @param {object} oSettings dataTables settings object
|
|
2720 * @memberof DataTable#oApi
|
|
2721 */
|
|
2722 function _fnFeatureHtmlFilter ( settings )
|
|
2723 {
|
|
2724 var classes = settings.oClasses;
|
|
2725 var tableId = settings.sTableId;
|
|
2726 var language = settings.oLanguage;
|
|
2727 var previousSearch = settings.oPreviousSearch;
|
|
2728 var features = settings.aanFeatures;
|
|
2729 var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
|
|
2730
|
|
2731 var str = language.sSearch;
|
|
2732 str = str.match(/_INPUT_/) ?
|
|
2733 str.replace('_INPUT_', input) :
|
|
2734 str+input;
|
|
2735
|
|
2736 var filter = $('<div/>', {
|
|
2737 'id': ! features.f ? tableId+'_filter' : null,
|
|
2738 'class': classes.sFilter
|
|
2739 } )
|
|
2740 .append( $('<label/>' ).append( str ) );
|
|
2741
|
|
2742 var searchFn = function() {
|
|
2743 /* Update all other filter input elements for the new display */
|
|
2744 var n = features.f;
|
|
2745 var val = !this.value ? "" : this.value; // mental IE8 fix :-(
|
|
2746
|
|
2747 /* Now do the filter */
|
|
2748 if ( val != previousSearch.sSearch ) {
|
|
2749 _fnFilterComplete( settings, {
|
|
2750 "sSearch": val,
|
|
2751 "bRegex": previousSearch.bRegex,
|
|
2752 "bSmart": previousSearch.bSmart ,
|
|
2753 "bCaseInsensitive": previousSearch.bCaseInsensitive
|
|
2754 } );
|
|
2755
|
|
2756 // Need to redraw, without resorting
|
|
2757 settings._iDisplayStart = 0;
|
|
2758 _fnDraw( settings );
|
|
2759 }
|
|
2760 };
|
|
2761
|
|
2762 var searchDelay = settings.searchDelay !== null ?
|
|
2763 settings.searchDelay :
|
|
2764 _fnDataSource( settings ) === 'ssp' ?
|
|
2765 400 :
|
|
2766 0;
|
|
2767
|
|
2768 var jqFilter = $('input', filter)
|
|
2769 .val( previousSearch.sSearch )
|
|
2770 .attr( 'placeholder', language.sSearchPlaceholder )
|
|
2771 .bind(
|
|
2772 'keyup.DT search.DT input.DT paste.DT cut.DT',
|
|
2773 searchDelay ?
|
|
2774 _fnThrottle( searchFn, searchDelay ) :
|
|
2775 searchFn
|
|
2776 )
|
|
2777 .bind( 'keypress.DT', function(e) {
|
|
2778 /* Prevent form submission */
|
|
2779 if ( e.keyCode == 13 ) {
|
|
2780 return false;
|
|
2781 }
|
|
2782 } )
|
|
2783 .attr('aria-controls', tableId);
|
|
2784
|
|
2785 // Update the input elements whenever the table is filtered
|
|
2786 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
|
|
2787 if ( settings === s ) {
|
|
2788 // IE9 throws an 'unknown error' if document.activeElement is used
|
|
2789 // inside an iframe or frame...
|
|
2790 try {
|
|
2791 if ( jqFilter[0] !== document.activeElement ) {
|
|
2792 jqFilter.val( previousSearch.sSearch );
|
|
2793 }
|
|
2794 }
|
|
2795 catch ( e ) {}
|
|
2796 }
|
|
2797 } );
|
|
2798
|
|
2799 return filter[0];
|
|
2800 }
|
|
2801
|
|
2802
|
|
2803 /**
|
|
2804 * Filter the table using both the global filter and column based filtering
|
|
2805 * @param {object} oSettings dataTables settings object
|
|
2806 * @param {object} oSearch search information
|
|
2807 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
|
|
2808 * @memberof DataTable#oApi
|
|
2809 */
|
|
2810 function _fnFilterComplete ( oSettings, oInput, iForce )
|
|
2811 {
|
|
2812 var oPrevSearch = oSettings.oPreviousSearch;
|
|
2813 var aoPrevSearch = oSettings.aoPreSearchCols;
|
|
2814 var fnSaveFilter = function ( oFilter ) {
|
|
2815 /* Save the filtering values */
|
|
2816 oPrevSearch.sSearch = oFilter.sSearch;
|
|
2817 oPrevSearch.bRegex = oFilter.bRegex;
|
|
2818 oPrevSearch.bSmart = oFilter.bSmart;
|
|
2819 oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
|
|
2820 };
|
|
2821 var fnRegex = function ( o ) {
|
|
2822 // Backwards compatibility with the bEscapeRegex option
|
|
2823 return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
|
|
2824 };
|
|
2825
|
|
2826 // Resolve any column types that are unknown due to addition or invalidation
|
|
2827 // @todo As per sort - can this be moved into an event handler?
|
|
2828 _fnColumnTypes( oSettings );
|
|
2829
|
|
2830 /* In server-side processing all filtering is done by the server, so no point hanging around here */
|
|
2831 if ( _fnDataSource( oSettings ) != 'ssp' )
|
|
2832 {
|
|
2833 /* Global filter */
|
|
2834 _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
|
|
2835 fnSaveFilter( oInput );
|
|
2836
|
|
2837 /* Now do the individual column filter */
|
|
2838 for ( var i=0 ; i<aoPrevSearch.length ; i++ )
|
|
2839 {
|
|
2840 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
|
|
2841 aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
|
|
2842 }
|
|
2843
|
|
2844 /* Custom filtering */
|
|
2845 _fnFilterCustom( oSettings );
|
|
2846 }
|
|
2847 else
|
|
2848 {
|
|
2849 fnSaveFilter( oInput );
|
|
2850 }
|
|
2851
|
|
2852 /* Tell the draw function we have been filtering */
|
|
2853 oSettings.bFiltered = true;
|
|
2854 _fnCallbackFire( oSettings, null, 'search', [oSettings] );
|
|
2855 }
|
|
2856
|
|
2857
|
|
2858 /**
|
|
2859 * Apply custom filtering functions
|
|
2860 * @param {object} oSettings dataTables settings object
|
|
2861 * @memberof DataTable#oApi
|
|
2862 */
|
|
2863 function _fnFilterCustom( settings )
|
|
2864 {
|
|
2865 var filters = DataTable.ext.search;
|
|
2866 var displayRows = settings.aiDisplay;
|
|
2867 var row, rowIdx;
|
|
2868
|
|
2869 for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
|
|
2870 var rows = [];
|
|
2871
|
|
2872 // Loop over each row and see if it should be included
|
|
2873 for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
|
|
2874 rowIdx = displayRows[ j ];
|
|
2875 row = settings.aoData[ rowIdx ];
|
|
2876
|
|
2877 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
|
|
2878 rows.push( rowIdx );
|
|
2879 }
|
|
2880 }
|
|
2881
|
|
2882 // So the array reference doesn't break set the results into the
|
|
2883 // existing array
|
|
2884 displayRows.length = 0;
|
|
2885 displayRows.push.apply( displayRows, rows );
|
|
2886 }
|
|
2887 }
|
|
2888
|
|
2889
|
|
2890 /**
|
|
2891 * Filter the table on a per-column basis
|
|
2892 * @param {object} oSettings dataTables settings object
|
|
2893 * @param {string} sInput string to filter on
|
|
2894 * @param {int} iColumn column to filter
|
|
2895 * @param {bool} bRegex treat search string as a regular expression or not
|
|
2896 * @param {bool} bSmart use smart filtering or not
|
|
2897 * @param {bool} bCaseInsensitive Do case insenstive matching or not
|
|
2898 * @memberof DataTable#oApi
|
|
2899 */
|
|
2900 function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
|
|
2901 {
|
|
2902 if ( searchStr === '' ) {
|
|
2903 return;
|
|
2904 }
|
|
2905
|
|
2906 var data;
|
|
2907 var display = settings.aiDisplay;
|
|
2908 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
|
|
2909
|
|
2910 for ( var i=display.length-1 ; i>=0 ; i-- ) {
|
|
2911 data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
|
|
2912
|
|
2913 if ( ! rpSearch.test( data ) ) {
|
|
2914 display.splice( i, 1 );
|
|
2915 }
|
|
2916 }
|
|
2917 }
|
|
2918
|
|
2919
|
|
2920 /**
|
|
2921 * Filter the data table based on user input and draw the table
|
|
2922 * @param {object} settings dataTables settings object
|
|
2923 * @param {string} input string to filter on
|
|
2924 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
|
|
2925 * @param {bool} regex treat as a regular expression or not
|
|
2926 * @param {bool} smart perform smart filtering or not
|
|
2927 * @param {bool} caseInsensitive Do case insenstive matching or not
|
|
2928 * @memberof DataTable#oApi
|
|
2929 */
|
|
2930 function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
|
|
2931 {
|
|
2932 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
|
|
2933 var prevSearch = settings.oPreviousSearch.sSearch;
|
|
2934 var displayMaster = settings.aiDisplayMaster;
|
|
2935 var display, invalidated, i;
|
|
2936
|
|
2937 // Need to take account of custom filtering functions - always filter
|
|
2938 if ( DataTable.ext.search.length !== 0 ) {
|
|
2939 force = true;
|
|
2940 }
|
|
2941
|
|
2942 // Check if any of the rows were invalidated
|
|
2943 invalidated = _fnFilterData( settings );
|
|
2944
|
|
2945 // If the input is blank - we just want the full data set
|
|
2946 if ( input.length <= 0 ) {
|
|
2947 settings.aiDisplay = displayMaster.slice();
|
|
2948 }
|
|
2949 else {
|
|
2950 // New search - start from the master array
|
|
2951 if ( invalidated ||
|
|
2952 force ||
|
|
2953 prevSearch.length > input.length ||
|
|
2954 input.indexOf(prevSearch) !== 0 ||
|
|
2955 settings.bSorted // On resort, the display master needs to be
|
|
2956 // re-filtered since indexes will have changed
|
|
2957 ) {
|
|
2958 settings.aiDisplay = displayMaster.slice();
|
|
2959 }
|
|
2960
|
|
2961 // Search the display array
|
|
2962 display = settings.aiDisplay;
|
|
2963
|
|
2964 for ( i=display.length-1 ; i>=0 ; i-- ) {
|
|
2965 if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
|
|
2966 display.splice( i, 1 );
|
|
2967 }
|
|
2968 }
|
|
2969 }
|
|
2970 }
|
|
2971
|
|
2972
|
|
2973 /**
|
|
2974 * Build a regular expression object suitable for searching a table
|
|
2975 * @param {string} sSearch string to search for
|
|
2976 * @param {bool} bRegex treat as a regular expression or not
|
|
2977 * @param {bool} bSmart perform smart filtering or not
|
|
2978 * @param {bool} bCaseInsensitive Do case insensitive matching or not
|
|
2979 * @returns {RegExp} constructed object
|
|
2980 * @memberof DataTable#oApi
|
|
2981 */
|
|
2982 function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
|
|
2983 {
|
|
2984 search = regex ?
|
|
2985 search :
|
|
2986 _fnEscapeRegex( search );
|
|
2987
|
|
2988 if ( smart ) {
|
|
2989 /* For smart filtering we want to allow the search to work regardless of
|
|
2990 * word order. We also want double quoted text to be preserved, so word
|
|
2991 * order is important - a la google. So this is what we want to
|
|
2992 * generate:
|
|
2993 *
|
|
2994 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
|
|
2995 */
|
|
2996 var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || '', function ( word ) {
|
|
2997 if ( word.charAt(0) === '"' ) {
|
|
2998 var m = word.match( /^"(.*)"$/ );
|
|
2999 word = m ? m[1] : word;
|
|
3000 }
|
|
3001
|
|
3002 return word.replace('"', '');
|
|
3003 } );
|
|
3004
|
|
3005 search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
|
|
3006 }
|
|
3007
|
|
3008 return new RegExp( search, caseInsensitive ? 'i' : '' );
|
|
3009 }
|
|
3010
|
|
3011
|
|
3012 /**
|
|
3013 * Escape a string such that it can be used in a regular expression
|
|
3014 * @param {string} sVal string to escape
|
|
3015 * @returns {string} escaped string
|
|
3016 * @memberof DataTable#oApi
|
|
3017 */
|
|
3018 function _fnEscapeRegex ( sVal )
|
|
3019 {
|
|
3020 return sVal.replace( _re_escape_regex, '\\$1' );
|
|
3021 }
|
|
3022
|
|
3023
|
|
3024
|
|
3025 var __filter_div = $('<div>')[0];
|
|
3026 var __filter_div_textContent = __filter_div.textContent !== undefined;
|
|
3027
|
|
3028 // Update the filtering data for each row if needed (by invalidation or first run)
|
|
3029 function _fnFilterData ( settings )
|
|
3030 {
|
|
3031 var columns = settings.aoColumns;
|
|
3032 var column;
|
|
3033 var i, j, ien, jen, filterData, cellData, row;
|
|
3034 var fomatters = DataTable.ext.type.search;
|
|
3035 var wasInvalidated = false;
|
|
3036
|
|
3037 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
3038 row = settings.aoData[i];
|
|
3039
|
|
3040 if ( ! row._aFilterData ) {
|
|
3041 filterData = [];
|
|
3042
|
|
3043 for ( j=0, jen=columns.length ; j<jen ; j++ ) {
|
|
3044 column = columns[j];
|
|
3045
|
|
3046 if ( column.bSearchable ) {
|
|
3047 cellData = _fnGetCellData( settings, i, j, 'filter' );
|
|
3048
|
|
3049 if ( fomatters[ column.sType ] ) {
|
|
3050 cellData = fomatters[ column.sType ]( cellData );
|
|
3051 }
|
|
3052
|
|
3053 // Search in DataTables 1.10 is string based. In 1.11 this
|
|
3054 // should be altered to also allow strict type checking.
|
|
3055 if ( cellData === null ) {
|
|
3056 cellData = '';
|
|
3057 }
|
|
3058
|
|
3059 if ( typeof cellData !== 'string' && cellData.toString ) {
|
|
3060 cellData = cellData.toString();
|
|
3061 }
|
|
3062 }
|
|
3063 else {
|
|
3064 cellData = '';
|
|
3065 }
|
|
3066
|
|
3067 // If it looks like there is an HTML entity in the string,
|
|
3068 // attempt to decode it so sorting works as expected. Note that
|
|
3069 // we could use a single line of jQuery to do this, but the DOM
|
|
3070 // method used here is much faster http://jsperf.com/html-decode
|
|
3071 if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
|
|
3072 __filter_div.innerHTML = cellData;
|
|
3073 cellData = __filter_div_textContent ?
|
|
3074 __filter_div.textContent :
|
|
3075 __filter_div.innerText;
|
|
3076 }
|
|
3077
|
|
3078 if ( cellData.replace ) {
|
|
3079 cellData = cellData.replace(/[\r\n]/g, '');
|
|
3080 }
|
|
3081
|
|
3082 filterData.push( cellData );
|
|
3083 }
|
|
3084
|
|
3085 row._aFilterData = filterData;
|
|
3086 row._sFilterRow = filterData.join(' ');
|
|
3087 wasInvalidated = true;
|
|
3088 }
|
|
3089 }
|
|
3090
|
|
3091 return wasInvalidated;
|
|
3092 }
|
|
3093
|
|
3094
|
|
3095 /**
|
|
3096 * Convert from the internal Hungarian notation to camelCase for external
|
|
3097 * interaction
|
|
3098 * @param {object} obj Object to convert
|
|
3099 * @returns {object} Inverted object
|
|
3100 * @memberof DataTable#oApi
|
|
3101 */
|
|
3102 function _fnSearchToCamel ( obj )
|
|
3103 {
|
|
3104 return {
|
|
3105 search: obj.sSearch,
|
|
3106 smart: obj.bSmart,
|
|
3107 regex: obj.bRegex,
|
|
3108 caseInsensitive: obj.bCaseInsensitive
|
|
3109 };
|
|
3110 }
|
|
3111
|
|
3112
|
|
3113
|
|
3114 /**
|
|
3115 * Convert from camelCase notation to the internal Hungarian. We could use the
|
|
3116 * Hungarian convert function here, but this is cleaner
|
|
3117 * @param {object} obj Object to convert
|
|
3118 * @returns {object} Inverted object
|
|
3119 * @memberof DataTable#oApi
|
|
3120 */
|
|
3121 function _fnSearchToHung ( obj )
|
|
3122 {
|
|
3123 return {
|
|
3124 sSearch: obj.search,
|
|
3125 bSmart: obj.smart,
|
|
3126 bRegex: obj.regex,
|
|
3127 bCaseInsensitive: obj.caseInsensitive
|
|
3128 };
|
|
3129 }
|
|
3130
|
|
3131 /**
|
|
3132 * Generate the node required for the info display
|
|
3133 * @param {object} oSettings dataTables settings object
|
|
3134 * @returns {node} Information element
|
|
3135 * @memberof DataTable#oApi
|
|
3136 */
|
|
3137 function _fnFeatureHtmlInfo ( settings )
|
|
3138 {
|
|
3139 var
|
|
3140 tid = settings.sTableId,
|
|
3141 nodes = settings.aanFeatures.i,
|
|
3142 n = $('<div/>', {
|
|
3143 'class': settings.oClasses.sInfo,
|
|
3144 'id': ! nodes ? tid+'_info' : null
|
|
3145 } );
|
|
3146
|
|
3147 if ( ! nodes ) {
|
|
3148 // Update display on each draw
|
|
3149 settings.aoDrawCallback.push( {
|
|
3150 "fn": _fnUpdateInfo,
|
|
3151 "sName": "information"
|
|
3152 } );
|
|
3153
|
|
3154 n
|
|
3155 .attr( 'role', 'status' )
|
|
3156 .attr( 'aria-live', 'polite' );
|
|
3157
|
|
3158 // Table is described by our info div
|
|
3159 $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
|
|
3160 }
|
|
3161
|
|
3162 return n[0];
|
|
3163 }
|
|
3164
|
|
3165
|
|
3166 /**
|
|
3167 * Update the information elements in the display
|
|
3168 * @param {object} settings dataTables settings object
|
|
3169 * @memberof DataTable#oApi
|
|
3170 */
|
|
3171 function _fnUpdateInfo ( settings )
|
|
3172 {
|
|
3173 /* Show information about the table */
|
|
3174 var nodes = settings.aanFeatures.i;
|
|
3175 if ( nodes.length === 0 ) {
|
|
3176 return;
|
|
3177 }
|
|
3178
|
|
3179 var
|
|
3180 lang = settings.oLanguage,
|
|
3181 start = settings._iDisplayStart+1,
|
|
3182 end = settings.fnDisplayEnd(),
|
|
3183 max = settings.fnRecordsTotal(),
|
|
3184 total = settings.fnRecordsDisplay(),
|
|
3185 out = total ?
|
|
3186 lang.sInfo :
|
|
3187 lang.sInfoEmpty;
|
|
3188
|
|
3189 if ( total !== max ) {
|
|
3190 /* Record set after filtering */
|
|
3191 out += ' ' + lang.sInfoFiltered;
|
|
3192 }
|
|
3193
|
|
3194 // Convert the macros
|
|
3195 out += lang.sInfoPostFix;
|
|
3196 out = _fnInfoMacros( settings, out );
|
|
3197
|
|
3198 var callback = lang.fnInfoCallback;
|
|
3199 if ( callback !== null ) {
|
|
3200 out = callback.call( settings.oInstance,
|
|
3201 settings, start, end, max, total, out
|
|
3202 );
|
|
3203 }
|
|
3204
|
|
3205 $(nodes).html( out );
|
|
3206 }
|
|
3207
|
|
3208
|
|
3209 function _fnInfoMacros ( settings, str )
|
|
3210 {
|
|
3211 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
|
|
3212 // internally
|
|
3213 var
|
|
3214 formatter = settings.fnFormatNumber,
|
|
3215 start = settings._iDisplayStart+1,
|
|
3216 len = settings._iDisplayLength,
|
|
3217 vis = settings.fnRecordsDisplay(),
|
|
3218 all = len === -1;
|
|
3219
|
|
3220 return str.
|
|
3221 replace(/_START_/g, formatter.call( settings, start ) ).
|
|
3222 replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ).
|
|
3223 replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ).
|
|
3224 replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
|
|
3225 replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
|
|
3226 replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
|
|
3227 }
|
|
3228
|
|
3229
|
|
3230
|
|
3231 /**
|
|
3232 * Draw the table for the first time, adding all required features
|
|
3233 * @param {object} settings dataTables settings object
|
|
3234 * @memberof DataTable#oApi
|
|
3235 */
|
|
3236 function _fnInitialise ( settings )
|
|
3237 {
|
|
3238 var i, iLen, iAjaxStart=settings.iInitDisplayStart;
|
|
3239 var columns = settings.aoColumns, column;
|
|
3240 var features = settings.oFeatures;
|
|
3241
|
|
3242 /* Ensure that the table data is fully initialised */
|
|
3243 if ( ! settings.bInitialised ) {
|
|
3244 setTimeout( function(){ _fnInitialise( settings ); }, 200 );
|
|
3245 return;
|
|
3246 }
|
|
3247
|
|
3248 /* Show the display HTML options */
|
|
3249 _fnAddOptionsHtml( settings );
|
|
3250
|
|
3251 /* Build and draw the header / footer for the table */
|
|
3252 _fnBuildHead( settings );
|
|
3253 _fnDrawHead( settings, settings.aoHeader );
|
|
3254 _fnDrawHead( settings, settings.aoFooter );
|
|
3255
|
|
3256 /* Okay to show that something is going on now */
|
|
3257 _fnProcessingDisplay( settings, true );
|
|
3258
|
|
3259 /* Calculate sizes for columns */
|
|
3260 if ( features.bAutoWidth ) {
|
|
3261 _fnCalculateColumnWidths( settings );
|
|
3262 }
|
|
3263
|
|
3264 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
|
|
3265 column = columns[i];
|
|
3266
|
|
3267 if ( column.sWidth ) {
|
|
3268 column.nTh.style.width = _fnStringToCss( column.sWidth );
|
|
3269 }
|
|
3270 }
|
|
3271
|
|
3272 // If there is default sorting required - let's do it. The sort function
|
|
3273 // will do the drawing for us. Otherwise we draw the table regardless of the
|
|
3274 // Ajax source - this allows the table to look initialised for Ajax sourcing
|
|
3275 // data (show 'loading' message possibly)
|
|
3276 _fnReDraw( settings );
|
|
3277
|
|
3278 // Server-side processing init complete is done by _fnAjaxUpdateDraw
|
|
3279 var dataSrc = _fnDataSource( settings );
|
|
3280 if ( dataSrc != 'ssp' ) {
|
|
3281 // if there is an ajax source load the data
|
|
3282 if ( dataSrc == 'ajax' ) {
|
|
3283 _fnBuildAjax( settings, [], function(json) {
|
|
3284 var aData = _fnAjaxDataSrc( settings, json );
|
|
3285
|
|
3286 // Got the data - add it to the table
|
|
3287 for ( i=0 ; i<aData.length ; i++ ) {
|
|
3288 _fnAddData( settings, aData[i] );
|
|
3289 }
|
|
3290
|
|
3291 // Reset the init display for cookie saving. We've already done
|
|
3292 // a filter, and therefore cleared it before. So we need to make
|
|
3293 // it appear 'fresh'
|
|
3294 settings.iInitDisplayStart = iAjaxStart;
|
|
3295
|
|
3296 _fnReDraw( settings );
|
|
3297
|
|
3298 _fnProcessingDisplay( settings, false );
|
|
3299 _fnInitComplete( settings, json );
|
|
3300 }, settings );
|
|
3301 }
|
|
3302 else {
|
|
3303 _fnProcessingDisplay( settings, false );
|
|
3304 _fnInitComplete( settings );
|
|
3305 }
|
|
3306 }
|
|
3307 }
|
|
3308
|
|
3309
|
|
3310 /**
|
|
3311 * Draw the table for the first time, adding all required features
|
|
3312 * @param {object} oSettings dataTables settings object
|
|
3313 * @param {object} [json] JSON from the server that completed the table, if using Ajax source
|
|
3314 * with client-side processing (optional)
|
|
3315 * @memberof DataTable#oApi
|
|
3316 */
|
|
3317 function _fnInitComplete ( settings, json )
|
|
3318 {
|
|
3319 settings._bInitComplete = true;
|
|
3320
|
|
3321 // On an Ajax load we now have data and therefore want to apply the column
|
|
3322 // sizing
|
|
3323 if ( json ) {
|
|
3324 _fnAdjustColumnSizing( settings );
|
|
3325 }
|
|
3326
|
|
3327 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
|
|
3328 }
|
|
3329
|
|
3330
|
|
3331 function _fnLengthChange ( settings, val )
|
|
3332 {
|
|
3333 var len = parseInt( val, 10 );
|
|
3334 settings._iDisplayLength = len;
|
|
3335
|
|
3336 _fnLengthOverflow( settings );
|
|
3337
|
|
3338 // Fire length change event
|
|
3339 _fnCallbackFire( settings, null, 'length', [settings, len] );
|
|
3340 }
|
|
3341
|
|
3342
|
|
3343 /**
|
|
3344 * Generate the node required for user display length changing
|
|
3345 * @param {object} settings dataTables settings object
|
|
3346 * @returns {node} Display length feature node
|
|
3347 * @memberof DataTable#oApi
|
|
3348 */
|
|
3349 function _fnFeatureHtmlLength ( settings )
|
|
3350 {
|
|
3351 var
|
|
3352 classes = settings.oClasses,
|
|
3353 tableId = settings.sTableId,
|
|
3354 menu = settings.aLengthMenu,
|
|
3355 d2 = $.isArray( menu[0] ),
|
|
3356 lengths = d2 ? menu[0] : menu,
|
|
3357 language = d2 ? menu[1] : menu;
|
|
3358
|
|
3359 var select = $('<select/>', {
|
|
3360 'name': tableId+'_length',
|
|
3361 'aria-controls': tableId,
|
|
3362 'class': classes.sLengthSelect
|
|
3363 } );
|
|
3364
|
|
3365 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
|
|
3366 select[0][ i ] = new Option( language[i], lengths[i] );
|
|
3367 }
|
|
3368
|
|
3369 var div = $('<div><label/></div>').addClass( classes.sLength );
|
|
3370 if ( ! settings.aanFeatures.l ) {
|
|
3371 div[0].id = tableId+'_length';
|
|
3372 }
|
|
3373
|
|
3374 div.children().append(
|
|
3375 settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
|
|
3376 );
|
|
3377
|
|
3378 // Can't use `select` variable as user might provide their own and the
|
|
3379 // reference is broken by the use of outerHTML
|
|
3380 $('select', div)
|
|
3381 .val( settings._iDisplayLength )
|
|
3382 .bind( 'change.DT', function(e) {
|
|
3383 _fnLengthChange( settings, $(this).val() );
|
|
3384 _fnDraw( settings );
|
|
3385 } );
|
|
3386
|
|
3387 // Update node value whenever anything changes the table's length
|
|
3388 $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
|
|
3389 if ( settings === s ) {
|
|
3390 $('select', div).val( len );
|
|
3391 }
|
|
3392 } );
|
|
3393
|
|
3394 return div[0];
|
|
3395 }
|
|
3396
|
|
3397
|
|
3398
|
|
3399 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
3400 * Note that most of the paging logic is done in
|
|
3401 * DataTable.ext.pager
|
|
3402 */
|
|
3403
|
|
3404 /**
|
|
3405 * Generate the node required for default pagination
|
|
3406 * @param {object} oSettings dataTables settings object
|
|
3407 * @returns {node} Pagination feature node
|
|
3408 * @memberof DataTable#oApi
|
|
3409 */
|
|
3410 function _fnFeatureHtmlPaginate ( settings )
|
|
3411 {
|
|
3412 var
|
|
3413 type = settings.sPaginationType,
|
|
3414 plugin = DataTable.ext.pager[ type ],
|
|
3415 modern = typeof plugin === 'function',
|
|
3416 redraw = function( settings ) {
|
|
3417 _fnDraw( settings );
|
|
3418 },
|
|
3419 node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
|
|
3420 features = settings.aanFeatures;
|
|
3421
|
|
3422 if ( ! modern ) {
|
|
3423 plugin.fnInit( settings, node, redraw );
|
|
3424 }
|
|
3425
|
|
3426 /* Add a draw callback for the pagination on first instance, to update the paging display */
|
|
3427 if ( ! features.p )
|
|
3428 {
|
|
3429 node.id = settings.sTableId+'_paginate';
|
|
3430
|
|
3431 settings.aoDrawCallback.push( {
|
|
3432 "fn": function( settings ) {
|
|
3433 if ( modern ) {
|
|
3434 var
|
|
3435 start = settings._iDisplayStart,
|
|
3436 len = settings._iDisplayLength,
|
|
3437 visRecords = settings.fnRecordsDisplay(),
|
|
3438 all = len === -1,
|
|
3439 page = all ? 0 : Math.ceil( start / len ),
|
|
3440 pages = all ? 1 : Math.ceil( visRecords / len ),
|
|
3441 buttons = plugin(page, pages),
|
|
3442 i, ien;
|
|
3443
|
|
3444 for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
|
|
3445 _fnRenderer( settings, 'pageButton' )(
|
|
3446 settings, features.p[i], i, buttons, page, pages
|
|
3447 );
|
|
3448 }
|
|
3449 }
|
|
3450 else {
|
|
3451 plugin.fnUpdate( settings, redraw );
|
|
3452 }
|
|
3453 },
|
|
3454 "sName": "pagination"
|
|
3455 } );
|
|
3456 }
|
|
3457
|
|
3458 return node;
|
|
3459 }
|
|
3460
|
|
3461
|
|
3462 /**
|
|
3463 * Alter the display settings to change the page
|
|
3464 * @param {object} settings DataTables settings object
|
|
3465 * @param {string|int} action Paging action to take: "first", "previous",
|
|
3466 * "next" or "last" or page number to jump to (integer)
|
|
3467 * @param [bool] redraw Automatically draw the update or not
|
|
3468 * @returns {bool} true page has changed, false - no change
|
|
3469 * @memberof DataTable#oApi
|
|
3470 */
|
|
3471 function _fnPageChange ( settings, action, redraw )
|
|
3472 {
|
|
3473 var
|
|
3474 start = settings._iDisplayStart,
|
|
3475 len = settings._iDisplayLength,
|
|
3476 records = settings.fnRecordsDisplay();
|
|
3477
|
|
3478 if ( records === 0 || len === -1 )
|
|
3479 {
|
|
3480 start = 0;
|
|
3481 }
|
|
3482 else if ( typeof action === "number" )
|
|
3483 {
|
|
3484 start = action * len;
|
|
3485
|
|
3486 if ( start > records )
|
|
3487 {
|
|
3488 start = 0;
|
|
3489 }
|
|
3490 }
|
|
3491 else if ( action == "first" )
|
|
3492 {
|
|
3493 start = 0;
|
|
3494 }
|
|
3495 else if ( action == "previous" )
|
|
3496 {
|
|
3497 start = len >= 0 ?
|
|
3498 start - len :
|
|
3499 0;
|
|
3500
|
|
3501 if ( start < 0 )
|
|
3502 {
|
|
3503 start = 0;
|
|
3504 }
|
|
3505 }
|
|
3506 else if ( action == "next" )
|
|
3507 {
|
|
3508 if ( start + len < records )
|
|
3509 {
|
|
3510 start += len;
|
|
3511 }
|
|
3512 }
|
|
3513 else if ( action == "last" )
|
|
3514 {
|
|
3515 start = Math.floor( (records-1) / len) * len;
|
|
3516 }
|
|
3517 else
|
|
3518 {
|
|
3519 _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
|
|
3520 }
|
|
3521
|
|
3522 var changed = settings._iDisplayStart !== start;
|
|
3523 settings._iDisplayStart = start;
|
|
3524
|
|
3525 if ( changed ) {
|
|
3526 _fnCallbackFire( settings, null, 'page', [settings] );
|
|
3527
|
|
3528 if ( redraw ) {
|
|
3529 _fnDraw( settings );
|
|
3530 }
|
|
3531 }
|
|
3532
|
|
3533 return changed;
|
|
3534 }
|
|
3535
|
|
3536
|
|
3537
|
|
3538 /**
|
|
3539 * Generate the node required for the processing node
|
|
3540 * @param {object} settings dataTables settings object
|
|
3541 * @returns {node} Processing element
|
|
3542 * @memberof DataTable#oApi
|
|
3543 */
|
|
3544 function _fnFeatureHtmlProcessing ( settings )
|
|
3545 {
|
|
3546 return $('<div/>', {
|
|
3547 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
|
|
3548 'class': settings.oClasses.sProcessing
|
|
3549 } )
|
|
3550 .html( settings.oLanguage.sProcessing )
|
|
3551 .insertBefore( settings.nTable )[0];
|
|
3552 }
|
|
3553
|
|
3554
|
|
3555 /**
|
|
3556 * Display or hide the processing indicator
|
|
3557 * @param {object} settings dataTables settings object
|
|
3558 * @param {bool} show Show the processing indicator (true) or not (false)
|
|
3559 * @memberof DataTable#oApi
|
|
3560 */
|
|
3561 function _fnProcessingDisplay ( settings, show )
|
|
3562 {
|
|
3563 if ( settings.oFeatures.bProcessing ) {
|
|
3564 $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
|
|
3565 }
|
|
3566
|
|
3567 _fnCallbackFire( settings, null, 'processing', [settings, show] );
|
|
3568 }
|
|
3569
|
|
3570 /**
|
|
3571 * Add any control elements for the table - specifically scrolling
|
|
3572 * @param {object} settings dataTables settings object
|
|
3573 * @returns {node} Node to add to the DOM
|
|
3574 * @memberof DataTable#oApi
|
|
3575 */
|
|
3576 function _fnFeatureHtmlTable ( settings )
|
|
3577 {
|
|
3578 var table = $(settings.nTable);
|
|
3579
|
|
3580 // Add the ARIA grid role to the table
|
|
3581 table.attr( 'role', 'grid' );
|
|
3582
|
|
3583 // Scrolling from here on in
|
|
3584 var scroll = settings.oScroll;
|
|
3585
|
|
3586 if ( scroll.sX === '' && scroll.sY === '' ) {
|
|
3587 return settings.nTable;
|
|
3588 }
|
|
3589
|
|
3590 var scrollX = scroll.sX;
|
|
3591 var scrollY = scroll.sY;
|
|
3592 var classes = settings.oClasses;
|
|
3593 var caption = table.children('caption');
|
|
3594 var captionSide = caption.length ? caption[0]._captionSide : null;
|
|
3595 var headerClone = $( table[0].cloneNode(false) );
|
|
3596 var footerClone = $( table[0].cloneNode(false) );
|
|
3597 var footer = table.children('tfoot');
|
|
3598 var _div = '<div/>';
|
|
3599 var size = function ( s ) {
|
|
3600 return !s ? null : _fnStringToCss( s );
|
|
3601 };
|
|
3602
|
|
3603 // This is fairly messy, but with x scrolling enabled, if the table has a
|
|
3604 // width attribute, regardless of any width applied using the column width
|
|
3605 // options, the browser will shrink or grow the table as needed to fit into
|
|
3606 // that 100%. That would make the width options useless. So we remove it.
|
|
3607 // This is okay, under the assumption that width:100% is applied to the
|
|
3608 // table in CSS (it is in the default stylesheet) which will set the table
|
|
3609 // width as appropriate (the attribute and css behave differently...)
|
|
3610 if ( scroll.sX && table.attr('width') === '100%' ) {
|
|
3611 table.removeAttr('width');
|
|
3612 }
|
|
3613
|
|
3614 if ( ! footer.length ) {
|
|
3615 footer = null;
|
|
3616 }
|
|
3617
|
|
3618 /*
|
|
3619 * The HTML structure that we want to generate in this function is:
|
|
3620 * div - scroller
|
|
3621 * div - scroll head
|
|
3622 * div - scroll head inner
|
|
3623 * table - scroll head table
|
|
3624 * thead - thead
|
|
3625 * div - scroll body
|
|
3626 * table - table (master table)
|
|
3627 * thead - thead clone for sizing
|
|
3628 * tbody - tbody
|
|
3629 * div - scroll foot
|
|
3630 * div - scroll foot inner
|
|
3631 * table - scroll foot table
|
|
3632 * tfoot - tfoot
|
|
3633 */
|
|
3634 var scroller = $( _div, { 'class': classes.sScrollWrapper } )
|
|
3635 .append(
|
|
3636 $(_div, { 'class': classes.sScrollHead } )
|
|
3637 .css( {
|
|
3638 overflow: 'hidden',
|
|
3639 position: 'relative',
|
|
3640 border: 0,
|
|
3641 width: scrollX ? size(scrollX) : '100%'
|
|
3642 } )
|
|
3643 .append(
|
|
3644 $(_div, { 'class': classes.sScrollHeadInner } )
|
|
3645 .css( {
|
|
3646 'box-sizing': 'content-box',
|
|
3647 width: scroll.sXInner || '100%'
|
|
3648 } )
|
|
3649 .append(
|
|
3650 headerClone
|
|
3651 .removeAttr('id')
|
|
3652 .css( 'margin-left', 0 )
|
|
3653 .append( captionSide === 'top' ? caption : null )
|
|
3654 .append(
|
|
3655 table.children('thead')
|
|
3656 )
|
|
3657 )
|
|
3658 )
|
|
3659 )
|
|
3660 .append(
|
|
3661 $(_div, { 'class': classes.sScrollBody } )
|
|
3662 .css( {
|
|
3663 overflow: 'auto',
|
|
3664 height: size( scrollY ),
|
|
3665 width: size( scrollX )
|
|
3666 } )
|
|
3667 .append( table )
|
|
3668 );
|
|
3669
|
|
3670 if ( footer ) {
|
|
3671 scroller.append(
|
|
3672 $(_div, { 'class': classes.sScrollFoot } )
|
|
3673 .css( {
|
|
3674 overflow: 'hidden',
|
|
3675 border: 0,
|
|
3676 width: scrollX ? size(scrollX) : '100%'
|
|
3677 } )
|
|
3678 .append(
|
|
3679 $(_div, { 'class': classes.sScrollFootInner } )
|
|
3680 .append(
|
|
3681 footerClone
|
|
3682 .removeAttr('id')
|
|
3683 .css( 'margin-left', 0 )
|
|
3684 .append( captionSide === 'bottom' ? caption : null )
|
|
3685 .append(
|
|
3686 table.children('tfoot')
|
|
3687 )
|
|
3688 )
|
|
3689 )
|
|
3690 );
|
|
3691 }
|
|
3692
|
|
3693 var children = scroller.children();
|
|
3694 var scrollHead = children[0];
|
|
3695 var scrollBody = children[1];
|
|
3696 var scrollFoot = footer ? children[2] : null;
|
|
3697
|
|
3698 // When the body is scrolled, then we also want to scroll the headers
|
|
3699 if ( scrollX ) {
|
|
3700 $(scrollBody).scroll( function (e) {
|
|
3701 var scrollLeft = this.scrollLeft;
|
|
3702
|
|
3703 scrollHead.scrollLeft = scrollLeft;
|
|
3704
|
|
3705 if ( footer ) {
|
|
3706 scrollFoot.scrollLeft = scrollLeft;
|
|
3707 }
|
|
3708 } );
|
|
3709 }
|
|
3710
|
|
3711 settings.nScrollHead = scrollHead;
|
|
3712 settings.nScrollBody = scrollBody;
|
|
3713 settings.nScrollFoot = scrollFoot;
|
|
3714
|
|
3715 // On redraw - align columns
|
|
3716 settings.aoDrawCallback.push( {
|
|
3717 "fn": _fnScrollDraw,
|
|
3718 "sName": "scrolling"
|
|
3719 } );
|
|
3720
|
|
3721 return scroller[0];
|
|
3722 }
|
|
3723
|
|
3724
|
|
3725
|
|
3726 /**
|
|
3727 * Update the header, footer and body tables for resizing - i.e. column
|
|
3728 * alignment.
|
|
3729 *
|
|
3730 * Welcome to the most horrible function DataTables. The process that this
|
|
3731 * function follows is basically:
|
|
3732 * 1. Re-create the table inside the scrolling div
|
|
3733 * 2. Take live measurements from the DOM
|
|
3734 * 3. Apply the measurements to align the columns
|
|
3735 * 4. Clean up
|
|
3736 *
|
|
3737 * @param {object} settings dataTables settings object
|
|
3738 * @memberof DataTable#oApi
|
|
3739 */
|
|
3740 function _fnScrollDraw ( settings )
|
|
3741 {
|
|
3742 // Given that this is such a monster function, a lot of variables are use
|
|
3743 // to try and keep the minimised size as small as possible
|
|
3744 var
|
|
3745 scroll = settings.oScroll,
|
|
3746 scrollX = scroll.sX,
|
|
3747 scrollXInner = scroll.sXInner,
|
|
3748 scrollY = scroll.sY,
|
|
3749 barWidth = scroll.iBarWidth,
|
|
3750 divHeader = $(settings.nScrollHead),
|
|
3751 divHeaderStyle = divHeader[0].style,
|
|
3752 divHeaderInner = divHeader.children('div'),
|
|
3753 divHeaderInnerStyle = divHeaderInner[0].style,
|
|
3754 divHeaderTable = divHeaderInner.children('table'),
|
|
3755 divBodyEl = settings.nScrollBody,
|
|
3756 divBody = $(divBodyEl),
|
|
3757 divBodyStyle = divBodyEl.style,
|
|
3758 divFooter = $(settings.nScrollFoot),
|
|
3759 divFooterInner = divFooter.children('div'),
|
|
3760 divFooterTable = divFooterInner.children('table'),
|
|
3761 header = $(settings.nTHead),
|
|
3762 table = $(settings.nTable),
|
|
3763 tableEl = table[0],
|
|
3764 tableStyle = tableEl.style,
|
|
3765 footer = settings.nTFoot ? $(settings.nTFoot) : null,
|
|
3766 browser = settings.oBrowser,
|
|
3767 ie67 = browser.bScrollOversize,
|
|
3768 headerTrgEls, footerTrgEls,
|
|
3769 headerSrcEls, footerSrcEls,
|
|
3770 headerCopy, footerCopy,
|
|
3771 headerWidths=[], footerWidths=[],
|
|
3772 headerContent=[],
|
|
3773 idx, correction, sanityWidth,
|
|
3774 zeroOut = function(nSizer) {
|
|
3775 var style = nSizer.style;
|
|
3776 style.paddingTop = "0";
|
|
3777 style.paddingBottom = "0";
|
|
3778 style.borderTopWidth = "0";
|
|
3779 style.borderBottomWidth = "0";
|
|
3780 style.height = 0;
|
|
3781 };
|
|
3782
|
|
3783 /*
|
|
3784 * 1. Re-create the table inside the scrolling div
|
|
3785 */
|
|
3786
|
|
3787 // Remove the old minimised thead and tfoot elements in the inner table
|
|
3788 table.children('thead, tfoot').remove();
|
|
3789
|
|
3790 // Clone the current header and footer elements and then place it into the inner table
|
|
3791 headerCopy = header.clone().prependTo( table );
|
|
3792 headerTrgEls = header.find('tr'); // original header is in its own table
|
|
3793 headerSrcEls = headerCopy.find('tr');
|
|
3794 headerCopy.find('th, td').removeAttr('tabindex');
|
|
3795
|
|
3796 if ( footer ) {
|
|
3797 footerCopy = footer.clone().prependTo( table );
|
|
3798 footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
|
|
3799 footerSrcEls = footerCopy.find('tr');
|
|
3800 }
|
|
3801
|
|
3802
|
|
3803 /*
|
|
3804 * 2. Take live measurements from the DOM - do not alter the DOM itself!
|
|
3805 */
|
|
3806
|
|
3807 // Remove old sizing and apply the calculated column widths
|
|
3808 // Get the unique column headers in the newly created (cloned) header. We want to apply the
|
|
3809 // calculated sizes to this header
|
|
3810 if ( ! scrollX )
|
|
3811 {
|
|
3812 divBodyStyle.width = '100%';
|
|
3813 divHeader[0].style.width = '100%';
|
|
3814 }
|
|
3815
|
|
3816 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
|
|
3817 idx = _fnVisibleToColumnIndex( settings, i );
|
|
3818 el.style.width = settings.aoColumns[idx].sWidth;
|
|
3819 } );
|
|
3820
|
|
3821 if ( footer ) {
|
|
3822 _fnApplyToChildren( function(n) {
|
|
3823 n.style.width = "";
|
|
3824 }, footerSrcEls );
|
|
3825 }
|
|
3826
|
|
3827 // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
|
|
3828 // will end up forcing the scrollbar to appear, making our measurements wrong for when we
|
|
3829 // then hide it (end of this function), so add the header height to the body scroller.
|
|
3830 if ( scroll.bCollapse && scrollY !== "" ) {
|
|
3831 divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
|
|
3832 }
|
|
3833
|
|
3834 // Size the table as a whole
|
|
3835 sanityWidth = table.outerWidth();
|
|
3836 if ( scrollX === "" ) {
|
|
3837 // No x scrolling
|
|
3838 tableStyle.width = "100%";
|
|
3839
|
|
3840 // IE7 will make the width of the table when 100% include the scrollbar
|
|
3841 // - which is shouldn't. When there is a scrollbar we need to take this
|
|
3842 // into account.
|
|
3843 if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
|
|
3844 divBody.css('overflow-y') == "scroll")
|
|
3845 ) {
|
|
3846 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
|
|
3847 }
|
|
3848 }
|
|
3849 else
|
|
3850 {
|
|
3851 // x scrolling
|
|
3852 if ( scrollXInner !== "" ) {
|
|
3853 // x scroll inner has been given - use it
|
|
3854 tableStyle.width = _fnStringToCss(scrollXInner);
|
|
3855 }
|
|
3856 else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
|
|
3857 // There is y-scrolling - try to take account of the y scroll bar
|
|
3858 tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
|
|
3859 if ( table.outerWidth() > sanityWidth-barWidth ) {
|
|
3860 // Not possible to take account of it
|
|
3861 tableStyle.width = _fnStringToCss( sanityWidth );
|
|
3862 }
|
|
3863 }
|
|
3864 else {
|
|
3865 // When all else fails
|
|
3866 tableStyle.width = _fnStringToCss( sanityWidth );
|
|
3867 }
|
|
3868 }
|
|
3869
|
|
3870 // Recalculate the sanity width - now that we've applied the required width,
|
|
3871 // before it was a temporary variable. This is required because the column
|
|
3872 // width calculation is done before this table DOM is created.
|
|
3873 sanityWidth = table.outerWidth();
|
|
3874
|
|
3875 // Hidden header should have zero height, so remove padding and borders. Then
|
|
3876 // set the width based on the real headers
|
|
3877
|
|
3878 // Apply all styles in one pass
|
|
3879 _fnApplyToChildren( zeroOut, headerSrcEls );
|
|
3880
|
|
3881 // Read all widths in next pass
|
|
3882 _fnApplyToChildren( function(nSizer) {
|
|
3883 headerContent.push( nSizer.innerHTML );
|
|
3884 headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
|
|
3885 }, headerSrcEls );
|
|
3886
|
|
3887 // Apply all widths in final pass
|
|
3888 _fnApplyToChildren( function(nToSize, i) {
|
|
3889 nToSize.style.width = headerWidths[i];
|
|
3890 }, headerTrgEls );
|
|
3891
|
|
3892 $(headerSrcEls).height(0);
|
|
3893
|
|
3894 /* Same again with the footer if we have one */
|
|
3895 if ( footer )
|
|
3896 {
|
|
3897 _fnApplyToChildren( zeroOut, footerSrcEls );
|
|
3898
|
|
3899 _fnApplyToChildren( function(nSizer) {
|
|
3900 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
|
|
3901 }, footerSrcEls );
|
|
3902
|
|
3903 _fnApplyToChildren( function(nToSize, i) {
|
|
3904 nToSize.style.width = footerWidths[i];
|
|
3905 }, footerTrgEls );
|
|
3906
|
|
3907 $(footerSrcEls).height(0);
|
|
3908 }
|
|
3909
|
|
3910
|
|
3911 /*
|
|
3912 * 3. Apply the measurements
|
|
3913 */
|
|
3914
|
|
3915 // "Hide" the header and footer that we used for the sizing. We need to keep
|
|
3916 // the content of the cell so that the width applied to the header and body
|
|
3917 // both match, but we want to hide it completely. We want to also fix their
|
|
3918 // width to what they currently are
|
|
3919 _fnApplyToChildren( function(nSizer, i) {
|
|
3920 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
|
|
3921 nSizer.style.width = headerWidths[i];
|
|
3922 }, headerSrcEls );
|
|
3923
|
|
3924 if ( footer )
|
|
3925 {
|
|
3926 _fnApplyToChildren( function(nSizer, i) {
|
|
3927 nSizer.innerHTML = "";
|
|
3928 nSizer.style.width = footerWidths[i];
|
|
3929 }, footerSrcEls );
|
|
3930 }
|
|
3931
|
|
3932 // Sanity check that the table is of a sensible width. If not then we are going to get
|
|
3933 // misalignment - try to prevent this by not allowing the table to shrink below its min width
|
|
3934 if ( table.outerWidth() < sanityWidth )
|
|
3935 {
|
|
3936 // The min width depends upon if we have a vertical scrollbar visible or not */
|
|
3937 correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
|
|
3938 divBody.css('overflow-y') == "scroll")) ?
|
|
3939 sanityWidth+barWidth :
|
|
3940 sanityWidth;
|
|
3941
|
|
3942 // IE6/7 are a law unto themselves...
|
|
3943 if ( ie67 && (divBodyEl.scrollHeight >
|
|
3944 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
|
|
3945 ) {
|
|
3946 tableStyle.width = _fnStringToCss( correction-barWidth );
|
|
3947 }
|
|
3948
|
|
3949 // And give the user a warning that we've stopped the table getting too small
|
|
3950 if ( scrollX === "" || scrollXInner !== "" ) {
|
|
3951 _fnLog( settings, 1, 'Possible column misalignment', 6 );
|
|
3952 }
|
|
3953 }
|
|
3954 else
|
|
3955 {
|
|
3956 correction = '100%';
|
|
3957 }
|
|
3958
|
|
3959 // Apply to the container elements
|
|
3960 divBodyStyle.width = _fnStringToCss( correction );
|
|
3961 divHeaderStyle.width = _fnStringToCss( correction );
|
|
3962
|
|
3963 if ( footer ) {
|
|
3964 settings.nScrollFoot.style.width = _fnStringToCss( correction );
|
|
3965 }
|
|
3966
|
|
3967
|
|
3968 /*
|
|
3969 * 4. Clean up
|
|
3970 */
|
|
3971 if ( ! scrollY ) {
|
|
3972 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
|
|
3973 * the scrollbar height from the visible display, rather than adding it on. We need to
|
|
3974 * set the height in order to sort this. Don't want to do it in any other browsers.
|
|
3975 */
|
|
3976 if ( ie67 ) {
|
|
3977 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
|
|
3978 }
|
|
3979 }
|
|
3980
|
|
3981 if ( scrollY && scroll.bCollapse ) {
|
|
3982 divBodyStyle.height = _fnStringToCss( scrollY );
|
|
3983
|
|
3984 var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
|
|
3985 barWidth :
|
|
3986 0;
|
|
3987
|
|
3988 if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
|
|
3989 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
|
|
3990 }
|
|
3991 }
|
|
3992
|
|
3993 /* Finally set the width's of the header and footer tables */
|
|
3994 var iOuterWidth = table.outerWidth();
|
|
3995 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
|
|
3996 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
|
|
3997
|
|
3998 // Figure out if there are scrollbar present - if so then we need a the header and footer to
|
|
3999 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
|
|
4000 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
|
|
4001 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
|
|
4002 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
|
|
4003
|
|
4004 if ( footer ) {
|
|
4005 divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
|
|
4006 divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
|
|
4007 divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
|
|
4008 }
|
|
4009
|
|
4010 /* Adjust the position of the header in case we loose the y-scrollbar */
|
|
4011 divBody.scroll();
|
|
4012
|
|
4013 // If sorting or filtering has occurred, jump the scrolling back to the top
|
|
4014 // only if we aren't holding the position
|
|
4015 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
|
|
4016 divBodyEl.scrollTop = 0;
|
|
4017 }
|
|
4018 }
|
|
4019
|
|
4020
|
|
4021
|
|
4022 /**
|
|
4023 * Apply a given function to the display child nodes of an element array (typically
|
|
4024 * TD children of TR rows
|
|
4025 * @param {function} fn Method to apply to the objects
|
|
4026 * @param array {nodes} an1 List of elements to look through for display children
|
|
4027 * @param array {nodes} an2 Another list (identical structure to the first) - optional
|
|
4028 * @memberof DataTable#oApi
|
|
4029 */
|
|
4030 function _fnApplyToChildren( fn, an1, an2 )
|
|
4031 {
|
|
4032 var index=0, i=0, iLen=an1.length;
|
|
4033 var nNode1, nNode2;
|
|
4034
|
|
4035 while ( i < iLen ) {
|
|
4036 nNode1 = an1[i].firstChild;
|
|
4037 nNode2 = an2 ? an2[i].firstChild : null;
|
|
4038
|
|
4039 while ( nNode1 ) {
|
|
4040 if ( nNode1.nodeType === 1 ) {
|
|
4041 if ( an2 ) {
|
|
4042 fn( nNode1, nNode2, index );
|
|
4043 }
|
|
4044 else {
|
|
4045 fn( nNode1, index );
|
|
4046 }
|
|
4047
|
|
4048 index++;
|
|
4049 }
|
|
4050
|
|
4051 nNode1 = nNode1.nextSibling;
|
|
4052 nNode2 = an2 ? nNode2.nextSibling : null;
|
|
4053 }
|
|
4054
|
|
4055 i++;
|
|
4056 }
|
|
4057 }
|
|
4058
|
|
4059
|
|
4060
|
|
4061 var __re_html_remove = /<.*?>/g;
|
|
4062
|
|
4063
|
|
4064 /**
|
|
4065 * Calculate the width of columns for the table
|
|
4066 * @param {object} oSettings dataTables settings object
|
|
4067 * @memberof DataTable#oApi
|
|
4068 */
|
|
4069 function _fnCalculateColumnWidths ( oSettings )
|
|
4070 {
|
|
4071 var
|
|
4072 table = oSettings.nTable,
|
|
4073 columns = oSettings.aoColumns,
|
|
4074 scroll = oSettings.oScroll,
|
|
4075 scrollY = scroll.sY,
|
|
4076 scrollX = scroll.sX,
|
|
4077 scrollXInner = scroll.sXInner,
|
|
4078 columnCount = columns.length,
|
|
4079 visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
|
|
4080 headerCells = $('th', oSettings.nTHead),
|
|
4081 tableWidthAttr = table.getAttribute('width'),
|
|
4082 tableContainer = table.parentNode,
|
|
4083 userInputs = false,
|
|
4084 i, column, columnIdx, width, outerWidth;
|
|
4085
|
|
4086 /* Convert any user input sizes into pixel sizes */
|
|
4087 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
4088 column = columns[ visibleColumns[i] ];
|
|
4089
|
|
4090 if ( column.sWidth !== null ) {
|
|
4091 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
|
|
4092
|
|
4093 userInputs = true;
|
|
4094 }
|
|
4095 }
|
|
4096
|
|
4097 /* If the number of columns in the DOM equals the number that we have to
|
|
4098 * process in DataTables, then we can use the offsets that are created by
|
|
4099 * the web- browser. No custom sizes can be set in order for this to happen,
|
|
4100 * nor scrolling used
|
|
4101 */
|
|
4102 if ( ! userInputs && ! scrollX && ! scrollY &&
|
|
4103 columnCount == _fnVisbleColumns( oSettings ) &&
|
|
4104 columnCount == headerCells.length
|
|
4105 ) {
|
|
4106 for ( i=0 ; i<columnCount ; i++ ) {
|
|
4107 columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
|
|
4108 }
|
|
4109 }
|
|
4110 else
|
|
4111 {
|
|
4112 // Otherwise construct a single row table with the widest node in the
|
|
4113 // data, assign any user defined widths, then insert it into the DOM and
|
|
4114 // allow the browser to do all the hard work of calculating table widths
|
|
4115 var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
|
|
4116 .empty()
|
|
4117 .css( 'visibility', 'hidden' )
|
|
4118 .removeAttr( 'id' )
|
|
4119 .append( $(oSettings.nTHead).clone( false ) )
|
|
4120 .append( $(oSettings.nTFoot).clone( false ) )
|
|
4121 .append( $('<tbody><tr/></tbody>') );
|
|
4122
|
|
4123 // Remove any assigned widths from the footer (from scrolling)
|
|
4124 tmpTable.find('tfoot th, tfoot td').css('width', '');
|
|
4125
|
|
4126 var tr = tmpTable.find( 'tbody tr' );
|
|
4127
|
|
4128 // Apply custom sizing to the cloned header
|
|
4129 headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
|
|
4130
|
|
4131 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
4132 column = columns[ visibleColumns[i] ];
|
|
4133
|
|
4134 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
|
|
4135 _fnStringToCss( column.sWidthOrig ) :
|
|
4136 '';
|
|
4137 }
|
|
4138
|
|
4139 // Find the widest cell for each column and put it into the table
|
|
4140 if ( oSettings.aoData.length ) {
|
|
4141 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
4142 columnIdx = visibleColumns[i];
|
|
4143 column = columns[ columnIdx ];
|
|
4144
|
|
4145 $( _fnGetWidestNode( oSettings, columnIdx ) )
|
|
4146 .clone( false )
|
|
4147 .append( column.sContentPadding )
|
|
4148 .appendTo( tr );
|
|
4149 }
|
|
4150 }
|
|
4151
|
|
4152 // Table has been built, attach to the document so we can work with it
|
|
4153 tmpTable.appendTo( tableContainer );
|
|
4154
|
|
4155 // When scrolling (X or Y) we want to set the width of the table as
|
|
4156 // appropriate. However, when not scrolling leave the table width as it
|
|
4157 // is. This results in slightly different, but I think correct behaviour
|
|
4158 if ( scrollX && scrollXInner ) {
|
|
4159 tmpTable.width( scrollXInner );
|
|
4160 }
|
|
4161 else if ( scrollX ) {
|
|
4162 tmpTable.css( 'width', 'auto' );
|
|
4163
|
|
4164 if ( tmpTable.width() < tableContainer.offsetWidth ) {
|
|
4165 tmpTable.width( tableContainer.offsetWidth );
|
|
4166 }
|
|
4167 }
|
|
4168 else if ( scrollY ) {
|
|
4169 tmpTable.width( tableContainer.offsetWidth );
|
|
4170 }
|
|
4171 else if ( tableWidthAttr ) {
|
|
4172 tmpTable.width( tableWidthAttr );
|
|
4173 }
|
|
4174
|
|
4175 // Take into account the y scrollbar
|
|
4176 _fnScrollingWidthAdjust( oSettings, tmpTable[0] );
|
|
4177
|
|
4178 // Browsers need a bit of a hand when a width is assigned to any columns
|
|
4179 // when x-scrolling as they tend to collapse the table to the min-width,
|
|
4180 // even if we sent the column widths. So we need to keep track of what
|
|
4181 // the table width should be by summing the user given values, and the
|
|
4182 // automatic values
|
|
4183 if ( scrollX )
|
|
4184 {
|
|
4185 var total = 0;
|
|
4186
|
|
4187 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
4188 column = columns[ visibleColumns[i] ];
|
|
4189 outerWidth = $(headerCells[i]).outerWidth();
|
|
4190
|
|
4191 total += column.sWidthOrig === null ?
|
|
4192 outerWidth :
|
|
4193 parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
|
|
4194 }
|
|
4195
|
|
4196 tmpTable.width( _fnStringToCss( total ) );
|
|
4197 table.style.width = _fnStringToCss( total );
|
|
4198 }
|
|
4199
|
|
4200 // Get the width of each column in the constructed table
|
|
4201 for ( i=0 ; i<visibleColumns.length ; i++ ) {
|
|
4202 column = columns[ visibleColumns[i] ];
|
|
4203 width = $(headerCells[i]).width();
|
|
4204
|
|
4205 if ( width ) {
|
|
4206 column.sWidth = _fnStringToCss( width );
|
|
4207 }
|
|
4208 }
|
|
4209
|
|
4210 table.style.width = _fnStringToCss( tmpTable.css('width') );
|
|
4211
|
|
4212 // Finished with the table - ditch it
|
|
4213 tmpTable.remove();
|
|
4214 }
|
|
4215
|
|
4216 // If there is a width attr, we want to attach an event listener which
|
|
4217 // allows the table sizing to automatically adjust when the window is
|
|
4218 // resized. Use the width attr rather than CSS, since we can't know if the
|
|
4219 // CSS is a relative value or absolute - DOM read is always px.
|
|
4220 if ( tableWidthAttr ) {
|
|
4221 table.style.width = _fnStringToCss( tableWidthAttr );
|
|
4222 }
|
|
4223
|
|
4224 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
|
|
4225 $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
|
|
4226 _fnAdjustColumnSizing( oSettings );
|
|
4227 } ) );
|
|
4228
|
|
4229 oSettings._reszEvt = true;
|
|
4230 }
|
|
4231 }
|
|
4232
|
|
4233
|
|
4234 /**
|
|
4235 * Throttle the calls to a function. Arguments and context are maintained for
|
|
4236 * the throttled function
|
|
4237 * @param {function} fn Function to be called
|
|
4238 * @param {int} [freq=200] call frequency in mS
|
|
4239 * @returns {function} wrapped function
|
|
4240 * @memberof DataTable#oApi
|
|
4241 */
|
|
4242 function _fnThrottle( fn, freq ) {
|
|
4243 var
|
|
4244 frequency = freq !== undefined ? freq : 200,
|
|
4245 last,
|
|
4246 timer;
|
|
4247
|
|
4248 return function () {
|
|
4249 var
|
|
4250 that = this,
|
|
4251 now = +new Date(),
|
|
4252 args = arguments;
|
|
4253
|
|
4254 if ( last && now < last + frequency ) {
|
|
4255 clearTimeout( timer );
|
|
4256
|
|
4257 timer = setTimeout( function () {
|
|
4258 last = undefined;
|
|
4259 fn.apply( that, args );
|
|
4260 }, frequency );
|
|
4261 }
|
|
4262 else if ( last ) {
|
|
4263 last = now;
|
|
4264 fn.apply( that, args );
|
|
4265 }
|
|
4266 else {
|
|
4267 last = now;
|
|
4268 }
|
|
4269 };
|
|
4270 }
|
|
4271
|
|
4272
|
|
4273 /**
|
|
4274 * Convert a CSS unit width to pixels (e.g. 2em)
|
|
4275 * @param {string} width width to be converted
|
|
4276 * @param {node} parent parent to get the with for (required for relative widths) - optional
|
|
4277 * @returns {int} width in pixels
|
|
4278 * @memberof DataTable#oApi
|
|
4279 */
|
|
4280 function _fnConvertToWidth ( width, parent )
|
|
4281 {
|
|
4282 if ( ! width ) {
|
|
4283 return 0;
|
|
4284 }
|
|
4285
|
|
4286 var n = $('<div/>')
|
|
4287 .css( 'width', _fnStringToCss( width ) )
|
|
4288 .appendTo( parent || document.body );
|
|
4289
|
|
4290 var val = n[0].offsetWidth;
|
|
4291 n.remove();
|
|
4292
|
|
4293 return val;
|
|
4294 }
|
|
4295
|
|
4296
|
|
4297 /**
|
|
4298 * Adjust a table's width to take account of vertical scroll bar
|
|
4299 * @param {object} oSettings dataTables settings object
|
|
4300 * @param {node} n table node
|
|
4301 * @memberof DataTable#oApi
|
|
4302 */
|
|
4303
|
|
4304 function _fnScrollingWidthAdjust ( settings, n )
|
|
4305 {
|
|
4306 var scroll = settings.oScroll;
|
|
4307
|
|
4308 if ( scroll.sX || scroll.sY ) {
|
|
4309 // When y-scrolling only, we want to remove the width of the scroll bar
|
|
4310 // so the table + scroll bar will fit into the area available, otherwise
|
|
4311 // we fix the table at its current size with no adjustment
|
|
4312 var correction = ! scroll.sX ? scroll.iBarWidth : 0;
|
|
4313 n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
|
|
4314 }
|
|
4315 }
|
|
4316
|
|
4317
|
|
4318 /**
|
|
4319 * Get the widest node
|
|
4320 * @param {object} settings dataTables settings object
|
|
4321 * @param {int} colIdx column of interest
|
|
4322 * @returns {node} widest table node
|
|
4323 * @memberof DataTable#oApi
|
|
4324 */
|
|
4325 function _fnGetWidestNode( settings, colIdx )
|
|
4326 {
|
|
4327 var idx = _fnGetMaxLenString( settings, colIdx );
|
|
4328 if ( idx < 0 ) {
|
|
4329 return null;
|
|
4330 }
|
|
4331
|
|
4332 var data = settings.aoData[ idx ];
|
|
4333 return ! data.nTr ? // Might not have been created when deferred rendering
|
|
4334 $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
|
|
4335 data.anCells[ colIdx ];
|
|
4336 }
|
|
4337
|
|
4338
|
|
4339 /**
|
|
4340 * Get the maximum strlen for each data column
|
|
4341 * @param {object} settings dataTables settings object
|
|
4342 * @param {int} colIdx column of interest
|
|
4343 * @returns {string} max string length for each column
|
|
4344 * @memberof DataTable#oApi
|
|
4345 */
|
|
4346 function _fnGetMaxLenString( settings, colIdx )
|
|
4347 {
|
|
4348 var s, max=-1, maxIdx = -1;
|
|
4349
|
|
4350 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
4351 s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
|
|
4352 s = s.replace( __re_html_remove, '' );
|
|
4353
|
|
4354 if ( s.length > max ) {
|
|
4355 max = s.length;
|
|
4356 maxIdx = i;
|
|
4357 }
|
|
4358 }
|
|
4359
|
|
4360 return maxIdx;
|
|
4361 }
|
|
4362
|
|
4363
|
|
4364 /**
|
|
4365 * Append a CSS unit (only if required) to a string
|
|
4366 * @param {string} value to css-ify
|
|
4367 * @returns {string} value with css unit
|
|
4368 * @memberof DataTable#oApi
|
|
4369 */
|
|
4370 function _fnStringToCss( s )
|
|
4371 {
|
|
4372 if ( s === null ) {
|
|
4373 return '0px';
|
|
4374 }
|
|
4375
|
|
4376 if ( typeof s == 'number' ) {
|
|
4377 return s < 0 ?
|
|
4378 '0px' :
|
|
4379 s+'px';
|
|
4380 }
|
|
4381
|
|
4382 // Check it has a unit character already
|
|
4383 return s.match(/\d$/) ?
|
|
4384 s+'px' :
|
|
4385 s;
|
|
4386 }
|
|
4387
|
|
4388
|
|
4389 /**
|
|
4390 * Get the width of a scroll bar in this browser being used
|
|
4391 * @returns {int} width in pixels
|
|
4392 * @memberof DataTable#oApi
|
|
4393 */
|
|
4394 function _fnScrollBarWidth ()
|
|
4395 {
|
|
4396 // On first run a static variable is set, since this is only needed once.
|
|
4397 // Subsequent runs will just use the previously calculated value
|
|
4398 if ( ! DataTable.__scrollbarWidth ) {
|
|
4399 var inner = $('<p/>').css( {
|
|
4400 width: '100%',
|
|
4401 height: 200,
|
|
4402 padding: 0
|
|
4403 } )[0];
|
|
4404
|
|
4405 var outer = $('<div/>')
|
|
4406 .css( {
|
|
4407 position: 'absolute',
|
|
4408 top: 0,
|
|
4409 left: 0,
|
|
4410 width: 200,
|
|
4411 height: 150,
|
|
4412 padding: 0,
|
|
4413 overflow: 'hidden',
|
|
4414 visibility: 'hidden'
|
|
4415 } )
|
|
4416 .append( inner )
|
|
4417 .appendTo( 'body' );
|
|
4418
|
|
4419 var w1 = inner.offsetWidth;
|
|
4420 outer.css( 'overflow', 'scroll' );
|
|
4421 var w2 = inner.offsetWidth;
|
|
4422
|
|
4423 if ( w1 === w2 ) {
|
|
4424 w2 = outer[0].clientWidth;
|
|
4425 }
|
|
4426
|
|
4427 outer.remove();
|
|
4428
|
|
4429 DataTable.__scrollbarWidth = w1 - w2;
|
|
4430 }
|
|
4431
|
|
4432 return DataTable.__scrollbarWidth;
|
|
4433 }
|
|
4434
|
|
4435
|
|
4436
|
|
4437 function _fnSortFlatten ( settings )
|
|
4438 {
|
|
4439 var
|
|
4440 i, iLen, k, kLen,
|
|
4441 aSort = [],
|
|
4442 aiOrig = [],
|
|
4443 aoColumns = settings.aoColumns,
|
|
4444 aDataSort, iCol, sType, srcCol,
|
|
4445 fixed = settings.aaSortingFixed,
|
|
4446 fixedObj = $.isPlainObject( fixed ),
|
|
4447 nestedSort = [],
|
|
4448 add = function ( a ) {
|
|
4449 if ( a.length && ! $.isArray( a[0] ) ) {
|
|
4450 // 1D array
|
|
4451 nestedSort.push( a );
|
|
4452 }
|
|
4453 else {
|
|
4454 // 2D array
|
|
4455 nestedSort.push.apply( nestedSort, a );
|
|
4456 }
|
|
4457 };
|
|
4458
|
|
4459 // Build the sort array, with pre-fix and post-fix options if they have been
|
|
4460 // specified
|
|
4461 if ( $.isArray( fixed ) ) {
|
|
4462 add( fixed );
|
|
4463 }
|
|
4464
|
|
4465 if ( fixedObj && fixed.pre ) {
|
|
4466 add( fixed.pre );
|
|
4467 }
|
|
4468
|
|
4469 add( settings.aaSorting );
|
|
4470
|
|
4471 if (fixedObj && fixed.post ) {
|
|
4472 add( fixed.post );
|
|
4473 }
|
|
4474
|
|
4475 for ( i=0 ; i<nestedSort.length ; i++ )
|
|
4476 {
|
|
4477 srcCol = nestedSort[i][0];
|
|
4478 aDataSort = aoColumns[ srcCol ].aDataSort;
|
|
4479
|
|
4480 for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
|
|
4481 {
|
|
4482 iCol = aDataSort[k];
|
|
4483 sType = aoColumns[ iCol ].sType || 'string';
|
|
4484
|
|
4485 if ( nestedSort[i]._idx === undefined ) {
|
|
4486 nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
|
|
4487 }
|
|
4488
|
|
4489 aSort.push( {
|
|
4490 src: srcCol,
|
|
4491 col: iCol,
|
|
4492 dir: nestedSort[i][1],
|
|
4493 index: nestedSort[i]._idx,
|
|
4494 type: sType,
|
|
4495 formatter: DataTable.ext.type.order[ sType+"-pre" ]
|
|
4496 } );
|
|
4497 }
|
|
4498 }
|
|
4499
|
|
4500 return aSort;
|
|
4501 }
|
|
4502
|
|
4503 /**
|
|
4504 * Change the order of the table
|
|
4505 * @param {object} oSettings dataTables settings object
|
|
4506 * @memberof DataTable#oApi
|
|
4507 * @todo This really needs split up!
|
|
4508 */
|
|
4509 function _fnSort ( oSettings )
|
|
4510 {
|
|
4511 var
|
|
4512 i, ien, iLen, j, jLen, k, kLen,
|
|
4513 sDataType, nTh,
|
|
4514 aiOrig = [],
|
|
4515 oExtSort = DataTable.ext.type.order,
|
|
4516 aoData = oSettings.aoData,
|
|
4517 aoColumns = oSettings.aoColumns,
|
|
4518 aDataSort, data, iCol, sType, oSort,
|
|
4519 formatters = 0,
|
|
4520 sortCol,
|
|
4521 displayMaster = oSettings.aiDisplayMaster,
|
|
4522 aSort;
|
|
4523
|
|
4524 // Resolve any column types that are unknown due to addition or invalidation
|
|
4525 // @todo Can this be moved into a 'data-ready' handler which is called when
|
|
4526 // data is going to be used in the table?
|
|
4527 _fnColumnTypes( oSettings );
|
|
4528
|
|
4529 aSort = _fnSortFlatten( oSettings );
|
|
4530
|
|
4531 for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
|
|
4532 sortCol = aSort[i];
|
|
4533
|
|
4534 // Track if we can use the fast sort algorithm
|
|
4535 if ( sortCol.formatter ) {
|
|
4536 formatters++;
|
|
4537 }
|
|
4538
|
|
4539 // Load the data needed for the sort, for each cell
|
|
4540 _fnSortData( oSettings, sortCol.col );
|
|
4541 }
|
|
4542
|
|
4543 /* No sorting required if server-side or no sorting array */
|
|
4544 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
|
|
4545 {
|
|
4546 // Create a value - key array of the current row positions such that we can use their
|
|
4547 // current position during the sort, if values match, in order to perform stable sorting
|
|
4548 for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
|
|
4549 aiOrig[ displayMaster[i] ] = i;
|
|
4550 }
|
|
4551
|
|
4552 /* Do the sort - here we want multi-column sorting based on a given data source (column)
|
|
4553 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
|
|
4554 * follow on it's own, but this is what we want (example two column sorting):
|
|
4555 * fnLocalSorting = function(a,b){
|
|
4556 * var iTest;
|
|
4557 * iTest = oSort['string-asc']('data11', 'data12');
|
|
4558 * if (iTest !== 0)
|
|
4559 * return iTest;
|
|
4560 * iTest = oSort['numeric-desc']('data21', 'data22');
|
|
4561 * if (iTest !== 0)
|
|
4562 * return iTest;
|
|
4563 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
|
|
4564 * }
|
|
4565 * Basically we have a test for each sorting column, if the data in that column is equal,
|
|
4566 * test the next column. If all columns match, then we use a numeric sort on the row
|
|
4567 * positions in the original data array to provide a stable sort.
|
|
4568 *
|
|
4569 * Note - I know it seems excessive to have two sorting methods, but the first is around
|
|
4570 * 15% faster, so the second is only maintained for backwards compatibility with sorting
|
|
4571 * methods which do not have a pre-sort formatting function.
|
|
4572 */
|
|
4573 if ( formatters === aSort.length ) {
|
|
4574 // All sort types have formatting functions
|
|
4575 displayMaster.sort( function ( a, b ) {
|
|
4576 var
|
|
4577 x, y, k, test, sort,
|
|
4578 len=aSort.length,
|
|
4579 dataA = aoData[a]._aSortData,
|
|
4580 dataB = aoData[b]._aSortData;
|
|
4581
|
|
4582 for ( k=0 ; k<len ; k++ ) {
|
|
4583 sort = aSort[k];
|
|
4584
|
|
4585 x = dataA[ sort.col ];
|
|
4586 y = dataB[ sort.col ];
|
|
4587
|
|
4588 test = x<y ? -1 : x>y ? 1 : 0;
|
|
4589 if ( test !== 0 ) {
|
|
4590 return sort.dir === 'asc' ? test : -test;
|
|
4591 }
|
|
4592 }
|
|
4593
|
|
4594 x = aiOrig[a];
|
|
4595 y = aiOrig[b];
|
|
4596 return x<y ? -1 : x>y ? 1 : 0;
|
|
4597 } );
|
|
4598 }
|
|
4599 else {
|
|
4600 // Depreciated - remove in 1.11 (providing a plug-in option)
|
|
4601 // Not all sort types have formatting methods, so we have to call their sorting
|
|
4602 // methods.
|
|
4603 displayMaster.sort( function ( a, b ) {
|
|
4604 var
|
|
4605 x, y, k, l, test, sort, fn,
|
|
4606 len=aSort.length,
|
|
4607 dataA = aoData[a]._aSortData,
|
|
4608 dataB = aoData[b]._aSortData;
|
|
4609
|
|
4610 for ( k=0 ; k<len ; k++ ) {
|
|
4611 sort = aSort[k];
|
|
4612
|
|
4613 x = dataA[ sort.col ];
|
|
4614 y = dataB[ sort.col ];
|
|
4615
|
|
4616 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
|
|
4617 test = fn( x, y );
|
|
4618 if ( test !== 0 ) {
|
|
4619 return test;
|
|
4620 }
|
|
4621 }
|
|
4622
|
|
4623 x = aiOrig[a];
|
|
4624 y = aiOrig[b];
|
|
4625 return x<y ? -1 : x>y ? 1 : 0;
|
|
4626 } );
|
|
4627 }
|
|
4628 }
|
|
4629
|
|
4630 /* Tell the draw function that we have sorted the data */
|
|
4631 oSettings.bSorted = true;
|
|
4632 }
|
|
4633
|
|
4634
|
|
4635 function _fnSortAria ( settings )
|
|
4636 {
|
|
4637 var label;
|
|
4638 var nextSort;
|
|
4639 var columns = settings.aoColumns;
|
|
4640 var aSort = _fnSortFlatten( settings );
|
|
4641 var oAria = settings.oLanguage.oAria;
|
|
4642
|
|
4643 // ARIA attributes - need to loop all columns, to update all (removing old
|
|
4644 // attributes as needed)
|
|
4645 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
|
|
4646 {
|
|
4647 var col = columns[i];
|
|
4648 var asSorting = col.asSorting;
|
|
4649 var sTitle = col.sTitle.replace( /<.*?>/g, "" );
|
|
4650 var th = col.nTh;
|
|
4651
|
|
4652 // IE7 is throwing an error when setting these properties with jQuery's
|
|
4653 // attr() and removeAttr() methods...
|
|
4654 th.removeAttribute('aria-sort');
|
|
4655
|
|
4656 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
|
|
4657 if ( col.bSortable ) {
|
|
4658 if ( aSort.length > 0 && aSort[0].col == i ) {
|
|
4659 th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
|
|
4660 nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
|
|
4661 }
|
|
4662 else {
|
|
4663 nextSort = asSorting[0];
|
|
4664 }
|
|
4665
|
|
4666 label = sTitle + ( nextSort === "asc" ?
|
|
4667 oAria.sSortAscending :
|
|
4668 oAria.sSortDescending
|
|
4669 );
|
|
4670 }
|
|
4671 else {
|
|
4672 label = sTitle;
|
|
4673 }
|
|
4674
|
|
4675 th.setAttribute('aria-label', label);
|
|
4676 }
|
|
4677 }
|
|
4678
|
|
4679
|
|
4680 /**
|
|
4681 * Function to run on user sort request
|
|
4682 * @param {object} settings dataTables settings object
|
|
4683 * @param {node} attachTo node to attach the handler to
|
|
4684 * @param {int} colIdx column sorting index
|
|
4685 * @param {boolean} [append=false] Append the requested sort to the existing
|
|
4686 * sort if true (i.e. multi-column sort)
|
|
4687 * @param {function} [callback] callback function
|
|
4688 * @memberof DataTable#oApi
|
|
4689 */
|
|
4690 function _fnSortListener ( settings, colIdx, append, callback )
|
|
4691 {
|
|
4692 var col = settings.aoColumns[ colIdx ];
|
|
4693 var sorting = settings.aaSorting;
|
|
4694 var asSorting = col.asSorting;
|
|
4695 var nextSortIdx;
|
|
4696 var next = function ( a, overflow ) {
|
|
4697 var idx = a._idx;
|
|
4698 if ( idx === undefined ) {
|
|
4699 idx = $.inArray( a[1], asSorting );
|
|
4700 }
|
|
4701
|
|
4702 return idx+1 < asSorting.length ?
|
|
4703 idx+1 :
|
|
4704 overflow ?
|
|
4705 null :
|
|
4706 0;
|
|
4707 };
|
|
4708
|
|
4709 // Convert to 2D array if needed
|
|
4710 if ( typeof sorting[0] === 'number' ) {
|
|
4711 sorting = settings.aaSorting = [ sorting ];
|
|
4712 }
|
|
4713
|
|
4714 // If appending the sort then we are multi-column sorting
|
|
4715 if ( append && settings.oFeatures.bSortMulti ) {
|
|
4716 // Are we already doing some kind of sort on this column?
|
|
4717 var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
|
|
4718
|
|
4719 if ( sortIdx !== -1 ) {
|
|
4720 // Yes, modify the sort
|
|
4721 nextSortIdx = next( sorting[sortIdx], true );
|
|
4722
|
|
4723 if ( nextSortIdx === null ) {
|
|
4724 sorting.splice( sortIdx, 1 );
|
|
4725 }
|
|
4726 else {
|
|
4727 sorting[sortIdx][1] = asSorting[ nextSortIdx ];
|
|
4728 sorting[sortIdx]._idx = nextSortIdx;
|
|
4729 }
|
|
4730 }
|
|
4731 else {
|
|
4732 // No sort on this column yet
|
|
4733 sorting.push( [ colIdx, asSorting[0], 0 ] );
|
|
4734 sorting[sorting.length-1]._idx = 0;
|
|
4735 }
|
|
4736 }
|
|
4737 else if ( sorting.length && sorting[0][0] == colIdx ) {
|
|
4738 // Single column - already sorting on this column, modify the sort
|
|
4739 nextSortIdx = next( sorting[0] );
|
|
4740
|
|
4741 sorting.length = 1;
|
|
4742 sorting[0][1] = asSorting[ nextSortIdx ];
|
|
4743 sorting[0]._idx = nextSortIdx;
|
|
4744 }
|
|
4745 else {
|
|
4746 // Single column - sort only on this column
|
|
4747 sorting.length = 0;
|
|
4748 sorting.push( [ colIdx, asSorting[0] ] );
|
|
4749 sorting[0]._idx = 0;
|
|
4750 }
|
|
4751
|
|
4752 // Run the sort by calling a full redraw
|
|
4753 _fnReDraw( settings );
|
|
4754
|
|
4755 // callback used for async user interaction
|
|
4756 if ( typeof callback == 'function' ) {
|
|
4757 callback( settings );
|
|
4758 }
|
|
4759 }
|
|
4760
|
|
4761
|
|
4762 /**
|
|
4763 * Attach a sort handler (click) to a node
|
|
4764 * @param {object} settings dataTables settings object
|
|
4765 * @param {node} attachTo node to attach the handler to
|
|
4766 * @param {int} colIdx column sorting index
|
|
4767 * @param {function} [callback] callback function
|
|
4768 * @memberof DataTable#oApi
|
|
4769 */
|
|
4770 function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
|
|
4771 {
|
|
4772 var col = settings.aoColumns[ colIdx ];
|
|
4773
|
|
4774 _fnBindAction( attachTo, {}, function (e) {
|
|
4775 /* If the column is not sortable - don't to anything */
|
|
4776 if ( col.bSortable === false ) {
|
|
4777 return;
|
|
4778 }
|
|
4779
|
|
4780 // If processing is enabled use a timeout to allow the processing
|
|
4781 // display to be shown - otherwise to it synchronously
|
|
4782 if ( settings.oFeatures.bProcessing ) {
|
|
4783 _fnProcessingDisplay( settings, true );
|
|
4784
|
|
4785 setTimeout( function() {
|
|
4786 _fnSortListener( settings, colIdx, e.shiftKey, callback );
|
|
4787
|
|
4788 // In server-side processing, the draw callback will remove the
|
|
4789 // processing display
|
|
4790 if ( _fnDataSource( settings ) !== 'ssp' ) {
|
|
4791 _fnProcessingDisplay( settings, false );
|
|
4792 }
|
|
4793 }, 0 );
|
|
4794 }
|
|
4795 else {
|
|
4796 _fnSortListener( settings, colIdx, e.shiftKey, callback );
|
|
4797 }
|
|
4798 } );
|
|
4799 }
|
|
4800
|
|
4801
|
|
4802 /**
|
|
4803 * Set the sorting classes on table's body, Note: it is safe to call this function
|
|
4804 * when bSort and bSortClasses are false
|
|
4805 * @param {object} oSettings dataTables settings object
|
|
4806 * @memberof DataTable#oApi
|
|
4807 */
|
|
4808 function _fnSortingClasses( settings )
|
|
4809 {
|
|
4810 var oldSort = settings.aLastSort;
|
|
4811 var sortClass = settings.oClasses.sSortColumn;
|
|
4812 var sort = _fnSortFlatten( settings );
|
|
4813 var features = settings.oFeatures;
|
|
4814 var i, ien, colIdx;
|
|
4815
|
|
4816 if ( features.bSort && features.bSortClasses ) {
|
|
4817 // Remove old sorting classes
|
|
4818 for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
|
|
4819 colIdx = oldSort[i].src;
|
|
4820
|
|
4821 // Remove column sorting
|
|
4822 $( _pluck( settings.aoData, 'anCells', colIdx ) )
|
|
4823 .removeClass( sortClass + (i<2 ? i+1 : 3) );
|
|
4824 }
|
|
4825
|
|
4826 // Add new column sorting
|
|
4827 for ( i=0, ien=sort.length ; i<ien ; i++ ) {
|
|
4828 colIdx = sort[i].src;
|
|
4829
|
|
4830 $( _pluck( settings.aoData, 'anCells', colIdx ) )
|
|
4831 .addClass( sortClass + (i<2 ? i+1 : 3) );
|
|
4832 }
|
|
4833 }
|
|
4834
|
|
4835 settings.aLastSort = sort;
|
|
4836 }
|
|
4837
|
|
4838
|
|
4839 // Get the data to sort a column, be it from cache, fresh (populating the
|
|
4840 // cache), or from a sort formatter
|
|
4841 function _fnSortData( settings, idx )
|
|
4842 {
|
|
4843 // Custom sorting function - provided by the sort data type
|
|
4844 var column = settings.aoColumns[ idx ];
|
|
4845 var customSort = DataTable.ext.order[ column.sSortDataType ];
|
|
4846 var customData;
|
|
4847
|
|
4848 if ( customSort ) {
|
|
4849 customData = customSort.call( settings.oInstance, settings, idx,
|
|
4850 _fnColumnIndexToVisible( settings, idx )
|
|
4851 );
|
|
4852 }
|
|
4853
|
|
4854 // Use / populate cache
|
|
4855 var row, cellData;
|
|
4856 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
|
|
4857
|
|
4858 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
4859 row = settings.aoData[i];
|
|
4860
|
|
4861 if ( ! row._aSortData ) {
|
|
4862 row._aSortData = [];
|
|
4863 }
|
|
4864
|
|
4865 if ( ! row._aSortData[idx] || customSort ) {
|
|
4866 cellData = customSort ?
|
|
4867 customData[i] : // If there was a custom sort function, use data from there
|
|
4868 _fnGetCellData( settings, i, idx, 'sort' );
|
|
4869
|
|
4870 row._aSortData[ idx ] = formatter ?
|
|
4871 formatter( cellData ) :
|
|
4872 cellData;
|
|
4873 }
|
|
4874 }
|
|
4875 }
|
|
4876
|
|
4877
|
|
4878
|
|
4879 /**
|
|
4880 * Save the state of a table
|
|
4881 * @param {object} oSettings dataTables settings object
|
|
4882 * @memberof DataTable#oApi
|
|
4883 */
|
|
4884 function _fnSaveState ( settings )
|
|
4885 {
|
|
4886 if ( !settings.oFeatures.bStateSave || settings.bDestroying )
|
|
4887 {
|
|
4888 return;
|
|
4889 }
|
|
4890
|
|
4891 /* Store the interesting variables */
|
|
4892 var state = {
|
|
4893 time: +new Date(),
|
|
4894 start: settings._iDisplayStart,
|
|
4895 length: settings._iDisplayLength,
|
|
4896 order: $.extend( true, [], settings.aaSorting ),
|
|
4897 search: _fnSearchToCamel( settings.oPreviousSearch ),
|
|
4898 columns: $.map( settings.aoColumns, function ( col, i ) {
|
|
4899 return {
|
|
4900 visible: col.bVisible,
|
|
4901 search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
|
|
4902 };
|
|
4903 } )
|
|
4904 };
|
|
4905
|
|
4906 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
|
|
4907
|
|
4908 settings.oSavedState = state;
|
|
4909 settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
|
|
4910 }
|
|
4911
|
|
4912
|
|
4913 /**
|
|
4914 * Attempt to load a saved table state
|
|
4915 * @param {object} oSettings dataTables settings object
|
|
4916 * @param {object} oInit DataTables init object so we can override settings
|
|
4917 * @memberof DataTable#oApi
|
|
4918 */
|
|
4919 function _fnLoadState ( settings, oInit )
|
|
4920 {
|
|
4921 var i, ien;
|
|
4922 var columns = settings.aoColumns;
|
|
4923
|
|
4924 if ( ! settings.oFeatures.bStateSave ) {
|
|
4925 return;
|
|
4926 }
|
|
4927
|
|
4928 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
|
|
4929 if ( ! state || ! state.time ) {
|
|
4930 return;
|
|
4931 }
|
|
4932
|
|
4933 /* Allow custom and plug-in manipulation functions to alter the saved data set and
|
|
4934 * cancelling of loading by returning false
|
|
4935 */
|
|
4936 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
|
|
4937 if ( $.inArray( false, abStateLoad ) !== -1 ) {
|
|
4938 return;
|
|
4939 }
|
|
4940
|
|
4941 /* Reject old data */
|
|
4942 var duration = settings.iStateDuration;
|
|
4943 if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
|
|
4944 return;
|
|
4945 }
|
|
4946
|
|
4947 // Number of columns have changed - all bets are off, no restore of settings
|
|
4948 if ( columns.length !== state.columns.length ) {
|
|
4949 return;
|
|
4950 }
|
|
4951
|
|
4952 // Store the saved state so it might be accessed at any time
|
|
4953 settings.oLoadedState = $.extend( true, {}, state );
|
|
4954
|
|
4955 // Restore key features - todo - for 1.11 this needs to be done by
|
|
4956 // subscribed events
|
|
4957 settings._iDisplayStart = state.start;
|
|
4958 settings.iInitDisplayStart = state.start;
|
|
4959 settings._iDisplayLength = state.length;
|
|
4960 settings.aaSorting = [];
|
|
4961
|
|
4962 // Order
|
|
4963 $.each( state.order, function ( i, col ) {
|
|
4964 settings.aaSorting.push( col[0] >= columns.length ?
|
|
4965 [ 0, col[1] ] :
|
|
4966 col
|
|
4967 );
|
|
4968 } );
|
|
4969
|
|
4970 // Search
|
|
4971 $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
|
|
4972
|
|
4973 // Columns
|
|
4974 for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
|
|
4975 var col = state.columns[i];
|
|
4976
|
|
4977 // Visibility
|
|
4978 columns[i].bVisible = col.visible;
|
|
4979
|
|
4980 // Search
|
|
4981 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
|
|
4982 }
|
|
4983
|
|
4984 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
|
|
4985 }
|
|
4986
|
|
4987
|
|
4988 /**
|
|
4989 * Return the settings object for a particular table
|
|
4990 * @param {node} table table we are using as a dataTable
|
|
4991 * @returns {object} Settings object - or null if not found
|
|
4992 * @memberof DataTable#oApi
|
|
4993 */
|
|
4994 function _fnSettingsFromNode ( table )
|
|
4995 {
|
|
4996 var settings = DataTable.settings;
|
|
4997 var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
|
|
4998
|
|
4999 return idx !== -1 ?
|
|
5000 settings[ idx ] :
|
|
5001 null;
|
|
5002 }
|
|
5003
|
|
5004
|
|
5005 /**
|
|
5006 * Log an error message
|
|
5007 * @param {object} settings dataTables settings object
|
|
5008 * @param {int} level log error messages, or display them to the user
|
|
5009 * @param {string} msg error message
|
|
5010 * @param {int} tn Technical note id to get more information about the error.
|
|
5011 * @memberof DataTable#oApi
|
|
5012 */
|
|
5013 function _fnLog( settings, level, msg, tn )
|
|
5014 {
|
|
5015 msg = 'DataTables warning: '+
|
|
5016 (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
|
|
5017
|
|
5018 if ( tn ) {
|
|
5019 msg += '. For more information about this error, please see '+
|
|
5020 'http://datatables.net/tn/'+tn;
|
|
5021 }
|
|
5022
|
|
5023 if ( ! level ) {
|
|
5024 // Backwards compatibility pre 1.10
|
|
5025 var ext = DataTable.ext;
|
|
5026 var type = ext.sErrMode || ext.errMode;
|
|
5027
|
|
5028 if ( type == 'alert' ) {
|
|
5029 alert( msg );
|
|
5030 }
|
|
5031 else {
|
|
5032 throw new Error(msg);
|
|
5033 }
|
|
5034 }
|
|
5035 else if ( window.console && console.log ) {
|
|
5036 console.log( msg );
|
|
5037 }
|
|
5038 }
|
|
5039
|
|
5040
|
|
5041 /**
|
|
5042 * See if a property is defined on one object, if so assign it to the other object
|
|
5043 * @param {object} ret target object
|
|
5044 * @param {object} src source object
|
|
5045 * @param {string} name property
|
|
5046 * @param {string} [mappedName] name to map too - optional, name used if not given
|
|
5047 * @memberof DataTable#oApi
|
|
5048 */
|
|
5049 function _fnMap( ret, src, name, mappedName )
|
|
5050 {
|
|
5051 if ( $.isArray( name ) ) {
|
|
5052 $.each( name, function (i, val) {
|
|
5053 if ( $.isArray( val ) ) {
|
|
5054 _fnMap( ret, src, val[0], val[1] );
|
|
5055 }
|
|
5056 else {
|
|
5057 _fnMap( ret, src, val );
|
|
5058 }
|
|
5059 } );
|
|
5060
|
|
5061 return;
|
|
5062 }
|
|
5063
|
|
5064 if ( mappedName === undefined ) {
|
|
5065 mappedName = name;
|
|
5066 }
|
|
5067
|
|
5068 if ( src[name] !== undefined ) {
|
|
5069 ret[mappedName] = src[name];
|
|
5070 }
|
|
5071 }
|
|
5072
|
|
5073
|
|
5074 /**
|
|
5075 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
|
|
5076 * shallow copy arrays. The reason we need to do this, is that we don't want to
|
|
5077 * deep copy array init values (such as aaSorting) since the dev wouldn't be
|
|
5078 * able to override them, but we do want to deep copy arrays.
|
|
5079 * @param {object} out Object to extend
|
|
5080 * @param {object} extender Object from which the properties will be applied to
|
|
5081 * out
|
|
5082 * @param {boolean} breakRefs If true, then arrays will be sliced to take an
|
|
5083 * independent copy with the exception of the `data` or `aaData` parameters
|
|
5084 * if they are present. This is so you can pass in a collection to
|
|
5085 * DataTables and have that used as your data source without breaking the
|
|
5086 * references
|
|
5087 * @returns {object} out Reference, just for convenience - out === the return.
|
|
5088 * @memberof DataTable#oApi
|
|
5089 * @todo This doesn't take account of arrays inside the deep copied objects.
|
|
5090 */
|
|
5091 function _fnExtend( out, extender, breakRefs )
|
|
5092 {
|
|
5093 var val;
|
|
5094
|
|
5095 for ( var prop in extender ) {
|
|
5096 if ( extender.hasOwnProperty(prop) ) {
|
|
5097 val = extender[prop];
|
|
5098
|
|
5099 if ( $.isPlainObject( val ) ) {
|
|
5100 if ( ! $.isPlainObject( out[prop] ) ) {
|
|
5101 out[prop] = {};
|
|
5102 }
|
|
5103 $.extend( true, out[prop], val );
|
|
5104 }
|
|
5105 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
|
|
5106 out[prop] = val.slice();
|
|
5107 }
|
|
5108 else {
|
|
5109 out[prop] = val;
|
|
5110 }
|
|
5111 }
|
|
5112 }
|
|
5113
|
|
5114 return out;
|
|
5115 }
|
|
5116
|
|
5117
|
|
5118 /**
|
|
5119 * Bind an event handers to allow a click or return key to activate the callback.
|
|
5120 * This is good for accessibility since a return on the keyboard will have the
|
|
5121 * same effect as a click, if the element has focus.
|
|
5122 * @param {element} n Element to bind the action to
|
|
5123 * @param {object} oData Data object to pass to the triggered function
|
|
5124 * @param {function} fn Callback function for when the event is triggered
|
|
5125 * @memberof DataTable#oApi
|
|
5126 */
|
|
5127 function _fnBindAction( n, oData, fn )
|
|
5128 {
|
|
5129 $(n)
|
|
5130 .bind( 'click.DT', oData, function (e) {
|
|
5131 n.blur(); // Remove focus outline for mouse users
|
|
5132 fn(e);
|
|
5133 } )
|
|
5134 .bind( 'keypress.DT', oData, function (e){
|
|
5135 if ( e.which === 13 ) {
|
|
5136 e.preventDefault();
|
|
5137 fn(e);
|
|
5138 }
|
|
5139 } )
|
|
5140 .bind( 'selectstart.DT', function () {
|
|
5141 /* Take the brutal approach to cancelling text selection */
|
|
5142 return false;
|
|
5143 } );
|
|
5144 }
|
|
5145
|
|
5146
|
|
5147 /**
|
|
5148 * Register a callback function. Easily allows a callback function to be added to
|
|
5149 * an array store of callback functions that can then all be called together.
|
|
5150 * @param {object} oSettings dataTables settings object
|
|
5151 * @param {string} sStore Name of the array storage for the callbacks in oSettings
|
|
5152 * @param {function} fn Function to be called back
|
|
5153 * @param {string} sName Identifying name for the callback (i.e. a label)
|
|
5154 * @memberof DataTable#oApi
|
|
5155 */
|
|
5156 function _fnCallbackReg( oSettings, sStore, fn, sName )
|
|
5157 {
|
|
5158 if ( fn )
|
|
5159 {
|
|
5160 oSettings[sStore].push( {
|
|
5161 "fn": fn,
|
|
5162 "sName": sName
|
|
5163 } );
|
|
5164 }
|
|
5165 }
|
|
5166
|
|
5167
|
|
5168 /**
|
|
5169 * Fire callback functions and trigger events. Note that the loop over the
|
|
5170 * callback array store is done backwards! Further note that you do not want to
|
|
5171 * fire off triggers in time sensitive applications (for example cell creation)
|
|
5172 * as its slow.
|
|
5173 * @param {object} settings dataTables settings object
|
|
5174 * @param {string} callbackArr Name of the array storage for the callbacks in
|
|
5175 * oSettings
|
|
5176 * @param {string} event Name of the jQuery custom event to trigger. If null no
|
|
5177 * trigger is fired
|
|
5178 * @param {array} args Array of arguments to pass to the callback function /
|
|
5179 * trigger
|
|
5180 * @memberof DataTable#oApi
|
|
5181 */
|
|
5182 function _fnCallbackFire( settings, callbackArr, e, args )
|
|
5183 {
|
|
5184 var ret = [];
|
|
5185
|
|
5186 if ( callbackArr ) {
|
|
5187 ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
|
|
5188 return val.fn.apply( settings.oInstance, args );
|
|
5189 } );
|
|
5190 }
|
|
5191
|
|
5192 if ( e !== null ) {
|
|
5193 $(settings.nTable).trigger( e+'.dt', args );
|
|
5194 }
|
|
5195
|
|
5196 return ret;
|
|
5197 }
|
|
5198
|
|
5199
|
|
5200 function _fnLengthOverflow ( settings )
|
|
5201 {
|
|
5202 var
|
|
5203 start = settings._iDisplayStart,
|
|
5204 end = settings.fnDisplayEnd(),
|
|
5205 len = settings._iDisplayLength;
|
|
5206
|
|
5207 /* If we have space to show extra rows (backing up from the end point - then do so */
|
|
5208 if ( start >= end )
|
|
5209 {
|
|
5210 start = end - len;
|
|
5211 }
|
|
5212
|
|
5213 // Keep the start record on the current page
|
|
5214 start -= (start % len);
|
|
5215
|
|
5216 if ( len === -1 || start < 0 )
|
|
5217 {
|
|
5218 start = 0;
|
|
5219 }
|
|
5220
|
|
5221 settings._iDisplayStart = start;
|
|
5222 }
|
|
5223
|
|
5224
|
|
5225 function _fnRenderer( settings, type )
|
|
5226 {
|
|
5227 var renderer = settings.renderer;
|
|
5228 var host = DataTable.ext.renderer[type];
|
|
5229
|
|
5230 if ( $.isPlainObject( renderer ) && renderer[type] ) {
|
|
5231 // Specific renderer for this type. If available use it, otherwise use
|
|
5232 // the default.
|
|
5233 return host[renderer[type]] || host._;
|
|
5234 }
|
|
5235 else if ( typeof renderer === 'string' ) {
|
|
5236 // Common renderer - if there is one available for this type use it,
|
|
5237 // otherwise use the default
|
|
5238 return host[renderer] || host._;
|
|
5239 }
|
|
5240
|
|
5241 // Use the default
|
|
5242 return host._;
|
|
5243 }
|
|
5244
|
|
5245
|
|
5246 /**
|
|
5247 * Detect the data source being used for the table. Used to simplify the code
|
|
5248 * a little (ajax) and to make it compress a little smaller.
|
|
5249 *
|
|
5250 * @param {object} settings dataTables settings object
|
|
5251 * @returns {string} Data source
|
|
5252 * @memberof DataTable#oApi
|
|
5253 */
|
|
5254 function _fnDataSource ( settings )
|
|
5255 {
|
|
5256 if ( settings.oFeatures.bServerSide ) {
|
|
5257 return 'ssp';
|
|
5258 }
|
|
5259 else if ( settings.ajax || settings.sAjaxSource ) {
|
|
5260 return 'ajax';
|
|
5261 }
|
|
5262 return 'dom';
|
|
5263 }
|
|
5264
|
|
5265
|
|
5266 DataTable = function( options )
|
|
5267 {
|
|
5268 /**
|
|
5269 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
|
|
5270 * return the resulting jQuery object.
|
|
5271 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
|
|
5272 * @param {object} [oOpts] Optional parameters for modifying the rows to be included
|
|
5273 * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
|
|
5274 * criterion ("applied") or all TR elements (i.e. no filter).
|
|
5275 * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
|
|
5276 * Can be either 'current', whereby the current sorting of the table is used, or
|
|
5277 * 'original' whereby the original order the data was read into the table is used.
|
|
5278 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
|
|
5279 * ("current") or not ("all"). If 'current' is given, then order is assumed to be
|
|
5280 * 'current' and filter is 'applied', regardless of what they might be given as.
|
|
5281 * @returns {object} jQuery object, filtered by the given selector.
|
|
5282 * @dtopt API
|
|
5283 * @deprecated Since v1.10
|
|
5284 *
|
|
5285 * @example
|
|
5286 * $(document).ready(function() {
|
|
5287 * var oTable = $('#example').dataTable();
|
|
5288 *
|
|
5289 * // Highlight every second row
|
|
5290 * oTable.$('tr:odd').css('backgroundColor', 'blue');
|
|
5291 * } );
|
|
5292 *
|
|
5293 * @example
|
|
5294 * $(document).ready(function() {
|
|
5295 * var oTable = $('#example').dataTable();
|
|
5296 *
|
|
5297 * // Filter to rows with 'Webkit' in them, add a background colour and then
|
|
5298 * // remove the filter, thus highlighting the 'Webkit' rows only.
|
|
5299 * oTable.fnFilter('Webkit');
|
|
5300 * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
|
|
5301 * oTable.fnFilter('');
|
|
5302 * } );
|
|
5303 */
|
|
5304 this.$ = function ( sSelector, oOpts )
|
|
5305 {
|
|
5306 return this.api(true).$( sSelector, oOpts );
|
|
5307 };
|
|
5308
|
|
5309
|
|
5310 /**
|
|
5311 * Almost identical to $ in operation, but in this case returns the data for the matched
|
|
5312 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
|
|
5313 * rather than any descendants, so the data can be obtained for the row/cell. If matching
|
|
5314 * rows are found, the data returned is the original data array/object that was used to
|
|
5315 * create the row (or a generated array if from a DOM source).
|
|
5316 *
|
|
5317 * This method is often useful in-combination with $ where both functions are given the
|
|
5318 * same parameters and the array indexes will match identically.
|
|
5319 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
|
|
5320 * @param {object} [oOpts] Optional parameters for modifying the rows to be included
|
|
5321 * @param {string} [oOpts.filter=none] Select elements that meet the current filter
|
|
5322 * criterion ("applied") or all elements (i.e. no filter).
|
|
5323 * @param {string} [oOpts.order=current] Order of the data in the processed array.
|
|
5324 * Can be either 'current', whereby the current sorting of the table is used, or
|
|
5325 * 'original' whereby the original order the data was read into the table is used.
|
|
5326 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
|
|
5327 * ("current") or not ("all"). If 'current' is given, then order is assumed to be
|
|
5328 * 'current' and filter is 'applied', regardless of what they might be given as.
|
|
5329 * @returns {array} Data for the matched elements. If any elements, as a result of the
|
|
5330 * selector, were not TR, TD or TH elements in the DataTable, they will have a null
|
|
5331 * entry in the array.
|
|
5332 * @dtopt API
|
|
5333 * @deprecated Since v1.10
|
|
5334 *
|
|
5335 * @example
|
|
5336 * $(document).ready(function() {
|
|
5337 * var oTable = $('#example').dataTable();
|
|
5338 *
|
|
5339 * // Get the data from the first row in the table
|
|
5340 * var data = oTable._('tr:first');
|
|
5341 *
|
|
5342 * // Do something useful with the data
|
|
5343 * alert( "First cell is: "+data[0] );
|
|
5344 * } );
|
|
5345 *
|
|
5346 * @example
|
|
5347 * $(document).ready(function() {
|
|
5348 * var oTable = $('#example').dataTable();
|
|
5349 *
|
|
5350 * // Filter to 'Webkit' and get all data for
|
|
5351 * oTable.fnFilter('Webkit');
|
|
5352 * var data = oTable._('tr', {"search": "applied"});
|
|
5353 *
|
|
5354 * // Do something with the data
|
|
5355 * alert( data.length+" rows matched the search" );
|
|
5356 * } );
|
|
5357 */
|
|
5358 this._ = function ( sSelector, oOpts )
|
|
5359 {
|
|
5360 return this.api(true).rows( sSelector, oOpts ).data();
|
|
5361 };
|
|
5362
|
|
5363
|
|
5364 /**
|
|
5365 * Create a DataTables Api instance, with the currently selected tables for
|
|
5366 * the Api's context.
|
|
5367 * @param {boolean} [traditional=false] Set the API instance's context to be
|
|
5368 * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
|
|
5369 * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
|
|
5370 * or if all tables captured in the jQuery object should be used.
|
|
5371 * @return {DataTables.Api}
|
|
5372 */
|
|
5373 this.api = function ( traditional )
|
|
5374 {
|
|
5375 return traditional ?
|
|
5376 new _Api(
|
|
5377 _fnSettingsFromNode( this[ _ext.iApiIndex ] )
|
|
5378 ) :
|
|
5379 new _Api( this );
|
|
5380 };
|
|
5381
|
|
5382
|
|
5383 /**
|
|
5384 * Add a single new row or multiple rows of data to the table. Please note
|
|
5385 * that this is suitable for client-side processing only - if you are using
|
|
5386 * server-side processing (i.e. "bServerSide": true), then to add data, you
|
|
5387 * must add it to the data source, i.e. the server-side, through an Ajax call.
|
|
5388 * @param {array|object} data The data to be added to the table. This can be:
|
|
5389 * <ul>
|
|
5390 * <li>1D array of data - add a single row with the data provided</li>
|
|
5391 * <li>2D array of arrays - add multiple rows in a single call</li>
|
|
5392 * <li>object - data object when using <i>mData</i></li>
|
|
5393 * <li>array of objects - multiple data objects when using <i>mData</i></li>
|
|
5394 * </ul>
|
|
5395 * @param {bool} [redraw=true] redraw the table or not
|
|
5396 * @returns {array} An array of integers, representing the list of indexes in
|
|
5397 * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
|
|
5398 * the table.
|
|
5399 * @dtopt API
|
|
5400 * @deprecated Since v1.10
|
|
5401 *
|
|
5402 * @example
|
|
5403 * // Global var for counter
|
|
5404 * var giCount = 2;
|
|
5405 *
|
|
5406 * $(document).ready(function() {
|
|
5407 * $('#example').dataTable();
|
|
5408 * } );
|
|
5409 *
|
|
5410 * function fnClickAddRow() {
|
|
5411 * $('#example').dataTable().fnAddData( [
|
|
5412 * giCount+".1",
|
|
5413 * giCount+".2",
|
|
5414 * giCount+".3",
|
|
5415 * giCount+".4" ]
|
|
5416 * );
|
|
5417 *
|
|
5418 * giCount++;
|
|
5419 * }
|
|
5420 */
|
|
5421 this.fnAddData = function( data, redraw )
|
|
5422 {
|
|
5423 var api = this.api( true );
|
|
5424
|
|
5425 /* Check if we want to add multiple rows or not */
|
|
5426 var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
|
|
5427 api.rows.add( data ) :
|
|
5428 api.row.add( data );
|
|
5429
|
|
5430 if ( redraw === undefined || redraw ) {
|
|
5431 api.draw();
|
|
5432 }
|
|
5433
|
|
5434 return rows.flatten().toArray();
|
|
5435 };
|
|
5436
|
|
5437
|
|
5438 /**
|
|
5439 * This function will make DataTables recalculate the column sizes, based on the data
|
|
5440 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
|
|
5441 * through the sWidth parameter). This can be useful when the width of the table's
|
|
5442 * parent element changes (for example a window resize).
|
|
5443 * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
|
|
5444 * @dtopt API
|
|
5445 * @deprecated Since v1.10
|
|
5446 *
|
|
5447 * @example
|
|
5448 * $(document).ready(function() {
|
|
5449 * var oTable = $('#example').dataTable( {
|
|
5450 * "sScrollY": "200px",
|
|
5451 * "bPaginate": false
|
|
5452 * } );
|
|
5453 *
|
|
5454 * $(window).bind('resize', function () {
|
|
5455 * oTable.fnAdjustColumnSizing();
|
|
5456 * } );
|
|
5457 * } );
|
|
5458 */
|
|
5459 this.fnAdjustColumnSizing = function ( bRedraw )
|
|
5460 {
|
|
5461 var api = this.api( true ).columns.adjust();
|
|
5462 var settings = api.settings()[0];
|
|
5463 var scroll = settings.oScroll;
|
|
5464
|
|
5465 if ( bRedraw === undefined || bRedraw ) {
|
|
5466 api.draw( false );
|
|
5467 }
|
|
5468 else if ( scroll.sX !== "" || scroll.sY !== "" ) {
|
|
5469 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
|
|
5470 _fnScrollDraw( settings );
|
|
5471 }
|
|
5472 };
|
|
5473
|
|
5474
|
|
5475 /**
|
|
5476 * Quickly and simply clear a table
|
|
5477 * @param {bool} [bRedraw=true] redraw the table or not
|
|
5478 * @dtopt API
|
|
5479 * @deprecated Since v1.10
|
|
5480 *
|
|
5481 * @example
|
|
5482 * $(document).ready(function() {
|
|
5483 * var oTable = $('#example').dataTable();
|
|
5484 *
|
|
5485 * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
|
|
5486 * oTable.fnClearTable();
|
|
5487 * } );
|
|
5488 */
|
|
5489 this.fnClearTable = function( bRedraw )
|
|
5490 {
|
|
5491 var api = this.api( true ).clear();
|
|
5492
|
|
5493 if ( bRedraw === undefined || bRedraw ) {
|
|
5494 api.draw();
|
|
5495 }
|
|
5496 };
|
|
5497
|
|
5498
|
|
5499 /**
|
|
5500 * The exact opposite of 'opening' a row, this function will close any rows which
|
|
5501 * are currently 'open'.
|
|
5502 * @param {node} nTr the table row to 'close'
|
|
5503 * @returns {int} 0 on success, or 1 if failed (can't find the row)
|
|
5504 * @dtopt API
|
|
5505 * @deprecated Since v1.10
|
|
5506 *
|
|
5507 * @example
|
|
5508 * $(document).ready(function() {
|
|
5509 * var oTable;
|
|
5510 *
|
|
5511 * // 'open' an information row when a row is clicked on
|
|
5512 * $('#example tbody tr').click( function () {
|
|
5513 * if ( oTable.fnIsOpen(this) ) {
|
|
5514 * oTable.fnClose( this );
|
|
5515 * } else {
|
|
5516 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
|
|
5517 * }
|
|
5518 * } );
|
|
5519 *
|
|
5520 * oTable = $('#example').dataTable();
|
|
5521 * } );
|
|
5522 */
|
|
5523 this.fnClose = function( nTr )
|
|
5524 {
|
|
5525 this.api( true ).row( nTr ).child.hide();
|
|
5526 };
|
|
5527
|
|
5528
|
|
5529 /**
|
|
5530 * Remove a row for the table
|
|
5531 * @param {mixed} target The index of the row from aoData to be deleted, or
|
|
5532 * the TR element you want to delete
|
|
5533 * @param {function|null} [callBack] Callback function
|
|
5534 * @param {bool} [redraw=true] Redraw the table or not
|
|
5535 * @returns {array} The row that was deleted
|
|
5536 * @dtopt API
|
|
5537 * @deprecated Since v1.10
|
|
5538 *
|
|
5539 * @example
|
|
5540 * $(document).ready(function() {
|
|
5541 * var oTable = $('#example').dataTable();
|
|
5542 *
|
|
5543 * // Immediately remove the first row
|
|
5544 * oTable.fnDeleteRow( 0 );
|
|
5545 * } );
|
|
5546 */
|
|
5547 this.fnDeleteRow = function( target, callback, redraw )
|
|
5548 {
|
|
5549 var api = this.api( true );
|
|
5550 var rows = api.rows( target );
|
|
5551 var settings = rows.settings()[0];
|
|
5552 var data = settings.aoData[ rows[0][0] ];
|
|
5553
|
|
5554 rows.remove();
|
|
5555
|
|
5556 if ( callback ) {
|
|
5557 callback.call( this, settings, data );
|
|
5558 }
|
|
5559
|
|
5560 if ( redraw === undefined || redraw ) {
|
|
5561 api.draw();
|
|
5562 }
|
|
5563
|
|
5564 return data;
|
|
5565 };
|
|
5566
|
|
5567
|
|
5568 /**
|
|
5569 * Restore the table to it's original state in the DOM by removing all of DataTables
|
|
5570 * enhancements, alterations to the DOM structure of the table and event listeners.
|
|
5571 * @param {boolean} [remove=false] Completely remove the table from the DOM
|
|
5572 * @dtopt API
|
|
5573 * @deprecated Since v1.10
|
|
5574 *
|
|
5575 * @example
|
|
5576 * $(document).ready(function() {
|
|
5577 * // This example is fairly pointless in reality, but shows how fnDestroy can be used
|
|
5578 * var oTable = $('#example').dataTable();
|
|
5579 * oTable.fnDestroy();
|
|
5580 * } );
|
|
5581 */
|
|
5582 this.fnDestroy = function ( remove )
|
|
5583 {
|
|
5584 this.api( true ).destroy( remove );
|
|
5585 };
|
|
5586
|
|
5587
|
|
5588 /**
|
|
5589 * Redraw the table
|
|
5590 * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
|
|
5591 * @dtopt API
|
|
5592 * @deprecated Since v1.10
|
|
5593 *
|
|
5594 * @example
|
|
5595 * $(document).ready(function() {
|
|
5596 * var oTable = $('#example').dataTable();
|
|
5597 *
|
|
5598 * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
|
|
5599 * oTable.fnDraw();
|
|
5600 * } );
|
|
5601 */
|
|
5602 this.fnDraw = function( complete )
|
|
5603 {
|
|
5604 // Note that this isn't an exact match to the old call to _fnDraw - it takes
|
|
5605 // into account the new data, but can old position.
|
|
5606 this.api( true ).draw( ! complete );
|
|
5607 };
|
|
5608
|
|
5609
|
|
5610 /**
|
|
5611 * Filter the input based on data
|
|
5612 * @param {string} sInput String to filter the table on
|
|
5613 * @param {int|null} [iColumn] Column to limit filtering to
|
|
5614 * @param {bool} [bRegex=false] Treat as regular expression or not
|
|
5615 * @param {bool} [bSmart=true] Perform smart filtering or not
|
|
5616 * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
|
|
5617 * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
|
|
5618 * @dtopt API
|
|
5619 * @deprecated Since v1.10
|
|
5620 *
|
|
5621 * @example
|
|
5622 * $(document).ready(function() {
|
|
5623 * var oTable = $('#example').dataTable();
|
|
5624 *
|
|
5625 * // Sometime later - filter...
|
|
5626 * oTable.fnFilter( 'test string' );
|
|
5627 * } );
|
|
5628 */
|
|
5629 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
|
|
5630 {
|
|
5631 var api = this.api( true );
|
|
5632
|
|
5633 if ( iColumn === null || iColumn === undefined ) {
|
|
5634 api.search( sInput, bRegex, bSmart, bCaseInsensitive );
|
|
5635 }
|
|
5636 else {
|
|
5637 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
|
|
5638 }
|
|
5639
|
|
5640 api.draw();
|
|
5641 };
|
|
5642
|
|
5643
|
|
5644 /**
|
|
5645 * Get the data for the whole table, an individual row or an individual cell based on the
|
|
5646 * provided parameters.
|
|
5647 * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
|
|
5648 * a TR node then the data source for the whole row will be returned. If given as a
|
|
5649 * TD/TH cell node then iCol will be automatically calculated and the data for the
|
|
5650 * cell returned. If given as an integer, then this is treated as the aoData internal
|
|
5651 * data index for the row (see fnGetPosition) and the data for that row used.
|
|
5652 * @param {int} [col] Optional column index that you want the data of.
|
|
5653 * @returns {array|object|string} If mRow is undefined, then the data for all rows is
|
|
5654 * returned. If mRow is defined, just data for that row, and is iCol is
|
|
5655 * defined, only data for the designated cell is returned.
|
|
5656 * @dtopt API
|
|
5657 * @deprecated Since v1.10
|
|
5658 *
|
|
5659 * @example
|
|
5660 * // Row data
|
|
5661 * $(document).ready(function() {
|
|
5662 * oTable = $('#example').dataTable();
|
|
5663 *
|
|
5664 * oTable.$('tr').click( function () {
|
|
5665 * var data = oTable.fnGetData( this );
|
|
5666 * // ... do something with the array / object of data for the row
|
|
5667 * } );
|
|
5668 * } );
|
|
5669 *
|
|
5670 * @example
|
|
5671 * // Individual cell data
|
|
5672 * $(document).ready(function() {
|
|
5673 * oTable = $('#example').dataTable();
|
|
5674 *
|
|
5675 * oTable.$('td').click( function () {
|
|
5676 * var sData = oTable.fnGetData( this );
|
|
5677 * alert( 'The cell clicked on had the value of '+sData );
|
|
5678 * } );
|
|
5679 * } );
|
|
5680 */
|
|
5681 this.fnGetData = function( src, col )
|
|
5682 {
|
|
5683 var api = this.api( true );
|
|
5684
|
|
5685 if ( src !== undefined ) {
|
|
5686 var type = src.nodeName ? src.nodeName.toLowerCase() : '';
|
|
5687
|
|
5688 return col !== undefined || type == 'td' || type == 'th' ?
|
|
5689 api.cell( src, col ).data() :
|
|
5690 api.row( src ).data() || null;
|
|
5691 }
|
|
5692
|
|
5693 return api.data().toArray();
|
|
5694 };
|
|
5695
|
|
5696
|
|
5697 /**
|
|
5698 * Get an array of the TR nodes that are used in the table's body. Note that you will
|
|
5699 * typically want to use the '$' API method in preference to this as it is more
|
|
5700 * flexible.
|
|
5701 * @param {int} [iRow] Optional row index for the TR element you want
|
|
5702 * @returns {array|node} If iRow is undefined, returns an array of all TR elements
|
|
5703 * in the table's body, or iRow is defined, just the TR element requested.
|
|
5704 * @dtopt API
|
|
5705 * @deprecated Since v1.10
|
|
5706 *
|
|
5707 * @example
|
|
5708 * $(document).ready(function() {
|
|
5709 * var oTable = $('#example').dataTable();
|
|
5710 *
|
|
5711 * // Get the nodes from the table
|
|
5712 * var nNodes = oTable.fnGetNodes( );
|
|
5713 * } );
|
|
5714 */
|
|
5715 this.fnGetNodes = function( iRow )
|
|
5716 {
|
|
5717 var api = this.api( true );
|
|
5718
|
|
5719 return iRow !== undefined ?
|
|
5720 api.row( iRow ).node() :
|
|
5721 api.rows().nodes().flatten().toArray();
|
|
5722 };
|
|
5723
|
|
5724
|
|
5725 /**
|
|
5726 * Get the array indexes of a particular cell from it's DOM element
|
|
5727 * and column index including hidden columns
|
|
5728 * @param {node} node this can either be a TR, TD or TH in the table's body
|
|
5729 * @returns {int} If nNode is given as a TR, then a single index is returned, or
|
|
5730 * if given as a cell, an array of [row index, column index (visible),
|
|
5731 * column index (all)] is given.
|
|
5732 * @dtopt API
|
|
5733 * @deprecated Since v1.10
|
|
5734 *
|
|
5735 * @example
|
|
5736 * $(document).ready(function() {
|
|
5737 * $('#example tbody td').click( function () {
|
|
5738 * // Get the position of the current data from the node
|
|
5739 * var aPos = oTable.fnGetPosition( this );
|
|
5740 *
|
|
5741 * // Get the data array for this row
|
|
5742 * var aData = oTable.fnGetData( aPos[0] );
|
|
5743 *
|
|
5744 * // Update the data array and return the value
|
|
5745 * aData[ aPos[1] ] = 'clicked';
|
|
5746 * this.innerHTML = 'clicked';
|
|
5747 * } );
|
|
5748 *
|
|
5749 * // Init DataTables
|
|
5750 * oTable = $('#example').dataTable();
|
|
5751 * } );
|
|
5752 */
|
|
5753 this.fnGetPosition = function( node )
|
|
5754 {
|
|
5755 var api = this.api( true );
|
|
5756 var nodeName = node.nodeName.toUpperCase();
|
|
5757
|
|
5758 if ( nodeName == 'TR' ) {
|
|
5759 return api.row( node ).index();
|
|
5760 }
|
|
5761 else if ( nodeName == 'TD' || nodeName == 'TH' ) {
|
|
5762 var cell = api.cell( node ).index();
|
|
5763
|
|
5764 return [
|
|
5765 cell.row,
|
|
5766 cell.columnVisible,
|
|
5767 cell.column
|
|
5768 ];
|
|
5769 }
|
|
5770 return null;
|
|
5771 };
|
|
5772
|
|
5773
|
|
5774 /**
|
|
5775 * Check to see if a row is 'open' or not.
|
|
5776 * @param {node} nTr the table row to check
|
|
5777 * @returns {boolean} true if the row is currently open, false otherwise
|
|
5778 * @dtopt API
|
|
5779 * @deprecated Since v1.10
|
|
5780 *
|
|
5781 * @example
|
|
5782 * $(document).ready(function() {
|
|
5783 * var oTable;
|
|
5784 *
|
|
5785 * // 'open' an information row when a row is clicked on
|
|
5786 * $('#example tbody tr').click( function () {
|
|
5787 * if ( oTable.fnIsOpen(this) ) {
|
|
5788 * oTable.fnClose( this );
|
|
5789 * } else {
|
|
5790 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
|
|
5791 * }
|
|
5792 * } );
|
|
5793 *
|
|
5794 * oTable = $('#example').dataTable();
|
|
5795 * } );
|
|
5796 */
|
|
5797 this.fnIsOpen = function( nTr )
|
|
5798 {
|
|
5799 return this.api( true ).row( nTr ).child.isShown();
|
|
5800 };
|
|
5801
|
|
5802
|
|
5803 /**
|
|
5804 * This function will place a new row directly after a row which is currently
|
|
5805 * on display on the page, with the HTML contents that is passed into the
|
|
5806 * function. This can be used, for example, to ask for confirmation that a
|
|
5807 * particular record should be deleted.
|
|
5808 * @param {node} nTr The table row to 'open'
|
|
5809 * @param {string|node|jQuery} mHtml The HTML to put into the row
|
|
5810 * @param {string} sClass Class to give the new TD cell
|
|
5811 * @returns {node} The row opened. Note that if the table row passed in as the
|
|
5812 * first parameter, is not found in the table, this method will silently
|
|
5813 * return.
|
|
5814 * @dtopt API
|
|
5815 * @deprecated Since v1.10
|
|
5816 *
|
|
5817 * @example
|
|
5818 * $(document).ready(function() {
|
|
5819 * var oTable;
|
|
5820 *
|
|
5821 * // 'open' an information row when a row is clicked on
|
|
5822 * $('#example tbody tr').click( function () {
|
|
5823 * if ( oTable.fnIsOpen(this) ) {
|
|
5824 * oTable.fnClose( this );
|
|
5825 * } else {
|
|
5826 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
|
|
5827 * }
|
|
5828 * } );
|
|
5829 *
|
|
5830 * oTable = $('#example').dataTable();
|
|
5831 * } );
|
|
5832 */
|
|
5833 this.fnOpen = function( nTr, mHtml, sClass )
|
|
5834 {
|
|
5835 return this.api( true )
|
|
5836 .row( nTr )
|
|
5837 .child( mHtml, sClass )
|
|
5838 .show()
|
|
5839 .child()[0];
|
|
5840 };
|
|
5841
|
|
5842
|
|
5843 /**
|
|
5844 * Change the pagination - provides the internal logic for pagination in a simple API
|
|
5845 * function. With this function you can have a DataTables table go to the next,
|
|
5846 * previous, first or last pages.
|
|
5847 * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
|
|
5848 * or page number to jump to (integer), note that page 0 is the first page.
|
|
5849 * @param {bool} [bRedraw=true] Redraw the table or not
|
|
5850 * @dtopt API
|
|
5851 * @deprecated Since v1.10
|
|
5852 *
|
|
5853 * @example
|
|
5854 * $(document).ready(function() {
|
|
5855 * var oTable = $('#example').dataTable();
|
|
5856 * oTable.fnPageChange( 'next' );
|
|
5857 * } );
|
|
5858 */
|
|
5859 this.fnPageChange = function ( mAction, bRedraw )
|
|
5860 {
|
|
5861 var api = this.api( true ).page( mAction );
|
|
5862
|
|
5863 if ( bRedraw === undefined || bRedraw ) {
|
|
5864 api.draw(false);
|
|
5865 }
|
|
5866 };
|
|
5867
|
|
5868
|
|
5869 /**
|
|
5870 * Show a particular column
|
|
5871 * @param {int} iCol The column whose display should be changed
|
|
5872 * @param {bool} bShow Show (true) or hide (false) the column
|
|
5873 * @param {bool} [bRedraw=true] Redraw the table or not
|
|
5874 * @dtopt API
|
|
5875 * @deprecated Since v1.10
|
|
5876 *
|
|
5877 * @example
|
|
5878 * $(document).ready(function() {
|
|
5879 * var oTable = $('#example').dataTable();
|
|
5880 *
|
|
5881 * // Hide the second column after initialisation
|
|
5882 * oTable.fnSetColumnVis( 1, false );
|
|
5883 * } );
|
|
5884 */
|
|
5885 this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
|
|
5886 {
|
|
5887 var api = this.api( true ).column( iCol ).visible( bShow );
|
|
5888
|
|
5889 if ( bRedraw === undefined || bRedraw ) {
|
|
5890 api.columns.adjust().draw();
|
|
5891 }
|
|
5892 };
|
|
5893
|
|
5894
|
|
5895 /**
|
|
5896 * Get the settings for a particular table for external manipulation
|
|
5897 * @returns {object} DataTables settings object. See
|
|
5898 * {@link DataTable.models.oSettings}
|
|
5899 * @dtopt API
|
|
5900 * @deprecated Since v1.10
|
|
5901 *
|
|
5902 * @example
|
|
5903 * $(document).ready(function() {
|
|
5904 * var oTable = $('#example').dataTable();
|
|
5905 * var oSettings = oTable.fnSettings();
|
|
5906 *
|
|
5907 * // Show an example parameter from the settings
|
|
5908 * alert( oSettings._iDisplayStart );
|
|
5909 * } );
|
|
5910 */
|
|
5911 this.fnSettings = function()
|
|
5912 {
|
|
5913 return _fnSettingsFromNode( this[_ext.iApiIndex] );
|
|
5914 };
|
|
5915
|
|
5916
|
|
5917 /**
|
|
5918 * Sort the table by a particular column
|
|
5919 * @param {int} iCol the data index to sort on. Note that this will not match the
|
|
5920 * 'display index' if you have hidden data entries
|
|
5921 * @dtopt API
|
|
5922 * @deprecated Since v1.10
|
|
5923 *
|
|
5924 * @example
|
|
5925 * $(document).ready(function() {
|
|
5926 * var oTable = $('#example').dataTable();
|
|
5927 *
|
|
5928 * // Sort immediately with columns 0 and 1
|
|
5929 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
|
|
5930 * } );
|
|
5931 */
|
|
5932 this.fnSort = function( aaSort )
|
|
5933 {
|
|
5934 this.api( true ).order( aaSort ).draw();
|
|
5935 };
|
|
5936
|
|
5937
|
|
5938 /**
|
|
5939 * Attach a sort listener to an element for a given column
|
|
5940 * @param {node} nNode the element to attach the sort listener to
|
|
5941 * @param {int} iColumn the column that a click on this node will sort on
|
|
5942 * @param {function} [fnCallback] callback function when sort is run
|
|
5943 * @dtopt API
|
|
5944 * @deprecated Since v1.10
|
|
5945 *
|
|
5946 * @example
|
|
5947 * $(document).ready(function() {
|
|
5948 * var oTable = $('#example').dataTable();
|
|
5949 *
|
|
5950 * // Sort on column 1, when 'sorter' is clicked on
|
|
5951 * oTable.fnSortListener( document.getElementById('sorter'), 1 );
|
|
5952 * } );
|
|
5953 */
|
|
5954 this.fnSortListener = function( nNode, iColumn, fnCallback )
|
|
5955 {
|
|
5956 this.api( true ).order.listener( nNode, iColumn, fnCallback );
|
|
5957 };
|
|
5958
|
|
5959
|
|
5960 /**
|
|
5961 * Update a table cell or row - this method will accept either a single value to
|
|
5962 * update the cell with, an array of values with one element for each column or
|
|
5963 * an object in the same format as the original data source. The function is
|
|
5964 * self-referencing in order to make the multi column updates easier.
|
|
5965 * @param {object|array|string} mData Data to update the cell/row with
|
|
5966 * @param {node|int} mRow TR element you want to update or the aoData index
|
|
5967 * @param {int} [iColumn] The column to update, give as null or undefined to
|
|
5968 * update a whole row.
|
|
5969 * @param {bool} [bRedraw=true] Redraw the table or not
|
|
5970 * @param {bool} [bAction=true] Perform pre-draw actions or not
|
|
5971 * @returns {int} 0 on success, 1 on error
|
|
5972 * @dtopt API
|
|
5973 * @deprecated Since v1.10
|
|
5974 *
|
|
5975 * @example
|
|
5976 * $(document).ready(function() {
|
|
5977 * var oTable = $('#example').dataTable();
|
|
5978 * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
|
|
5979 * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
|
|
5980 * } );
|
|
5981 */
|
|
5982 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
|
|
5983 {
|
|
5984 var api = this.api( true );
|
|
5985
|
|
5986 if ( iColumn === undefined || iColumn === null ) {
|
|
5987 api.row( mRow ).data( mData );
|
|
5988 }
|
|
5989 else {
|
|
5990 api.cell( mRow, iColumn ).data( mData );
|
|
5991 }
|
|
5992
|
|
5993 if ( bAction === undefined || bAction ) {
|
|
5994 api.columns.adjust();
|
|
5995 }
|
|
5996
|
|
5997 if ( bRedraw === undefined || bRedraw ) {
|
|
5998 api.draw();
|
|
5999 }
|
|
6000 return 0;
|
|
6001 };
|
|
6002
|
|
6003
|
|
6004 /**
|
|
6005 * Provide a common method for plug-ins to check the version of DataTables being used, in order
|
|
6006 * to ensure compatibility.
|
|
6007 * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
|
|
6008 * formats "X" and "X.Y" are also acceptable.
|
|
6009 * @returns {boolean} true if this version of DataTables is greater or equal to the required
|
|
6010 * version, or false if this version of DataTales is not suitable
|
|
6011 * @method
|
|
6012 * @dtopt API
|
|
6013 * @deprecated Since v1.10
|
|
6014 *
|
|
6015 * @example
|
|
6016 * $(document).ready(function() {
|
|
6017 * var oTable = $('#example').dataTable();
|
|
6018 * alert( oTable.fnVersionCheck( '1.9.0' ) );
|
|
6019 * } );
|
|
6020 */
|
|
6021 this.fnVersionCheck = _ext.fnVersionCheck;
|
|
6022
|
|
6023
|
|
6024 var _that = this;
|
|
6025 var emptyInit = options === undefined;
|
|
6026 var len = this.length;
|
|
6027
|
|
6028 if ( emptyInit ) {
|
|
6029 options = {};
|
|
6030 }
|
|
6031
|
|
6032 this.oApi = this.internal = _ext.internal;
|
|
6033
|
|
6034 // Extend with old style plug-in API methods
|
|
6035 for ( var fn in DataTable.ext.internal ) {
|
|
6036 if ( fn ) {
|
|
6037 this[fn] = _fnExternApiFunc(fn);
|
|
6038 }
|
|
6039 }
|
|
6040
|
|
6041 this.each(function() {
|
|
6042 // For each initialisation we want to give it a clean initialisation
|
|
6043 // object that can be bashed around
|
|
6044 var o = {};
|
|
6045 var oInit = len > 1 ? // optimisation for single table case
|
|
6046 _fnExtend( o, options, true ) :
|
|
6047 options;
|
|
6048
|
|
6049 /*global oInit,_that,emptyInit*/
|
|
6050 var i=0, iLen, j, jLen, k, kLen;
|
|
6051 var sId = this.getAttribute( 'id' );
|
|
6052 var bInitHandedOff = false;
|
|
6053 var defaults = DataTable.defaults;
|
|
6054
|
|
6055
|
|
6056 /* Sanity check */
|
|
6057 if ( this.nodeName.toLowerCase() != 'table' )
|
|
6058 {
|
|
6059 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
|
|
6060 return;
|
|
6061 }
|
|
6062
|
|
6063 /* Backwards compatibility for the defaults */
|
|
6064 _fnCompatOpts( defaults );
|
|
6065 _fnCompatCols( defaults.column );
|
|
6066
|
|
6067 /* Convert the camel-case defaults to Hungarian */
|
|
6068 _fnCamelToHungarian( defaults, defaults, true );
|
|
6069 _fnCamelToHungarian( defaults.column, defaults.column, true );
|
|
6070
|
|
6071 /* Setting up the initialisation object */
|
|
6072 _fnCamelToHungarian( defaults, oInit );
|
|
6073
|
|
6074 /* Check to see if we are re-initialising a table */
|
|
6075 var allSettings = DataTable.settings;
|
|
6076 for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
|
|
6077 {
|
|
6078 /* Base check on table node */
|
|
6079 if ( allSettings[i].nTable == this )
|
|
6080 {
|
|
6081 var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
|
|
6082 var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
|
|
6083
|
|
6084 if ( emptyInit || bRetrieve )
|
|
6085 {
|
|
6086 return allSettings[i].oInstance;
|
|
6087 }
|
|
6088 else if ( bDestroy )
|
|
6089 {
|
|
6090 allSettings[i].oInstance.fnDestroy();
|
|
6091 break;
|
|
6092 }
|
|
6093 else
|
|
6094 {
|
|
6095 _fnLog( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );
|
|
6096 return;
|
|
6097 }
|
|
6098 }
|
|
6099
|
|
6100 /* If the element we are initialising has the same ID as a table which was previously
|
|
6101 * initialised, but the table nodes don't match (from before) then we destroy the old
|
|
6102 * instance by simply deleting it. This is under the assumption that the table has been
|
|
6103 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
|
|
6104 */
|
|
6105 if ( allSettings[i].sTableId == this.id )
|
|
6106 {
|
|
6107 allSettings.splice( i, 1 );
|
|
6108 break;
|
|
6109 }
|
|
6110 }
|
|
6111
|
|
6112 /* Ensure the table has an ID - required for accessibility */
|
|
6113 if ( sId === null || sId === "" )
|
|
6114 {
|
|
6115 sId = "DataTables_Table_"+(DataTable.ext._unique++);
|
|
6116 this.id = sId;
|
|
6117 }
|
|
6118
|
|
6119 /* Create the settings object for this table and set some of the default parameters */
|
|
6120 var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
|
|
6121 "nTable": this,
|
|
6122 "oApi": _that.internal,
|
|
6123 "oInit": oInit,
|
|
6124 "sDestroyWidth": $(this)[0].style.width,
|
|
6125 "sInstance": sId,
|
|
6126 "sTableId": sId
|
|
6127 } );
|
|
6128 allSettings.push( oSettings );
|
|
6129
|
|
6130 // Need to add the instance after the instance after the settings object has been added
|
|
6131 // to the settings array, so we can self reference the table instance if more than one
|
|
6132 oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
|
|
6133
|
|
6134 // Backwards compatibility, before we apply all the defaults
|
|
6135 _fnCompatOpts( oInit );
|
|
6136
|
|
6137 if ( oInit.oLanguage )
|
|
6138 {
|
|
6139 _fnLanguageCompat( oInit.oLanguage );
|
|
6140 }
|
|
6141
|
|
6142 // If the length menu is given, but the init display length is not, use the length menu
|
|
6143 if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
|
|
6144 {
|
|
6145 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
|
|
6146 oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
|
|
6147 }
|
|
6148
|
|
6149 // Apply the defaults and init options to make a single init object will all
|
|
6150 // options defined from defaults and instance options.
|
|
6151 oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
|
|
6152
|
|
6153
|
|
6154 // Map the initialisation options onto the settings object
|
|
6155 _fnMap( oSettings.oFeatures, oInit, [
|
|
6156 "bPaginate",
|
|
6157 "bLengthChange",
|
|
6158 "bFilter",
|
|
6159 "bSort",
|
|
6160 "bSortMulti",
|
|
6161 "bInfo",
|
|
6162 "bProcessing",
|
|
6163 "bAutoWidth",
|
|
6164 "bSortClasses",
|
|
6165 "bServerSide",
|
|
6166 "bDeferRender"
|
|
6167 ] );
|
|
6168 _fnMap( oSettings, oInit, [
|
|
6169 "asStripeClasses",
|
|
6170 "ajax",
|
|
6171 "fnServerData",
|
|
6172 "fnFormatNumber",
|
|
6173 "sServerMethod",
|
|
6174 "aaSorting",
|
|
6175 "aaSortingFixed",
|
|
6176 "aLengthMenu",
|
|
6177 "sPaginationType",
|
|
6178 "sAjaxSource",
|
|
6179 "sAjaxDataProp",
|
|
6180 "iStateDuration",
|
|
6181 "sDom",
|
|
6182 "bSortCellsTop",
|
|
6183 "iTabIndex",
|
|
6184 "fnStateLoadCallback",
|
|
6185 "fnStateSaveCallback",
|
|
6186 "renderer",
|
|
6187 "searchDelay",
|
|
6188 [ "iCookieDuration", "iStateDuration" ], // backwards compat
|
|
6189 [ "oSearch", "oPreviousSearch" ],
|
|
6190 [ "aoSearchCols", "aoPreSearchCols" ],
|
|
6191 [ "iDisplayLength", "_iDisplayLength" ],
|
|
6192 [ "bJQueryUI", "bJUI" ]
|
|
6193 ] );
|
|
6194 _fnMap( oSettings.oScroll, oInit, [
|
|
6195 [ "sScrollX", "sX" ],
|
|
6196 [ "sScrollXInner", "sXInner" ],
|
|
6197 [ "sScrollY", "sY" ],
|
|
6198 [ "bScrollCollapse", "bCollapse" ]
|
|
6199 ] );
|
|
6200 _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
|
|
6201
|
|
6202 /* Callback functions which are array driven */
|
|
6203 _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
|
|
6204 _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
|
|
6205 _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
|
|
6206 _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
|
|
6207 _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
|
|
6208 _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
|
|
6209 _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
|
|
6210 _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
|
|
6211 _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
|
|
6212 _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
|
|
6213 _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
|
|
6214
|
|
6215 var oClasses = oSettings.oClasses;
|
|
6216
|
|
6217 // @todo Remove in 1.11
|
|
6218 if ( oInit.bJQueryUI )
|
|
6219 {
|
|
6220 /* Use the JUI classes object for display. You could clone the oStdClasses object if
|
|
6221 * you want to have multiple tables with multiple independent classes
|
|
6222 */
|
|
6223 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
|
|
6224
|
|
6225 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
|
|
6226 {
|
|
6227 /* Set the DOM to use a layout suitable for jQuery UI's theming */
|
|
6228 oSettings.sDom = '<"H"lfr>t<"F"ip>';
|
|
6229 }
|
|
6230
|
|
6231 if ( ! oSettings.renderer ) {
|
|
6232 oSettings.renderer = 'jqueryui';
|
|
6233 }
|
|
6234 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
|
|
6235 oSettings.renderer.header = 'jqueryui';
|
|
6236 }
|
|
6237 }
|
|
6238 else
|
|
6239 {
|
|
6240 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
|
|
6241 }
|
|
6242 $(this).addClass( oClasses.sTable );
|
|
6243
|
|
6244 /* Calculate the scroll bar width and cache it for use later on */
|
|
6245 if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
|
|
6246 {
|
|
6247 oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
|
|
6248 }
|
|
6249 if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
|
|
6250 oSettings.oScroll.sX = '100%';
|
|
6251 }
|
|
6252
|
|
6253 if ( oSettings.iInitDisplayStart === undefined )
|
|
6254 {
|
|
6255 /* Display start point, taking into account the save saving */
|
|
6256 oSettings.iInitDisplayStart = oInit.iDisplayStart;
|
|
6257 oSettings._iDisplayStart = oInit.iDisplayStart;
|
|
6258 }
|
|
6259
|
|
6260 if ( oInit.iDeferLoading !== null )
|
|
6261 {
|
|
6262 oSettings.bDeferLoading = true;
|
|
6263 var tmp = $.isArray( oInit.iDeferLoading );
|
|
6264 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
|
|
6265 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
|
|
6266 }
|
|
6267
|
|
6268 /* Language definitions */
|
|
6269 var oLanguage = oSettings.oLanguage;
|
|
6270 $.extend( true, oLanguage, oInit.oLanguage );
|
|
6271
|
|
6272 if ( oLanguage.sUrl !== "" )
|
|
6273 {
|
|
6274 /* Get the language definitions from a file - because this Ajax call makes the language
|
|
6275 * get async to the remainder of this function we use bInitHandedOff to indicate that
|
|
6276 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
|
|
6277 */
|
|
6278 $.ajax( {
|
|
6279 dataType: 'json',
|
|
6280 url: oLanguage.sUrl,
|
|
6281 success: function ( json ) {
|
|
6282 _fnLanguageCompat( json );
|
|
6283 _fnCamelToHungarian( defaults.oLanguage, json );
|
|
6284 $.extend( true, oLanguage, json );
|
|
6285 _fnInitialise( oSettings );
|
|
6286 },
|
|
6287 error: function () {
|
|
6288 // Error occurred loading language file, continue on as best we can
|
|
6289 _fnInitialise( oSettings );
|
|
6290 }
|
|
6291 } );
|
|
6292 bInitHandedOff = true;
|
|
6293 }
|
|
6294
|
|
6295 /*
|
|
6296 * Stripes
|
|
6297 */
|
|
6298 if ( oInit.asStripeClasses === null )
|
|
6299 {
|
|
6300 oSettings.asStripeClasses =[
|
|
6301 oClasses.sStripeOdd,
|
|
6302 oClasses.sStripeEven
|
|
6303 ];
|
|
6304 }
|
|
6305
|
|
6306 /* Remove row stripe classes if they are already on the table row */
|
|
6307 var stripeClasses = oSettings.asStripeClasses;
|
|
6308 var rowOne = $('tbody tr:eq(0)', this);
|
|
6309 if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
|
|
6310 return rowOne.hasClass(el);
|
|
6311 } ) ) !== -1 ) {
|
|
6312 $('tbody tr', this).removeClass( stripeClasses.join(' ') );
|
|
6313 oSettings.asDestroyStripes = stripeClasses.slice();
|
|
6314 }
|
|
6315
|
|
6316 /*
|
|
6317 * Columns
|
|
6318 * See if we should load columns automatically or use defined ones
|
|
6319 */
|
|
6320 var anThs = [];
|
|
6321 var aoColumnsInit;
|
|
6322 var nThead = this.getElementsByTagName('thead');
|
|
6323 if ( nThead.length !== 0 )
|
|
6324 {
|
|
6325 _fnDetectHeader( oSettings.aoHeader, nThead[0] );
|
|
6326 anThs = _fnGetUniqueThs( oSettings );
|
|
6327 }
|
|
6328
|
|
6329 /* If not given a column array, generate one with nulls */
|
|
6330 if ( oInit.aoColumns === null )
|
|
6331 {
|
|
6332 aoColumnsInit = [];
|
|
6333 for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
|
|
6334 {
|
|
6335 aoColumnsInit.push( null );
|
|
6336 }
|
|
6337 }
|
|
6338 else
|
|
6339 {
|
|
6340 aoColumnsInit = oInit.aoColumns;
|
|
6341 }
|
|
6342
|
|
6343 /* Add the columns */
|
|
6344 for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
|
|
6345 {
|
|
6346 _fnAddColumn( oSettings, anThs ? anThs[i] : null );
|
|
6347 }
|
|
6348
|
|
6349 /* Apply the column definitions */
|
|
6350 _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
|
|
6351 _fnColumnOptions( oSettings, iCol, oDef );
|
|
6352 } );
|
|
6353
|
|
6354 /* HTML5 attribute detection - build an mData object automatically if the
|
|
6355 * attributes are found
|
|
6356 */
|
|
6357 if ( rowOne.length ) {
|
|
6358 var a = function ( cell, name ) {
|
|
6359 return cell.getAttribute( 'data-'+name ) ? name : null;
|
|
6360 };
|
|
6361
|
|
6362 $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
|
|
6363 var col = oSettings.aoColumns[i];
|
|
6364
|
|
6365 if ( col.mData === i ) {
|
|
6366 var sort = a( cell, 'sort' ) || a( cell, 'order' );
|
|
6367 var filter = a( cell, 'filter' ) || a( cell, 'search' );
|
|
6368
|
|
6369 if ( sort !== null || filter !== null ) {
|
|
6370 col.mData = {
|
|
6371 _: i+'.display',
|
|
6372 sort: sort !== null ? i+'.@data-'+sort : undefined,
|
|
6373 type: sort !== null ? i+'.@data-'+sort : undefined,
|
|
6374 filter: filter !== null ? i+'.@data-'+filter : undefined
|
|
6375 };
|
|
6376
|
|
6377 _fnColumnOptions( oSettings, i );
|
|
6378 }
|
|
6379 }
|
|
6380 } );
|
|
6381 }
|
|
6382
|
|
6383 var features = oSettings.oFeatures;
|
|
6384
|
|
6385 /* Must be done after everything which can be overridden by the state saving! */
|
|
6386 if ( oInit.bStateSave )
|
|
6387 {
|
|
6388 features.bStateSave = true;
|
|
6389 _fnLoadState( oSettings, oInit );
|
|
6390 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
|
|
6391 }
|
|
6392
|
|
6393
|
|
6394 /*
|
|
6395 * Sorting
|
|
6396 * @todo For modularisation (1.11) this needs to do into a sort start up handler
|
|
6397 */
|
|
6398
|
|
6399 // If aaSorting is not defined, then we use the first indicator in asSorting
|
|
6400 // in case that has been altered, so the default sort reflects that option
|
|
6401 if ( oInit.aaSorting === undefined )
|
|
6402 {
|
|
6403 var sorting = oSettings.aaSorting;
|
|
6404 for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
|
|
6405 {
|
|
6406 sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
|
|
6407 }
|
|
6408 }
|
|
6409
|
|
6410 /* Do a first pass on the sorting classes (allows any size changes to be taken into
|
|
6411 * account, and also will apply sorting disabled classes if disabled
|
|
6412 */
|
|
6413 _fnSortingClasses( oSettings );
|
|
6414
|
|
6415 if ( features.bSort )
|
|
6416 {
|
|
6417 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
|
|
6418 if ( oSettings.bSorted ) {
|
|
6419 var aSort = _fnSortFlatten( oSettings );
|
|
6420 var sortedColumns = {};
|
|
6421
|
|
6422 $.each( aSort, function (i, val) {
|
|
6423 sortedColumns[ val.src ] = val.dir;
|
|
6424 } );
|
|
6425
|
|
6426 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
|
|
6427 _fnSortAria( oSettings );
|
|
6428 }
|
|
6429 } );
|
|
6430 }
|
|
6431
|
|
6432 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
|
|
6433 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
|
|
6434 _fnSortingClasses( oSettings );
|
|
6435 }
|
|
6436 }, 'sc' );
|
|
6437
|
|
6438
|
|
6439 /*
|
|
6440 * Final init
|
|
6441 * Cache the header, body and footer as required, creating them if needed
|
|
6442 */
|
|
6443
|
|
6444 /* Browser support detection */
|
|
6445 _fnBrowserDetect( oSettings );
|
|
6446
|
|
6447 // Work around for Webkit bug 83867 - store the caption-side before removing from doc
|
|
6448 var captions = $(this).children('caption').each( function () {
|
|
6449 this._captionSide = $(this).css('caption-side');
|
|
6450 } );
|
|
6451
|
|
6452 var thead = $(this).children('thead');
|
|
6453 if ( thead.length === 0 )
|
|
6454 {
|
|
6455 thead = $('<thead/>').appendTo(this);
|
|
6456 }
|
|
6457 oSettings.nTHead = thead[0];
|
|
6458
|
|
6459 var tbody = $(this).children('tbody');
|
|
6460 if ( tbody.length === 0 )
|
|
6461 {
|
|
6462 tbody = $('<tbody/>').appendTo(this);
|
|
6463 }
|
|
6464 oSettings.nTBody = tbody[0];
|
|
6465
|
|
6466 var tfoot = $(this).children('tfoot');
|
|
6467 if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
|
|
6468 {
|
|
6469 // If we are a scrolling table, and no footer has been given, then we need to create
|
|
6470 // a tfoot element for the caption element to be appended to
|
|
6471 tfoot = $('<tfoot/>').appendTo(this);
|
|
6472 }
|
|
6473
|
|
6474 if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
|
|
6475 $(this).addClass( oClasses.sNoFooter );
|
|
6476 }
|
|
6477 else if ( tfoot.length > 0 ) {
|
|
6478 oSettings.nTFoot = tfoot[0];
|
|
6479 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
|
|
6480 }
|
|
6481
|
|
6482 /* Check if there is data passing into the constructor */
|
|
6483 if ( oInit.aaData )
|
|
6484 {
|
|
6485 for ( i=0 ; i<oInit.aaData.length ; i++ )
|
|
6486 {
|
|
6487 _fnAddData( oSettings, oInit.aaData[ i ] );
|
|
6488 }
|
|
6489 }
|
|
6490 else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
|
|
6491 {
|
|
6492 /* Grab the data from the page - only do this when deferred loading or no Ajax
|
|
6493 * source since there is no point in reading the DOM data if we are then going
|
|
6494 * to replace it with Ajax data
|
|
6495 */
|
|
6496 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
|
|
6497 }
|
|
6498
|
|
6499 /* Copy the data index array */
|
|
6500 oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
|
|
6501
|
|
6502 /* Initialisation complete - table can be drawn */
|
|
6503 oSettings.bInitialised = true;
|
|
6504
|
|
6505 /* Check if we need to initialise the table (it might not have been handed off to the
|
|
6506 * language processor)
|
|
6507 */
|
|
6508 if ( bInitHandedOff === false )
|
|
6509 {
|
|
6510 _fnInitialise( oSettings );
|
|
6511 }
|
|
6512 } );
|
|
6513 _that = null;
|
|
6514 return this;
|
|
6515 };
|
|
6516
|
|
6517
|
|
6518
|
|
6519 /**
|
|
6520 * Computed structure of the DataTables API, defined by the options passed to
|
|
6521 * `DataTable.Api.register()` when building the API.
|
|
6522 *
|
|
6523 * The structure is built in order to speed creation and extension of the Api
|
|
6524 * objects since the extensions are effectively pre-parsed.
|
|
6525 *
|
|
6526 * The array is an array of objects with the following structure, where this
|
|
6527 * base array represents the Api prototype base:
|
|
6528 *
|
|
6529 * [
|
|
6530 * {
|
|
6531 * name: 'data' -- string - Property name
|
|
6532 * val: function () {}, -- function - Api method (or undefined if just an object
|
|
6533 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
|
|
6534 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
|
|
6535 * },
|
|
6536 * {
|
|
6537 * name: 'row'
|
|
6538 * val: {},
|
|
6539 * methodExt: [ ... ],
|
|
6540 * propExt: [
|
|
6541 * {
|
|
6542 * name: 'data'
|
|
6543 * val: function () {},
|
|
6544 * methodExt: [ ... ],
|
|
6545 * propExt: [ ... ]
|
|
6546 * },
|
|
6547 * ...
|
|
6548 * ]
|
|
6549 * }
|
|
6550 * ]
|
|
6551 *
|
|
6552 * @type {Array}
|
|
6553 * @ignore
|
|
6554 */
|
|
6555 var __apiStruct = [];
|
|
6556
|
|
6557
|
|
6558 /**
|
|
6559 * `Array.prototype` reference.
|
|
6560 *
|
|
6561 * @type object
|
|
6562 * @ignore
|
|
6563 */
|
|
6564 var __arrayProto = Array.prototype;
|
|
6565
|
|
6566
|
|
6567 /**
|
|
6568 * Abstraction for `context` parameter of the `Api` constructor to allow it to
|
|
6569 * take several different forms for ease of use.
|
|
6570 *
|
|
6571 * Each of the input parameter types will be converted to a DataTables settings
|
|
6572 * object where possible.
|
|
6573 *
|
|
6574 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
|
|
6575 * of:
|
|
6576 *
|
|
6577 * * `string` - jQuery selector. Any DataTables' matching the given selector
|
|
6578 * with be found and used.
|
|
6579 * * `node` - `TABLE` node which has already been formed into a DataTable.
|
|
6580 * * `jQuery` - A jQuery object of `TABLE` nodes.
|
|
6581 * * `object` - DataTables settings object
|
|
6582 * * `DataTables.Api` - API instance
|
|
6583 * @return {array|null} Matching DataTables settings objects. `null` or
|
|
6584 * `undefined` is returned if no matching DataTable is found.
|
|
6585 * @ignore
|
|
6586 */
|
|
6587 var _toSettings = function ( mixed )
|
|
6588 {
|
|
6589 var idx, jq;
|
|
6590 var settings = DataTable.settings;
|
|
6591 var tables = $.map( settings, function (el, i) {
|
|
6592 return el.nTable;
|
|
6593 } );
|
|
6594
|
|
6595 if ( ! mixed ) {
|
|
6596 return [];
|
|
6597 }
|
|
6598 else if ( mixed.nTable && mixed.oApi ) {
|
|
6599 // DataTables settings object
|
|
6600 return [ mixed ];
|
|
6601 }
|
|
6602 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
|
|
6603 // Table node
|
|
6604 idx = $.inArray( mixed, tables );
|
|
6605 return idx !== -1 ? [ settings[idx] ] : null;
|
|
6606 }
|
|
6607 else if ( mixed && typeof mixed.settings === 'function' ) {
|
|
6608 return mixed.settings().toArray();
|
|
6609 }
|
|
6610 else if ( typeof mixed === 'string' ) {
|
|
6611 // jQuery selector
|
|
6612 jq = $(mixed);
|
|
6613 }
|
|
6614 else if ( mixed instanceof $ ) {
|
|
6615 // jQuery object (also DataTables instance)
|
|
6616 jq = mixed;
|
|
6617 }
|
|
6618
|
|
6619 if ( jq ) {
|
|
6620 return jq.map( function(i) {
|
|
6621 idx = $.inArray( this, tables );
|
|
6622 return idx !== -1 ? settings[idx] : null;
|
|
6623 } ).toArray();
|
|
6624 }
|
|
6625 };
|
|
6626
|
|
6627
|
|
6628 /**
|
|
6629 * DataTables API class - used to control and interface with one or more
|
|
6630 * DataTables enhanced tables.
|
|
6631 *
|
|
6632 * The API class is heavily based on jQuery, presenting a chainable interface
|
|
6633 * that you can use to interact with tables. Each instance of the API class has
|
|
6634 * a "context" - i.e. the tables that it will operate on. This could be a single
|
|
6635 * table, all tables on a page or a sub-set thereof.
|
|
6636 *
|
|
6637 * Additionally the API is designed to allow you to easily work with the data in
|
|
6638 * the tables, retrieving and manipulating it as required. This is done by
|
|
6639 * presenting the API class as an array like interface. The contents of the
|
|
6640 * array depend upon the actions requested by each method (for example
|
|
6641 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
|
|
6642 * return an array of objects or arrays depending upon your table's
|
|
6643 * configuration). The API object has a number of array like methods (`push`,
|
|
6644 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
|
|
6645 * `unique` etc) to assist your working with the data held in a table.
|
|
6646 *
|
|
6647 * Most methods (those which return an Api instance) are chainable, which means
|
|
6648 * the return from a method call also has all of the methods available that the
|
|
6649 * top level object had. For example, these two calls are equivalent:
|
|
6650 *
|
|
6651 * // Not chained
|
|
6652 * api.row.add( {...} );
|
|
6653 * api.draw();
|
|
6654 *
|
|
6655 * // Chained
|
|
6656 * api.row.add( {...} ).draw();
|
|
6657 *
|
|
6658 * @class DataTable.Api
|
|
6659 * @param {array|object|string|jQuery} context DataTable identifier. This is
|
|
6660 * used to define which DataTables enhanced tables this API will operate on.
|
|
6661 * Can be one of:
|
|
6662 *
|
|
6663 * * `string` - jQuery selector. Any DataTables' matching the given selector
|
|
6664 * with be found and used.
|
|
6665 * * `node` - `TABLE` node which has already been formed into a DataTable.
|
|
6666 * * `jQuery` - A jQuery object of `TABLE` nodes.
|
|
6667 * * `object` - DataTables settings object
|
|
6668 * @param {array} [data] Data to initialise the Api instance with.
|
|
6669 *
|
|
6670 * @example
|
|
6671 * // Direct initialisation during DataTables construction
|
|
6672 * var api = $('#example').DataTable();
|
|
6673 *
|
|
6674 * @example
|
|
6675 * // Initialisation using a DataTables jQuery object
|
|
6676 * var api = $('#example').dataTable().api();
|
|
6677 *
|
|
6678 * @example
|
|
6679 * // Initialisation as a constructor
|
|
6680 * var api = new $.fn.DataTable.Api( 'table.dataTable' );
|
|
6681 */
|
|
6682 _Api = function ( context, data )
|
|
6683 {
|
|
6684 if ( ! this instanceof _Api ) {
|
|
6685 throw 'DT API must be constructed as a new object';
|
|
6686 // or should it do the 'new' for the caller?
|
|
6687 // return new _Api.apply( this, arguments );
|
|
6688 }
|
|
6689
|
|
6690 var settings = [];
|
|
6691 var ctxSettings = function ( o ) {
|
|
6692 var a = _toSettings( o );
|
|
6693 if ( a ) {
|
|
6694 settings.push.apply( settings, a );
|
|
6695 }
|
|
6696 };
|
|
6697
|
|
6698 if ( $.isArray( context ) ) {
|
|
6699 for ( var i=0, ien=context.length ; i<ien ; i++ ) {
|
|
6700 ctxSettings( context[i] );
|
|
6701 }
|
|
6702 }
|
|
6703 else {
|
|
6704 ctxSettings( context );
|
|
6705 }
|
|
6706
|
|
6707 // Remove duplicates
|
|
6708 this.context = _unique( settings );
|
|
6709
|
|
6710 // Initial data
|
|
6711 if ( data ) {
|
|
6712 this.push.apply( this, data.toArray ? data.toArray() : data );
|
|
6713 }
|
|
6714
|
|
6715 // selector
|
|
6716 this.selector = {
|
|
6717 rows: null,
|
|
6718 cols: null,
|
|
6719 opts: null
|
|
6720 };
|
|
6721
|
|
6722 _Api.extend( this, this, __apiStruct );
|
|
6723 };
|
|
6724
|
|
6725 DataTable.Api = _Api;
|
|
6726
|
|
6727 _Api.prototype = /** @lends DataTables.Api */{
|
|
6728 /**
|
|
6729 * Return a new Api instance, comprised of the data held in the current
|
|
6730 * instance, join with the other array(s) and/or value(s).
|
|
6731 *
|
|
6732 * An alias for `Array.prototype.concat`.
|
|
6733 *
|
|
6734 * @type method
|
|
6735 * @param {*} value1 Arrays and/or values to concatenate.
|
|
6736 * @param {*} [...] Additional arrays and/or values to concatenate.
|
|
6737 * @returns {DataTables.Api} New API instance, comprising of the combined
|
|
6738 * array.
|
|
6739 */
|
|
6740 concat: __arrayProto.concat,
|
|
6741
|
|
6742
|
|
6743 context: [], // array of table settings objects
|
|
6744
|
|
6745
|
|
6746 each: function ( fn )
|
|
6747 {
|
|
6748 for ( var i=0, ien=this.length ; i<ien; i++ ) {
|
|
6749 fn.call( this, this[i], i, this );
|
|
6750 }
|
|
6751
|
|
6752 return this;
|
|
6753 },
|
|
6754
|
|
6755
|
|
6756 eq: function ( idx )
|
|
6757 {
|
|
6758 var ctx = this.context;
|
|
6759
|
|
6760 return ctx.length > idx ?
|
|
6761 new _Api( ctx[idx], this[idx] ) :
|
|
6762 null;
|
|
6763 },
|
|
6764
|
|
6765
|
|
6766 filter: function ( fn )
|
|
6767 {
|
|
6768 var a = [];
|
|
6769
|
|
6770 if ( __arrayProto.filter ) {
|
|
6771 a = __arrayProto.filter.call( this, fn, this );
|
|
6772 }
|
|
6773 else {
|
|
6774 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
|
|
6775 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
|
|
6776 if ( fn.call( this, this[i], i, this ) ) {
|
|
6777 a.push( this[i] );
|
|
6778 }
|
|
6779 }
|
|
6780 }
|
|
6781
|
|
6782 return new _Api( this.context, a );
|
|
6783 },
|
|
6784
|
|
6785
|
|
6786 flatten: function ()
|
|
6787 {
|
|
6788 var a = [];
|
|
6789 return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
|
|
6790 },
|
|
6791
|
|
6792
|
|
6793 join: __arrayProto.join,
|
|
6794
|
|
6795
|
|
6796 indexOf: __arrayProto.indexOf || function (obj, start)
|
|
6797 {
|
|
6798 for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
|
|
6799 if ( this[i] === obj ) {
|
|
6800 return i;
|
|
6801 }
|
|
6802 }
|
|
6803 return -1;
|
|
6804 },
|
|
6805
|
|
6806 // Note that `alwaysNew` is internal - use iteratorNew externally
|
|
6807 iterator: function ( flatten, type, fn, alwaysNew ) {
|
|
6808 var
|
|
6809 a = [], ret,
|
|
6810 i, ien, j, jen,
|
|
6811 context = this.context,
|
|
6812 rows, items, item,
|
|
6813 selector = this.selector;
|
|
6814
|
|
6815 // Argument shifting
|
|
6816 if ( typeof flatten === 'string' ) {
|
|
6817 alwaysNew = fn;
|
|
6818 fn = type;
|
|
6819 type = flatten;
|
|
6820 flatten = false;
|
|
6821 }
|
|
6822
|
|
6823 for ( i=0, ien=context.length ; i<ien ; i++ ) {
|
|
6824 var apiInst = new _Api( context[i] );
|
|
6825
|
|
6826 if ( type === 'table' ) {
|
|
6827 ret = fn.call( apiInst, context[i], i );
|
|
6828
|
|
6829 if ( ret !== undefined ) {
|
|
6830 a.push( ret );
|
|
6831 }
|
|
6832 }
|
|
6833 else if ( type === 'columns' || type === 'rows' ) {
|
|
6834 // this has same length as context - one entry for each table
|
|
6835 ret = fn.call( apiInst, context[i], this[i], i );
|
|
6836
|
|
6837 if ( ret !== undefined ) {
|
|
6838 a.push( ret );
|
|
6839 }
|
|
6840 }
|
|
6841 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
|
|
6842 // columns and rows share the same structure.
|
|
6843 // 'this' is an array of column indexes for each context
|
|
6844 items = this[i];
|
|
6845
|
|
6846 if ( type === 'column-rows' ) {
|
|
6847 rows = _selector_row_indexes( context[i], selector.opts );
|
|
6848 }
|
|
6849
|
|
6850 for ( j=0, jen=items.length ; j<jen ; j++ ) {
|
|
6851 item = items[j];
|
|
6852
|
|
6853 if ( type === 'cell' ) {
|
|
6854 ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
|
|
6855 }
|
|
6856 else {
|
|
6857 ret = fn.call( apiInst, context[i], item, i, j, rows );
|
|
6858 }
|
|
6859
|
|
6860 if ( ret !== undefined ) {
|
|
6861 a.push( ret );
|
|
6862 }
|
|
6863 }
|
|
6864 }
|
|
6865 }
|
|
6866
|
|
6867 if ( a.length || alwaysNew ) {
|
|
6868 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
|
|
6869 var apiSelector = api.selector;
|
|
6870 apiSelector.rows = selector.rows;
|
|
6871 apiSelector.cols = selector.cols;
|
|
6872 apiSelector.opts = selector.opts;
|
|
6873 return api;
|
|
6874 }
|
|
6875 return this;
|
|
6876 },
|
|
6877
|
|
6878
|
|
6879 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
|
|
6880 {
|
|
6881 // Bit cheeky...
|
|
6882 return this.indexOf.apply( this.toArray.reverse(), arguments );
|
|
6883 },
|
|
6884
|
|
6885
|
|
6886 length: 0,
|
|
6887
|
|
6888
|
|
6889 map: function ( fn )
|
|
6890 {
|
|
6891 var a = [];
|
|
6892
|
|
6893 if ( __arrayProto.map ) {
|
|
6894 a = __arrayProto.map.call( this, fn, this );
|
|
6895 }
|
|
6896 else {
|
|
6897 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
|
|
6898 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
|
|
6899 a.push( fn.call( this, this[i], i ) );
|
|
6900 }
|
|
6901 }
|
|
6902
|
|
6903 return new _Api( this.context, a );
|
|
6904 },
|
|
6905
|
|
6906
|
|
6907 pluck: function ( prop )
|
|
6908 {
|
|
6909 return this.map( function ( el ) {
|
|
6910 return el[ prop ];
|
|
6911 } );
|
|
6912 },
|
|
6913
|
|
6914 pop: __arrayProto.pop,
|
|
6915
|
|
6916
|
|
6917 push: __arrayProto.push,
|
|
6918
|
|
6919
|
|
6920 // Does not return an API instance
|
|
6921 reduce: __arrayProto.reduce || function ( fn, init )
|
|
6922 {
|
|
6923 return _fnReduce( this, fn, init, 0, this.length, 1 );
|
|
6924 },
|
|
6925
|
|
6926
|
|
6927 reduceRight: __arrayProto.reduceRight || function ( fn, init )
|
|
6928 {
|
|
6929 return _fnReduce( this, fn, init, this.length-1, -1, -1 );
|
|
6930 },
|
|
6931
|
|
6932
|
|
6933 reverse: __arrayProto.reverse,
|
|
6934
|
|
6935
|
|
6936 // Object with rows, columns and opts
|
|
6937 selector: null,
|
|
6938
|
|
6939
|
|
6940 shift: __arrayProto.shift,
|
|
6941
|
|
6942
|
|
6943 sort: __arrayProto.sort, // ? name - order?
|
|
6944
|
|
6945
|
|
6946 splice: __arrayProto.splice,
|
|
6947
|
|
6948
|
|
6949 toArray: function ()
|
|
6950 {
|
|
6951 return __arrayProto.slice.call( this );
|
|
6952 },
|
|
6953
|
|
6954
|
|
6955 to$: function ()
|
|
6956 {
|
|
6957 return $( this );
|
|
6958 },
|
|
6959
|
|
6960
|
|
6961 toJQuery: function ()
|
|
6962 {
|
|
6963 return $( this );
|
|
6964 },
|
|
6965
|
|
6966
|
|
6967 unique: function ()
|
|
6968 {
|
|
6969 return new _Api( this.context, _unique(this) );
|
|
6970 },
|
|
6971
|
|
6972
|
|
6973 unshift: __arrayProto.unshift
|
|
6974 };
|
|
6975
|
|
6976
|
|
6977 _Api.extend = function ( scope, obj, ext )
|
|
6978 {
|
|
6979 // Only extend API instances and static properties of the API
|
|
6980 if ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
|
|
6981 return;
|
|
6982 }
|
|
6983
|
|
6984 var
|
|
6985 i, ien,
|
|
6986 j, jen,
|
|
6987 struct, inner,
|
|
6988 methodScoping = function ( scope, fn, struc ) {
|
|
6989 return function () {
|
|
6990 var ret = fn.apply( scope, arguments );
|
|
6991
|
|
6992 // Method extension
|
|
6993 _Api.extend( ret, ret, struc.methodExt );
|
|
6994 return ret;
|
|
6995 };
|
|
6996 };
|
|
6997
|
|
6998 for ( i=0, ien=ext.length ; i<ien ; i++ ) {
|
|
6999 struct = ext[i];
|
|
7000
|
|
7001 // Value
|
|
7002 obj[ struct.name ] = typeof struct.val === 'function' ?
|
|
7003 methodScoping( scope, struct.val, struct ) :
|
|
7004 $.isPlainObject( struct.val ) ?
|
|
7005 {} :
|
|
7006 struct.val;
|
|
7007
|
|
7008 obj[ struct.name ].__dt_wrapper = true;
|
|
7009
|
|
7010 // Property extension
|
|
7011 _Api.extend( scope, obj[ struct.name ], struct.propExt );
|
|
7012 }
|
|
7013 };
|
|
7014
|
|
7015
|
|
7016 // @todo - Is there need for an augment function?
|
|
7017 // _Api.augment = function ( inst, name )
|
|
7018 // {
|
|
7019 // // Find src object in the structure from the name
|
|
7020 // var parts = name.split('.');
|
|
7021
|
|
7022 // _Api.extend( inst, obj );
|
|
7023 // };
|
|
7024
|
|
7025
|
|
7026 // [
|
|
7027 // {
|
|
7028 // name: 'data' -- string - Property name
|
|
7029 // val: function () {}, -- function - Api method (or undefined if just an object
|
|
7030 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
|
|
7031 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
|
|
7032 // },
|
|
7033 // {
|
|
7034 // name: 'row'
|
|
7035 // val: {},
|
|
7036 // methodExt: [ ... ],
|
|
7037 // propExt: [
|
|
7038 // {
|
|
7039 // name: 'data'
|
|
7040 // val: function () {},
|
|
7041 // methodExt: [ ... ],
|
|
7042 // propExt: [ ... ]
|
|
7043 // },
|
|
7044 // ...
|
|
7045 // ]
|
|
7046 // }
|
|
7047 // ]
|
|
7048
|
|
7049 _Api.register = _api_register = function ( name, val )
|
|
7050 {
|
|
7051 if ( $.isArray( name ) ) {
|
|
7052 for ( var j=0, jen=name.length ; j<jen ; j++ ) {
|
|
7053 _Api.register( name[j], val );
|
|
7054 }
|
|
7055 return;
|
|
7056 }
|
|
7057
|
|
7058 var
|
|
7059 i, ien,
|
|
7060 heir = name.split('.'),
|
|
7061 struct = __apiStruct,
|
|
7062 key, method;
|
|
7063
|
|
7064 var find = function ( src, name ) {
|
|
7065 for ( var i=0, ien=src.length ; i<ien ; i++ ) {
|
|
7066 if ( src[i].name === name ) {
|
|
7067 return src[i];
|
|
7068 }
|
|
7069 }
|
|
7070 return null;
|
|
7071 };
|
|
7072
|
|
7073 for ( i=0, ien=heir.length ; i<ien ; i++ ) {
|
|
7074 method = heir[i].indexOf('()') !== -1;
|
|
7075 key = method ?
|
|
7076 heir[i].replace('()', '') :
|
|
7077 heir[i];
|
|
7078
|
|
7079 var src = find( struct, key );
|
|
7080 if ( ! src ) {
|
|
7081 src = {
|
|
7082 name: key,
|
|
7083 val: {},
|
|
7084 methodExt: [],
|
|
7085 propExt: []
|
|
7086 };
|
|
7087 struct.push( src );
|
|
7088 }
|
|
7089
|
|
7090 if ( i === ien-1 ) {
|
|
7091 src.val = val;
|
|
7092 }
|
|
7093 else {
|
|
7094 struct = method ?
|
|
7095 src.methodExt :
|
|
7096 src.propExt;
|
|
7097 }
|
|
7098 }
|
|
7099 };
|
|
7100
|
|
7101
|
|
7102 _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
|
|
7103 _Api.register( pluralName, val );
|
|
7104
|
|
7105 _Api.register( singularName, function () {
|
|
7106 var ret = val.apply( this, arguments );
|
|
7107
|
|
7108 if ( ret === this ) {
|
|
7109 // Returned item is the API instance that was passed in, return it
|
|
7110 return this;
|
|
7111 }
|
|
7112 else if ( ret instanceof _Api ) {
|
|
7113 // New API instance returned, want the value from the first item
|
|
7114 // in the returned array for the singular result.
|
|
7115 return ret.length ?
|
|
7116 $.isArray( ret[0] ) ?
|
|
7117 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
|
|
7118 ret[0] :
|
|
7119 undefined;
|
|
7120 }
|
|
7121
|
|
7122 // Non-API return - just fire it back
|
|
7123 return ret;
|
|
7124 } );
|
|
7125 };
|
|
7126
|
|
7127
|
|
7128 /**
|
|
7129 * Selector for HTML tables. Apply the given selector to the give array of
|
|
7130 * DataTables settings objects.
|
|
7131 *
|
|
7132 * @param {string|integer} [selector] jQuery selector string or integer
|
|
7133 * @param {array} Array of DataTables settings objects to be filtered
|
|
7134 * @return {array}
|
|
7135 * @ignore
|
|
7136 */
|
|
7137 var __table_selector = function ( selector, a )
|
|
7138 {
|
|
7139 // Integer is used to pick out a table by index
|
|
7140 if ( typeof selector === 'number' ) {
|
|
7141 return [ a[ selector ] ];
|
|
7142 }
|
|
7143
|
|
7144 // Perform a jQuery selector on the table nodes
|
|
7145 var nodes = $.map( a, function (el, i) {
|
|
7146 return el.nTable;
|
|
7147 } );
|
|
7148
|
|
7149 return $(nodes)
|
|
7150 .filter( selector )
|
|
7151 .map( function (i) {
|
|
7152 // Need to translate back from the table node to the settings
|
|
7153 var idx = $.inArray( this, nodes );
|
|
7154 return a[ idx ];
|
|
7155 } )
|
|
7156 .toArray();
|
|
7157 };
|
|
7158
|
|
7159
|
|
7160
|
|
7161 /**
|
|
7162 * Context selector for the API's context (i.e. the tables the API instance
|
|
7163 * refers to.
|
|
7164 *
|
|
7165 * @name DataTable.Api#tables
|
|
7166 * @param {string|integer} [selector] Selector to pick which tables the iterator
|
|
7167 * should operate on. If not given, all tables in the current context are
|
|
7168 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
|
|
7169 * select multiple tables or as an integer to select a single table.
|
|
7170 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
|
|
7171 */
|
|
7172 _api_register( 'tables()', function ( selector ) {
|
|
7173 // A new instance is created if there was a selector specified
|
|
7174 return selector ?
|
|
7175 new _Api( __table_selector( selector, this.context ) ) :
|
|
7176 this;
|
|
7177 } );
|
|
7178
|
|
7179
|
|
7180 _api_register( 'table()', function ( selector ) {
|
|
7181 var tables = this.tables( selector );
|
|
7182 var ctx = tables.context;
|
|
7183
|
|
7184 // Truncate to the first matched table
|
|
7185 return ctx.length ?
|
|
7186 new _Api( ctx[0] ) :
|
|
7187 tables;
|
|
7188 } );
|
|
7189
|
|
7190
|
|
7191 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
|
|
7192 return this.iterator( 'table', function ( ctx ) {
|
|
7193 return ctx.nTable;
|
|
7194 }, 1 );
|
|
7195 } );
|
|
7196
|
|
7197
|
|
7198 _api_registerPlural( 'tables().body()', 'table().body()' , function () {
|
|
7199 return this.iterator( 'table', function ( ctx ) {
|
|
7200 return ctx.nTBody;
|
|
7201 }, 1 );
|
|
7202 } );
|
|
7203
|
|
7204
|
|
7205 _api_registerPlural( 'tables().header()', 'table().header()' , function () {
|
|
7206 return this.iterator( 'table', function ( ctx ) {
|
|
7207 return ctx.nTHead;
|
|
7208 }, 1 );
|
|
7209 } );
|
|
7210
|
|
7211
|
|
7212 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
|
|
7213 return this.iterator( 'table', function ( ctx ) {
|
|
7214 return ctx.nTFoot;
|
|
7215 }, 1 );
|
|
7216 } );
|
|
7217
|
|
7218
|
|
7219 _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
|
|
7220 return this.iterator( 'table', function ( ctx ) {
|
|
7221 return ctx.nTableWrapper;
|
|
7222 }, 1 );
|
|
7223 } );
|
|
7224
|
|
7225
|
|
7226
|
|
7227 /**
|
|
7228 * Redraw the tables in the current context.
|
|
7229 *
|
|
7230 * @param {boolean} [reset=true] Reset (default) or hold the current paging
|
|
7231 * position. A full re-sort and re-filter is performed when this method is
|
|
7232 * called, which is why the pagination reset is the default action.
|
|
7233 * @returns {DataTables.Api} this
|
|
7234 */
|
|
7235 _api_register( 'draw()', function ( resetPaging ) {
|
|
7236 return this.iterator( 'table', function ( settings ) {
|
|
7237 _fnReDraw( settings, resetPaging===false );
|
|
7238 } );
|
|
7239 } );
|
|
7240
|
|
7241
|
|
7242
|
|
7243 /**
|
|
7244 * Get the current page index.
|
|
7245 *
|
|
7246 * @return {integer} Current page index (zero based)
|
|
7247 *//**
|
|
7248 * Set the current page.
|
|
7249 *
|
|
7250 * Note that if you attempt to show a page which does not exist, DataTables will
|
|
7251 * not throw an error, but rather reset the paging.
|
|
7252 *
|
|
7253 * @param {integer|string} action The paging action to take. This can be one of:
|
|
7254 * * `integer` - The page index to jump to
|
|
7255 * * `string` - An action to take:
|
|
7256 * * `first` - Jump to first page.
|
|
7257 * * `next` - Jump to the next page
|
|
7258 * * `previous` - Jump to previous page
|
|
7259 * * `last` - Jump to the last page.
|
|
7260 * @returns {DataTables.Api} this
|
|
7261 */
|
|
7262 _api_register( 'page()', function ( action ) {
|
|
7263 if ( action === undefined ) {
|
|
7264 return this.page.info().page; // not an expensive call
|
|
7265 }
|
|
7266
|
|
7267 // else, have an action to take on all tables
|
|
7268 return this.iterator( 'table', function ( settings ) {
|
|
7269 _fnPageChange( settings, action );
|
|
7270 } );
|
|
7271 } );
|
|
7272
|
|
7273
|
|
7274 /**
|
|
7275 * Paging information for the first table in the current context.
|
|
7276 *
|
|
7277 * If you require paging information for another table, use the `table()` method
|
|
7278 * with a suitable selector.
|
|
7279 *
|
|
7280 * @return {object} Object with the following properties set:
|
|
7281 * * `page` - Current page index (zero based - i.e. the first page is `0`)
|
|
7282 * * `pages` - Total number of pages
|
|
7283 * * `start` - Display index for the first record shown on the current page
|
|
7284 * * `end` - Display index for the last record shown on the current page
|
|
7285 * * `length` - Display length (number of records). Note that generally `start
|
|
7286 * + length = end`, but this is not always true, for example if there are
|
|
7287 * only 2 records to show on the final page, with a length of 10.
|
|
7288 * * `recordsTotal` - Full data set length
|
|
7289 * * `recordsDisplay` - Data set length once the current filtering criterion
|
|
7290 * are applied.
|
|
7291 */
|
|
7292 _api_register( 'page.info()', function ( action ) {
|
|
7293 if ( this.context.length === 0 ) {
|
|
7294 return undefined;
|
|
7295 }
|
|
7296
|
|
7297 var
|
|
7298 settings = this.context[0],
|
|
7299 start = settings._iDisplayStart,
|
|
7300 len = settings._iDisplayLength,
|
|
7301 visRecords = settings.fnRecordsDisplay(),
|
|
7302 all = len === -1;
|
|
7303
|
|
7304 return {
|
|
7305 "page": all ? 0 : Math.floor( start / len ),
|
|
7306 "pages": all ? 1 : Math.ceil( visRecords / len ),
|
|
7307 "start": start,
|
|
7308 "end": settings.fnDisplayEnd(),
|
|
7309 "length": len,
|
|
7310 "recordsTotal": settings.fnRecordsTotal(),
|
|
7311 "recordsDisplay": visRecords
|
|
7312 };
|
|
7313 } );
|
|
7314
|
|
7315
|
|
7316 /**
|
|
7317 * Get the current page length.
|
|
7318 *
|
|
7319 * @return {integer} Current page length. Note `-1` indicates that all records
|
|
7320 * are to be shown.
|
|
7321 *//**
|
|
7322 * Set the current page length.
|
|
7323 *
|
|
7324 * @param {integer} Page length to set. Use `-1` to show all records.
|
|
7325 * @returns {DataTables.Api} this
|
|
7326 */
|
|
7327 _api_register( 'page.len()', function ( len ) {
|
|
7328 // Note that we can't call this function 'length()' because `length`
|
|
7329 // is a Javascript property of functions which defines how many arguments
|
|
7330 // the function expects.
|
|
7331 if ( len === undefined ) {
|
|
7332 return this.context.length !== 0 ?
|
|
7333 this.context[0]._iDisplayLength :
|
|
7334 undefined;
|
|
7335 }
|
|
7336
|
|
7337 // else, set the page length
|
|
7338 return this.iterator( 'table', function ( settings ) {
|
|
7339 _fnLengthChange( settings, len );
|
|
7340 } );
|
|
7341 } );
|
|
7342
|
|
7343
|
|
7344
|
|
7345 var __reload = function ( settings, holdPosition, callback ) {
|
|
7346 if ( _fnDataSource( settings ) == 'ssp' ) {
|
|
7347 _fnReDraw( settings, holdPosition );
|
|
7348 }
|
|
7349 else {
|
|
7350 // Trigger xhr
|
|
7351 _fnProcessingDisplay( settings, true );
|
|
7352
|
|
7353 _fnBuildAjax( settings, [], function( json ) {
|
|
7354 _fnClearTable( settings );
|
|
7355
|
|
7356 var data = _fnAjaxDataSrc( settings, json );
|
|
7357 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
7358 _fnAddData( settings, data[i] );
|
|
7359 }
|
|
7360
|
|
7361 _fnReDraw( settings, holdPosition );
|
|
7362 _fnProcessingDisplay( settings, false );
|
|
7363 } );
|
|
7364 }
|
|
7365
|
|
7366 // Use the draw event to trigger a callback, regardless of if it is an async
|
|
7367 // or sync draw
|
|
7368 if ( callback ) {
|
|
7369 var api = new _Api( settings );
|
|
7370
|
|
7371 api.one( 'draw', function () {
|
|
7372 callback( api.ajax.json() );
|
|
7373 } );
|
|
7374 }
|
|
7375 };
|
|
7376
|
|
7377
|
|
7378 /**
|
|
7379 * Get the JSON response from the last Ajax request that DataTables made to the
|
|
7380 * server. Note that this returns the JSON from the first table in the current
|
|
7381 * context.
|
|
7382 *
|
|
7383 * @return {object} JSON received from the server.
|
|
7384 */
|
|
7385 _api_register( 'ajax.json()', function () {
|
|
7386 var ctx = this.context;
|
|
7387
|
|
7388 if ( ctx.length > 0 ) {
|
|
7389 return ctx[0].json;
|
|
7390 }
|
|
7391
|
|
7392 // else return undefined;
|
|
7393 } );
|
|
7394
|
|
7395
|
|
7396 /**
|
|
7397 * Get the data submitted in the last Ajax request
|
|
7398 */
|
|
7399 _api_register( 'ajax.params()', function () {
|
|
7400 var ctx = this.context;
|
|
7401
|
|
7402 if ( ctx.length > 0 ) {
|
|
7403 return ctx[0].oAjaxData;
|
|
7404 }
|
|
7405
|
|
7406 // else return undefined;
|
|
7407 } );
|
|
7408
|
|
7409
|
|
7410 /**
|
|
7411 * Reload tables from the Ajax data source. Note that this function will
|
|
7412 * automatically re-draw the table when the remote data has been loaded.
|
|
7413 *
|
|
7414 * @param {boolean} [reset=true] Reset (default) or hold the current paging
|
|
7415 * position. A full re-sort and re-filter is performed when this method is
|
|
7416 * called, which is why the pagination reset is the default action.
|
|
7417 * @returns {DataTables.Api} this
|
|
7418 */
|
|
7419 _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
|
|
7420 return this.iterator( 'table', function (settings) {
|
|
7421 __reload( settings, resetPaging===false, callback );
|
|
7422 } );
|
|
7423 } );
|
|
7424
|
|
7425
|
|
7426 /**
|
|
7427 * Get the current Ajax URL. Note that this returns the URL from the first
|
|
7428 * table in the current context.
|
|
7429 *
|
|
7430 * @return {string} Current Ajax source URL
|
|
7431 *//**
|
|
7432 * Set the Ajax URL. Note that this will set the URL for all tables in the
|
|
7433 * current context.
|
|
7434 *
|
|
7435 * @param {string} url URL to set.
|
|
7436 * @returns {DataTables.Api} this
|
|
7437 */
|
|
7438 _api_register( 'ajax.url()', function ( url ) {
|
|
7439 var ctx = this.context;
|
|
7440
|
|
7441 if ( url === undefined ) {
|
|
7442 // get
|
|
7443 if ( ctx.length === 0 ) {
|
|
7444 return undefined;
|
|
7445 }
|
|
7446 ctx = ctx[0];
|
|
7447
|
|
7448 return ctx.ajax ?
|
|
7449 $.isPlainObject( ctx.ajax ) ?
|
|
7450 ctx.ajax.url :
|
|
7451 ctx.ajax :
|
|
7452 ctx.sAjaxSource;
|
|
7453 }
|
|
7454
|
|
7455 // set
|
|
7456 return this.iterator( 'table', function ( settings ) {
|
|
7457 if ( $.isPlainObject( settings.ajax ) ) {
|
|
7458 settings.ajax.url = url;
|
|
7459 }
|
|
7460 else {
|
|
7461 settings.ajax = url;
|
|
7462 }
|
|
7463 // No need to consider sAjaxSource here since DataTables gives priority
|
|
7464 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
|
|
7465 // value of `sAjaxSource` redundant.
|
|
7466 } );
|
|
7467 } );
|
|
7468
|
|
7469
|
|
7470 /**
|
|
7471 * Load data from the newly set Ajax URL. Note that this method is only
|
|
7472 * available when `ajax.url()` is used to set a URL. Additionally, this method
|
|
7473 * has the same effect as calling `ajax.reload()` but is provided for
|
|
7474 * convenience when setting a new URL. Like `ajax.reload()` it will
|
|
7475 * automatically redraw the table once the remote data has been loaded.
|
|
7476 *
|
|
7477 * @returns {DataTables.Api} this
|
|
7478 */
|
|
7479 _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
|
|
7480 // Same as a reload, but makes sense to present it for easy access after a
|
|
7481 // url change
|
|
7482 return this.iterator( 'table', function ( ctx ) {
|
|
7483 __reload( ctx, resetPaging===false, callback );
|
|
7484 } );
|
|
7485 } );
|
|
7486
|
|
7487
|
|
7488
|
|
7489
|
|
7490 var _selector_run = function ( selector, select )
|
|
7491 {
|
|
7492 var
|
|
7493 out = [], res,
|
|
7494 a, i, ien, j, jen,
|
|
7495 selectorType = typeof selector;
|
|
7496
|
|
7497 // Can't just check for isArray here, as an API or jQuery instance might be
|
|
7498 // given with their array like look
|
|
7499 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
|
|
7500 selector = [ selector ];
|
|
7501 }
|
|
7502
|
|
7503 for ( i=0, ien=selector.length ; i<ien ; i++ ) {
|
|
7504 a = selector[i] && selector[i].split ?
|
|
7505 selector[i].split(',') :
|
|
7506 [ selector[i] ];
|
|
7507
|
|
7508 for ( j=0, jen=a.length ; j<jen ; j++ ) {
|
|
7509 res = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
|
|
7510
|
|
7511 if ( res && res.length ) {
|
|
7512 out.push.apply( out, res );
|
|
7513 }
|
|
7514 }
|
|
7515 }
|
|
7516
|
|
7517 return out;
|
|
7518 };
|
|
7519
|
|
7520
|
|
7521 var _selector_opts = function ( opts )
|
|
7522 {
|
|
7523 if ( ! opts ) {
|
|
7524 opts = {};
|
|
7525 }
|
|
7526
|
|
7527 // Backwards compatibility for 1.9- which used the terminology filter rather
|
|
7528 // than search
|
|
7529 if ( opts.filter && ! opts.search ) {
|
|
7530 opts.search = opts.filter;
|
|
7531 }
|
|
7532
|
|
7533 return {
|
|
7534 search: opts.search || 'none',
|
|
7535 order: opts.order || 'current',
|
|
7536 page: opts.page || 'all'
|
|
7537 };
|
|
7538 };
|
|
7539
|
|
7540
|
|
7541 var _selector_first = function ( inst )
|
|
7542 {
|
|
7543 // Reduce the API instance to the first item found
|
|
7544 for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
|
|
7545 if ( inst[i].length > 0 ) {
|
|
7546 // Assign the first element to the first item in the instance
|
|
7547 // and truncate the instance and context
|
|
7548 inst[0] = inst[i];
|
|
7549 inst.length = 1;
|
|
7550 inst.context = [ inst.context[i] ];
|
|
7551
|
|
7552 return inst;
|
|
7553 }
|
|
7554 }
|
|
7555
|
|
7556 // Not found - return an empty instance
|
|
7557 inst.length = 0;
|
|
7558 return inst;
|
|
7559 };
|
|
7560
|
|
7561
|
|
7562 var _selector_row_indexes = function ( settings, opts )
|
|
7563 {
|
|
7564 var
|
|
7565 i, ien, tmp, a=[],
|
|
7566 displayFiltered = settings.aiDisplay,
|
|
7567 displayMaster = settings.aiDisplayMaster;
|
|
7568
|
|
7569 var
|
|
7570 search = opts.search, // none, applied, removed
|
|
7571 order = opts.order, // applied, current, index (original - compatibility with 1.9)
|
|
7572 page = opts.page; // all, current
|
|
7573
|
|
7574 if ( _fnDataSource( settings ) == 'ssp' ) {
|
|
7575 // In server-side processing mode, most options are irrelevant since
|
|
7576 // rows not shown don't exist and the index order is the applied order
|
|
7577 // Removed is a special case - for consistency just return an empty
|
|
7578 // array
|
|
7579 return search === 'removed' ?
|
|
7580 [] :
|
|
7581 _range( 0, displayMaster.length );
|
|
7582 }
|
|
7583 else if ( page == 'current' ) {
|
|
7584 // Current page implies that order=current and fitler=applied, since it is
|
|
7585 // fairly senseless otherwise, regardless of what order and search actually
|
|
7586 // are
|
|
7587 for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
|
|
7588 a.push( displayFiltered[i] );
|
|
7589 }
|
|
7590 }
|
|
7591 else if ( order == 'current' || order == 'applied' ) {
|
|
7592 a = search == 'none' ?
|
|
7593 displayMaster.slice() : // no search
|
|
7594 search == 'applied' ?
|
|
7595 displayFiltered.slice() : // applied search
|
|
7596 $.map( displayMaster, function (el, i) { // removed search
|
|
7597 return $.inArray( el, displayFiltered ) === -1 ? el : null;
|
|
7598 } );
|
|
7599 }
|
|
7600 else if ( order == 'index' || order == 'original' ) {
|
|
7601 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
|
|
7602 if ( search == 'none' ) {
|
|
7603 a.push( i );
|
|
7604 }
|
|
7605 else { // applied | removed
|
|
7606 tmp = $.inArray( i, displayFiltered );
|
|
7607
|
|
7608 if ((tmp === -1 && search == 'removed') ||
|
|
7609 (tmp >= 0 && search == 'applied') )
|
|
7610 {
|
|
7611 a.push( i );
|
|
7612 }
|
|
7613 }
|
|
7614 }
|
|
7615 }
|
|
7616
|
|
7617 return a;
|
|
7618 };
|
|
7619
|
|
7620
|
|
7621 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
7622 * Rows
|
|
7623 *
|
|
7624 * {} - no selector - use all available rows
|
|
7625 * {integer} - row aoData index
|
|
7626 * {node} - TR node
|
|
7627 * {string} - jQuery selector to apply to the TR elements
|
|
7628 * {array} - jQuery array of nodes, or simply an array of TR nodes
|
|
7629 *
|
|
7630 */
|
|
7631
|
|
7632
|
|
7633 var __row_selector = function ( settings, selector, opts )
|
|
7634 {
|
|
7635 return _selector_run( selector, function ( sel ) {
|
|
7636 var selInt = _intVal( sel );
|
|
7637 var i, ien;
|
|
7638
|
|
7639 // Short cut - selector is a number and no options provided (default is
|
|
7640 // all records, so no need to check if the index is in there, since it
|
|
7641 // must be - dev error if the index doesn't exist).
|
|
7642 if ( selInt !== null && ! opts ) {
|
|
7643 return [ selInt ];
|
|
7644 }
|
|
7645
|
|
7646 var rows = _selector_row_indexes( settings, opts );
|
|
7647
|
|
7648 if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
|
|
7649 // Selector - integer
|
|
7650 return [ selInt ];
|
|
7651 }
|
|
7652 else if ( ! sel ) {
|
|
7653 // Selector - none
|
|
7654 return rows;
|
|
7655 }
|
|
7656
|
|
7657 // Selector - function
|
|
7658 if ( typeof sel === 'function' ) {
|
|
7659 return $.map( rows, function (idx) {
|
|
7660 var row = settings.aoData[ idx ];
|
|
7661 return sel( idx, row._aData, row.nTr ) ? idx : null;
|
|
7662 } );
|
|
7663 }
|
|
7664
|
|
7665 // Get nodes in the order from the `rows` array with null values removed
|
|
7666 var nodes = _removeEmpty(
|
|
7667 _pluck_order( settings.aoData, rows, 'nTr' )
|
|
7668 );
|
|
7669
|
|
7670 // Selector - node
|
|
7671 if ( sel.nodeName ) {
|
|
7672 if ( $.inArray( sel, nodes ) !== -1 ) {
|
|
7673 return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table
|
|
7674 // and DataTables adds a prop for fast lookup
|
|
7675 }
|
|
7676 }
|
|
7677
|
|
7678 // Selector - jQuery selector string, array of nodes or jQuery object/
|
|
7679 // As jQuery's .filter() allows jQuery objects to be passed in filter,
|
|
7680 // it also allows arrays, so this will cope with all three options
|
|
7681 return $(nodes)
|
|
7682 .filter( sel )
|
|
7683 .map( function () {
|
|
7684 return this._DT_RowIndex;
|
|
7685 } )
|
|
7686 .toArray();
|
|
7687 } );
|
|
7688 };
|
|
7689
|
|
7690
|
|
7691 /**
|
|
7692 *
|
|
7693 */
|
|
7694 _api_register( 'rows()', function ( selector, opts ) {
|
|
7695 // argument shifting
|
|
7696 if ( selector === undefined ) {
|
|
7697 selector = '';
|
|
7698 }
|
|
7699 else if ( $.isPlainObject( selector ) ) {
|
|
7700 opts = selector;
|
|
7701 selector = '';
|
|
7702 }
|
|
7703
|
|
7704 opts = _selector_opts( opts );
|
|
7705
|
|
7706 var inst = this.iterator( 'table', function ( settings ) {
|
|
7707 return __row_selector( settings, selector, opts );
|
|
7708 }, 1 );
|
|
7709
|
|
7710 // Want argument shifting here and in __row_selector?
|
|
7711 inst.selector.rows = selector;
|
|
7712 inst.selector.opts = opts;
|
|
7713
|
|
7714 return inst;
|
|
7715 } );
|
|
7716
|
|
7717
|
|
7718 _api_register( 'rows().nodes()', function () {
|
|
7719 return this.iterator( 'row', function ( settings, row ) {
|
|
7720 return settings.aoData[ row ].nTr || undefined;
|
|
7721 }, 1 );
|
|
7722 } );
|
|
7723
|
|
7724 _api_register( 'rows().data()', function () {
|
|
7725 return this.iterator( true, 'rows', function ( settings, rows ) {
|
|
7726 return _pluck_order( settings.aoData, rows, '_aData' );
|
|
7727 }, 1 );
|
|
7728 } );
|
|
7729
|
|
7730 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
|
|
7731 return this.iterator( 'row', function ( settings, row ) {
|
|
7732 var r = settings.aoData[ row ];
|
|
7733 return type === 'search' ? r._aFilterData : r._aSortData;
|
|
7734 }, 1 );
|
|
7735 } );
|
|
7736
|
|
7737 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
|
|
7738 return this.iterator( 'row', function ( settings, row ) {
|
|
7739 _fnInvalidate( settings, row, src );
|
|
7740 } );
|
|
7741 } );
|
|
7742
|
|
7743 _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
|
|
7744 return this.iterator( 'row', function ( settings, row ) {
|
|
7745 return row;
|
|
7746 }, 1 );
|
|
7747 } );
|
|
7748
|
|
7749 _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
|
|
7750 var that = this;
|
|
7751
|
|
7752 return this.iterator( 'row', function ( settings, row, thatIdx ) {
|
|
7753 var data = settings.aoData;
|
|
7754
|
|
7755 data.splice( row, 1 );
|
|
7756
|
|
7757 // Update the _DT_RowIndex parameter on all rows in the table
|
|
7758 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
7759 if ( data[i].nTr !== null ) {
|
|
7760 data[i].nTr._DT_RowIndex = i;
|
|
7761 }
|
|
7762 }
|
|
7763
|
|
7764 // Remove the target row from the search array
|
|
7765 var displayIndex = $.inArray( row, settings.aiDisplay );
|
|
7766
|
|
7767 // Delete from the display arrays
|
|
7768 _fnDeleteIndex( settings.aiDisplayMaster, row );
|
|
7769 _fnDeleteIndex( settings.aiDisplay, row );
|
|
7770 _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
|
|
7771
|
|
7772 // Check for an 'overflow' they case for displaying the table
|
|
7773 _fnLengthOverflow( settings );
|
|
7774 } );
|
|
7775 } );
|
|
7776
|
|
7777
|
|
7778 _api_register( 'rows.add()', function ( rows ) {
|
|
7779 var newRows = this.iterator( 'table', function ( settings ) {
|
|
7780 var row, i, ien;
|
|
7781 var out = [];
|
|
7782
|
|
7783 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
|
|
7784 row = rows[i];
|
|
7785
|
|
7786 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
|
|
7787 out.push( _fnAddTr( settings, row )[0] );
|
|
7788 }
|
|
7789 else {
|
|
7790 out.push( _fnAddData( settings, row ) );
|
|
7791 }
|
|
7792 }
|
|
7793
|
|
7794 return out;
|
|
7795 }, 1 );
|
|
7796
|
|
7797 // Return an Api.rows() extended instance, so rows().nodes() etc can be used
|
|
7798 var modRows = this.rows( -1 );
|
|
7799 modRows.pop();
|
|
7800 modRows.push.apply( modRows, newRows.toArray() );
|
|
7801
|
|
7802 return modRows;
|
|
7803 } );
|
|
7804
|
|
7805
|
|
7806
|
|
7807
|
|
7808
|
|
7809 /**
|
|
7810 *
|
|
7811 */
|
|
7812 _api_register( 'row()', function ( selector, opts ) {
|
|
7813 return _selector_first( this.rows( selector, opts ) );
|
|
7814 } );
|
|
7815
|
|
7816
|
|
7817 _api_register( 'row().data()', function ( data ) {
|
|
7818 var ctx = this.context;
|
|
7819
|
|
7820 if ( data === undefined ) {
|
|
7821 // Get
|
|
7822 return ctx.length && this.length ?
|
|
7823 ctx[0].aoData[ this[0] ]._aData :
|
|
7824 undefined;
|
|
7825 }
|
|
7826
|
|
7827 // Set
|
|
7828 ctx[0].aoData[ this[0] ]._aData = data;
|
|
7829
|
|
7830 // Automatically invalidate
|
|
7831 _fnInvalidate( ctx[0], this[0], 'data' );
|
|
7832
|
|
7833 return this;
|
|
7834 } );
|
|
7835
|
|
7836
|
|
7837 _api_register( 'row().node()', function () {
|
|
7838 var ctx = this.context;
|
|
7839
|
|
7840 return ctx.length && this.length ?
|
|
7841 ctx[0].aoData[ this[0] ].nTr || null :
|
|
7842 null;
|
|
7843 } );
|
|
7844
|
|
7845
|
|
7846 _api_register( 'row.add()', function ( row ) {
|
|
7847 // Allow a jQuery object to be passed in - only a single row is added from
|
|
7848 // it though - the first element in the set
|
|
7849 if ( row instanceof $ && row.length ) {
|
|
7850 row = row[0];
|
|
7851 }
|
|
7852
|
|
7853 var rows = this.iterator( 'table', function ( settings ) {
|
|
7854 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
|
|
7855 return _fnAddTr( settings, row )[0];
|
|
7856 }
|
|
7857 return _fnAddData( settings, row );
|
|
7858 } );
|
|
7859
|
|
7860 // Return an Api.rows() extended instance, with the newly added row selected
|
|
7861 return this.row( rows[0] );
|
|
7862 } );
|
|
7863
|
|
7864
|
|
7865
|
|
7866 var __details_add = function ( ctx, row, data, klass )
|
|
7867 {
|
|
7868 // Convert to array of TR elements
|
|
7869 var rows = [];
|
|
7870 var addRow = function ( r, k ) {
|
|
7871 // If we get a TR element, then just add it directly - up to the dev
|
|
7872 // to add the correct number of columns etc
|
|
7873 if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
|
|
7874 rows.push( r );
|
|
7875 }
|
|
7876 else {
|
|
7877 // Otherwise create a row with a wrapper
|
|
7878 var created = $('<tr><td/></tr>').addClass( k );
|
|
7879 $('td', created)
|
|
7880 .addClass( k )
|
|
7881 .html( r )
|
|
7882 [0].colSpan = _fnVisbleColumns( ctx );
|
|
7883
|
|
7884 rows.push( created[0] );
|
|
7885 }
|
|
7886 };
|
|
7887
|
|
7888 if ( $.isArray( data ) || data instanceof $ ) {
|
|
7889 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
7890 addRow( data[i], klass );
|
|
7891 }
|
|
7892 }
|
|
7893 else {
|
|
7894 addRow( data, klass );
|
|
7895 }
|
|
7896
|
|
7897 if ( row._details ) {
|
|
7898 row._details.remove();
|
|
7899 }
|
|
7900
|
|
7901 row._details = $(rows);
|
|
7902
|
|
7903 // If the children were already shown, that state should be retained
|
|
7904 if ( row._detailsShow ) {
|
|
7905 row._details.insertAfter( row.nTr );
|
|
7906 }
|
|
7907 };
|
|
7908
|
|
7909
|
|
7910 var __details_remove = function ( api, idx )
|
|
7911 {
|
|
7912 var ctx = api.context;
|
|
7913
|
|
7914 if ( ctx.length ) {
|
|
7915 var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
|
|
7916
|
|
7917 if ( row._details ) {
|
|
7918 row._details.remove();
|
|
7919
|
|
7920 row._detailsShow = undefined;
|
|
7921 row._details = undefined;
|
|
7922 }
|
|
7923 }
|
|
7924 };
|
|
7925
|
|
7926
|
|
7927 var __details_display = function ( api, show ) {
|
|
7928 var ctx = api.context;
|
|
7929
|
|
7930 if ( ctx.length && api.length ) {
|
|
7931 var row = ctx[0].aoData[ api[0] ];
|
|
7932
|
|
7933 if ( row._details ) {
|
|
7934 row._detailsShow = show;
|
|
7935
|
|
7936 if ( show ) {
|
|
7937 row._details.insertAfter( row.nTr );
|
|
7938 }
|
|
7939 else {
|
|
7940 row._details.detach();
|
|
7941 }
|
|
7942
|
|
7943 __details_events( ctx[0] );
|
|
7944 }
|
|
7945 }
|
|
7946 };
|
|
7947
|
|
7948
|
|
7949 var __details_events = function ( settings )
|
|
7950 {
|
|
7951 var api = new _Api( settings );
|
|
7952 var namespace = '.dt.DT_details';
|
|
7953 var drawEvent = 'draw'+namespace;
|
|
7954 var colvisEvent = 'column-visibility'+namespace;
|
|
7955 var destroyEvent = 'destroy'+namespace;
|
|
7956 var data = settings.aoData;
|
|
7957
|
|
7958 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
|
|
7959
|
|
7960 if ( _pluck( data, '_details' ).length > 0 ) {
|
|
7961 // On each draw, insert the required elements into the document
|
|
7962 api.on( drawEvent, function ( e, ctx ) {
|
|
7963 if ( settings !== ctx ) {
|
|
7964 return;
|
|
7965 }
|
|
7966
|
|
7967 api.rows( {page:'current'} ).eq(0).each( function (idx) {
|
|
7968 // Internal data grab
|
|
7969 var row = data[ idx ];
|
|
7970
|
|
7971 if ( row._detailsShow ) {
|
|
7972 row._details.insertAfter( row.nTr );
|
|
7973 }
|
|
7974 } );
|
|
7975 } );
|
|
7976
|
|
7977 // Column visibility change - update the colspan
|
|
7978 api.on( colvisEvent, function ( e, ctx, idx, vis ) {
|
|
7979 if ( settings !== ctx ) {
|
|
7980 return;
|
|
7981 }
|
|
7982
|
|
7983 // Update the colspan for the details rows (note, only if it already has
|
|
7984 // a colspan)
|
|
7985 var row, visible = _fnVisbleColumns( ctx );
|
|
7986
|
|
7987 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
7988 row = data[i];
|
|
7989
|
|
7990 if ( row._details ) {
|
|
7991 row._details.children('td[colspan]').attr('colspan', visible );
|
|
7992 }
|
|
7993 }
|
|
7994 } );
|
|
7995
|
|
7996 // Table destroyed - nuke any child rows
|
|
7997 api.on( destroyEvent, function ( e, ctx ) {
|
|
7998 if ( settings !== ctx ) {
|
|
7999 return;
|
|
8000 }
|
|
8001
|
|
8002 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
8003 if ( data[i]._details ) {
|
|
8004 __details_remove( api, i );
|
|
8005 }
|
|
8006 }
|
|
8007 } );
|
|
8008 }
|
|
8009 };
|
|
8010
|
|
8011 // Strings for the method names to help minification
|
|
8012 var _emp = '';
|
|
8013 var _child_obj = _emp+'row().child';
|
|
8014 var _child_mth = _child_obj+'()';
|
|
8015
|
|
8016 // data can be:
|
|
8017 // tr
|
|
8018 // string
|
|
8019 // jQuery or array of any of the above
|
|
8020 _api_register( _child_mth, function ( data, klass ) {
|
|
8021 var ctx = this.context;
|
|
8022
|
|
8023 if ( data === undefined ) {
|
|
8024 // get
|
|
8025 return ctx.length && this.length ?
|
|
8026 ctx[0].aoData[ this[0] ]._details :
|
|
8027 undefined;
|
|
8028 }
|
|
8029 else if ( data === true ) {
|
|
8030 // show
|
|
8031 this.child.show();
|
|
8032 }
|
|
8033 else if ( data === false ) {
|
|
8034 // remove
|
|
8035 __details_remove( this );
|
|
8036 }
|
|
8037 else if ( ctx.length && this.length ) {
|
|
8038 // set
|
|
8039 __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
|
|
8040 }
|
|
8041
|
|
8042 return this;
|
|
8043 } );
|
|
8044
|
|
8045
|
|
8046 _api_register( [
|
|
8047 _child_obj+'.show()',
|
|
8048 _child_mth+'.show()' // only when `child()` was called with parameters (without
|
|
8049 ], function ( show ) { // it returns an object and this method is not executed)
|
|
8050 __details_display( this, true );
|
|
8051 return this;
|
|
8052 } );
|
|
8053
|
|
8054
|
|
8055 _api_register( [
|
|
8056 _child_obj+'.hide()',
|
|
8057 _child_mth+'.hide()' // only when `child()` was called with parameters (without
|
|
8058 ], function () { // it returns an object and this method is not executed)
|
|
8059 __details_display( this, false );
|
|
8060 return this;
|
|
8061 } );
|
|
8062
|
|
8063
|
|
8064 _api_register( [
|
|
8065 _child_obj+'.remove()',
|
|
8066 _child_mth+'.remove()' // only when `child()` was called with parameters (without
|
|
8067 ], function () { // it returns an object and this method is not executed)
|
|
8068 __details_remove( this );
|
|
8069 return this;
|
|
8070 } );
|
|
8071
|
|
8072
|
|
8073 _api_register( _child_obj+'.isShown()', function () {
|
|
8074 var ctx = this.context;
|
|
8075
|
|
8076 if ( ctx.length && this.length ) {
|
|
8077 // _detailsShown as false or undefined will fall through to return false
|
|
8078 return ctx[0].aoData[ this[0] ]._detailsShow || false;
|
|
8079 }
|
|
8080 return false;
|
|
8081 } );
|
|
8082
|
|
8083
|
|
8084
|
|
8085 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
8086 * Columns
|
|
8087 *
|
|
8088 * {integer} - column index (>=0 count from left, <0 count from right)
|
|
8089 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
|
|
8090 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
|
|
8091 * "{string}:name" - column name
|
|
8092 * "{string}" - jQuery selector on column header nodes
|
|
8093 *
|
|
8094 */
|
|
8095
|
|
8096 // can be an array of these items, comma separated list, or an array of comma
|
|
8097 // separated lists
|
|
8098
|
|
8099 var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
|
|
8100
|
|
8101
|
|
8102 // r1 and r2 are redundant - but it means that the parameters match for the
|
|
8103 // iterator callback in columns().data()
|
|
8104 var __columnData = function ( settings, column, r1, r2, rows ) {
|
|
8105 var a = [];
|
|
8106 for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
|
|
8107 a.push( _fnGetCellData( settings, rows[row], column ) );
|
|
8108 }
|
|
8109 return a;
|
|
8110 };
|
|
8111
|
|
8112
|
|
8113 var __column_selector = function ( settings, selector, opts )
|
|
8114 {
|
|
8115 var
|
|
8116 columns = settings.aoColumns,
|
|
8117 names = _pluck( columns, 'sName' ),
|
|
8118 nodes = _pluck( columns, 'nTh' );
|
|
8119
|
|
8120 return _selector_run( selector, function ( s ) {
|
|
8121 var selInt = _intVal( s );
|
|
8122
|
|
8123 // Selector - all
|
|
8124 if ( s === '' ) {
|
|
8125 return _range( columns.length );
|
|
8126 }
|
|
8127
|
|
8128 // Selector - index
|
|
8129 if ( selInt !== null ) {
|
|
8130 return [ selInt >= 0 ?
|
|
8131 selInt : // Count from left
|
|
8132 columns.length + selInt // Count from right (+ because its a negative value)
|
|
8133 ];
|
|
8134 }
|
|
8135
|
|
8136 // Selector = function
|
|
8137 if ( typeof s === 'function' ) {
|
|
8138 var rows = _selector_row_indexes( settings, opts );
|
|
8139
|
|
8140 return $.map( columns, function (col, idx) {
|
|
8141 return s(
|
|
8142 idx,
|
|
8143 __columnData( settings, idx, 0, 0, rows ),
|
|
8144 nodes[ idx ]
|
|
8145 ) ? idx : null;
|
|
8146 } );
|
|
8147 }
|
|
8148
|
|
8149 // jQuery or string selector
|
|
8150 var match = typeof s === 'string' ?
|
|
8151 s.match( __re_column_selector ) :
|
|
8152 '';
|
|
8153
|
|
8154 if ( match ) {
|
|
8155 switch( match[2] ) {
|
|
8156 case 'visIdx':
|
|
8157 case 'visible':
|
|
8158 var idx = parseInt( match[1], 10 );
|
|
8159 // Visible index given, convert to column index
|
|
8160 if ( idx < 0 ) {
|
|
8161 // Counting from the right
|
|
8162 var visColumns = $.map( columns, function (col,i) {
|
|
8163 return col.bVisible ? i : null;
|
|
8164 } );
|
|
8165 return [ visColumns[ visColumns.length + idx ] ];
|
|
8166 }
|
|
8167 // Counting from the left
|
|
8168 return [ _fnVisibleToColumnIndex( settings, idx ) ];
|
|
8169
|
|
8170 case 'name':
|
|
8171 // match by name. `names` is column index complete and in order
|
|
8172 return $.map( names, function (name, i) {
|
|
8173 return name === match[1] ? i : null;
|
|
8174 } );
|
|
8175 }
|
|
8176 }
|
|
8177 else {
|
|
8178 // jQuery selector on the TH elements for the columns
|
|
8179 return $( nodes )
|
|
8180 .filter( s )
|
|
8181 .map( function () {
|
|
8182 return $.inArray( this, nodes ); // `nodes` is column index complete and in order
|
|
8183 } )
|
|
8184 .toArray();
|
|
8185 }
|
|
8186 } );
|
|
8187 };
|
|
8188
|
|
8189
|
|
8190 var __setColumnVis = function ( settings, column, vis, recalc ) {
|
|
8191 var
|
|
8192 cols = settings.aoColumns,
|
|
8193 col = cols[ column ],
|
|
8194 data = settings.aoData,
|
|
8195 row, cells, i, ien, tr;
|
|
8196
|
|
8197 // Get
|
|
8198 if ( vis === undefined ) {
|
|
8199 return col.bVisible;
|
|
8200 }
|
|
8201
|
|
8202 // Set
|
|
8203 // No change
|
|
8204 if ( col.bVisible === vis ) {
|
|
8205 return;
|
|
8206 }
|
|
8207
|
|
8208 if ( vis ) {
|
|
8209 // Insert column
|
|
8210 // Need to decide if we should use appendChild or insertBefore
|
|
8211 var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
|
|
8212
|
|
8213 for ( i=0, ien=data.length ; i<ien ; i++ ) {
|
|
8214 tr = data[i].nTr;
|
|
8215 cells = data[i].anCells;
|
|
8216
|
|
8217 if ( tr ) {
|
|
8218 // insertBefore can act like appendChild if 2nd arg is null
|
|
8219 tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
|
|
8220 }
|
|
8221 }
|
|
8222 }
|
|
8223 else {
|
|
8224 // Remove column
|
|
8225 $( _pluck( settings.aoData, 'anCells', column ) ).detach();
|
|
8226 }
|
|
8227
|
|
8228 // Common actions
|
|
8229 col.bVisible = vis;
|
|
8230 _fnDrawHead( settings, settings.aoHeader );
|
|
8231 _fnDrawHead( settings, settings.aoFooter );
|
|
8232
|
|
8233 if ( recalc === undefined || recalc ) {
|
|
8234 // Automatically adjust column sizing
|
|
8235 _fnAdjustColumnSizing( settings );
|
|
8236
|
|
8237 // Realign columns for scrolling
|
|
8238 if ( settings.oScroll.sX || settings.oScroll.sY ) {
|
|
8239 _fnScrollDraw( settings );
|
|
8240 }
|
|
8241 }
|
|
8242
|
|
8243 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
|
|
8244
|
|
8245 _fnSaveState( settings );
|
|
8246 };
|
|
8247
|
|
8248
|
|
8249 /**
|
|
8250 *
|
|
8251 */
|
|
8252 _api_register( 'columns()', function ( selector, opts ) {
|
|
8253 // argument shifting
|
|
8254 if ( selector === undefined ) {
|
|
8255 selector = '';
|
|
8256 }
|
|
8257 else if ( $.isPlainObject( selector ) ) {
|
|
8258 opts = selector;
|
|
8259 selector = '';
|
|
8260 }
|
|
8261
|
|
8262 opts = _selector_opts( opts );
|
|
8263
|
|
8264 var inst = this.iterator( 'table', function ( settings ) {
|
|
8265 return __column_selector( settings, selector, opts );
|
|
8266 }, 1 );
|
|
8267
|
|
8268 // Want argument shifting here and in _row_selector?
|
|
8269 inst.selector.cols = selector;
|
|
8270 inst.selector.opts = opts;
|
|
8271
|
|
8272 return inst;
|
|
8273 } );
|
|
8274
|
|
8275
|
|
8276 /**
|
|
8277 *
|
|
8278 */
|
|
8279 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
|
|
8280 return this.iterator( 'column', function ( settings, column ) {
|
|
8281 return settings.aoColumns[column].nTh;
|
|
8282 }, 1 );
|
|
8283 } );
|
|
8284
|
|
8285
|
|
8286 /**
|
|
8287 *
|
|
8288 */
|
|
8289 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
|
|
8290 return this.iterator( 'column', function ( settings, column ) {
|
|
8291 return settings.aoColumns[column].nTf;
|
|
8292 }, 1 );
|
|
8293 } );
|
|
8294
|
|
8295
|
|
8296 /**
|
|
8297 *
|
|
8298 */
|
|
8299 _api_registerPlural( 'columns().data()', 'column().data()', function () {
|
|
8300 return this.iterator( 'column-rows', __columnData, 1 );
|
|
8301 } );
|
|
8302
|
|
8303
|
|
8304 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
|
|
8305 return this.iterator( 'column', function ( settings, column ) {
|
|
8306 return settings.aoColumns[column].mData;
|
|
8307 }, 1 );
|
|
8308 } );
|
|
8309
|
|
8310
|
|
8311 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
|
|
8312 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
|
|
8313 return _pluck_order( settings.aoData, rows,
|
|
8314 type === 'search' ? '_aFilterData' : '_aSortData', column
|
|
8315 );
|
|
8316 }, 1 );
|
|
8317 } );
|
|
8318
|
|
8319
|
|
8320 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
|
|
8321 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
|
|
8322 return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
|
|
8323 }, 1 );
|
|
8324 } );
|
|
8325
|
|
8326
|
|
8327
|
|
8328 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
|
|
8329 return this.iterator( 'column', function ( settings, column ) {
|
|
8330 if ( vis === undefined ) {
|
|
8331 return settings.aoColumns[ column ].bVisible;
|
|
8332 } // else
|
|
8333 __setColumnVis( settings, column, vis, calc );
|
|
8334 } );
|
|
8335 } );
|
|
8336
|
|
8337
|
|
8338
|
|
8339 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
|
|
8340 return this.iterator( 'column', function ( settings, column ) {
|
|
8341 return type === 'visible' ?
|
|
8342 _fnColumnIndexToVisible( settings, column ) :
|
|
8343 column;
|
|
8344 }, 1 );
|
|
8345 } );
|
|
8346
|
|
8347
|
|
8348 // _api_register( 'columns().show()', function () {
|
|
8349 // var selector = this.selector;
|
|
8350 // return this.columns( selector.cols, selector.opts ).visible( true );
|
|
8351 // } );
|
|
8352
|
|
8353
|
|
8354 // _api_register( 'columns().hide()', function () {
|
|
8355 // var selector = this.selector;
|
|
8356 // return this.columns( selector.cols, selector.opts ).visible( false );
|
|
8357 // } );
|
|
8358
|
|
8359
|
|
8360
|
|
8361 _api_register( 'columns.adjust()', function () {
|
|
8362 return this.iterator( 'table', function ( settings ) {
|
|
8363 _fnAdjustColumnSizing( settings );
|
|
8364 }, 1 );
|
|
8365 } );
|
|
8366
|
|
8367
|
|
8368 // Convert from one column index type, to another type
|
|
8369 _api_register( 'column.index()', function ( type, idx ) {
|
|
8370 if ( this.context.length !== 0 ) {
|
|
8371 var ctx = this.context[0];
|
|
8372
|
|
8373 if ( type === 'fromVisible' || type === 'toData' ) {
|
|
8374 return _fnVisibleToColumnIndex( ctx, idx );
|
|
8375 }
|
|
8376 else if ( type === 'fromData' || type === 'toVisible' ) {
|
|
8377 return _fnColumnIndexToVisible( ctx, idx );
|
|
8378 }
|
|
8379 }
|
|
8380 } );
|
|
8381
|
|
8382
|
|
8383 _api_register( 'column()', function ( selector, opts ) {
|
|
8384 return _selector_first( this.columns( selector, opts ) );
|
|
8385 } );
|
|
8386
|
|
8387
|
|
8388
|
|
8389
|
|
8390 var __cell_selector = function ( settings, selector, opts )
|
|
8391 {
|
|
8392 var data = settings.aoData;
|
|
8393 var rows = _selector_row_indexes( settings, opts );
|
|
8394 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
|
|
8395 var allCells = $( [].concat.apply([], cells) );
|
|
8396 var row;
|
|
8397 var columns = settings.aoColumns.length;
|
|
8398 var a, i, ien, j, o, host;
|
|
8399
|
|
8400 return _selector_run( selector, function ( s ) {
|
|
8401 var fnSelector = typeof s === 'function';
|
|
8402
|
|
8403 if ( s === null || s === undefined || fnSelector ) {
|
|
8404 // All cells and function selectors
|
|
8405 a = [];
|
|
8406
|
|
8407 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
|
|
8408 row = rows[i];
|
|
8409
|
|
8410 for ( j=0 ; j<columns ; j++ ) {
|
|
8411 o = {
|
|
8412 row: row,
|
|
8413 column: j
|
|
8414 };
|
|
8415
|
|
8416 if ( fnSelector ) {
|
|
8417 // Selector - function
|
|
8418 host = settings.aoData[ row ];
|
|
8419
|
|
8420 if ( s( o, _fnGetCellData(settings, row, j), host.anCells[j] ) ) {
|
|
8421 a.push( o );
|
|
8422 }
|
|
8423 }
|
|
8424 else {
|
|
8425 // Selector - all
|
|
8426 a.push( o );
|
|
8427 }
|
|
8428 }
|
|
8429 }
|
|
8430
|
|
8431 return a;
|
|
8432 }
|
|
8433
|
|
8434 // Selector - index
|
|
8435 if ( $.isPlainObject( s ) ) {
|
|
8436 return [s];
|
|
8437 }
|
|
8438
|
|
8439 // Selector - jQuery filtered cells
|
|
8440 return allCells
|
|
8441 .filter( s )
|
|
8442 .map( function (i, el) {
|
|
8443 row = el.parentNode._DT_RowIndex;
|
|
8444
|
|
8445 return {
|
|
8446 row: row,
|
|
8447 column: $.inArray( el, data[ row ].anCells )
|
|
8448 };
|
|
8449 } )
|
|
8450 .toArray();
|
|
8451 } );
|
|
8452 };
|
|
8453
|
|
8454
|
|
8455
|
|
8456
|
|
8457 _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
|
|
8458 // Argument shifting
|
|
8459 if ( $.isPlainObject( rowSelector ) ) {
|
|
8460 // Indexes
|
|
8461 if ( typeof rowSelector.row !== undefined ) {
|
|
8462 opts = columnSelector;
|
|
8463 columnSelector = null;
|
|
8464 }
|
|
8465 else {
|
|
8466 opts = rowSelector;
|
|
8467 rowSelector = null;
|
|
8468 }
|
|
8469 }
|
|
8470 if ( $.isPlainObject( columnSelector ) ) {
|
|
8471 opts = columnSelector;
|
|
8472 columnSelector = null;
|
|
8473 }
|
|
8474
|
|
8475 // Cell selector
|
|
8476 if ( columnSelector === null || columnSelector === undefined ) {
|
|
8477 return this.iterator( 'table', function ( settings ) {
|
|
8478 return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
|
|
8479 } );
|
|
8480 }
|
|
8481
|
|
8482 // Row + column selector
|
|
8483 var columns = this.columns( columnSelector, opts );
|
|
8484 var rows = this.rows( rowSelector, opts );
|
|
8485 var a, i, ien, j, jen;
|
|
8486
|
|
8487 var cells = this.iterator( 'table', function ( settings, idx ) {
|
|
8488 a = [];
|
|
8489
|
|
8490 for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
|
|
8491 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
|
|
8492 a.push( {
|
|
8493 row: rows[idx][i],
|
|
8494 column: columns[idx][j]
|
|
8495 } );
|
|
8496 }
|
|
8497 }
|
|
8498
|
|
8499 return a;
|
|
8500 }, 1 );
|
|
8501
|
|
8502 $.extend( cells.selector, {
|
|
8503 cols: columnSelector,
|
|
8504 rows: rowSelector,
|
|
8505 opts: opts
|
|
8506 } );
|
|
8507
|
|
8508 return cells;
|
|
8509 } );
|
|
8510
|
|
8511
|
|
8512 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
|
|
8513 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
8514 var cells = settings.aoData[ row ].anCells;
|
|
8515 return cells ?
|
|
8516 cells[ column ] :
|
|
8517 undefined;
|
|
8518 }, 1 );
|
|
8519 } );
|
|
8520
|
|
8521
|
|
8522 _api_register( 'cells().data()', function () {
|
|
8523 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
8524 return _fnGetCellData( settings, row, column );
|
|
8525 }, 1 );
|
|
8526 } );
|
|
8527
|
|
8528
|
|
8529 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
|
|
8530 type = type === 'search' ? '_aFilterData' : '_aSortData';
|
|
8531
|
|
8532 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
8533 return settings.aoData[ row ][ type ][ column ];
|
|
8534 }, 1 );
|
|
8535 } );
|
|
8536
|
|
8537
|
|
8538 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
|
|
8539 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
8540 return _fnGetCellData( settings, row, column, type );
|
|
8541 }, 1 );
|
|
8542 } );
|
|
8543
|
|
8544
|
|
8545 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
|
|
8546 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
8547 return {
|
|
8548 row: row,
|
|
8549 column: column,
|
|
8550 columnVisible: _fnColumnIndexToVisible( settings, column )
|
|
8551 };
|
|
8552 }, 1 );
|
|
8553 } );
|
|
8554
|
|
8555
|
|
8556 _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
|
|
8557 return this.iterator( 'cell', function ( settings, row, column ) {
|
|
8558 _fnInvalidate( settings, row, src, column );
|
|
8559 } );
|
|
8560 } );
|
|
8561
|
|
8562
|
|
8563
|
|
8564 _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
|
|
8565 return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
|
|
8566 } );
|
|
8567
|
|
8568
|
|
8569 _api_register( 'cell().data()', function ( data ) {
|
|
8570 var ctx = this.context;
|
|
8571 var cell = this[0];
|
|
8572
|
|
8573 if ( data === undefined ) {
|
|
8574 // Get
|
|
8575 return ctx.length && cell.length ?
|
|
8576 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
|
|
8577 undefined;
|
|
8578 }
|
|
8579
|
|
8580 // Set
|
|
8581 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
|
|
8582 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
|
|
8583
|
|
8584 return this;
|
|
8585 } );
|
|
8586
|
|
8587
|
|
8588
|
|
8589 /**
|
|
8590 * Get current ordering (sorting) that has been applied to the table.
|
|
8591 *
|
|
8592 * @returns {array} 2D array containing the sorting information for the first
|
|
8593 * table in the current context. Each element in the parent array represents
|
|
8594 * a column being sorted upon (i.e. multi-sorting with two columns would have
|
|
8595 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
|
|
8596 * the column index that the sorting condition applies to, the second is the
|
|
8597 * direction of the sort (`desc` or `asc`) and, optionally, the third is the
|
|
8598 * index of the sorting order from the `column.sorting` initialisation array.
|
|
8599 *//**
|
|
8600 * Set the ordering for the table.
|
|
8601 *
|
|
8602 * @param {integer} order Column index to sort upon.
|
|
8603 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
|
|
8604 * @returns {DataTables.Api} this
|
|
8605 *//**
|
|
8606 * Set the ordering for the table.
|
|
8607 *
|
|
8608 * @param {array} order 1D array of sorting information to be applied.
|
|
8609 * @param {array} [...] Optional additional sorting conditions
|
|
8610 * @returns {DataTables.Api} this
|
|
8611 *//**
|
|
8612 * Set the ordering for the table.
|
|
8613 *
|
|
8614 * @param {array} order 2D array of sorting information to be applied.
|
|
8615 * @returns {DataTables.Api} this
|
|
8616 */
|
|
8617 _api_register( 'order()', function ( order, dir ) {
|
|
8618 var ctx = this.context;
|
|
8619
|
|
8620 if ( order === undefined ) {
|
|
8621 // get
|
|
8622 return ctx.length !== 0 ?
|
|
8623 ctx[0].aaSorting :
|
|
8624 undefined;
|
|
8625 }
|
|
8626
|
|
8627 // set
|
|
8628 if ( typeof order === 'number' ) {
|
|
8629 // Simple column / direction passed in
|
|
8630 order = [ [ order, dir ] ];
|
|
8631 }
|
|
8632 else if ( ! $.isArray( order[0] ) ) {
|
|
8633 // Arguments passed in (list of 1D arrays)
|
|
8634 order = Array.prototype.slice.call( arguments );
|
|
8635 }
|
|
8636 // otherwise a 2D array was passed in
|
|
8637
|
|
8638 return this.iterator( 'table', function ( settings ) {
|
|
8639 settings.aaSorting = order.slice();
|
|
8640 } );
|
|
8641 } );
|
|
8642
|
|
8643
|
|
8644 /**
|
|
8645 * Attach a sort listener to an element for a given column
|
|
8646 *
|
|
8647 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
|
|
8648 * listener to. This can take the form of a single DOM node, a jQuery
|
|
8649 * collection of nodes or a jQuery selector which will identify the node(s).
|
|
8650 * @param {integer} column the column that a click on this node will sort on
|
|
8651 * @param {function} [callback] callback function when sort is run
|
|
8652 * @returns {DataTables.Api} this
|
|
8653 */
|
|
8654 _api_register( 'order.listener()', function ( node, column, callback ) {
|
|
8655 return this.iterator( 'table', function ( settings ) {
|
|
8656 _fnSortAttachListener( settings, node, column, callback );
|
|
8657 } );
|
|
8658 } );
|
|
8659
|
|
8660
|
|
8661 // Order by the selected column(s)
|
|
8662 _api_register( [
|
|
8663 'columns().order()',
|
|
8664 'column().order()'
|
|
8665 ], function ( dir ) {
|
|
8666 var that = this;
|
|
8667
|
|
8668 return this.iterator( 'table', function ( settings, i ) {
|
|
8669 var sort = [];
|
|
8670
|
|
8671 $.each( that[i], function (j, col) {
|
|
8672 sort.push( [ col, dir ] );
|
|
8673 } );
|
|
8674
|
|
8675 settings.aaSorting = sort;
|
|
8676 } );
|
|
8677 } );
|
|
8678
|
|
8679
|
|
8680
|
|
8681 _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
|
|
8682 var ctx = this.context;
|
|
8683
|
|
8684 if ( input === undefined ) {
|
|
8685 // get
|
|
8686 return ctx.length !== 0 ?
|
|
8687 ctx[0].oPreviousSearch.sSearch :
|
|
8688 undefined;
|
|
8689 }
|
|
8690
|
|
8691 // set
|
|
8692 return this.iterator( 'table', function ( settings ) {
|
|
8693 if ( ! settings.oFeatures.bFilter ) {
|
|
8694 return;
|
|
8695 }
|
|
8696
|
|
8697 _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
|
|
8698 "sSearch": input+"",
|
|
8699 "bRegex": regex === null ? false : regex,
|
|
8700 "bSmart": smart === null ? true : smart,
|
|
8701 "bCaseInsensitive": caseInsen === null ? true : caseInsen
|
|
8702 } ), 1 );
|
|
8703 } );
|
|
8704 } );
|
|
8705
|
|
8706
|
|
8707 _api_registerPlural(
|
|
8708 'columns().search()',
|
|
8709 'column().search()',
|
|
8710 function ( input, regex, smart, caseInsen ) {
|
|
8711 return this.iterator( 'column', function ( settings, column ) {
|
|
8712 var preSearch = settings.aoPreSearchCols;
|
|
8713
|
|
8714 if ( input === undefined ) {
|
|
8715 // get
|
|
8716 return preSearch[ column ].sSearch;
|
|
8717 }
|
|
8718
|
|
8719 // set
|
|
8720 if ( ! settings.oFeatures.bFilter ) {
|
|
8721 return;
|
|
8722 }
|
|
8723
|
|
8724 $.extend( preSearch[ column ], {
|
|
8725 "sSearch": input+"",
|
|
8726 "bRegex": regex === null ? false : regex,
|
|
8727 "bSmart": smart === null ? true : smart,
|
|
8728 "bCaseInsensitive": caseInsen === null ? true : caseInsen
|
|
8729 } );
|
|
8730
|
|
8731 _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
|
|
8732 } );
|
|
8733 }
|
|
8734 );
|
|
8735
|
|
8736 /*
|
|
8737 * State API methods
|
|
8738 */
|
|
8739
|
|
8740 _api_register( 'state()', function () {
|
|
8741 return this.context.length ?
|
|
8742 this.context[0].oSavedState :
|
|
8743 null;
|
|
8744 } );
|
|
8745
|
|
8746
|
|
8747 _api_register( 'state.clear()', function () {
|
|
8748 return this.iterator( 'table', function ( settings ) {
|
|
8749 // Save an empty object
|
|
8750 settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
|
|
8751 } );
|
|
8752 } );
|
|
8753
|
|
8754
|
|
8755 _api_register( 'state.loaded()', function () {
|
|
8756 return this.context.length ?
|
|
8757 this.context[0].oLoadedState :
|
|
8758 null;
|
|
8759 } );
|
|
8760
|
|
8761
|
|
8762 _api_register( 'state.save()', function () {
|
|
8763 return this.iterator( 'table', function ( settings ) {
|
|
8764 _fnSaveState( settings );
|
|
8765 } );
|
|
8766 } );
|
|
8767
|
|
8768
|
|
8769
|
|
8770 /**
|
|
8771 * Provide a common method for plug-ins to check the version of DataTables being
|
|
8772 * used, in order to ensure compatibility.
|
|
8773 *
|
|
8774 * @param {string} version Version string to check for, in the format "X.Y.Z".
|
|
8775 * Note that the formats "X" and "X.Y" are also acceptable.
|
|
8776 * @returns {boolean} true if this version of DataTables is greater or equal to
|
|
8777 * the required version, or false if this version of DataTales is not
|
|
8778 * suitable
|
|
8779 * @static
|
|
8780 * @dtopt API-Static
|
|
8781 *
|
|
8782 * @example
|
|
8783 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
|
|
8784 */
|
|
8785 DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
|
|
8786 {
|
|
8787 var aThis = DataTable.version.split('.');
|
|
8788 var aThat = version.split('.');
|
|
8789 var iThis, iThat;
|
|
8790
|
|
8791 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
|
|
8792 iThis = parseInt( aThis[i], 10 ) || 0;
|
|
8793 iThat = parseInt( aThat[i], 10 ) || 0;
|
|
8794
|
|
8795 // Parts are the same, keep comparing
|
|
8796 if (iThis === iThat) {
|
|
8797 continue;
|
|
8798 }
|
|
8799
|
|
8800 // Parts are different, return immediately
|
|
8801 return iThis > iThat;
|
|
8802 }
|
|
8803
|
|
8804 return true;
|
|
8805 };
|
|
8806
|
|
8807
|
|
8808 /**
|
|
8809 * Check if a `<table>` node is a DataTable table already or not.
|
|
8810 *
|
|
8811 * @param {node|jquery|string} table Table node, jQuery object or jQuery
|
|
8812 * selector for the table to test. Note that if more than more than one
|
|
8813 * table is passed on, only the first will be checked
|
|
8814 * @returns {boolean} true the table given is a DataTable, or false otherwise
|
|
8815 * @static
|
|
8816 * @dtopt API-Static
|
|
8817 *
|
|
8818 * @example
|
|
8819 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
|
|
8820 * $('#example').dataTable();
|
|
8821 * }
|
|
8822 */
|
|
8823 DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
|
|
8824 {
|
|
8825 var t = $(table).get(0);
|
|
8826 var is = false;
|
|
8827
|
|
8828 $.each( DataTable.settings, function (i, o) {
|
|
8829 if ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {
|
|
8830 is = true;
|
|
8831 }
|
|
8832 } );
|
|
8833
|
|
8834 return is;
|
|
8835 };
|
|
8836
|
|
8837
|
|
8838 /**
|
|
8839 * Get all DataTable tables that have been initialised - optionally you can
|
|
8840 * select to get only currently visible tables.
|
|
8841 *
|
|
8842 * @param {boolean} [visible=false] Flag to indicate if you want all (default)
|
|
8843 * or visible tables only.
|
|
8844 * @returns {array} Array of `table` nodes (not DataTable instances) which are
|
|
8845 * DataTables
|
|
8846 * @static
|
|
8847 * @dtopt API-Static
|
|
8848 *
|
|
8849 * @example
|
|
8850 * $.each( $.fn.dataTable.tables(true), function () {
|
|
8851 * $(table).DataTable().columns.adjust();
|
|
8852 * } );
|
|
8853 */
|
|
8854 DataTable.tables = DataTable.fnTables = function ( visible )
|
|
8855 {
|
|
8856 return $.map( DataTable.settings, function (o) {
|
|
8857 if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
|
|
8858 return o.nTable;
|
|
8859 }
|
|
8860 } );
|
|
8861 };
|
|
8862
|
|
8863
|
|
8864 /**
|
|
8865 * DataTables utility methods
|
|
8866 *
|
|
8867 * This namespace provides helper methods that DataTables uses internally to
|
|
8868 * create a DataTable, but which are not exclusively used only for DataTables.
|
|
8869 * These methods can be used by extension authors to save the duplication of
|
|
8870 * code.
|
|
8871 *
|
|
8872 * @namespace
|
|
8873 */
|
|
8874 DataTable.util = {
|
|
8875 /**
|
|
8876 * Throttle the calls to a function. Arguments and context are maintained
|
|
8877 * for the throttled function.
|
|
8878 *
|
|
8879 * @param {function} fn Function to be called
|
|
8880 * @param {integer} freq Call frequency in mS
|
|
8881 * @return {function} Wrapped function
|
|
8882 */
|
|
8883 throttle: _fnThrottle,
|
|
8884
|
|
8885
|
|
8886 /**
|
|
8887 * Escape a string such that it can be used in a regular expression
|
|
8888 *
|
|
8889 * @param {string} sVal string to escape
|
|
8890 * @returns {string} escaped string
|
|
8891 */
|
|
8892 escapeRegex: _fnEscapeRegex
|
|
8893 };
|
|
8894
|
|
8895
|
|
8896 /**
|
|
8897 * Convert from camel case parameters to Hungarian notation. This is made public
|
|
8898 * for the extensions to provide the same ability as DataTables core to accept
|
|
8899 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
|
|
8900 * parameters.
|
|
8901 *
|
|
8902 * @param {object} src The model object which holds all parameters that can be
|
|
8903 * mapped.
|
|
8904 * @param {object} user The object to convert from camel case to Hungarian.
|
|
8905 * @param {boolean} force When set to `true`, properties which already have a
|
|
8906 * Hungarian value in the `user` object will be overwritten. Otherwise they
|
|
8907 * won't be.
|
|
8908 */
|
|
8909 DataTable.camelToHungarian = _fnCamelToHungarian;
|
|
8910
|
|
8911
|
|
8912
|
|
8913 /**
|
|
8914 *
|
|
8915 */
|
|
8916 _api_register( '$()', function ( selector, opts ) {
|
|
8917 var
|
|
8918 rows = this.rows( opts ).nodes(), // Get all rows
|
|
8919 jqRows = $(rows);
|
|
8920
|
|
8921 return $( [].concat(
|
|
8922 jqRows.filter( selector ).toArray(),
|
|
8923 jqRows.find( selector ).toArray()
|
|
8924 ) );
|
|
8925 } );
|
|
8926
|
|
8927
|
|
8928 // jQuery functions to operate on the tables
|
|
8929 $.each( [ 'on', 'one', 'off' ], function (i, key) {
|
|
8930 _api_register( key+'()', function ( /* event, handler */ ) {
|
|
8931 var args = Array.prototype.slice.call(arguments);
|
|
8932
|
|
8933 // Add the `dt` namespace automatically if it isn't already present
|
|
8934 if ( ! args[0].match(/\.dt\b/) ) {
|
|
8935 args[0] += '.dt';
|
|
8936 }
|
|
8937
|
|
8938 var inst = $( this.tables().nodes() );
|
|
8939 inst[key].apply( inst, args );
|
|
8940 return this;
|
|
8941 } );
|
|
8942 } );
|
|
8943
|
|
8944
|
|
8945 _api_register( 'clear()', function () {
|
|
8946 return this.iterator( 'table', function ( settings ) {
|
|
8947 _fnClearTable( settings );
|
|
8948 } );
|
|
8949 } );
|
|
8950
|
|
8951
|
|
8952 _api_register( 'settings()', function () {
|
|
8953 return new _Api( this.context, this.context );
|
|
8954 } );
|
|
8955
|
|
8956
|
|
8957 _api_register( 'data()', function () {
|
|
8958 return this.iterator( 'table', function ( settings ) {
|
|
8959 return _pluck( settings.aoData, '_aData' );
|
|
8960 } ).flatten();
|
|
8961 } );
|
|
8962
|
|
8963
|
|
8964 _api_register( 'destroy()', function ( remove ) {
|
|
8965 remove = remove || false;
|
|
8966
|
|
8967 return this.iterator( 'table', function ( settings ) {
|
|
8968 var orig = settings.nTableWrapper.parentNode;
|
|
8969 var classes = settings.oClasses;
|
|
8970 var table = settings.nTable;
|
|
8971 var tbody = settings.nTBody;
|
|
8972 var thead = settings.nTHead;
|
|
8973 var tfoot = settings.nTFoot;
|
|
8974 var jqTable = $(table);
|
|
8975 var jqTbody = $(tbody);
|
|
8976 var jqWrapper = $(settings.nTableWrapper);
|
|
8977 var rows = $.map( settings.aoData, function (r) { return r.nTr; } );
|
|
8978 var i, ien;
|
|
8979
|
|
8980 // Flag to note that the table is currently being destroyed - no action
|
|
8981 // should be taken
|
|
8982 settings.bDestroying = true;
|
|
8983
|
|
8984 // Fire off the destroy callbacks for plug-ins etc
|
|
8985 _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
|
|
8986
|
|
8987 // If not being removed from the document, make all columns visible
|
|
8988 if ( ! remove ) {
|
|
8989 new _Api( settings ).columns().visible( true );
|
|
8990 }
|
|
8991
|
|
8992 // Blitz all `DT` namespaced events (these are internal events, the
|
|
8993 // lowercase, `dt` events are user subscribed and they are responsible
|
|
8994 // for removing them
|
|
8995 jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
|
|
8996 $(window).unbind('.DT-'+settings.sInstance);
|
|
8997
|
|
8998 // When scrolling we had to break the table up - restore it
|
|
8999 if ( table != thead.parentNode ) {
|
|
9000 jqTable.children('thead').detach();
|
|
9001 jqTable.append( thead );
|
|
9002 }
|
|
9003
|
|
9004 if ( tfoot && table != tfoot.parentNode ) {
|
|
9005 jqTable.children('tfoot').detach();
|
|
9006 jqTable.append( tfoot );
|
|
9007 }
|
|
9008
|
|
9009 // Remove the DataTables generated nodes, events and classes
|
|
9010 jqTable.detach();
|
|
9011 jqWrapper.detach();
|
|
9012
|
|
9013 settings.aaSorting = [];
|
|
9014 settings.aaSortingFixed = [];
|
|
9015 _fnSortingClasses( settings );
|
|
9016
|
|
9017 $( rows ).removeClass( settings.asStripeClasses.join(' ') );
|
|
9018
|
|
9019 $('th, td', thead).removeClass( classes.sSortable+' '+
|
|
9020 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
|
|
9021 );
|
|
9022
|
|
9023 if ( settings.bJUI ) {
|
|
9024 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
|
|
9025 $('th, td', thead).each( function () {
|
|
9026 var wrapper = $('div.'+classes.sSortJUIWrapper, this);
|
|
9027 $(this).append( wrapper.contents() );
|
|
9028 wrapper.detach();
|
|
9029 } );
|
|
9030 }
|
|
9031
|
|
9032 if ( ! remove && orig ) {
|
|
9033 // insertBefore acts like appendChild if !arg[1]
|
|
9034 orig.insertBefore( table, settings.nTableReinsertBefore );
|
|
9035 }
|
|
9036
|
|
9037 // Add the TR elements back into the table in their original order
|
|
9038 jqTbody.children().detach();
|
|
9039 jqTbody.append( rows );
|
|
9040
|
|
9041 // Restore the width of the original table - was read from the style property,
|
|
9042 // so we can restore directly to that
|
|
9043 jqTable
|
|
9044 .css( 'width', settings.sDestroyWidth )
|
|
9045 .removeClass( classes.sTable );
|
|
9046
|
|
9047 // If the were originally stripe classes - then we add them back here.
|
|
9048 // Note this is not fool proof (for example if not all rows had stripe
|
|
9049 // classes - but it's a good effort without getting carried away
|
|
9050 ien = settings.asDestroyStripes.length;
|
|
9051
|
|
9052 if ( ien ) {
|
|
9053 jqTbody.children().each( function (i) {
|
|
9054 $(this).addClass( settings.asDestroyStripes[i % ien] );
|
|
9055 } );
|
|
9056 }
|
|
9057
|
|
9058 /* Remove the settings object from the settings array */
|
|
9059 var idx = $.inArray( settings, DataTable.settings );
|
|
9060 if ( idx !== -1 ) {
|
|
9061 DataTable.settings.splice( idx, 1 );
|
|
9062 }
|
|
9063 } );
|
|
9064 } );
|
|
9065
|
|
9066
|
|
9067 /**
|
|
9068 * Version string for plug-ins to check compatibility. Allowed format is
|
|
9069 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
|
|
9070 * only for non-release builds. See http://semver.org/ for more information.
|
|
9071 * @member
|
|
9072 * @type string
|
|
9073 * @default Version number
|
|
9074 */
|
|
9075 DataTable.version = "1.10.4";
|
|
9076
|
|
9077 /**
|
|
9078 * Private data store, containing all of the settings objects that are
|
|
9079 * created for the tables on a given page.
|
|
9080 *
|
|
9081 * Note that the `DataTable.settings` object is aliased to
|
|
9082 * `jQuery.fn.dataTableExt` through which it may be accessed and
|
|
9083 * manipulated, or `jQuery.fn.dataTable.settings`.
|
|
9084 * @member
|
|
9085 * @type array
|
|
9086 * @default []
|
|
9087 * @private
|
|
9088 */
|
|
9089 DataTable.settings = [];
|
|
9090
|
|
9091 /**
|
|
9092 * Object models container, for the various models that DataTables has
|
|
9093 * available to it. These models define the objects that are used to hold
|
|
9094 * the active state and configuration of the table.
|
|
9095 * @namespace
|
|
9096 */
|
|
9097 DataTable.models = {};
|
|
9098
|
|
9099
|
|
9100
|
|
9101 /**
|
|
9102 * Template object for the way in which DataTables holds information about
|
|
9103 * search information for the global filter and individual column filters.
|
|
9104 * @namespace
|
|
9105 */
|
|
9106 DataTable.models.oSearch = {
|
|
9107 /**
|
|
9108 * Flag to indicate if the filtering should be case insensitive or not
|
|
9109 * @type boolean
|
|
9110 * @default true
|
|
9111 */
|
|
9112 "bCaseInsensitive": true,
|
|
9113
|
|
9114 /**
|
|
9115 * Applied search term
|
|
9116 * @type string
|
|
9117 * @default <i>Empty string</i>
|
|
9118 */
|
|
9119 "sSearch": "",
|
|
9120
|
|
9121 /**
|
|
9122 * Flag to indicate if the search term should be interpreted as a
|
|
9123 * regular expression (true) or not (false) and therefore and special
|
|
9124 * regex characters escaped.
|
|
9125 * @type boolean
|
|
9126 * @default false
|
|
9127 */
|
|
9128 "bRegex": false,
|
|
9129
|
|
9130 /**
|
|
9131 * Flag to indicate if DataTables is to use its smart filtering or not.
|
|
9132 * @type boolean
|
|
9133 * @default true
|
|
9134 */
|
|
9135 "bSmart": true
|
|
9136 };
|
|
9137
|
|
9138
|
|
9139
|
|
9140
|
|
9141 /**
|
|
9142 * Template object for the way in which DataTables holds information about
|
|
9143 * each individual row. This is the object format used for the settings
|
|
9144 * aoData array.
|
|
9145 * @namespace
|
|
9146 */
|
|
9147 DataTable.models.oRow = {
|
|
9148 /**
|
|
9149 * TR element for the row
|
|
9150 * @type node
|
|
9151 * @default null
|
|
9152 */
|
|
9153 "nTr": null,
|
|
9154
|
|
9155 /**
|
|
9156 * Array of TD elements for each row. This is null until the row has been
|
|
9157 * created.
|
|
9158 * @type array nodes
|
|
9159 * @default []
|
|
9160 */
|
|
9161 "anCells": null,
|
|
9162
|
|
9163 /**
|
|
9164 * Data object from the original data source for the row. This is either
|
|
9165 * an array if using the traditional form of DataTables, or an object if
|
|
9166 * using mData options. The exact type will depend on the passed in
|
|
9167 * data from the data source, or will be an array if using DOM a data
|
|
9168 * source.
|
|
9169 * @type array|object
|
|
9170 * @default []
|
|
9171 */
|
|
9172 "_aData": [],
|
|
9173
|
|
9174 /**
|
|
9175 * Sorting data cache - this array is ostensibly the same length as the
|
|
9176 * number of columns (although each index is generated only as it is
|
|
9177 * needed), and holds the data that is used for sorting each column in the
|
|
9178 * row. We do this cache generation at the start of the sort in order that
|
|
9179 * the formatting of the sort data need be done only once for each cell
|
|
9180 * per sort. This array should not be read from or written to by anything
|
|
9181 * other than the master sorting methods.
|
|
9182 * @type array
|
|
9183 * @default null
|
|
9184 * @private
|
|
9185 */
|
|
9186 "_aSortData": null,
|
|
9187
|
|
9188 /**
|
|
9189 * Per cell filtering data cache. As per the sort data cache, used to
|
|
9190 * increase the performance of the filtering in DataTables
|
|
9191 * @type array
|
|
9192 * @default null
|
|
9193 * @private
|
|
9194 */
|
|
9195 "_aFilterData": null,
|
|
9196
|
|
9197 /**
|
|
9198 * Filtering data cache. This is the same as the cell filtering cache, but
|
|
9199 * in this case a string rather than an array. This is easily computed with
|
|
9200 * a join on `_aFilterData`, but is provided as a cache so the join isn't
|
|
9201 * needed on every search (memory traded for performance)
|
|
9202 * @type array
|
|
9203 * @default null
|
|
9204 * @private
|
|
9205 */
|
|
9206 "_sFilterRow": null,
|
|
9207
|
|
9208 /**
|
|
9209 * Cache of the class name that DataTables has applied to the row, so we
|
|
9210 * can quickly look at this variable rather than needing to do a DOM check
|
|
9211 * on className for the nTr property.
|
|
9212 * @type string
|
|
9213 * @default <i>Empty string</i>
|
|
9214 * @private
|
|
9215 */
|
|
9216 "_sRowStripe": "",
|
|
9217
|
|
9218 /**
|
|
9219 * Denote if the original data source was from the DOM, or the data source
|
|
9220 * object. This is used for invalidating data, so DataTables can
|
|
9221 * automatically read data from the original source, unless uninstructed
|
|
9222 * otherwise.
|
|
9223 * @type string
|
|
9224 * @default null
|
|
9225 * @private
|
|
9226 */
|
|
9227 "src": null
|
|
9228 };
|
|
9229
|
|
9230
|
|
9231 /**
|
|
9232 * Template object for the column information object in DataTables. This object
|
|
9233 * is held in the settings aoColumns array and contains all the information that
|
|
9234 * DataTables needs about each individual column.
|
|
9235 *
|
|
9236 * Note that this object is related to {@link DataTable.defaults.column}
|
|
9237 * but this one is the internal data store for DataTables's cache of columns.
|
|
9238 * It should NOT be manipulated outside of DataTables. Any configuration should
|
|
9239 * be done through the initialisation options.
|
|
9240 * @namespace
|
|
9241 */
|
|
9242 DataTable.models.oColumn = {
|
|
9243 /**
|
|
9244 * Column index. This could be worked out on-the-fly with $.inArray, but it
|
|
9245 * is faster to just hold it as a variable
|
|
9246 * @type integer
|
|
9247 * @default null
|
|
9248 */
|
|
9249 "idx": null,
|
|
9250
|
|
9251 /**
|
|
9252 * A list of the columns that sorting should occur on when this column
|
|
9253 * is sorted. That this property is an array allows multi-column sorting
|
|
9254 * to be defined for a column (for example first name / last name columns
|
|
9255 * would benefit from this). The values are integers pointing to the
|
|
9256 * columns to be sorted on (typically it will be a single integer pointing
|
|
9257 * at itself, but that doesn't need to be the case).
|
|
9258 * @type array
|
|
9259 */
|
|
9260 "aDataSort": null,
|
|
9261
|
|
9262 /**
|
|
9263 * Define the sorting directions that are applied to the column, in sequence
|
|
9264 * as the column is repeatedly sorted upon - i.e. the first value is used
|
|
9265 * as the sorting direction when the column if first sorted (clicked on).
|
|
9266 * Sort it again (click again) and it will move on to the next index.
|
|
9267 * Repeat until loop.
|
|
9268 * @type array
|
|
9269 */
|
|
9270 "asSorting": null,
|
|
9271
|
|
9272 /**
|
|
9273 * Flag to indicate if the column is searchable, and thus should be included
|
|
9274 * in the filtering or not.
|
|
9275 * @type boolean
|
|
9276 */
|
|
9277 "bSearchable": null,
|
|
9278
|
|
9279 /**
|
|
9280 * Flag to indicate if the column is sortable or not.
|
|
9281 * @type boolean
|
|
9282 */
|
|
9283 "bSortable": null,
|
|
9284
|
|
9285 /**
|
|
9286 * Flag to indicate if the column is currently visible in the table or not
|
|
9287 * @type boolean
|
|
9288 */
|
|
9289 "bVisible": null,
|
|
9290
|
|
9291 /**
|
|
9292 * Store for manual type assignment using the `column.type` option. This
|
|
9293 * is held in store so we can manipulate the column's `sType` property.
|
|
9294 * @type string
|
|
9295 * @default null
|
|
9296 * @private
|
|
9297 */
|
|
9298 "_sManualType": null,
|
|
9299
|
|
9300 /**
|
|
9301 * Flag to indicate if HTML5 data attributes should be used as the data
|
|
9302 * source for filtering or sorting. True is either are.
|
|
9303 * @type boolean
|
|
9304 * @default false
|
|
9305 * @private
|
|
9306 */
|
|
9307 "_bAttrSrc": false,
|
|
9308
|
|
9309 /**
|
|
9310 * Developer definable function that is called whenever a cell is created (Ajax source,
|
|
9311 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
|
|
9312 * allowing you to modify the DOM element (add background colour for example) when the
|
|
9313 * element is available.
|
|
9314 * @type function
|
|
9315 * @param {element} nTd The TD node that has been created
|
|
9316 * @param {*} sData The Data for the cell
|
|
9317 * @param {array|object} oData The data for the whole row
|
|
9318 * @param {int} iRow The row index for the aoData data store
|
|
9319 * @default null
|
|
9320 */
|
|
9321 "fnCreatedCell": null,
|
|
9322
|
|
9323 /**
|
|
9324 * Function to get data from a cell in a column. You should <b>never</b>
|
|
9325 * access data directly through _aData internally in DataTables - always use
|
|
9326 * the method attached to this property. It allows mData to function as
|
|
9327 * required. This function is automatically assigned by the column
|
|
9328 * initialisation method
|
|
9329 * @type function
|
|
9330 * @param {array|object} oData The data array/object for the array
|
|
9331 * (i.e. aoData[]._aData)
|
|
9332 * @param {string} sSpecific The specific data type you want to get -
|
|
9333 * 'display', 'type' 'filter' 'sort'
|
|
9334 * @returns {*} The data for the cell from the given row's data
|
|
9335 * @default null
|
|
9336 */
|
|
9337 "fnGetData": null,
|
|
9338
|
|
9339 /**
|
|
9340 * Function to set data for a cell in the column. You should <b>never</b>
|
|
9341 * set the data directly to _aData internally in DataTables - always use
|
|
9342 * this method. It allows mData to function as required. This function
|
|
9343 * is automatically assigned by the column initialisation method
|
|
9344 * @type function
|
|
9345 * @param {array|object} oData The data array/object for the array
|
|
9346 * (i.e. aoData[]._aData)
|
|
9347 * @param {*} sValue Value to set
|
|
9348 * @default null
|
|
9349 */
|
|
9350 "fnSetData": null,
|
|
9351
|
|
9352 /**
|
|
9353 * Property to read the value for the cells in the column from the data
|
|
9354 * source array / object. If null, then the default content is used, if a
|
|
9355 * function is given then the return from the function is used.
|
|
9356 * @type function|int|string|null
|
|
9357 * @default null
|
|
9358 */
|
|
9359 "mData": null,
|
|
9360
|
|
9361 /**
|
|
9362 * Partner property to mData which is used (only when defined) to get
|
|
9363 * the data - i.e. it is basically the same as mData, but without the
|
|
9364 * 'set' option, and also the data fed to it is the result from mData.
|
|
9365 * This is the rendering method to match the data method of mData.
|
|
9366 * @type function|int|string|null
|
|
9367 * @default null
|
|
9368 */
|
|
9369 "mRender": null,
|
|
9370
|
|
9371 /**
|
|
9372 * Unique header TH/TD element for this column - this is what the sorting
|
|
9373 * listener is attached to (if sorting is enabled.)
|
|
9374 * @type node
|
|
9375 * @default null
|
|
9376 */
|
|
9377 "nTh": null,
|
|
9378
|
|
9379 /**
|
|
9380 * Unique footer TH/TD element for this column (if there is one). Not used
|
|
9381 * in DataTables as such, but can be used for plug-ins to reference the
|
|
9382 * footer for each column.
|
|
9383 * @type node
|
|
9384 * @default null
|
|
9385 */
|
|
9386 "nTf": null,
|
|
9387
|
|
9388 /**
|
|
9389 * The class to apply to all TD elements in the table's TBODY for the column
|
|
9390 * @type string
|
|
9391 * @default null
|
|
9392 */
|
|
9393 "sClass": null,
|
|
9394
|
|
9395 /**
|
|
9396 * When DataTables calculates the column widths to assign to each column,
|
|
9397 * it finds the longest string in each column and then constructs a
|
|
9398 * temporary table and reads the widths from that. The problem with this
|
|
9399 * is that "mmm" is much wider then "iiii", but the latter is a longer
|
|
9400 * string - thus the calculation can go wrong (doing it properly and putting
|
|
9401 * it into an DOM object and measuring that is horribly(!) slow). Thus as
|
|
9402 * a "work around" we provide this option. It will append its value to the
|
|
9403 * text that is found to be the longest string for the column - i.e. padding.
|
|
9404 * @type string
|
|
9405 */
|
|
9406 "sContentPadding": null,
|
|
9407
|
|
9408 /**
|
|
9409 * Allows a default value to be given for a column's data, and will be used
|
|
9410 * whenever a null data source is encountered (this can be because mData
|
|
9411 * is set to null, or because the data source itself is null).
|
|
9412 * @type string
|
|
9413 * @default null
|
|
9414 */
|
|
9415 "sDefaultContent": null,
|
|
9416
|
|
9417 /**
|
|
9418 * Name for the column, allowing reference to the column by name as well as
|
|
9419 * by index (needs a lookup to work by name).
|
|
9420 * @type string
|
|
9421 */
|
|
9422 "sName": null,
|
|
9423
|
|
9424 /**
|
|
9425 * Custom sorting data type - defines which of the available plug-ins in
|
|
9426 * afnSortData the custom sorting will use - if any is defined.
|
|
9427 * @type string
|
|
9428 * @default std
|
|
9429 */
|
|
9430 "sSortDataType": 'std',
|
|
9431
|
|
9432 /**
|
|
9433 * Class to be applied to the header element when sorting on this column
|
|
9434 * @type string
|
|
9435 * @default null
|
|
9436 */
|
|
9437 "sSortingClass": null,
|
|
9438
|
|
9439 /**
|
|
9440 * Class to be applied to the header element when sorting on this column -
|
|
9441 * when jQuery UI theming is used.
|
|
9442 * @type string
|
|
9443 * @default null
|
|
9444 */
|
|
9445 "sSortingClassJUI": null,
|
|
9446
|
|
9447 /**
|
|
9448 * Title of the column - what is seen in the TH element (nTh).
|
|
9449 * @type string
|
|
9450 */
|
|
9451 "sTitle": null,
|
|
9452
|
|
9453 /**
|
|
9454 * Column sorting and filtering type
|
|
9455 * @type string
|
|
9456 * @default null
|
|
9457 */
|
|
9458 "sType": null,
|
|
9459
|
|
9460 /**
|
|
9461 * Width of the column
|
|
9462 * @type string
|
|
9463 * @default null
|
|
9464 */
|
|
9465 "sWidth": null,
|
|
9466
|
|
9467 /**
|
|
9468 * Width of the column when it was first "encountered"
|
|
9469 * @type string
|
|
9470 * @default null
|
|
9471 */
|
|
9472 "sWidthOrig": null
|
|
9473 };
|
|
9474
|
|
9475
|
|
9476 /*
|
|
9477 * Developer note: The properties of the object below are given in Hungarian
|
|
9478 * notation, that was used as the interface for DataTables prior to v1.10, however
|
|
9479 * from v1.10 onwards the primary interface is camel case. In order to avoid
|
|
9480 * breaking backwards compatibility utterly with this change, the Hungarian
|
|
9481 * version is still, internally the primary interface, but is is not documented
|
|
9482 * - hence the @name tags in each doc comment. This allows a Javascript function
|
|
9483 * to create a map from Hungarian notation to camel case (going the other direction
|
|
9484 * would require each property to be listed, which would at around 3K to the size
|
|
9485 * of DataTables, while this method is about a 0.5K hit.
|
|
9486 *
|
|
9487 * Ultimately this does pave the way for Hungarian notation to be dropped
|
|
9488 * completely, but that is a massive amount of work and will break current
|
|
9489 * installs (therefore is on-hold until v2).
|
|
9490 */
|
|
9491
|
|
9492 /**
|
|
9493 * Initialisation options that can be given to DataTables at initialisation
|
|
9494 * time.
|
|
9495 * @namespace
|
|
9496 */
|
|
9497 DataTable.defaults = {
|
|
9498 /**
|
|
9499 * An array of data to use for the table, passed in at initialisation which
|
|
9500 * will be used in preference to any data which is already in the DOM. This is
|
|
9501 * particularly useful for constructing tables purely in Javascript, for
|
|
9502 * example with a custom Ajax call.
|
|
9503 * @type array
|
|
9504 * @default null
|
|
9505 *
|
|
9506 * @dtopt Option
|
|
9507 * @name DataTable.defaults.data
|
|
9508 *
|
|
9509 * @example
|
|
9510 * // Using a 2D array data source
|
|
9511 * $(document).ready( function () {
|
|
9512 * $('#example').dataTable( {
|
|
9513 * "data": [
|
|
9514 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
|
|
9515 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
|
|
9516 * ],
|
|
9517 * "columns": [
|
|
9518 * { "title": "Engine" },
|
|
9519 * { "title": "Browser" },
|
|
9520 * { "title": "Platform" },
|
|
9521 * { "title": "Version" },
|
|
9522 * { "title": "Grade" }
|
|
9523 * ]
|
|
9524 * } );
|
|
9525 * } );
|
|
9526 *
|
|
9527 * @example
|
|
9528 * // Using an array of objects as a data source (`data`)
|
|
9529 * $(document).ready( function () {
|
|
9530 * $('#example').dataTable( {
|
|
9531 * "data": [
|
|
9532 * {
|
|
9533 * "engine": "Trident",
|
|
9534 * "browser": "Internet Explorer 4.0",
|
|
9535 * "platform": "Win 95+",
|
|
9536 * "version": 4,
|
|
9537 * "grade": "X"
|
|
9538 * },
|
|
9539 * {
|
|
9540 * "engine": "Trident",
|
|
9541 * "browser": "Internet Explorer 5.0",
|
|
9542 * "platform": "Win 95+",
|
|
9543 * "version": 5,
|
|
9544 * "grade": "C"
|
|
9545 * }
|
|
9546 * ],
|
|
9547 * "columns": [
|
|
9548 * { "title": "Engine", "data": "engine" },
|
|
9549 * { "title": "Browser", "data": "browser" },
|
|
9550 * { "title": "Platform", "data": "platform" },
|
|
9551 * { "title": "Version", "data": "version" },
|
|
9552 * { "title": "Grade", "data": "grade" }
|
|
9553 * ]
|
|
9554 * } );
|
|
9555 * } );
|
|
9556 */
|
|
9557 "aaData": null,
|
|
9558
|
|
9559
|
|
9560 /**
|
|
9561 * If ordering is enabled, then DataTables will perform a first pass sort on
|
|
9562 * initialisation. You can define which column(s) the sort is performed
|
|
9563 * upon, and the sorting direction, with this variable. The `sorting` array
|
|
9564 * should contain an array for each column to be sorted initially containing
|
|
9565 * the column's index and a direction string ('asc' or 'desc').
|
|
9566 * @type array
|
|
9567 * @default [[0,'asc']]
|
|
9568 *
|
|
9569 * @dtopt Option
|
|
9570 * @name DataTable.defaults.order
|
|
9571 *
|
|
9572 * @example
|
|
9573 * // Sort by 3rd column first, and then 4th column
|
|
9574 * $(document).ready( function() {
|
|
9575 * $('#example').dataTable( {
|
|
9576 * "order": [[2,'asc'], [3,'desc']]
|
|
9577 * } );
|
|
9578 * } );
|
|
9579 *
|
|
9580 * // No initial sorting
|
|
9581 * $(document).ready( function() {
|
|
9582 * $('#example').dataTable( {
|
|
9583 * "order": []
|
|
9584 * } );
|
|
9585 * } );
|
|
9586 */
|
|
9587 "aaSorting": [[0,'asc']],
|
|
9588
|
|
9589
|
|
9590 /**
|
|
9591 * This parameter is basically identical to the `sorting` parameter, but
|
|
9592 * cannot be overridden by user interaction with the table. What this means
|
|
9593 * is that you could have a column (visible or hidden) which the sorting
|
|
9594 * will always be forced on first - any sorting after that (from the user)
|
|
9595 * will then be performed as required. This can be useful for grouping rows
|
|
9596 * together.
|
|
9597 * @type array
|
|
9598 * @default null
|
|
9599 *
|
|
9600 * @dtopt Option
|
|
9601 * @name DataTable.defaults.orderFixed
|
|
9602 *
|
|
9603 * @example
|
|
9604 * $(document).ready( function() {
|
|
9605 * $('#example').dataTable( {
|
|
9606 * "orderFixed": [[0,'asc']]
|
|
9607 * } );
|
|
9608 * } )
|
|
9609 */
|
|
9610 "aaSortingFixed": [],
|
|
9611
|
|
9612
|
|
9613 /**
|
|
9614 * DataTables can be instructed to load data to display in the table from a
|
|
9615 * Ajax source. This option defines how that Ajax call is made and where to.
|
|
9616 *
|
|
9617 * The `ajax` property has three different modes of operation, depending on
|
|
9618 * how it is defined. These are:
|
|
9619 *
|
|
9620 * * `string` - Set the URL from where the data should be loaded from.
|
|
9621 * * `object` - Define properties for `jQuery.ajax`.
|
|
9622 * * `function` - Custom data get function
|
|
9623 *
|
|
9624 * `string`
|
|
9625 * --------
|
|
9626 *
|
|
9627 * As a string, the `ajax` property simply defines the URL from which
|
|
9628 * DataTables will load data.
|
|
9629 *
|
|
9630 * `object`
|
|
9631 * --------
|
|
9632 *
|
|
9633 * As an object, the parameters in the object are passed to
|
|
9634 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
|
|
9635 * of the Ajax request. DataTables has a number of default parameters which
|
|
9636 * you can override using this option. Please refer to the jQuery
|
|
9637 * documentation for a full description of the options available, although
|
|
9638 * the following parameters provide additional options in DataTables or
|
|
9639 * require special consideration:
|
|
9640 *
|
|
9641 * * `data` - As with jQuery, `data` can be provided as an object, but it
|
|
9642 * can also be used as a function to manipulate the data DataTables sends
|
|
9643 * to the server. The function takes a single parameter, an object of
|
|
9644 * parameters with the values that DataTables has readied for sending. An
|
|
9645 * object may be returned which will be merged into the DataTables
|
|
9646 * defaults, or you can add the items to the object that was passed in and
|
|
9647 * not return anything from the function. This supersedes `fnServerParams`
|
|
9648 * from DataTables 1.9-.
|
|
9649 *
|
|
9650 * * `dataSrc` - By default DataTables will look for the property `data` (or
|
|
9651 * `aaData` for compatibility with DataTables 1.9-) when obtaining data
|
|
9652 * from an Ajax source or for server-side processing - this parameter
|
|
9653 * allows that property to be changed. You can use Javascript dotted
|
|
9654 * object notation to get a data source for multiple levels of nesting, or
|
|
9655 * it my be used as a function. As a function it takes a single parameter,
|
|
9656 * the JSON returned from the server, which can be manipulated as
|
|
9657 * required, with the returned value being that used by DataTables as the
|
|
9658 * data source for the table. This supersedes `sAjaxDataProp` from
|
|
9659 * DataTables 1.9-.
|
|
9660 *
|
|
9661 * * `success` - Should not be overridden it is used internally in
|
|
9662 * DataTables. To manipulate / transform the data returned by the server
|
|
9663 * use `ajax.dataSrc`, or use `ajax` as a function (see below).
|
|
9664 *
|
|
9665 * `function`
|
|
9666 * ----------
|
|
9667 *
|
|
9668 * As a function, making the Ajax call is left up to yourself allowing
|
|
9669 * complete control of the Ajax request. Indeed, if desired, a method other
|
|
9670 * than Ajax could be used to obtain the required data, such as Web storage
|
|
9671 * or an AIR database.
|
|
9672 *
|
|
9673 * The function is given four parameters and no return is required. The
|
|
9674 * parameters are:
|
|
9675 *
|
|
9676 * 1. _object_ - Data to send to the server
|
|
9677 * 2. _function_ - Callback function that must be executed when the required
|
|
9678 * data has been obtained. That data should be passed into the callback
|
|
9679 * as the only parameter
|
|
9680 * 3. _object_ - DataTables settings object for the table
|
|
9681 *
|
|
9682 * Note that this supersedes `fnServerData` from DataTables 1.9-.
|
|
9683 *
|
|
9684 * @type string|object|function
|
|
9685 * @default null
|
|
9686 *
|
|
9687 * @dtopt Option
|
|
9688 * @name DataTable.defaults.ajax
|
|
9689 * @since 1.10.0
|
|
9690 *
|
|
9691 * @example
|
|
9692 * // Get JSON data from a file via Ajax.
|
|
9693 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
|
|
9694 * $('#example').dataTable( {
|
|
9695 * "ajax": "data.json"
|
|
9696 * } );
|
|
9697 *
|
|
9698 * @example
|
|
9699 * // Get JSON data from a file via Ajax, using `dataSrc` to change
|
|
9700 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
|
|
9701 * $('#example').dataTable( {
|
|
9702 * "ajax": {
|
|
9703 * "url": "data.json",
|
|
9704 * "dataSrc": "tableData"
|
|
9705 * }
|
|
9706 * } );
|
|
9707 *
|
|
9708 * @example
|
|
9709 * // Get JSON data from a file via Ajax, using `dataSrc` to read data
|
|
9710 * // from a plain array rather than an array in an object
|
|
9711 * $('#example').dataTable( {
|
|
9712 * "ajax": {
|
|
9713 * "url": "data.json",
|
|
9714 * "dataSrc": ""
|
|
9715 * }
|
|
9716 * } );
|
|
9717 *
|
|
9718 * @example
|
|
9719 * // Manipulate the data returned from the server - add a link to data
|
|
9720 * // (note this can, should, be done using `render` for the column - this
|
|
9721 * // is just a simple example of how the data can be manipulated).
|
|
9722 * $('#example').dataTable( {
|
|
9723 * "ajax": {
|
|
9724 * "url": "data.json",
|
|
9725 * "dataSrc": function ( json ) {
|
|
9726 * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
|
|
9727 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
|
|
9728 * }
|
|
9729 * return json;
|
|
9730 * }
|
|
9731 * }
|
|
9732 * } );
|
|
9733 *
|
|
9734 * @example
|
|
9735 * // Add data to the request
|
|
9736 * $('#example').dataTable( {
|
|
9737 * "ajax": {
|
|
9738 * "url": "data.json",
|
|
9739 * "data": function ( d ) {
|
|
9740 * return {
|
|
9741 * "extra_search": $('#extra').val()
|
|
9742 * };
|
|
9743 * }
|
|
9744 * }
|
|
9745 * } );
|
|
9746 *
|
|
9747 * @example
|
|
9748 * // Send request as POST
|
|
9749 * $('#example').dataTable( {
|
|
9750 * "ajax": {
|
|
9751 * "url": "data.json",
|
|
9752 * "type": "POST"
|
|
9753 * }
|
|
9754 * } );
|
|
9755 *
|
|
9756 * @example
|
|
9757 * // Get the data from localStorage (could interface with a form for
|
|
9758 * // adding, editing and removing rows).
|
|
9759 * $('#example').dataTable( {
|
|
9760 * "ajax": function (data, callback, settings) {
|
|
9761 * callback(
|
|
9762 * JSON.parse( localStorage.getItem('dataTablesData') )
|
|
9763 * );
|
|
9764 * }
|
|
9765 * } );
|
|
9766 */
|
|
9767 "ajax": null,
|
|
9768
|
|
9769
|
|
9770 /**
|
|
9771 * This parameter allows you to readily specify the entries in the length drop
|
|
9772 * down menu that DataTables shows when pagination is enabled. It can be
|
|
9773 * either a 1D array of options which will be used for both the displayed
|
|
9774 * option and the value, or a 2D array which will use the array in the first
|
|
9775 * position as the value, and the array in the second position as the
|
|
9776 * displayed options (useful for language strings such as 'All').
|
|
9777 *
|
|
9778 * Note that the `pageLength` property will be automatically set to the
|
|
9779 * first value given in this array, unless `pageLength` is also provided.
|
|
9780 * @type array
|
|
9781 * @default [ 10, 25, 50, 100 ]
|
|
9782 *
|
|
9783 * @dtopt Option
|
|
9784 * @name DataTable.defaults.lengthMenu
|
|
9785 *
|
|
9786 * @example
|
|
9787 * $(document).ready( function() {
|
|
9788 * $('#example').dataTable( {
|
|
9789 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
|
|
9790 * } );
|
|
9791 * } );
|
|
9792 */
|
|
9793 "aLengthMenu": [ 10, 25, 50, 100 ],
|
|
9794
|
|
9795
|
|
9796 /**
|
|
9797 * The `columns` option in the initialisation parameter allows you to define
|
|
9798 * details about the way individual columns behave. For a full list of
|
|
9799 * column options that can be set, please see
|
|
9800 * {@link DataTable.defaults.column}. Note that if you use `columns` to
|
|
9801 * define your columns, you must have an entry in the array for every single
|
|
9802 * column that you have in your table (these can be null if you don't which
|
|
9803 * to specify any options).
|
|
9804 * @member
|
|
9805 *
|
|
9806 * @name DataTable.defaults.column
|
|
9807 */
|
|
9808 "aoColumns": null,
|
|
9809
|
|
9810 /**
|
|
9811 * Very similar to `columns`, `columnDefs` allows you to target a specific
|
|
9812 * column, multiple columns, or all columns, using the `targets` property of
|
|
9813 * each object in the array. This allows great flexibility when creating
|
|
9814 * tables, as the `columnDefs` arrays can be of any length, targeting the
|
|
9815 * columns you specifically want. `columnDefs` may use any of the column
|
|
9816 * options available: {@link DataTable.defaults.column}, but it _must_
|
|
9817 * have `targets` defined in each object in the array. Values in the `targets`
|
|
9818 * array may be:
|
|
9819 * <ul>
|
|
9820 * <li>a string - class name will be matched on the TH for the column</li>
|
|
9821 * <li>0 or a positive integer - column index counting from the left</li>
|
|
9822 * <li>a negative integer - column index counting from the right</li>
|
|
9823 * <li>the string "_all" - all columns (i.e. assign a default)</li>
|
|
9824 * </ul>
|
|
9825 * @member
|
|
9826 *
|
|
9827 * @name DataTable.defaults.columnDefs
|
|
9828 */
|
|
9829 "aoColumnDefs": null,
|
|
9830
|
|
9831
|
|
9832 /**
|
|
9833 * Basically the same as `search`, this parameter defines the individual column
|
|
9834 * filtering state at initialisation time. The array must be of the same size
|
|
9835 * as the number of columns, and each element be an object with the parameters
|
|
9836 * `search` and `escapeRegex` (the latter is optional). 'null' is also
|
|
9837 * accepted and the default will be used.
|
|
9838 * @type array
|
|
9839 * @default []
|
|
9840 *
|
|
9841 * @dtopt Option
|
|
9842 * @name DataTable.defaults.searchCols
|
|
9843 *
|
|
9844 * @example
|
|
9845 * $(document).ready( function() {
|
|
9846 * $('#example').dataTable( {
|
|
9847 * "searchCols": [
|
|
9848 * null,
|
|
9849 * { "search": "My filter" },
|
|
9850 * null,
|
|
9851 * { "search": "^[0-9]", "escapeRegex": false }
|
|
9852 * ]
|
|
9853 * } );
|
|
9854 * } )
|
|
9855 */
|
|
9856 "aoSearchCols": [],
|
|
9857
|
|
9858
|
|
9859 /**
|
|
9860 * An array of CSS classes that should be applied to displayed rows. This
|
|
9861 * array may be of any length, and DataTables will apply each class
|
|
9862 * sequentially, looping when required.
|
|
9863 * @type array
|
|
9864 * @default null <i>Will take the values determined by the `oClasses.stripe*`
|
|
9865 * options</i>
|
|
9866 *
|
|
9867 * @dtopt Option
|
|
9868 * @name DataTable.defaults.stripeClasses
|
|
9869 *
|
|
9870 * @example
|
|
9871 * $(document).ready( function() {
|
|
9872 * $('#example').dataTable( {
|
|
9873 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
|
|
9874 * } );
|
|
9875 * } )
|
|
9876 */
|
|
9877 "asStripeClasses": null,
|
|
9878
|
|
9879
|
|
9880 /**
|
|
9881 * Enable or disable automatic column width calculation. This can be disabled
|
|
9882 * as an optimisation (it takes some time to calculate the widths) if the
|
|
9883 * tables widths are passed in using `columns`.
|
|
9884 * @type boolean
|
|
9885 * @default true
|
|
9886 *
|
|
9887 * @dtopt Features
|
|
9888 * @name DataTable.defaults.autoWidth
|
|
9889 *
|
|
9890 * @example
|
|
9891 * $(document).ready( function () {
|
|
9892 * $('#example').dataTable( {
|
|
9893 * "autoWidth": false
|
|
9894 * } );
|
|
9895 * } );
|
|
9896 */
|
|
9897 "bAutoWidth": true,
|
|
9898
|
|
9899
|
|
9900 /**
|
|
9901 * Deferred rendering can provide DataTables with a huge speed boost when you
|
|
9902 * are using an Ajax or JS data source for the table. This option, when set to
|
|
9903 * true, will cause DataTables to defer the creation of the table elements for
|
|
9904 * each row until they are needed for a draw - saving a significant amount of
|
|
9905 * time.
|
|
9906 * @type boolean
|
|
9907 * @default false
|
|
9908 *
|
|
9909 * @dtopt Features
|
|
9910 * @name DataTable.defaults.deferRender
|
|
9911 *
|
|
9912 * @example
|
|
9913 * $(document).ready( function() {
|
|
9914 * $('#example').dataTable( {
|
|
9915 * "ajax": "sources/arrays.txt",
|
|
9916 * "deferRender": true
|
|
9917 * } );
|
|
9918 * } );
|
|
9919 */
|
|
9920 "bDeferRender": false,
|
|
9921
|
|
9922
|
|
9923 /**
|
|
9924 * Replace a DataTable which matches the given selector and replace it with
|
|
9925 * one which has the properties of the new initialisation object passed. If no
|
|
9926 * table matches the selector, then the new DataTable will be constructed as
|
|
9927 * per normal.
|
|
9928 * @type boolean
|
|
9929 * @default false
|
|
9930 *
|
|
9931 * @dtopt Options
|
|
9932 * @name DataTable.defaults.destroy
|
|
9933 *
|
|
9934 * @example
|
|
9935 * $(document).ready( function() {
|
|
9936 * $('#example').dataTable( {
|
|
9937 * "srollY": "200px",
|
|
9938 * "paginate": false
|
|
9939 * } );
|
|
9940 *
|
|
9941 * // Some time later....
|
|
9942 * $('#example').dataTable( {
|
|
9943 * "filter": false,
|
|
9944 * "destroy": true
|
|
9945 * } );
|
|
9946 * } );
|
|
9947 */
|
|
9948 "bDestroy": false,
|
|
9949
|
|
9950
|
|
9951 /**
|
|
9952 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
|
|
9953 * that it allows the end user to input multiple words (space separated) and
|
|
9954 * will match a row containing those words, even if not in the order that was
|
|
9955 * specified (this allow matching across multiple columns). Note that if you
|
|
9956 * wish to use filtering in DataTables this must remain 'true' - to remove the
|
|
9957 * default filtering input box and retain filtering abilities, please use
|
|
9958 * {@link DataTable.defaults.dom}.
|
|
9959 * @type boolean
|
|
9960 * @default true
|
|
9961 *
|
|
9962 * @dtopt Features
|
|
9963 * @name DataTable.defaults.searching
|
|
9964 *
|
|
9965 * @example
|
|
9966 * $(document).ready( function () {
|
|
9967 * $('#example').dataTable( {
|
|
9968 * "searching": false
|
|
9969 * } );
|
|
9970 * } );
|
|
9971 */
|
|
9972 "bFilter": true,
|
|
9973
|
|
9974
|
|
9975 /**
|
|
9976 * Enable or disable the table information display. This shows information
|
|
9977 * about the data that is currently visible on the page, including information
|
|
9978 * about filtered data if that action is being performed.
|
|
9979 * @type boolean
|
|
9980 * @default true
|
|
9981 *
|
|
9982 * @dtopt Features
|
|
9983 * @name DataTable.defaults.info
|
|
9984 *
|
|
9985 * @example
|
|
9986 * $(document).ready( function () {
|
|
9987 * $('#example').dataTable( {
|
|
9988 * "info": false
|
|
9989 * } );
|
|
9990 * } );
|
|
9991 */
|
|
9992 "bInfo": true,
|
|
9993
|
|
9994
|
|
9995 /**
|
|
9996 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
|
|
9997 * slightly different and additional mark-up from what DataTables has
|
|
9998 * traditionally used).
|
|
9999 * @type boolean
|
|
10000 * @default false
|
|
10001 *
|
|
10002 * @dtopt Features
|
|
10003 * @name DataTable.defaults.jQueryUI
|
|
10004 *
|
|
10005 * @example
|
|
10006 * $(document).ready( function() {
|
|
10007 * $('#example').dataTable( {
|
|
10008 * "jQueryUI": true
|
|
10009 * } );
|
|
10010 * } );
|
|
10011 */
|
|
10012 "bJQueryUI": false,
|
|
10013
|
|
10014
|
|
10015 /**
|
|
10016 * Allows the end user to select the size of a formatted page from a select
|
|
10017 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
|
|
10018 * @type boolean
|
|
10019 * @default true
|
|
10020 *
|
|
10021 * @dtopt Features
|
|
10022 * @name DataTable.defaults.lengthChange
|
|
10023 *
|
|
10024 * @example
|
|
10025 * $(document).ready( function () {
|
|
10026 * $('#example').dataTable( {
|
|
10027 * "lengthChange": false
|
|
10028 * } );
|
|
10029 * } );
|
|
10030 */
|
|
10031 "bLengthChange": true,
|
|
10032
|
|
10033
|
|
10034 /**
|
|
10035 * Enable or disable pagination.
|
|
10036 * @type boolean
|
|
10037 * @default true
|
|
10038 *
|
|
10039 * @dtopt Features
|
|
10040 * @name DataTable.defaults.paging
|
|
10041 *
|
|
10042 * @example
|
|
10043 * $(document).ready( function () {
|
|
10044 * $('#example').dataTable( {
|
|
10045 * "paging": false
|
|
10046 * } );
|
|
10047 * } );
|
|
10048 */
|
|
10049 "bPaginate": true,
|
|
10050
|
|
10051
|
|
10052 /**
|
|
10053 * Enable or disable the display of a 'processing' indicator when the table is
|
|
10054 * being processed (e.g. a sort). This is particularly useful for tables with
|
|
10055 * large amounts of data where it can take a noticeable amount of time to sort
|
|
10056 * the entries.
|
|
10057 * @type boolean
|
|
10058 * @default false
|
|
10059 *
|
|
10060 * @dtopt Features
|
|
10061 * @name DataTable.defaults.processing
|
|
10062 *
|
|
10063 * @example
|
|
10064 * $(document).ready( function () {
|
|
10065 * $('#example').dataTable( {
|
|
10066 * "processing": true
|
|
10067 * } );
|
|
10068 * } );
|
|
10069 */
|
|
10070 "bProcessing": false,
|
|
10071
|
|
10072
|
|
10073 /**
|
|
10074 * Retrieve the DataTables object for the given selector. Note that if the
|
|
10075 * table has already been initialised, this parameter will cause DataTables
|
|
10076 * to simply return the object that has already been set up - it will not take
|
|
10077 * account of any changes you might have made to the initialisation object
|
|
10078 * passed to DataTables (setting this parameter to true is an acknowledgement
|
|
10079 * that you understand this). `destroy` can be used to reinitialise a table if
|
|
10080 * you need.
|
|
10081 * @type boolean
|
|
10082 * @default false
|
|
10083 *
|
|
10084 * @dtopt Options
|
|
10085 * @name DataTable.defaults.retrieve
|
|
10086 *
|
|
10087 * @example
|
|
10088 * $(document).ready( function() {
|
|
10089 * initTable();
|
|
10090 * tableActions();
|
|
10091 * } );
|
|
10092 *
|
|
10093 * function initTable ()
|
|
10094 * {
|
|
10095 * return $('#example').dataTable( {
|
|
10096 * "scrollY": "200px",
|
|
10097 * "paginate": false,
|
|
10098 * "retrieve": true
|
|
10099 * } );
|
|
10100 * }
|
|
10101 *
|
|
10102 * function tableActions ()
|
|
10103 * {
|
|
10104 * var table = initTable();
|
|
10105 * // perform API operations with oTable
|
|
10106 * }
|
|
10107 */
|
|
10108 "bRetrieve": false,
|
|
10109
|
|
10110
|
|
10111 /**
|
|
10112 * When vertical (y) scrolling is enabled, DataTables will force the height of
|
|
10113 * the table's viewport to the given height at all times (useful for layout).
|
|
10114 * However, this can look odd when filtering data down to a small data set,
|
|
10115 * and the footer is left "floating" further down. This parameter (when
|
|
10116 * enabled) will cause DataTables to collapse the table's viewport down when
|
|
10117 * the result set will fit within the given Y height.
|
|
10118 * @type boolean
|
|
10119 * @default false
|
|
10120 *
|
|
10121 * @dtopt Options
|
|
10122 * @name DataTable.defaults.scrollCollapse
|
|
10123 *
|
|
10124 * @example
|
|
10125 * $(document).ready( function() {
|
|
10126 * $('#example').dataTable( {
|
|
10127 * "scrollY": "200",
|
|
10128 * "scrollCollapse": true
|
|
10129 * } );
|
|
10130 * } );
|
|
10131 */
|
|
10132 "bScrollCollapse": false,
|
|
10133
|
|
10134
|
|
10135 /**
|
|
10136 * Configure DataTables to use server-side processing. Note that the
|
|
10137 * `ajax` parameter must also be given in order to give DataTables a
|
|
10138 * source to obtain the required data for each draw.
|
|
10139 * @type boolean
|
|
10140 * @default false
|
|
10141 *
|
|
10142 * @dtopt Features
|
|
10143 * @dtopt Server-side
|
|
10144 * @name DataTable.defaults.serverSide
|
|
10145 *
|
|
10146 * @example
|
|
10147 * $(document).ready( function () {
|
|
10148 * $('#example').dataTable( {
|
|
10149 * "serverSide": true,
|
|
10150 * "ajax": "xhr.php"
|
|
10151 * } );
|
|
10152 * } );
|
|
10153 */
|
|
10154 "bServerSide": false,
|
|
10155
|
|
10156
|
|
10157 /**
|
|
10158 * Enable or disable sorting of columns. Sorting of individual columns can be
|
|
10159 * disabled by the `sortable` option for each column.
|
|
10160 * @type boolean
|
|
10161 * @default true
|
|
10162 *
|
|
10163 * @dtopt Features
|
|
10164 * @name DataTable.defaults.ordering
|
|
10165 *
|
|
10166 * @example
|
|
10167 * $(document).ready( function () {
|
|
10168 * $('#example').dataTable( {
|
|
10169 * "ordering": false
|
|
10170 * } );
|
|
10171 * } );
|
|
10172 */
|
|
10173 "bSort": true,
|
|
10174
|
|
10175
|
|
10176 /**
|
|
10177 * Enable or display DataTables' ability to sort multiple columns at the
|
|
10178 * same time (activated by shift-click by the user).
|
|
10179 * @type boolean
|
|
10180 * @default true
|
|
10181 *
|
|
10182 * @dtopt Options
|
|
10183 * @name DataTable.defaults.orderMulti
|
|
10184 *
|
|
10185 * @example
|
|
10186 * // Disable multiple column sorting ability
|
|
10187 * $(document).ready( function () {
|
|
10188 * $('#example').dataTable( {
|
|
10189 * "orderMulti": false
|
|
10190 * } );
|
|
10191 * } );
|
|
10192 */
|
|
10193 "bSortMulti": true,
|
|
10194
|
|
10195
|
|
10196 /**
|
|
10197 * Allows control over whether DataTables should use the top (true) unique
|
|
10198 * cell that is found for a single column, or the bottom (false - default).
|
|
10199 * This is useful when using complex headers.
|
|
10200 * @type boolean
|
|
10201 * @default false
|
|
10202 *
|
|
10203 * @dtopt Options
|
|
10204 * @name DataTable.defaults.orderCellsTop
|
|
10205 *
|
|
10206 * @example
|
|
10207 * $(document).ready( function() {
|
|
10208 * $('#example').dataTable( {
|
|
10209 * "orderCellsTop": true
|
|
10210 * } );
|
|
10211 * } );
|
|
10212 */
|
|
10213 "bSortCellsTop": false,
|
|
10214
|
|
10215
|
|
10216 /**
|
|
10217 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
|
|
10218 * `sorting\_3` to the columns which are currently being sorted on. This is
|
|
10219 * presented as a feature switch as it can increase processing time (while
|
|
10220 * classes are removed and added) so for large data sets you might want to
|
|
10221 * turn this off.
|
|
10222 * @type boolean
|
|
10223 * @default true
|
|
10224 *
|
|
10225 * @dtopt Features
|
|
10226 * @name DataTable.defaults.orderClasses
|
|
10227 *
|
|
10228 * @example
|
|
10229 * $(document).ready( function () {
|
|
10230 * $('#example').dataTable( {
|
|
10231 * "orderClasses": false
|
|
10232 * } );
|
|
10233 * } );
|
|
10234 */
|
|
10235 "bSortClasses": true,
|
|
10236
|
|
10237
|
|
10238 /**
|
|
10239 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
|
|
10240 * used to save table display information such as pagination information,
|
|
10241 * display length, filtering and sorting. As such when the end user reloads
|
|
10242 * the page the display display will match what thy had previously set up.
|
|
10243 *
|
|
10244 * Due to the use of `localStorage` the default state saving is not supported
|
|
10245 * in IE6 or 7. If state saving is required in those browsers, use
|
|
10246 * `stateSaveCallback` to provide a storage solution such as cookies.
|
|
10247 * @type boolean
|
|
10248 * @default false
|
|
10249 *
|
|
10250 * @dtopt Features
|
|
10251 * @name DataTable.defaults.stateSave
|
|
10252 *
|
|
10253 * @example
|
|
10254 * $(document).ready( function () {
|
|
10255 * $('#example').dataTable( {
|
|
10256 * "stateSave": true
|
|
10257 * } );
|
|
10258 * } );
|
|
10259 */
|
|
10260 "bStateSave": false,
|
|
10261
|
|
10262
|
|
10263 /**
|
|
10264 * This function is called when a TR element is created (and all TD child
|
|
10265 * elements have been inserted), or registered if using a DOM source, allowing
|
|
10266 * manipulation of the TR element (adding classes etc).
|
|
10267 * @type function
|
|
10268 * @param {node} row "TR" element for the current row
|
|
10269 * @param {array} data Raw data array for this row
|
|
10270 * @param {int} dataIndex The index of this row in the internal aoData array
|
|
10271 *
|
|
10272 * @dtopt Callbacks
|
|
10273 * @name DataTable.defaults.createdRow
|
|
10274 *
|
|
10275 * @example
|
|
10276 * $(document).ready( function() {
|
|
10277 * $('#example').dataTable( {
|
|
10278 * "createdRow": function( row, data, dataIndex ) {
|
|
10279 * // Bold the grade for all 'A' grade browsers
|
|
10280 * if ( data[4] == "A" )
|
|
10281 * {
|
|
10282 * $('td:eq(4)', row).html( '<b>A</b>' );
|
|
10283 * }
|
|
10284 * }
|
|
10285 * } );
|
|
10286 * } );
|
|
10287 */
|
|
10288 "fnCreatedRow": null,
|
|
10289
|
|
10290
|
|
10291 /**
|
|
10292 * This function is called on every 'draw' event, and allows you to
|
|
10293 * dynamically modify any aspect you want about the created DOM.
|
|
10294 * @type function
|
|
10295 * @param {object} settings DataTables settings object
|
|
10296 *
|
|
10297 * @dtopt Callbacks
|
|
10298 * @name DataTable.defaults.drawCallback
|
|
10299 *
|
|
10300 * @example
|
|
10301 * $(document).ready( function() {
|
|
10302 * $('#example').dataTable( {
|
|
10303 * "drawCallback": function( settings ) {
|
|
10304 * alert( 'DataTables has redrawn the table' );
|
|
10305 * }
|
|
10306 * } );
|
|
10307 * } );
|
|
10308 */
|
|
10309 "fnDrawCallback": null,
|
|
10310
|
|
10311
|
|
10312 /**
|
|
10313 * Identical to fnHeaderCallback() but for the table footer this function
|
|
10314 * allows you to modify the table footer on every 'draw' event.
|
|
10315 * @type function
|
|
10316 * @param {node} foot "TR" element for the footer
|
|
10317 * @param {array} data Full table data (as derived from the original HTML)
|
|
10318 * @param {int} start Index for the current display starting point in the
|
|
10319 * display array
|
|
10320 * @param {int} end Index for the current display ending point in the
|
|
10321 * display array
|
|
10322 * @param {array int} display Index array to translate the visual position
|
|
10323 * to the full data array
|
|
10324 *
|
|
10325 * @dtopt Callbacks
|
|
10326 * @name DataTable.defaults.footerCallback
|
|
10327 *
|
|
10328 * @example
|
|
10329 * $(document).ready( function() {
|
|
10330 * $('#example').dataTable( {
|
|
10331 * "footerCallback": function( tfoot, data, start, end, display ) {
|
|
10332 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
|
|
10333 * }
|
|
10334 * } );
|
|
10335 * } )
|
|
10336 */
|
|
10337 "fnFooterCallback": null,
|
|
10338
|
|
10339
|
|
10340 /**
|
|
10341 * When rendering large numbers in the information element for the table
|
|
10342 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
|
|
10343 * to have a comma separator for the 'thousands' units (e.g. 1 million is
|
|
10344 * rendered as "1,000,000") to help readability for the end user. This
|
|
10345 * function will override the default method DataTables uses.
|
|
10346 * @type function
|
|
10347 * @member
|
|
10348 * @param {int} toFormat number to be formatted
|
|
10349 * @returns {string} formatted string for DataTables to show the number
|
|
10350 *
|
|
10351 * @dtopt Callbacks
|
|
10352 * @name DataTable.defaults.formatNumber
|
|
10353 *
|
|
10354 * @example
|
|
10355 * // Format a number using a single quote for the separator (note that
|
|
10356 * // this can also be done with the language.thousands option)
|
|
10357 * $(document).ready( function() {
|
|
10358 * $('#example').dataTable( {
|
|
10359 * "formatNumber": function ( toFormat ) {
|
|
10360 * return toFormat.toString().replace(
|
|
10361 * /\B(?=(\d{3})+(?!\d))/g, "'"
|
|
10362 * );
|
|
10363 * };
|
|
10364 * } );
|
|
10365 * } );
|
|
10366 */
|
|
10367 "fnFormatNumber": function ( toFormat ) {
|
|
10368 return toFormat.toString().replace(
|
|
10369 /\B(?=(\d{3})+(?!\d))/g,
|
|
10370 this.oLanguage.sThousands
|
|
10371 );
|
|
10372 },
|
|
10373
|
|
10374
|
|
10375 /**
|
|
10376 * This function is called on every 'draw' event, and allows you to
|
|
10377 * dynamically modify the header row. This can be used to calculate and
|
|
10378 * display useful information about the table.
|
|
10379 * @type function
|
|
10380 * @param {node} head "TR" element for the header
|
|
10381 * @param {array} data Full table data (as derived from the original HTML)
|
|
10382 * @param {int} start Index for the current display starting point in the
|
|
10383 * display array
|
|
10384 * @param {int} end Index for the current display ending point in the
|
|
10385 * display array
|
|
10386 * @param {array int} display Index array to translate the visual position
|
|
10387 * to the full data array
|
|
10388 *
|
|
10389 * @dtopt Callbacks
|
|
10390 * @name DataTable.defaults.headerCallback
|
|
10391 *
|
|
10392 * @example
|
|
10393 * $(document).ready( function() {
|
|
10394 * $('#example').dataTable( {
|
|
10395 * "fheaderCallback": function( head, data, start, end, display ) {
|
|
10396 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
|
|
10397 * }
|
|
10398 * } );
|
|
10399 * } )
|
|
10400 */
|
|
10401 "fnHeaderCallback": null,
|
|
10402
|
|
10403
|
|
10404 /**
|
|
10405 * The information element can be used to convey information about the current
|
|
10406 * state of the table. Although the internationalisation options presented by
|
|
10407 * DataTables are quite capable of dealing with most customisations, there may
|
|
10408 * be times where you wish to customise the string further. This callback
|
|
10409 * allows you to do exactly that.
|
|
10410 * @type function
|
|
10411 * @param {object} oSettings DataTables settings object
|
|
10412 * @param {int} start Starting position in data for the draw
|
|
10413 * @param {int} end End position in data for the draw
|
|
10414 * @param {int} max Total number of rows in the table (regardless of
|
|
10415 * filtering)
|
|
10416 * @param {int} total Total number of rows in the data set, after filtering
|
|
10417 * @param {string} pre The string that DataTables has formatted using it's
|
|
10418 * own rules
|
|
10419 * @returns {string} The string to be displayed in the information element.
|
|
10420 *
|
|
10421 * @dtopt Callbacks
|
|
10422 * @name DataTable.defaults.infoCallback
|
|
10423 *
|
|
10424 * @example
|
|
10425 * $('#example').dataTable( {
|
|
10426 * "infoCallback": function( settings, start, end, max, total, pre ) {
|
|
10427 * return start +" to "+ end;
|
|
10428 * }
|
|
10429 * } );
|
|
10430 */
|
|
10431 "fnInfoCallback": null,
|
|
10432
|
|
10433
|
|
10434 /**
|
|
10435 * Called when the table has been initialised. Normally DataTables will
|
|
10436 * initialise sequentially and there will be no need for this function,
|
|
10437 * however, this does not hold true when using external language information
|
|
10438 * since that is obtained using an async XHR call.
|
|
10439 * @type function
|
|
10440 * @param {object} settings DataTables settings object
|
|
10441 * @param {object} json The JSON object request from the server - only
|
|
10442 * present if client-side Ajax sourced data is used
|
|
10443 *
|
|
10444 * @dtopt Callbacks
|
|
10445 * @name DataTable.defaults.initComplete
|
|
10446 *
|
|
10447 * @example
|
|
10448 * $(document).ready( function() {
|
|
10449 * $('#example').dataTable( {
|
|
10450 * "initComplete": function(settings, json) {
|
|
10451 * alert( 'DataTables has finished its initialisation.' );
|
|
10452 * }
|
|
10453 * } );
|
|
10454 * } )
|
|
10455 */
|
|
10456 "fnInitComplete": null,
|
|
10457
|
|
10458
|
|
10459 /**
|
|
10460 * Called at the very start of each table draw and can be used to cancel the
|
|
10461 * draw by returning false, any other return (including undefined) results in
|
|
10462 * the full draw occurring).
|
|
10463 * @type function
|
|
10464 * @param {object} settings DataTables settings object
|
|
10465 * @returns {boolean} False will cancel the draw, anything else (including no
|
|
10466 * return) will allow it to complete.
|
|
10467 *
|
|
10468 * @dtopt Callbacks
|
|
10469 * @name DataTable.defaults.preDrawCallback
|
|
10470 *
|
|
10471 * @example
|
|
10472 * $(document).ready( function() {
|
|
10473 * $('#example').dataTable( {
|
|
10474 * "preDrawCallback": function( settings ) {
|
|
10475 * if ( $('#test').val() == 1 ) {
|
|
10476 * return false;
|
|
10477 * }
|
|
10478 * }
|
|
10479 * } );
|
|
10480 * } );
|
|
10481 */
|
|
10482 "fnPreDrawCallback": null,
|
|
10483
|
|
10484
|
|
10485 /**
|
|
10486 * This function allows you to 'post process' each row after it have been
|
|
10487 * generated for each table draw, but before it is rendered on screen. This
|
|
10488 * function might be used for setting the row class name etc.
|
|
10489 * @type function
|
|
10490 * @param {node} row "TR" element for the current row
|
|
10491 * @param {array} data Raw data array for this row
|
|
10492 * @param {int} displayIndex The display index for the current table draw
|
|
10493 * @param {int} displayIndexFull The index of the data in the full list of
|
|
10494 * rows (after filtering)
|
|
10495 *
|
|
10496 * @dtopt Callbacks
|
|
10497 * @name DataTable.defaults.rowCallback
|
|
10498 *
|
|
10499 * @example
|
|
10500 * $(document).ready( function() {
|
|
10501 * $('#example').dataTable( {
|
|
10502 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
|
|
10503 * // Bold the grade for all 'A' grade browsers
|
|
10504 * if ( data[4] == "A" ) {
|
|
10505 * $('td:eq(4)', row).html( '<b>A</b>' );
|
|
10506 * }
|
|
10507 * }
|
|
10508 * } );
|
|
10509 * } );
|
|
10510 */
|
|
10511 "fnRowCallback": null,
|
|
10512
|
|
10513
|
|
10514 /**
|
|
10515 * __Deprecated__ The functionality provided by this parameter has now been
|
|
10516 * superseded by that provided through `ajax`, which should be used instead.
|
|
10517 *
|
|
10518 * This parameter allows you to override the default function which obtains
|
|
10519 * the data from the server so something more suitable for your application.
|
|
10520 * For example you could use POST data, or pull information from a Gears or
|
|
10521 * AIR database.
|
|
10522 * @type function
|
|
10523 * @member
|
|
10524 * @param {string} source HTTP source to obtain the data from (`ajax`)
|
|
10525 * @param {array} data A key/value pair object containing the data to send
|
|
10526 * to the server
|
|
10527 * @param {function} callback to be called on completion of the data get
|
|
10528 * process that will draw the data on the page.
|
|
10529 * @param {object} settings DataTables settings object
|
|
10530 *
|
|
10531 * @dtopt Callbacks
|
|
10532 * @dtopt Server-side
|
|
10533 * @name DataTable.defaults.serverData
|
|
10534 *
|
|
10535 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
10536 */
|
|
10537 "fnServerData": null,
|
|
10538
|
|
10539
|
|
10540 /**
|
|
10541 * __Deprecated__ The functionality provided by this parameter has now been
|
|
10542 * superseded by that provided through `ajax`, which should be used instead.
|
|
10543 *
|
|
10544 * It is often useful to send extra data to the server when making an Ajax
|
|
10545 * request - for example custom filtering information, and this callback
|
|
10546 * function makes it trivial to send extra information to the server. The
|
|
10547 * passed in parameter is the data set that has been constructed by
|
|
10548 * DataTables, and you can add to this or modify it as you require.
|
|
10549 * @type function
|
|
10550 * @param {array} data Data array (array of objects which are name/value
|
|
10551 * pairs) that has been constructed by DataTables and will be sent to the
|
|
10552 * server. In the case of Ajax sourced data with server-side processing
|
|
10553 * this will be an empty array, for server-side processing there will be a
|
|
10554 * significant number of parameters!
|
|
10555 * @returns {undefined} Ensure that you modify the data array passed in,
|
|
10556 * as this is passed by reference.
|
|
10557 *
|
|
10558 * @dtopt Callbacks
|
|
10559 * @dtopt Server-side
|
|
10560 * @name DataTable.defaults.serverParams
|
|
10561 *
|
|
10562 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
10563 */
|
|
10564 "fnServerParams": null,
|
|
10565
|
|
10566
|
|
10567 /**
|
|
10568 * Load the table state. With this function you can define from where, and how, the
|
|
10569 * state of a table is loaded. By default DataTables will load from `localStorage`
|
|
10570 * but you might wish to use a server-side database or cookies.
|
|
10571 * @type function
|
|
10572 * @member
|
|
10573 * @param {object} settings DataTables settings object
|
|
10574 * @return {object} The DataTables state object to be loaded
|
|
10575 *
|
|
10576 * @dtopt Callbacks
|
|
10577 * @name DataTable.defaults.stateLoadCallback
|
|
10578 *
|
|
10579 * @example
|
|
10580 * $(document).ready( function() {
|
|
10581 * $('#example').dataTable( {
|
|
10582 * "stateSave": true,
|
|
10583 * "stateLoadCallback": function (settings) {
|
|
10584 * var o;
|
|
10585 *
|
|
10586 * // Send an Ajax request to the server to get the data. Note that
|
|
10587 * // this is a synchronous request.
|
|
10588 * $.ajax( {
|
|
10589 * "url": "/state_load",
|
|
10590 * "async": false,
|
|
10591 * "dataType": "json",
|
|
10592 * "success": function (json) {
|
|
10593 * o = json;
|
|
10594 * }
|
|
10595 * } );
|
|
10596 *
|
|
10597 * return o;
|
|
10598 * }
|
|
10599 * } );
|
|
10600 * } );
|
|
10601 */
|
|
10602 "fnStateLoadCallback": function ( settings ) {
|
|
10603 try {
|
|
10604 return JSON.parse(
|
|
10605 (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
|
|
10606 'DataTables_'+settings.sInstance+'_'+location.pathname
|
|
10607 )
|
|
10608 );
|
|
10609 } catch (e) {}
|
|
10610 },
|
|
10611
|
|
10612
|
|
10613 /**
|
|
10614 * Callback which allows modification of the saved state prior to loading that state.
|
|
10615 * This callback is called when the table is loading state from the stored data, but
|
|
10616 * prior to the settings object being modified by the saved state. Note that for
|
|
10617 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
|
|
10618 * a plug-in.
|
|
10619 * @type function
|
|
10620 * @param {object} settings DataTables settings object
|
|
10621 * @param {object} data The state object that is to be loaded
|
|
10622 *
|
|
10623 * @dtopt Callbacks
|
|
10624 * @name DataTable.defaults.stateLoadParams
|
|
10625 *
|
|
10626 * @example
|
|
10627 * // Remove a saved filter, so filtering is never loaded
|
|
10628 * $(document).ready( function() {
|
|
10629 * $('#example').dataTable( {
|
|
10630 * "stateSave": true,
|
|
10631 * "stateLoadParams": function (settings, data) {
|
|
10632 * data.oSearch.sSearch = "";
|
|
10633 * }
|
|
10634 * } );
|
|
10635 * } );
|
|
10636 *
|
|
10637 * @example
|
|
10638 * // Disallow state loading by returning false
|
|
10639 * $(document).ready( function() {
|
|
10640 * $('#example').dataTable( {
|
|
10641 * "stateSave": true,
|
|
10642 * "stateLoadParams": function (settings, data) {
|
|
10643 * return false;
|
|
10644 * }
|
|
10645 * } );
|
|
10646 * } );
|
|
10647 */
|
|
10648 "fnStateLoadParams": null,
|
|
10649
|
|
10650
|
|
10651 /**
|
|
10652 * Callback that is called when the state has been loaded from the state saving method
|
|
10653 * and the DataTables settings object has been modified as a result of the loaded state.
|
|
10654 * @type function
|
|
10655 * @param {object} settings DataTables settings object
|
|
10656 * @param {object} data The state object that was loaded
|
|
10657 *
|
|
10658 * @dtopt Callbacks
|
|
10659 * @name DataTable.defaults.stateLoaded
|
|
10660 *
|
|
10661 * @example
|
|
10662 * // Show an alert with the filtering value that was saved
|
|
10663 * $(document).ready( function() {
|
|
10664 * $('#example').dataTable( {
|
|
10665 * "stateSave": true,
|
|
10666 * "stateLoaded": function (settings, data) {
|
|
10667 * alert( 'Saved filter was: '+data.oSearch.sSearch );
|
|
10668 * }
|
|
10669 * } );
|
|
10670 * } );
|
|
10671 */
|
|
10672 "fnStateLoaded": null,
|
|
10673
|
|
10674
|
|
10675 /**
|
|
10676 * Save the table state. This function allows you to define where and how the state
|
|
10677 * information for the table is stored By default DataTables will use `localStorage`
|
|
10678 * but you might wish to use a server-side database or cookies.
|
|
10679 * @type function
|
|
10680 * @member
|
|
10681 * @param {object} settings DataTables settings object
|
|
10682 * @param {object} data The state object to be saved
|
|
10683 *
|
|
10684 * @dtopt Callbacks
|
|
10685 * @name DataTable.defaults.stateSaveCallback
|
|
10686 *
|
|
10687 * @example
|
|
10688 * $(document).ready( function() {
|
|
10689 * $('#example').dataTable( {
|
|
10690 * "stateSave": true,
|
|
10691 * "stateSaveCallback": function (settings, data) {
|
|
10692 * // Send an Ajax request to the server with the state object
|
|
10693 * $.ajax( {
|
|
10694 * "url": "/state_save",
|
|
10695 * "data": data,
|
|
10696 * "dataType": "json",
|
|
10697 * "method": "POST"
|
|
10698 * "success": function () {}
|
|
10699 * } );
|
|
10700 * }
|
|
10701 * } );
|
|
10702 * } );
|
|
10703 */
|
|
10704 "fnStateSaveCallback": function ( settings, data ) {
|
|
10705 try {
|
|
10706 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
|
|
10707 'DataTables_'+settings.sInstance+'_'+location.pathname,
|
|
10708 JSON.stringify( data )
|
|
10709 );
|
|
10710 } catch (e) {}
|
|
10711 },
|
|
10712
|
|
10713
|
|
10714 /**
|
|
10715 * Callback which allows modification of the state to be saved. Called when the table
|
|
10716 * has changed state a new state save is required. This method allows modification of
|
|
10717 * the state saving object prior to actually doing the save, including addition or
|
|
10718 * other state properties or modification. Note that for plug-in authors, you should
|
|
10719 * use the `stateSaveParams` event to save parameters for a plug-in.
|
|
10720 * @type function
|
|
10721 * @param {object} settings DataTables settings object
|
|
10722 * @param {object} data The state object to be saved
|
|
10723 *
|
|
10724 * @dtopt Callbacks
|
|
10725 * @name DataTable.defaults.stateSaveParams
|
|
10726 *
|
|
10727 * @example
|
|
10728 * // Remove a saved filter, so filtering is never saved
|
|
10729 * $(document).ready( function() {
|
|
10730 * $('#example').dataTable( {
|
|
10731 * "stateSave": true,
|
|
10732 * "stateSaveParams": function (settings, data) {
|
|
10733 * data.oSearch.sSearch = "";
|
|
10734 * }
|
|
10735 * } );
|
|
10736 * } );
|
|
10737 */
|
|
10738 "fnStateSaveParams": null,
|
|
10739
|
|
10740
|
|
10741 /**
|
|
10742 * Duration for which the saved state information is considered valid. After this period
|
|
10743 * has elapsed the state will be returned to the default.
|
|
10744 * Value is given in seconds.
|
|
10745 * @type int
|
|
10746 * @default 7200 <i>(2 hours)</i>
|
|
10747 *
|
|
10748 * @dtopt Options
|
|
10749 * @name DataTable.defaults.stateDuration
|
|
10750 *
|
|
10751 * @example
|
|
10752 * $(document).ready( function() {
|
|
10753 * $('#example').dataTable( {
|
|
10754 * "stateDuration": 60*60*24; // 1 day
|
|
10755 * } );
|
|
10756 * } )
|
|
10757 */
|
|
10758 "iStateDuration": 7200,
|
|
10759
|
|
10760
|
|
10761 /**
|
|
10762 * When enabled DataTables will not make a request to the server for the first
|
|
10763 * page draw - rather it will use the data already on the page (no sorting etc
|
|
10764 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
|
|
10765 * is used to indicate that deferred loading is required, but it is also used
|
|
10766 * to tell DataTables how many records there are in the full table (allowing
|
|
10767 * the information element and pagination to be displayed correctly). In the case
|
|
10768 * where a filtering is applied to the table on initial load, this can be
|
|
10769 * indicated by giving the parameter as an array, where the first element is
|
|
10770 * the number of records available after filtering and the second element is the
|
|
10771 * number of records without filtering (allowing the table information element
|
|
10772 * to be shown correctly).
|
|
10773 * @type int | array
|
|
10774 * @default null
|
|
10775 *
|
|
10776 * @dtopt Options
|
|
10777 * @name DataTable.defaults.deferLoading
|
|
10778 *
|
|
10779 * @example
|
|
10780 * // 57 records available in the table, no filtering applied
|
|
10781 * $(document).ready( function() {
|
|
10782 * $('#example').dataTable( {
|
|
10783 * "serverSide": true,
|
|
10784 * "ajax": "scripts/server_processing.php",
|
|
10785 * "deferLoading": 57
|
|
10786 * } );
|
|
10787 * } );
|
|
10788 *
|
|
10789 * @example
|
|
10790 * // 57 records after filtering, 100 without filtering (an initial filter applied)
|
|
10791 * $(document).ready( function() {
|
|
10792 * $('#example').dataTable( {
|
|
10793 * "serverSide": true,
|
|
10794 * "ajax": "scripts/server_processing.php",
|
|
10795 * "deferLoading": [ 57, 100 ],
|
|
10796 * "search": {
|
|
10797 * "search": "my_filter"
|
|
10798 * }
|
|
10799 * } );
|
|
10800 * } );
|
|
10801 */
|
|
10802 "iDeferLoading": null,
|
|
10803
|
|
10804
|
|
10805 /**
|
|
10806 * Number of rows to display on a single page when using pagination. If
|
|
10807 * feature enabled (`lengthChange`) then the end user will be able to override
|
|
10808 * this to a custom setting using a pop-up menu.
|
|
10809 * @type int
|
|
10810 * @default 10
|
|
10811 *
|
|
10812 * @dtopt Options
|
|
10813 * @name DataTable.defaults.pageLength
|
|
10814 *
|
|
10815 * @example
|
|
10816 * $(document).ready( function() {
|
|
10817 * $('#example').dataTable( {
|
|
10818 * "pageLength": 50
|
|
10819 * } );
|
|
10820 * } )
|
|
10821 */
|
|
10822 "iDisplayLength": 10,
|
|
10823
|
|
10824
|
|
10825 /**
|
|
10826 * Define the starting point for data display when using DataTables with
|
|
10827 * pagination. Note that this parameter is the number of records, rather than
|
|
10828 * the page number, so if you have 10 records per page and want to start on
|
|
10829 * the third page, it should be "20".
|
|
10830 * @type int
|
|
10831 * @default 0
|
|
10832 *
|
|
10833 * @dtopt Options
|
|
10834 * @name DataTable.defaults.displayStart
|
|
10835 *
|
|
10836 * @example
|
|
10837 * $(document).ready( function() {
|
|
10838 * $('#example').dataTable( {
|
|
10839 * "displayStart": 20
|
|
10840 * } );
|
|
10841 * } )
|
|
10842 */
|
|
10843 "iDisplayStart": 0,
|
|
10844
|
|
10845
|
|
10846 /**
|
|
10847 * By default DataTables allows keyboard navigation of the table (sorting, paging,
|
|
10848 * and filtering) by adding a `tabindex` attribute to the required elements. This
|
|
10849 * allows you to tab through the controls and press the enter key to activate them.
|
|
10850 * The tabindex is default 0, meaning that the tab follows the flow of the document.
|
|
10851 * You can overrule this using this parameter if you wish. Use a value of -1 to
|
|
10852 * disable built-in keyboard navigation.
|
|
10853 * @type int
|
|
10854 * @default 0
|
|
10855 *
|
|
10856 * @dtopt Options
|
|
10857 * @name DataTable.defaults.tabIndex
|
|
10858 *
|
|
10859 * @example
|
|
10860 * $(document).ready( function() {
|
|
10861 * $('#example').dataTable( {
|
|
10862 * "tabIndex": 1
|
|
10863 * } );
|
|
10864 * } );
|
|
10865 */
|
|
10866 "iTabIndex": 0,
|
|
10867
|
|
10868
|
|
10869 /**
|
|
10870 * Classes that DataTables assigns to the various components and features
|
|
10871 * that it adds to the HTML table. This allows classes to be configured
|
|
10872 * during initialisation in addition to through the static
|
|
10873 * {@link DataTable.ext.oStdClasses} object).
|
|
10874 * @namespace
|
|
10875 * @name DataTable.defaults.classes
|
|
10876 */
|
|
10877 "oClasses": {},
|
|
10878
|
|
10879
|
|
10880 /**
|
|
10881 * All strings that DataTables uses in the user interface that it creates
|
|
10882 * are defined in this object, allowing you to modified them individually or
|
|
10883 * completely replace them all as required.
|
|
10884 * @namespace
|
|
10885 * @name DataTable.defaults.language
|
|
10886 */
|
|
10887 "oLanguage": {
|
|
10888 /**
|
|
10889 * Strings that are used for WAI-ARIA labels and controls only (these are not
|
|
10890 * actually visible on the page, but will be read by screenreaders, and thus
|
|
10891 * must be internationalised as well).
|
|
10892 * @namespace
|
|
10893 * @name DataTable.defaults.language.aria
|
|
10894 */
|
|
10895 "oAria": {
|
|
10896 /**
|
|
10897 * ARIA label that is added to the table headers when the column may be
|
|
10898 * sorted ascending by activing the column (click or return when focused).
|
|
10899 * Note that the column header is prefixed to this string.
|
|
10900 * @type string
|
|
10901 * @default : activate to sort column ascending
|
|
10902 *
|
|
10903 * @dtopt Language
|
|
10904 * @name DataTable.defaults.language.aria.sortAscending
|
|
10905 *
|
|
10906 * @example
|
|
10907 * $(document).ready( function() {
|
|
10908 * $('#example').dataTable( {
|
|
10909 * "language": {
|
|
10910 * "aria": {
|
|
10911 * "sortAscending": " - click/return to sort ascending"
|
|
10912 * }
|
|
10913 * }
|
|
10914 * } );
|
|
10915 * } );
|
|
10916 */
|
|
10917 "sSortAscending": ": activate to sort column ascending",
|
|
10918
|
|
10919 /**
|
|
10920 * ARIA label that is added to the table headers when the column may be
|
|
10921 * sorted descending by activing the column (click or return when focused).
|
|
10922 * Note that the column header is prefixed to this string.
|
|
10923 * @type string
|
|
10924 * @default : activate to sort column ascending
|
|
10925 *
|
|
10926 * @dtopt Language
|
|
10927 * @name DataTable.defaults.language.aria.sortDescending
|
|
10928 *
|
|
10929 * @example
|
|
10930 * $(document).ready( function() {
|
|
10931 * $('#example').dataTable( {
|
|
10932 * "language": {
|
|
10933 * "aria": {
|
|
10934 * "sortDescending": " - click/return to sort descending"
|
|
10935 * }
|
|
10936 * }
|
|
10937 * } );
|
|
10938 * } );
|
|
10939 */
|
|
10940 "sSortDescending": ": activate to sort column descending"
|
|
10941 },
|
|
10942
|
|
10943 /**
|
|
10944 * Pagination string used by DataTables for the built-in pagination
|
|
10945 * control types.
|
|
10946 * @namespace
|
|
10947 * @name DataTable.defaults.language.paginate
|
|
10948 */
|
|
10949 "oPaginate": {
|
|
10950 /**
|
|
10951 * Text to use when using the 'full_numbers' type of pagination for the
|
|
10952 * button to take the user to the first page.
|
|
10953 * @type string
|
|
10954 * @default First
|
|
10955 *
|
|
10956 * @dtopt Language
|
|
10957 * @name DataTable.defaults.language.paginate.first
|
|
10958 *
|
|
10959 * @example
|
|
10960 * $(document).ready( function() {
|
|
10961 * $('#example').dataTable( {
|
|
10962 * "language": {
|
|
10963 * "paginate": {
|
|
10964 * "first": "First page"
|
|
10965 * }
|
|
10966 * }
|
|
10967 * } );
|
|
10968 * } );
|
|
10969 */
|
|
10970 "sFirst": "First",
|
|
10971
|
|
10972
|
|
10973 /**
|
|
10974 * Text to use when using the 'full_numbers' type of pagination for the
|
|
10975 * button to take the user to the last page.
|
|
10976 * @type string
|
|
10977 * @default Last
|
|
10978 *
|
|
10979 * @dtopt Language
|
|
10980 * @name DataTable.defaults.language.paginate.last
|
|
10981 *
|
|
10982 * @example
|
|
10983 * $(document).ready( function() {
|
|
10984 * $('#example').dataTable( {
|
|
10985 * "language": {
|
|
10986 * "paginate": {
|
|
10987 * "last": "Last page"
|
|
10988 * }
|
|
10989 * }
|
|
10990 * } );
|
|
10991 * } );
|
|
10992 */
|
|
10993 "sLast": "Last",
|
|
10994
|
|
10995
|
|
10996 /**
|
|
10997 * Text to use for the 'next' pagination button (to take the user to the
|
|
10998 * next page).
|
|
10999 * @type string
|
|
11000 * @default Next
|
|
11001 *
|
|
11002 * @dtopt Language
|
|
11003 * @name DataTable.defaults.language.paginate.next
|
|
11004 *
|
|
11005 * @example
|
|
11006 * $(document).ready( function() {
|
|
11007 * $('#example').dataTable( {
|
|
11008 * "language": {
|
|
11009 * "paginate": {
|
|
11010 * "next": "Next page"
|
|
11011 * }
|
|
11012 * }
|
|
11013 * } );
|
|
11014 * } );
|
|
11015 */
|
|
11016 "sNext": "Next",
|
|
11017
|
|
11018
|
|
11019 /**
|
|
11020 * Text to use for the 'previous' pagination button (to take the user to
|
|
11021 * the previous page).
|
|
11022 * @type string
|
|
11023 * @default Previous
|
|
11024 *
|
|
11025 * @dtopt Language
|
|
11026 * @name DataTable.defaults.language.paginate.previous
|
|
11027 *
|
|
11028 * @example
|
|
11029 * $(document).ready( function() {
|
|
11030 * $('#example').dataTable( {
|
|
11031 * "language": {
|
|
11032 * "paginate": {
|
|
11033 * "previous": "Previous page"
|
|
11034 * }
|
|
11035 * }
|
|
11036 * } );
|
|
11037 * } );
|
|
11038 */
|
|
11039 "sPrevious": "Previous"
|
|
11040 },
|
|
11041
|
|
11042 /**
|
|
11043 * This string is shown in preference to `zeroRecords` when the table is
|
|
11044 * empty of data (regardless of filtering). Note that this is an optional
|
|
11045 * parameter - if it is not given, the value of `zeroRecords` will be used
|
|
11046 * instead (either the default or given value).
|
|
11047 * @type string
|
|
11048 * @default No data available in table
|
|
11049 *
|
|
11050 * @dtopt Language
|
|
11051 * @name DataTable.defaults.language.emptyTable
|
|
11052 *
|
|
11053 * @example
|
|
11054 * $(document).ready( function() {
|
|
11055 * $('#example').dataTable( {
|
|
11056 * "language": {
|
|
11057 * "emptyTable": "No data available in table"
|
|
11058 * }
|
|
11059 * } );
|
|
11060 * } );
|
|
11061 */
|
|
11062 "sEmptyTable": "No data available in table",
|
|
11063
|
|
11064
|
|
11065 /**
|
|
11066 * This string gives information to the end user about the information
|
|
11067 * that is current on display on the page. The following tokens can be
|
|
11068 * used in the string and will be dynamically replaced as the table
|
|
11069 * display updates. This tokens can be placed anywhere in the string, or
|
|
11070 * removed as needed by the language requires:
|
|
11071 *
|
|
11072 * * `\_START\_` - Display index of the first record on the current page
|
|
11073 * * `\_END\_` - Display index of the last record on the current page
|
|
11074 * * `\_TOTAL\_` - Number of records in the table after filtering
|
|
11075 * * `\_MAX\_` - Number of records in the table without filtering
|
|
11076 * * `\_PAGE\_` - Current page number
|
|
11077 * * `\_PAGES\_` - Total number of pages of data in the table
|
|
11078 *
|
|
11079 * @type string
|
|
11080 * @default Showing _START_ to _END_ of _TOTAL_ entries
|
|
11081 *
|
|
11082 * @dtopt Language
|
|
11083 * @name DataTable.defaults.language.info
|
|
11084 *
|
|
11085 * @example
|
|
11086 * $(document).ready( function() {
|
|
11087 * $('#example').dataTable( {
|
|
11088 * "language": {
|
|
11089 * "info": "Showing page _PAGE_ of _PAGES_"
|
|
11090 * }
|
|
11091 * } );
|
|
11092 * } );
|
|
11093 */
|
|
11094 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
|
|
11095
|
|
11096
|
|
11097 /**
|
|
11098 * Display information string for when the table is empty. Typically the
|
|
11099 * format of this string should match `info`.
|
|
11100 * @type string
|
|
11101 * @default Showing 0 to 0 of 0 entries
|
|
11102 *
|
|
11103 * @dtopt Language
|
|
11104 * @name DataTable.defaults.language.infoEmpty
|
|
11105 *
|
|
11106 * @example
|
|
11107 * $(document).ready( function() {
|
|
11108 * $('#example').dataTable( {
|
|
11109 * "language": {
|
|
11110 * "infoEmpty": "No entries to show"
|
|
11111 * }
|
|
11112 * } );
|
|
11113 * } );
|
|
11114 */
|
|
11115 "sInfoEmpty": "Showing 0 to 0 of 0 entries",
|
|
11116
|
|
11117
|
|
11118 /**
|
|
11119 * When a user filters the information in a table, this string is appended
|
|
11120 * to the information (`info`) to give an idea of how strong the filtering
|
|
11121 * is. The variable _MAX_ is dynamically updated.
|
|
11122 * @type string
|
|
11123 * @default (filtered from _MAX_ total entries)
|
|
11124 *
|
|
11125 * @dtopt Language
|
|
11126 * @name DataTable.defaults.language.infoFiltered
|
|
11127 *
|
|
11128 * @example
|
|
11129 * $(document).ready( function() {
|
|
11130 * $('#example').dataTable( {
|
|
11131 * "language": {
|
|
11132 * "infoFiltered": " - filtering from _MAX_ records"
|
|
11133 * }
|
|
11134 * } );
|
|
11135 * } );
|
|
11136 */
|
|
11137 "sInfoFiltered": "(filtered from _MAX_ total entries)",
|
|
11138
|
|
11139
|
|
11140 /**
|
|
11141 * If can be useful to append extra information to the info string at times,
|
|
11142 * and this variable does exactly that. This information will be appended to
|
|
11143 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
|
|
11144 * being used) at all times.
|
|
11145 * @type string
|
|
11146 * @default <i>Empty string</i>
|
|
11147 *
|
|
11148 * @dtopt Language
|
|
11149 * @name DataTable.defaults.language.infoPostFix
|
|
11150 *
|
|
11151 * @example
|
|
11152 * $(document).ready( function() {
|
|
11153 * $('#example').dataTable( {
|
|
11154 * "language": {
|
|
11155 * "infoPostFix": "All records shown are derived from real information."
|
|
11156 * }
|
|
11157 * } );
|
|
11158 * } );
|
|
11159 */
|
|
11160 "sInfoPostFix": "",
|
|
11161
|
|
11162
|
|
11163 /**
|
|
11164 * This decimal place operator is a little different from the other
|
|
11165 * language options since DataTables doesn't output floating point
|
|
11166 * numbers, so it won't ever use this for display of a number. Rather,
|
|
11167 * what this parameter does is modify the sort methods of the table so
|
|
11168 * that numbers which are in a format which has a character other than
|
|
11169 * a period (`.`) as a decimal place will be sorted numerically.
|
|
11170 *
|
|
11171 * Note that numbers with different decimal places cannot be shown in
|
|
11172 * the same table and still be sortable, the table must be consistent.
|
|
11173 * However, multiple different tables on the page can use different
|
|
11174 * decimal place characters.
|
|
11175 * @type string
|
|
11176 * @default
|
|
11177 *
|
|
11178 * @dtopt Language
|
|
11179 * @name DataTable.defaults.language.decimal
|
|
11180 *
|
|
11181 * @example
|
|
11182 * $(document).ready( function() {
|
|
11183 * $('#example').dataTable( {
|
|
11184 * "language": {
|
|
11185 * "decimal": ","
|
|
11186 * "thousands": "."
|
|
11187 * }
|
|
11188 * } );
|
|
11189 * } );
|
|
11190 */
|
|
11191 "sDecimal": "",
|
|
11192
|
|
11193
|
|
11194 /**
|
|
11195 * DataTables has a build in number formatter (`formatNumber`) which is
|
|
11196 * used to format large numbers that are used in the table information.
|
|
11197 * By default a comma is used, but this can be trivially changed to any
|
|
11198 * character you wish with this parameter.
|
|
11199 * @type string
|
|
11200 * @default ,
|
|
11201 *
|
|
11202 * @dtopt Language
|
|
11203 * @name DataTable.defaults.language.thousands
|
|
11204 *
|
|
11205 * @example
|
|
11206 * $(document).ready( function() {
|
|
11207 * $('#example').dataTable( {
|
|
11208 * "language": {
|
|
11209 * "thousands": "'"
|
|
11210 * }
|
|
11211 * } );
|
|
11212 * } );
|
|
11213 */
|
|
11214 "sThousands": ",",
|
|
11215
|
|
11216
|
|
11217 /**
|
|
11218 * Detail the action that will be taken when the drop down menu for the
|
|
11219 * pagination length option is changed. The '_MENU_' variable is replaced
|
|
11220 * with a default select list of 10, 25, 50 and 100, and can be replaced
|
|
11221 * with a custom select box if required.
|
|
11222 * @type string
|
|
11223 * @default Show _MENU_ entries
|
|
11224 *
|
|
11225 * @dtopt Language
|
|
11226 * @name DataTable.defaults.language.lengthMenu
|
|
11227 *
|
|
11228 * @example
|
|
11229 * // Language change only
|
|
11230 * $(document).ready( function() {
|
|
11231 * $('#example').dataTable( {
|
|
11232 * "language": {
|
|
11233 * "lengthMenu": "Display _MENU_ records"
|
|
11234 * }
|
|
11235 * } );
|
|
11236 * } );
|
|
11237 *
|
|
11238 * @example
|
|
11239 * // Language and options change
|
|
11240 * $(document).ready( function() {
|
|
11241 * $('#example').dataTable( {
|
|
11242 * "language": {
|
|
11243 * "lengthMenu": 'Display <select>'+
|
|
11244 * '<option value="10">10</option>'+
|
|
11245 * '<option value="20">20</option>'+
|
|
11246 * '<option value="30">30</option>'+
|
|
11247 * '<option value="40">40</option>'+
|
|
11248 * '<option value="50">50</option>'+
|
|
11249 * '<option value="-1">All</option>'+
|
|
11250 * '</select> records'
|
|
11251 * }
|
|
11252 * } );
|
|
11253 * } );
|
|
11254 */
|
|
11255 "sLengthMenu": "Show _MENU_ entries",
|
|
11256
|
|
11257
|
|
11258 /**
|
|
11259 * When using Ajax sourced data and during the first draw when DataTables is
|
|
11260 * gathering the data, this message is shown in an empty row in the table to
|
|
11261 * indicate to the end user the the data is being loaded. Note that this
|
|
11262 * parameter is not used when loading data by server-side processing, just
|
|
11263 * Ajax sourced data with client-side processing.
|
|
11264 * @type string
|
|
11265 * @default Loading...
|
|
11266 *
|
|
11267 * @dtopt Language
|
|
11268 * @name DataTable.defaults.language.loadingRecords
|
|
11269 *
|
|
11270 * @example
|
|
11271 * $(document).ready( function() {
|
|
11272 * $('#example').dataTable( {
|
|
11273 * "language": {
|
|
11274 * "loadingRecords": "Please wait - loading..."
|
|
11275 * }
|
|
11276 * } );
|
|
11277 * } );
|
|
11278 */
|
|
11279 "sLoadingRecords": "Loading...",
|
|
11280
|
|
11281
|
|
11282 /**
|
|
11283 * Text which is displayed when the table is processing a user action
|
|
11284 * (usually a sort command or similar).
|
|
11285 * @type string
|
|
11286 * @default Processing...
|
|
11287 *
|
|
11288 * @dtopt Language
|
|
11289 * @name DataTable.defaults.language.processing
|
|
11290 *
|
|
11291 * @example
|
|
11292 * $(document).ready( function() {
|
|
11293 * $('#example').dataTable( {
|
|
11294 * "language": {
|
|
11295 * "processing": "DataTables is currently busy"
|
|
11296 * }
|
|
11297 * } );
|
|
11298 * } );
|
|
11299 */
|
|
11300 "sProcessing": "Processing...",
|
|
11301
|
|
11302
|
|
11303 /**
|
|
11304 * Details the actions that will be taken when the user types into the
|
|
11305 * filtering input text box. The variable "_INPUT_", if used in the string,
|
|
11306 * is replaced with the HTML text box for the filtering input allowing
|
|
11307 * control over where it appears in the string. If "_INPUT_" is not given
|
|
11308 * then the input box is appended to the string automatically.
|
|
11309 * @type string
|
|
11310 * @default Search:
|
|
11311 *
|
|
11312 * @dtopt Language
|
|
11313 * @name DataTable.defaults.language.search
|
|
11314 *
|
|
11315 * @example
|
|
11316 * // Input text box will be appended at the end automatically
|
|
11317 * $(document).ready( function() {
|
|
11318 * $('#example').dataTable( {
|
|
11319 * "language": {
|
|
11320 * "search": "Filter records:"
|
|
11321 * }
|
|
11322 * } );
|
|
11323 * } );
|
|
11324 *
|
|
11325 * @example
|
|
11326 * // Specify where the filter should appear
|
|
11327 * $(document).ready( function() {
|
|
11328 * $('#example').dataTable( {
|
|
11329 * "language": {
|
|
11330 * "search": "Apply filter _INPUT_ to table"
|
|
11331 * }
|
|
11332 * } );
|
|
11333 * } );
|
|
11334 */
|
|
11335 "sSearch": "Search:",
|
|
11336
|
|
11337
|
|
11338 /**
|
|
11339 * Assign a `placeholder` attribute to the search `input` element
|
|
11340 * @type string
|
|
11341 * @default
|
|
11342 *
|
|
11343 * @dtopt Language
|
|
11344 * @name DataTable.defaults.language.searchPlaceholder
|
|
11345 */
|
|
11346 "sSearchPlaceholder": "",
|
|
11347
|
|
11348
|
|
11349 /**
|
|
11350 * All of the language information can be stored in a file on the
|
|
11351 * server-side, which DataTables will look up if this parameter is passed.
|
|
11352 * It must store the URL of the language file, which is in a JSON format,
|
|
11353 * and the object has the same properties as the oLanguage object in the
|
|
11354 * initialiser object (i.e. the above parameters). Please refer to one of
|
|
11355 * the example language files to see how this works in action.
|
|
11356 * @type string
|
|
11357 * @default <i>Empty string - i.e. disabled</i>
|
|
11358 *
|
|
11359 * @dtopt Language
|
|
11360 * @name DataTable.defaults.language.url
|
|
11361 *
|
|
11362 * @example
|
|
11363 * $(document).ready( function() {
|
|
11364 * $('#example').dataTable( {
|
|
11365 * "language": {
|
|
11366 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
|
|
11367 * }
|
|
11368 * } );
|
|
11369 * } );
|
|
11370 */
|
|
11371 "sUrl": "",
|
|
11372
|
|
11373
|
|
11374 /**
|
|
11375 * Text shown inside the table records when the is no information to be
|
|
11376 * displayed after filtering. `emptyTable` is shown when there is simply no
|
|
11377 * information in the table at all (regardless of filtering).
|
|
11378 * @type string
|
|
11379 * @default No matching records found
|
|
11380 *
|
|
11381 * @dtopt Language
|
|
11382 * @name DataTable.defaults.language.zeroRecords
|
|
11383 *
|
|
11384 * @example
|
|
11385 * $(document).ready( function() {
|
|
11386 * $('#example').dataTable( {
|
|
11387 * "language": {
|
|
11388 * "zeroRecords": "No records to display"
|
|
11389 * }
|
|
11390 * } );
|
|
11391 * } );
|
|
11392 */
|
|
11393 "sZeroRecords": "No matching records found"
|
|
11394 },
|
|
11395
|
|
11396
|
|
11397 /**
|
|
11398 * This parameter allows you to have define the global filtering state at
|
|
11399 * initialisation time. As an object the `search` parameter must be
|
|
11400 * defined, but all other parameters are optional. When `regex` is true,
|
|
11401 * the search string will be treated as a regular expression, when false
|
|
11402 * (default) it will be treated as a straight string. When `smart`
|
|
11403 * DataTables will use it's smart filtering methods (to word match at
|
|
11404 * any point in the data), when false this will not be done.
|
|
11405 * @namespace
|
|
11406 * @extends DataTable.models.oSearch
|
|
11407 *
|
|
11408 * @dtopt Options
|
|
11409 * @name DataTable.defaults.search
|
|
11410 *
|
|
11411 * @example
|
|
11412 * $(document).ready( function() {
|
|
11413 * $('#example').dataTable( {
|
|
11414 * "search": {"search": "Initial search"}
|
|
11415 * } );
|
|
11416 * } )
|
|
11417 */
|
|
11418 "oSearch": $.extend( {}, DataTable.models.oSearch ),
|
|
11419
|
|
11420
|
|
11421 /**
|
|
11422 * __Deprecated__ The functionality provided by this parameter has now been
|
|
11423 * superseded by that provided through `ajax`, which should be used instead.
|
|
11424 *
|
|
11425 * By default DataTables will look for the property `data` (or `aaData` for
|
|
11426 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
|
|
11427 * source or for server-side processing - this parameter allows that
|
|
11428 * property to be changed. You can use Javascript dotted object notation to
|
|
11429 * get a data source for multiple levels of nesting.
|
|
11430 * @type string
|
|
11431 * @default data
|
|
11432 *
|
|
11433 * @dtopt Options
|
|
11434 * @dtopt Server-side
|
|
11435 * @name DataTable.defaults.ajaxDataProp
|
|
11436 *
|
|
11437 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
11438 */
|
|
11439 "sAjaxDataProp": "data",
|
|
11440
|
|
11441
|
|
11442 /**
|
|
11443 * __Deprecated__ The functionality provided by this parameter has now been
|
|
11444 * superseded by that provided through `ajax`, which should be used instead.
|
|
11445 *
|
|
11446 * You can instruct DataTables to load data from an external
|
|
11447 * source using this parameter (use aData if you want to pass data in you
|
|
11448 * already have). Simply provide a url a JSON object can be obtained from.
|
|
11449 * @type string
|
|
11450 * @default null
|
|
11451 *
|
|
11452 * @dtopt Options
|
|
11453 * @dtopt Server-side
|
|
11454 * @name DataTable.defaults.ajaxSource
|
|
11455 *
|
|
11456 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
11457 */
|
|
11458 "sAjaxSource": null,
|
|
11459
|
|
11460
|
|
11461 /**
|
|
11462 * This initialisation variable allows you to specify exactly where in the
|
|
11463 * DOM you want DataTables to inject the various controls it adds to the page
|
|
11464 * (for example you might want the pagination controls at the top of the
|
|
11465 * table). DIV elements (with or without a custom class) can also be added to
|
|
11466 * aid styling. The follow syntax is used:
|
|
11467 * <ul>
|
|
11468 * <li>The following options are allowed:
|
|
11469 * <ul>
|
|
11470 * <li>'l' - Length changing</li>
|
|
11471 * <li>'f' - Filtering input</li>
|
|
11472 * <li>'t' - The table!</li>
|
|
11473 * <li>'i' - Information</li>
|
|
11474 * <li>'p' - Pagination</li>
|
|
11475 * <li>'r' - pRocessing</li>
|
|
11476 * </ul>
|
|
11477 * </li>
|
|
11478 * <li>The following constants are allowed:
|
|
11479 * <ul>
|
|
11480 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
|
|
11481 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
|
|
11482 * </ul>
|
|
11483 * </li>
|
|
11484 * <li>The following syntax is expected:
|
|
11485 * <ul>
|
|
11486 * <li>'<' and '>' - div elements</li>
|
|
11487 * <li>'<"class" and '>' - div with a class</li>
|
|
11488 * <li>'<"#id" and '>' - div with an ID</li>
|
|
11489 * </ul>
|
|
11490 * </li>
|
|
11491 * <li>Examples:
|
|
11492 * <ul>
|
|
11493 * <li>'<"wrapper"flipt>'</li>
|
|
11494 * <li>'<lf<t>ip>'</li>
|
|
11495 * </ul>
|
|
11496 * </li>
|
|
11497 * </ul>
|
|
11498 * @type string
|
|
11499 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
|
|
11500 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
|
|
11501 *
|
|
11502 * @dtopt Options
|
|
11503 * @name DataTable.defaults.dom
|
|
11504 *
|
|
11505 * @example
|
|
11506 * $(document).ready( function() {
|
|
11507 * $('#example').dataTable( {
|
|
11508 * "dom": '<"top"i>rt<"bottom"flp><"clear">'
|
|
11509 * } );
|
|
11510 * } );
|
|
11511 */
|
|
11512 "sDom": "lfrtip",
|
|
11513
|
|
11514
|
|
11515 /**
|
|
11516 * Search delay option. This will throttle full table searches that use the
|
|
11517 * DataTables provided search input element (it does not effect calls to
|
|
11518 * `dt-api search()`, providing a delay before the search is made.
|
|
11519 * @type integer
|
|
11520 * @default 0
|
|
11521 *
|
|
11522 * @dtopt Options
|
|
11523 * @name DataTable.defaults.searchDelay
|
|
11524 *
|
|
11525 * @example
|
|
11526 * $(document).ready( function() {
|
|
11527 * $('#example').dataTable( {
|
|
11528 * "searchDelay": 200
|
|
11529 * } );
|
|
11530 * } )
|
|
11531 */
|
|
11532 "searchDelay": null,
|
|
11533
|
|
11534
|
|
11535 /**
|
|
11536 * DataTables features four different built-in options for the buttons to
|
|
11537 * display for pagination control:
|
|
11538 *
|
|
11539 * * `simple` - 'Previous' and 'Next' buttons only
|
|
11540 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
|
|
11541 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
|
|
11542 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
|
|
11543 * page numbers
|
|
11544 *
|
|
11545 * Further methods can be added using {@link DataTable.ext.oPagination}.
|
|
11546 * @type string
|
|
11547 * @default simple_numbers
|
|
11548 *
|
|
11549 * @dtopt Options
|
|
11550 * @name DataTable.defaults.pagingType
|
|
11551 *
|
|
11552 * @example
|
|
11553 * $(document).ready( function() {
|
|
11554 * $('#example').dataTable( {
|
|
11555 * "pagingType": "full_numbers"
|
|
11556 * } );
|
|
11557 * } )
|
|
11558 */
|
|
11559 "sPaginationType": "simple_numbers",
|
|
11560
|
|
11561
|
|
11562 /**
|
|
11563 * Enable horizontal scrolling. When a table is too wide to fit into a
|
|
11564 * certain layout, or you have a large number of columns in the table, you
|
|
11565 * can enable x-scrolling to show the table in a viewport, which can be
|
|
11566 * scrolled. This property can be `true` which will allow the table to
|
|
11567 * scroll horizontally when needed, or any CSS unit, or a number (in which
|
|
11568 * case it will be treated as a pixel measurement). Setting as simply `true`
|
|
11569 * is recommended.
|
|
11570 * @type boolean|string
|
|
11571 * @default <i>blank string - i.e. disabled</i>
|
|
11572 *
|
|
11573 * @dtopt Features
|
|
11574 * @name DataTable.defaults.scrollX
|
|
11575 *
|
|
11576 * @example
|
|
11577 * $(document).ready( function() {
|
|
11578 * $('#example').dataTable( {
|
|
11579 * "scrollX": true,
|
|
11580 * "scrollCollapse": true
|
|
11581 * } );
|
|
11582 * } );
|
|
11583 */
|
|
11584 "sScrollX": "",
|
|
11585
|
|
11586
|
|
11587 /**
|
|
11588 * This property can be used to force a DataTable to use more width than it
|
|
11589 * might otherwise do when x-scrolling is enabled. For example if you have a
|
|
11590 * table which requires to be well spaced, this parameter is useful for
|
|
11591 * "over-sizing" the table, and thus forcing scrolling. This property can by
|
|
11592 * any CSS unit, or a number (in which case it will be treated as a pixel
|
|
11593 * measurement).
|
|
11594 * @type string
|
|
11595 * @default <i>blank string - i.e. disabled</i>
|
|
11596 *
|
|
11597 * @dtopt Options
|
|
11598 * @name DataTable.defaults.scrollXInner
|
|
11599 *
|
|
11600 * @example
|
|
11601 * $(document).ready( function() {
|
|
11602 * $('#example').dataTable( {
|
|
11603 * "scrollX": "100%",
|
|
11604 * "scrollXInner": "110%"
|
|
11605 * } );
|
|
11606 * } );
|
|
11607 */
|
|
11608 "sScrollXInner": "",
|
|
11609
|
|
11610
|
|
11611 /**
|
|
11612 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
|
|
11613 * to the given height, and enable scrolling for any data which overflows the
|
|
11614 * current viewport. This can be used as an alternative to paging to display
|
|
11615 * a lot of data in a small area (although paging and scrolling can both be
|
|
11616 * enabled at the same time). This property can be any CSS unit, or a number
|
|
11617 * (in which case it will be treated as a pixel measurement).
|
|
11618 * @type string
|
|
11619 * @default <i>blank string - i.e. disabled</i>
|
|
11620 *
|
|
11621 * @dtopt Features
|
|
11622 * @name DataTable.defaults.scrollY
|
|
11623 *
|
|
11624 * @example
|
|
11625 * $(document).ready( function() {
|
|
11626 * $('#example').dataTable( {
|
|
11627 * "scrollY": "200px",
|
|
11628 * "paginate": false
|
|
11629 * } );
|
|
11630 * } );
|
|
11631 */
|
|
11632 "sScrollY": "",
|
|
11633
|
|
11634
|
|
11635 /**
|
|
11636 * __Deprecated__ The functionality provided by this parameter has now been
|
|
11637 * superseded by that provided through `ajax`, which should be used instead.
|
|
11638 *
|
|
11639 * Set the HTTP method that is used to make the Ajax call for server-side
|
|
11640 * processing or Ajax sourced data.
|
|
11641 * @type string
|
|
11642 * @default GET
|
|
11643 *
|
|
11644 * @dtopt Options
|
|
11645 * @dtopt Server-side
|
|
11646 * @name DataTable.defaults.serverMethod
|
|
11647 *
|
|
11648 * @deprecated 1.10. Please use `ajax` for this functionality now.
|
|
11649 */
|
|
11650 "sServerMethod": "GET",
|
|
11651
|
|
11652
|
|
11653 /**
|
|
11654 * DataTables makes use of renderers when displaying HTML elements for
|
|
11655 * a table. These renderers can be added or modified by plug-ins to
|
|
11656 * generate suitable mark-up for a site. For example the Bootstrap
|
|
11657 * integration plug-in for DataTables uses a paging button renderer to
|
|
11658 * display pagination buttons in the mark-up required by Bootstrap.
|
|
11659 *
|
|
11660 * For further information about the renderers available see
|
|
11661 * DataTable.ext.renderer
|
|
11662 * @type string|object
|
|
11663 * @default null
|
|
11664 *
|
|
11665 * @name DataTable.defaults.renderer
|
|
11666 *
|
|
11667 */
|
|
11668 "renderer": null
|
|
11669 };
|
|
11670
|
|
11671 _fnHungarianMap( DataTable.defaults );
|
|
11672
|
|
11673
|
|
11674
|
|
11675 /*
|
|
11676 * Developer note - See note in model.defaults.js about the use of Hungarian
|
|
11677 * notation and camel case.
|
|
11678 */
|
|
11679
|
|
11680 /**
|
|
11681 * Column options that can be given to DataTables at initialisation time.
|
|
11682 * @namespace
|
|
11683 */
|
|
11684 DataTable.defaults.column = {
|
|
11685 /**
|
|
11686 * Define which column(s) an order will occur on for this column. This
|
|
11687 * allows a column's ordering to take multiple columns into account when
|
|
11688 * doing a sort or use the data from a different column. For example first
|
|
11689 * name / last name columns make sense to do a multi-column sort over the
|
|
11690 * two columns.
|
|
11691 * @type array|int
|
|
11692 * @default null <i>Takes the value of the column index automatically</i>
|
|
11693 *
|
|
11694 * @name DataTable.defaults.column.orderData
|
|
11695 * @dtopt Columns
|
|
11696 *
|
|
11697 * @example
|
|
11698 * // Using `columnDefs`
|
|
11699 * $(document).ready( function() {
|
|
11700 * $('#example').dataTable( {
|
|
11701 * "columnDefs": [
|
|
11702 * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
|
|
11703 * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
|
|
11704 * { "orderData": 2, "targets": [ 2 ] }
|
|
11705 * ]
|
|
11706 * } );
|
|
11707 * } );
|
|
11708 *
|
|
11709 * @example
|
|
11710 * // Using `columns`
|
|
11711 * $(document).ready( function() {
|
|
11712 * $('#example').dataTable( {
|
|
11713 * "columns": [
|
|
11714 * { "orderData": [ 0, 1 ] },
|
|
11715 * { "orderData": [ 1, 0 ] },
|
|
11716 * { "orderData": 2 },
|
|
11717 * null,
|
|
11718 * null
|
|
11719 * ]
|
|
11720 * } );
|
|
11721 * } );
|
|
11722 */
|
|
11723 "aDataSort": null,
|
|
11724 "iDataSort": -1,
|
|
11725
|
|
11726
|
|
11727 /**
|
|
11728 * You can control the default ordering direction, and even alter the
|
|
11729 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
|
|
11730 * using this parameter.
|
|
11731 * @type array
|
|
11732 * @default [ 'asc', 'desc' ]
|
|
11733 *
|
|
11734 * @name DataTable.defaults.column.orderSequence
|
|
11735 * @dtopt Columns
|
|
11736 *
|
|
11737 * @example
|
|
11738 * // Using `columnDefs`
|
|
11739 * $(document).ready( function() {
|
|
11740 * $('#example').dataTable( {
|
|
11741 * "columnDefs": [
|
|
11742 * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
|
|
11743 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
|
|
11744 * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
|
|
11745 * ]
|
|
11746 * } );
|
|
11747 * } );
|
|
11748 *
|
|
11749 * @example
|
|
11750 * // Using `columns`
|
|
11751 * $(document).ready( function() {
|
|
11752 * $('#example').dataTable( {
|
|
11753 * "columns": [
|
|
11754 * null,
|
|
11755 * { "orderSequence": [ "asc" ] },
|
|
11756 * { "orderSequence": [ "desc", "asc", "asc" ] },
|
|
11757 * { "orderSequence": [ "desc" ] },
|
|
11758 * null
|
|
11759 * ]
|
|
11760 * } );
|
|
11761 * } );
|
|
11762 */
|
|
11763 "asSorting": [ 'asc', 'desc' ],
|
|
11764
|
|
11765
|
|
11766 /**
|
|
11767 * Enable or disable filtering on the data in this column.
|
|
11768 * @type boolean
|
|
11769 * @default true
|
|
11770 *
|
|
11771 * @name DataTable.defaults.column.searchable
|
|
11772 * @dtopt Columns
|
|
11773 *
|
|
11774 * @example
|
|
11775 * // Using `columnDefs`
|
|
11776 * $(document).ready( function() {
|
|
11777 * $('#example').dataTable( {
|
|
11778 * "columnDefs": [
|
|
11779 * { "searchable": false, "targets": [ 0 ] }
|
|
11780 * ] } );
|
|
11781 * } );
|
|
11782 *
|
|
11783 * @example
|
|
11784 * // Using `columns`
|
|
11785 * $(document).ready( function() {
|
|
11786 * $('#example').dataTable( {
|
|
11787 * "columns": [
|
|
11788 * { "searchable": false },
|
|
11789 * null,
|
|
11790 * null,
|
|
11791 * null,
|
|
11792 * null
|
|
11793 * ] } );
|
|
11794 * } );
|
|
11795 */
|
|
11796 "bSearchable": true,
|
|
11797
|
|
11798
|
|
11799 /**
|
|
11800 * Enable or disable ordering on this column.
|
|
11801 * @type boolean
|
|
11802 * @default true
|
|
11803 *
|
|
11804 * @name DataTable.defaults.column.orderable
|
|
11805 * @dtopt Columns
|
|
11806 *
|
|
11807 * @example
|
|
11808 * // Using `columnDefs`
|
|
11809 * $(document).ready( function() {
|
|
11810 * $('#example').dataTable( {
|
|
11811 * "columnDefs": [
|
|
11812 * { "orderable": false, "targets": [ 0 ] }
|
|
11813 * ] } );
|
|
11814 * } );
|
|
11815 *
|
|
11816 * @example
|
|
11817 * // Using `columns`
|
|
11818 * $(document).ready( function() {
|
|
11819 * $('#example').dataTable( {
|
|
11820 * "columns": [
|
|
11821 * { "orderable": false },
|
|
11822 * null,
|
|
11823 * null,
|
|
11824 * null,
|
|
11825 * null
|
|
11826 * ] } );
|
|
11827 * } );
|
|
11828 */
|
|
11829 "bSortable": true,
|
|
11830
|
|
11831
|
|
11832 /**
|
|
11833 * Enable or disable the display of this column.
|
|
11834 * @type boolean
|
|
11835 * @default true
|
|
11836 *
|
|
11837 * @name DataTable.defaults.column.visible
|
|
11838 * @dtopt Columns
|
|
11839 *
|
|
11840 * @example
|
|
11841 * // Using `columnDefs`
|
|
11842 * $(document).ready( function() {
|
|
11843 * $('#example').dataTable( {
|
|
11844 * "columnDefs": [
|
|
11845 * { "visible": false, "targets": [ 0 ] }
|
|
11846 * ] } );
|
|
11847 * } );
|
|
11848 *
|
|
11849 * @example
|
|
11850 * // Using `columns`
|
|
11851 * $(document).ready( function() {
|
|
11852 * $('#example').dataTable( {
|
|
11853 * "columns": [
|
|
11854 * { "visible": false },
|
|
11855 * null,
|
|
11856 * null,
|
|
11857 * null,
|
|
11858 * null
|
|
11859 * ] } );
|
|
11860 * } );
|
|
11861 */
|
|
11862 "bVisible": true,
|
|
11863
|
|
11864
|
|
11865 /**
|
|
11866 * Developer definable function that is called whenever a cell is created (Ajax source,
|
|
11867 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
|
|
11868 * allowing you to modify the DOM element (add background colour for example) when the
|
|
11869 * element is available.
|
|
11870 * @type function
|
|
11871 * @param {element} td The TD node that has been created
|
|
11872 * @param {*} cellData The Data for the cell
|
|
11873 * @param {array|object} rowData The data for the whole row
|
|
11874 * @param {int} row The row index for the aoData data store
|
|
11875 * @param {int} col The column index for aoColumns
|
|
11876 *
|
|
11877 * @name DataTable.defaults.column.createdCell
|
|
11878 * @dtopt Columns
|
|
11879 *
|
|
11880 * @example
|
|
11881 * $(document).ready( function() {
|
|
11882 * $('#example').dataTable( {
|
|
11883 * "columnDefs": [ {
|
|
11884 * "targets": [3],
|
|
11885 * "createdCell": function (td, cellData, rowData, row, col) {
|
|
11886 * if ( cellData == "1.7" ) {
|
|
11887 * $(td).css('color', 'blue')
|
|
11888 * }
|
|
11889 * }
|
|
11890 * } ]
|
|
11891 * });
|
|
11892 * } );
|
|
11893 */
|
|
11894 "fnCreatedCell": null,
|
|
11895
|
|
11896
|
|
11897 /**
|
|
11898 * This parameter has been replaced by `data` in DataTables to ensure naming
|
|
11899 * consistency. `dataProp` can still be used, as there is backwards
|
|
11900 * compatibility in DataTables for this option, but it is strongly
|
|
11901 * recommended that you use `data` in preference to `dataProp`.
|
|
11902 * @name DataTable.defaults.column.dataProp
|
|
11903 */
|
|
11904
|
|
11905
|
|
11906 /**
|
|
11907 * This property can be used to read data from any data source property,
|
|
11908 * including deeply nested objects / properties. `data` can be given in a
|
|
11909 * number of different ways which effect its behaviour:
|
|
11910 *
|
|
11911 * * `integer` - treated as an array index for the data source. This is the
|
|
11912 * default that DataTables uses (incrementally increased for each column).
|
|
11913 * * `string` - read an object property from the data source. There are
|
|
11914 * three 'special' options that can be used in the string to alter how
|
|
11915 * DataTables reads the data from the source object:
|
|
11916 * * `.` - Dotted Javascript notation. Just as you use a `.` in
|
|
11917 * Javascript to read from nested objects, so to can the options
|
|
11918 * specified in `data`. For example: `browser.version` or
|
|
11919 * `browser.name`. If your object parameter name contains a period, use
|
|
11920 * `\\` to escape it - i.e. `first\\.name`.
|
|
11921 * * `[]` - Array notation. DataTables can automatically combine data
|
|
11922 * from and array source, joining the data with the characters provided
|
|
11923 * between the two brackets. For example: `name[, ]` would provide a
|
|
11924 * comma-space separated list from the source array. If no characters
|
|
11925 * are provided between the brackets, the original array source is
|
|
11926 * returned.
|
|
11927 * * `()` - Function notation. Adding `()` to the end of a parameter will
|
|
11928 * execute a function of the name given. For example: `browser()` for a
|
|
11929 * simple function on the data source, `browser.version()` for a
|
|
11930 * function in a nested property or even `browser().version` to get an
|
|
11931 * object property if the function called returns an object. Note that
|
|
11932 * function notation is recommended for use in `render` rather than
|
|
11933 * `data` as it is much simpler to use as a renderer.
|
|
11934 * * `null` - use the original data source for the row rather than plucking
|
|
11935 * data directly from it. This action has effects on two other
|
|
11936 * initialisation options:
|
|
11937 * * `defaultContent` - When null is given as the `data` option and
|
|
11938 * `defaultContent` is specified for the column, the value defined by
|
|
11939 * `defaultContent` will be used for the cell.
|
|
11940 * * `render` - When null is used for the `data` option and the `render`
|
|
11941 * option is specified for the column, the whole data source for the
|
|
11942 * row is used for the renderer.
|
|
11943 * * `function` - the function given will be executed whenever DataTables
|
|
11944 * needs to set or get the data for a cell in the column. The function
|
|
11945 * takes three parameters:
|
|
11946 * * Parameters:
|
|
11947 * * `{array|object}` The data source for the row
|
|
11948 * * `{string}` The type call data requested - this will be 'set' when
|
|
11949 * setting data or 'filter', 'display', 'type', 'sort' or undefined
|
|
11950 * when gathering data. Note that when `undefined` is given for the
|
|
11951 * type DataTables expects to get the raw data for the object back<
|
|
11952 * * `{*}` Data to set when the second parameter is 'set'.
|
|
11953 * * Return:
|
|
11954 * * The return value from the function is not required when 'set' is
|
|
11955 * the type of call, but otherwise the return is what will be used
|
|
11956 * for the data requested.
|
|
11957 *
|
|
11958 * Note that `data` is a getter and setter option. If you just require
|
|
11959 * formatting of data for output, you will likely want to use `render` which
|
|
11960 * is simply a getter and thus simpler to use.
|
|
11961 *
|
|
11962 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
|
|
11963 * name change reflects the flexibility of this property and is consistent
|
|
11964 * with the naming of mRender. If 'mDataProp' is given, then it will still
|
|
11965 * be used by DataTables, as it automatically maps the old name to the new
|
|
11966 * if required.
|
|
11967 *
|
|
11968 * @type string|int|function|null
|
|
11969 * @default null <i>Use automatically calculated column index</i>
|
|
11970 *
|
|
11971 * @name DataTable.defaults.column.data
|
|
11972 * @dtopt Columns
|
|
11973 *
|
|
11974 * @example
|
|
11975 * // Read table data from objects
|
|
11976 * // JSON structure for each row:
|
|
11977 * // {
|
|
11978 * // "engine": {value},
|
|
11979 * // "browser": {value},
|
|
11980 * // "platform": {value},
|
|
11981 * // "version": {value},
|
|
11982 * // "grade": {value}
|
|
11983 * // }
|
|
11984 * $(document).ready( function() {
|
|
11985 * $('#example').dataTable( {
|
|
11986 * "ajaxSource": "sources/objects.txt",
|
|
11987 * "columns": [
|
|
11988 * { "data": "engine" },
|
|
11989 * { "data": "browser" },
|
|
11990 * { "data": "platform" },
|
|
11991 * { "data": "version" },
|
|
11992 * { "data": "grade" }
|
|
11993 * ]
|
|
11994 * } );
|
|
11995 * } );
|
|
11996 *
|
|
11997 * @example
|
|
11998 * // Read information from deeply nested objects
|
|
11999 * // JSON structure for each row:
|
|
12000 * // {
|
|
12001 * // "engine": {value},
|
|
12002 * // "browser": {value},
|
|
12003 * // "platform": {
|
|
12004 * // "inner": {value}
|
|
12005 * // },
|
|
12006 * // "details": [
|
|
12007 * // {value}, {value}
|
|
12008 * // ]
|
|
12009 * // }
|
|
12010 * $(document).ready( function() {
|
|
12011 * $('#example').dataTable( {
|
|
12012 * "ajaxSource": "sources/deep.txt",
|
|
12013 * "columns": [
|
|
12014 * { "data": "engine" },
|
|
12015 * { "data": "browser" },
|
|
12016 * { "data": "platform.inner" },
|
|
12017 * { "data": "platform.details.0" },
|
|
12018 * { "data": "platform.details.1" }
|
|
12019 * ]
|
|
12020 * } );
|
|
12021 * } );
|
|
12022 *
|
|
12023 * @example
|
|
12024 * // Using `data` as a function to provide different information for
|
|
12025 * // sorting, filtering and display. In this case, currency (price)
|
|
12026 * $(document).ready( function() {
|
|
12027 * $('#example').dataTable( {
|
|
12028 * "columnDefs": [ {
|
|
12029 * "targets": [ 0 ],
|
|
12030 * "data": function ( source, type, val ) {
|
|
12031 * if (type === 'set') {
|
|
12032 * source.price = val;
|
|
12033 * // Store the computed dislay and filter values for efficiency
|
|
12034 * source.price_display = val=="" ? "" : "$"+numberFormat(val);
|
|
12035 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
|
|
12036 * return;
|
|
12037 * }
|
|
12038 * else if (type === 'display') {
|
|
12039 * return source.price_display;
|
|
12040 * }
|
|
12041 * else if (type === 'filter') {
|
|
12042 * return source.price_filter;
|
|
12043 * }
|
|
12044 * // 'sort', 'type' and undefined all just use the integer
|
|
12045 * return source.price;
|
|
12046 * }
|
|
12047 * } ]
|
|
12048 * } );
|
|
12049 * } );
|
|
12050 *
|
|
12051 * @example
|
|
12052 * // Using default content
|
|
12053 * $(document).ready( function() {
|
|
12054 * $('#example').dataTable( {
|
|
12055 * "columnDefs": [ {
|
|
12056 * "targets": [ 0 ],
|
|
12057 * "data": null,
|
|
12058 * "defaultContent": "Click to edit"
|
|
12059 * } ]
|
|
12060 * } );
|
|
12061 * } );
|
|
12062 *
|
|
12063 * @example
|
|
12064 * // Using array notation - outputting a list from an array
|
|
12065 * $(document).ready( function() {
|
|
12066 * $('#example').dataTable( {
|
|
12067 * "columnDefs": [ {
|
|
12068 * "targets": [ 0 ],
|
|
12069 * "data": "name[, ]"
|
|
12070 * } ]
|
|
12071 * } );
|
|
12072 * } );
|
|
12073 *
|
|
12074 */
|
|
12075 "mData": null,
|
|
12076
|
|
12077
|
|
12078 /**
|
|
12079 * This property is the rendering partner to `data` and it is suggested that
|
|
12080 * when you want to manipulate data for display (including filtering,
|
|
12081 * sorting etc) without altering the underlying data for the table, use this
|
|
12082 * property. `render` can be considered to be the the read only companion to
|
|
12083 * `data` which is read / write (then as such more complex). Like `data`
|
|
12084 * this option can be given in a number of different ways to effect its
|
|
12085 * behaviour:
|
|
12086 *
|
|
12087 * * `integer` - treated as an array index for the data source. This is the
|
|
12088 * default that DataTables uses (incrementally increased for each column).
|
|
12089 * * `string` - read an object property from the data source. There are
|
|
12090 * three 'special' options that can be used in the string to alter how
|
|
12091 * DataTables reads the data from the source object:
|
|
12092 * * `.` - Dotted Javascript notation. Just as you use a `.` in
|
|
12093 * Javascript to read from nested objects, so to can the options
|
|
12094 * specified in `data`. For example: `browser.version` or
|
|
12095 * `browser.name`. If your object parameter name contains a period, use
|
|
12096 * `\\` to escape it - i.e. `first\\.name`.
|
|
12097 * * `[]` - Array notation. DataTables can automatically combine data
|
|
12098 * from and array source, joining the data with the characters provided
|
|
12099 * between the two brackets. For example: `name[, ]` would provide a
|
|
12100 * comma-space separated list from the source array. If no characters
|
|
12101 * are provided between the brackets, the original array source is
|
|
12102 * returned.
|
|
12103 * * `()` - Function notation. Adding `()` to the end of a parameter will
|
|
12104 * execute a function of the name given. For example: `browser()` for a
|
|
12105 * simple function on the data source, `browser.version()` for a
|
|
12106 * function in a nested property or even `browser().version` to get an
|
|
12107 * object property if the function called returns an object.
|
|
12108 * * `object` - use different data for the different data types requested by
|
|
12109 * DataTables ('filter', 'display', 'type' or 'sort'). The property names
|
|
12110 * of the object is the data type the property refers to and the value can
|
|
12111 * defined using an integer, string or function using the same rules as
|
|
12112 * `render` normally does. Note that an `_` option _must_ be specified.
|
|
12113 * This is the default value to use if you haven't specified a value for
|
|
12114 * the data type requested by DataTables.
|
|
12115 * * `function` - the function given will be executed whenever DataTables
|
|
12116 * needs to set or get the data for a cell in the column. The function
|
|
12117 * takes three parameters:
|
|
12118 * * Parameters:
|
|
12119 * * {array|object} The data source for the row (based on `data`)
|
|
12120 * * {string} The type call data requested - this will be 'filter',
|
|
12121 * 'display', 'type' or 'sort'.
|
|
12122 * * {array|object} The full data source for the row (not based on
|
|
12123 * `data`)
|
|
12124 * * Return:
|
|
12125 * * The return value from the function is what will be used for the
|
|
12126 * data requested.
|
|
12127 *
|
|
12128 * @type string|int|function|object|null
|
|
12129 * @default null Use the data source value.
|
|
12130 *
|
|
12131 * @name DataTable.defaults.column.render
|
|
12132 * @dtopt Columns
|
|
12133 *
|
|
12134 * @example
|
|
12135 * // Create a comma separated list from an array of objects
|
|
12136 * $(document).ready( function() {
|
|
12137 * $('#example').dataTable( {
|
|
12138 * "ajaxSource": "sources/deep.txt",
|
|
12139 * "columns": [
|
|
12140 * { "data": "engine" },
|
|
12141 * { "data": "browser" },
|
|
12142 * {
|
|
12143 * "data": "platform",
|
|
12144 * "render": "[, ].name"
|
|
12145 * }
|
|
12146 * ]
|
|
12147 * } );
|
|
12148 * } );
|
|
12149 *
|
|
12150 * @example
|
|
12151 * // Execute a function to obtain data
|
|
12152 * $(document).ready( function() {
|
|
12153 * $('#example').dataTable( {
|
|
12154 * "columnDefs": [ {
|
|
12155 * "targets": [ 0 ],
|
|
12156 * "data": null, // Use the full data source object for the renderer's source
|
|
12157 * "render": "browserName()"
|
|
12158 * } ]
|
|
12159 * } );
|
|
12160 * } );
|
|
12161 *
|
|
12162 * @example
|
|
12163 * // As an object, extracting different data for the different types
|
|
12164 * // This would be used with a data source such as:
|
|
12165 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
|
|
12166 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
|
|
12167 * // (which has both forms) is used for filtering for if a user inputs either format, while
|
|
12168 * // the formatted phone number is the one that is shown in the table.
|
|
12169 * $(document).ready( function() {
|
|
12170 * $('#example').dataTable( {
|
|
12171 * "columnDefs": [ {
|
|
12172 * "targets": [ 0 ],
|
|
12173 * "data": null, // Use the full data source object for the renderer's source
|
|
12174 * "render": {
|
|
12175 * "_": "phone",
|
|
12176 * "filter": "phone_filter",
|
|
12177 * "display": "phone_display"
|
|
12178 * }
|
|
12179 * } ]
|
|
12180 * } );
|
|
12181 * } );
|
|
12182 *
|
|
12183 * @example
|
|
12184 * // Use as a function to create a link from the data source
|
|
12185 * $(document).ready( function() {
|
|
12186 * $('#example').dataTable( {
|
|
12187 * "columnDefs": [ {
|
|
12188 * "targets": [ 0 ],
|
|
12189 * "data": "download_link",
|
|
12190 * "render": function ( data, type, full ) {
|
|
12191 * return '<a href="'+data+'">Download</a>';
|
|
12192 * }
|
|
12193 * } ]
|
|
12194 * } );
|
|
12195 * } );
|
|
12196 */
|
|
12197 "mRender": null,
|
|
12198
|
|
12199
|
|
12200 /**
|
|
12201 * Change the cell type created for the column - either TD cells or TH cells. This
|
|
12202 * can be useful as TH cells have semantic meaning in the table body, allowing them
|
|
12203 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
|
|
12204 * @type string
|
|
12205 * @default td
|
|
12206 *
|
|
12207 * @name DataTable.defaults.column.cellType
|
|
12208 * @dtopt Columns
|
|
12209 *
|
|
12210 * @example
|
|
12211 * // Make the first column use TH cells
|
|
12212 * $(document).ready( function() {
|
|
12213 * $('#example').dataTable( {
|
|
12214 * "columnDefs": [ {
|
|
12215 * "targets": [ 0 ],
|
|
12216 * "cellType": "th"
|
|
12217 * } ]
|
|
12218 * } );
|
|
12219 * } );
|
|
12220 */
|
|
12221 "sCellType": "td",
|
|
12222
|
|
12223
|
|
12224 /**
|
|
12225 * Class to give to each cell in this column.
|
|
12226 * @type string
|
|
12227 * @default <i>Empty string</i>
|
|
12228 *
|
|
12229 * @name DataTable.defaults.column.class
|
|
12230 * @dtopt Columns
|
|
12231 *
|
|
12232 * @example
|
|
12233 * // Using `columnDefs`
|
|
12234 * $(document).ready( function() {
|
|
12235 * $('#example').dataTable( {
|
|
12236 * "columnDefs": [
|
|
12237 * { "class": "my_class", "targets": [ 0 ] }
|
|
12238 * ]
|
|
12239 * } );
|
|
12240 * } );
|
|
12241 *
|
|
12242 * @example
|
|
12243 * // Using `columns`
|
|
12244 * $(document).ready( function() {
|
|
12245 * $('#example').dataTable( {
|
|
12246 * "columns": [
|
|
12247 * { "class": "my_class" },
|
|
12248 * null,
|
|
12249 * null,
|
|
12250 * null,
|
|
12251 * null
|
|
12252 * ]
|
|
12253 * } );
|
|
12254 * } );
|
|
12255 */
|
|
12256 "sClass": "",
|
|
12257
|
|
12258 /**
|
|
12259 * When DataTables calculates the column widths to assign to each column,
|
|
12260 * it finds the longest string in each column and then constructs a
|
|
12261 * temporary table and reads the widths from that. The problem with this
|
|
12262 * is that "mmm" is much wider then "iiii", but the latter is a longer
|
|
12263 * string - thus the calculation can go wrong (doing it properly and putting
|
|
12264 * it into an DOM object and measuring that is horribly(!) slow). Thus as
|
|
12265 * a "work around" we provide this option. It will append its value to the
|
|
12266 * text that is found to be the longest string for the column - i.e. padding.
|
|
12267 * Generally you shouldn't need this!
|
|
12268 * @type string
|
|
12269 * @default <i>Empty string<i>
|
|
12270 *
|
|
12271 * @name DataTable.defaults.column.contentPadding
|
|
12272 * @dtopt Columns
|
|
12273 *
|
|
12274 * @example
|
|
12275 * // Using `columns`
|
|
12276 * $(document).ready( function() {
|
|
12277 * $('#example').dataTable( {
|
|
12278 * "columns": [
|
|
12279 * null,
|
|
12280 * null,
|
|
12281 * null,
|
|
12282 * {
|
|
12283 * "contentPadding": "mmm"
|
|
12284 * }
|
|
12285 * ]
|
|
12286 * } );
|
|
12287 * } );
|
|
12288 */
|
|
12289 "sContentPadding": "",
|
|
12290
|
|
12291
|
|
12292 /**
|
|
12293 * Allows a default value to be given for a column's data, and will be used
|
|
12294 * whenever a null data source is encountered (this can be because `data`
|
|
12295 * is set to null, or because the data source itself is null).
|
|
12296 * @type string
|
|
12297 * @default null
|
|
12298 *
|
|
12299 * @name DataTable.defaults.column.defaultContent
|
|
12300 * @dtopt Columns
|
|
12301 *
|
|
12302 * @example
|
|
12303 * // Using `columnDefs`
|
|
12304 * $(document).ready( function() {
|
|
12305 * $('#example').dataTable( {
|
|
12306 * "columnDefs": [
|
|
12307 * {
|
|
12308 * "data": null,
|
|
12309 * "defaultContent": "Edit",
|
|
12310 * "targets": [ -1 ]
|
|
12311 * }
|
|
12312 * ]
|
|
12313 * } );
|
|
12314 * } );
|
|
12315 *
|
|
12316 * @example
|
|
12317 * // Using `columns`
|
|
12318 * $(document).ready( function() {
|
|
12319 * $('#example').dataTable( {
|
|
12320 * "columns": [
|
|
12321 * null,
|
|
12322 * null,
|
|
12323 * null,
|
|
12324 * {
|
|
12325 * "data": null,
|
|
12326 * "defaultContent": "Edit"
|
|
12327 * }
|
|
12328 * ]
|
|
12329 * } );
|
|
12330 * } );
|
|
12331 */
|
|
12332 "sDefaultContent": null,
|
|
12333
|
|
12334
|
|
12335 /**
|
|
12336 * This parameter is only used in DataTables' server-side processing. It can
|
|
12337 * be exceptionally useful to know what columns are being displayed on the
|
|
12338 * client side, and to map these to database fields. When defined, the names
|
|
12339 * also allow DataTables to reorder information from the server if it comes
|
|
12340 * back in an unexpected order (i.e. if you switch your columns around on the
|
|
12341 * client-side, your server-side code does not also need updating).
|
|
12342 * @type string
|
|
12343 * @default <i>Empty string</i>
|
|
12344 *
|
|
12345 * @name DataTable.defaults.column.name
|
|
12346 * @dtopt Columns
|
|
12347 *
|
|
12348 * @example
|
|
12349 * // Using `columnDefs`
|
|
12350 * $(document).ready( function() {
|
|
12351 * $('#example').dataTable( {
|
|
12352 * "columnDefs": [
|
|
12353 * { "name": "engine", "targets": [ 0 ] },
|
|
12354 * { "name": "browser", "targets": [ 1 ] },
|
|
12355 * { "name": "platform", "targets": [ 2 ] },
|
|
12356 * { "name": "version", "targets": [ 3 ] },
|
|
12357 * { "name": "grade", "targets": [ 4 ] }
|
|
12358 * ]
|
|
12359 * } );
|
|
12360 * } );
|
|
12361 *
|
|
12362 * @example
|
|
12363 * // Using `columns`
|
|
12364 * $(document).ready( function() {
|
|
12365 * $('#example').dataTable( {
|
|
12366 * "columns": [
|
|
12367 * { "name": "engine" },
|
|
12368 * { "name": "browser" },
|
|
12369 * { "name": "platform" },
|
|
12370 * { "name": "version" },
|
|
12371 * { "name": "grade" }
|
|
12372 * ]
|
|
12373 * } );
|
|
12374 * } );
|
|
12375 */
|
|
12376 "sName": "",
|
|
12377
|
|
12378
|
|
12379 /**
|
|
12380 * Defines a data source type for the ordering which can be used to read
|
|
12381 * real-time information from the table (updating the internally cached
|
|
12382 * version) prior to ordering. This allows ordering to occur on user
|
|
12383 * editable elements such as form inputs.
|
|
12384 * @type string
|
|
12385 * @default std
|
|
12386 *
|
|
12387 * @name DataTable.defaults.column.orderDataType
|
|
12388 * @dtopt Columns
|
|
12389 *
|
|
12390 * @example
|
|
12391 * // Using `columnDefs`
|
|
12392 * $(document).ready( function() {
|
|
12393 * $('#example').dataTable( {
|
|
12394 * "columnDefs": [
|
|
12395 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
|
|
12396 * { "type": "numeric", "targets": [ 3 ] },
|
|
12397 * { "orderDataType": "dom-select", "targets": [ 4 ] },
|
|
12398 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
|
|
12399 * ]
|
|
12400 * } );
|
|
12401 * } );
|
|
12402 *
|
|
12403 * @example
|
|
12404 * // Using `columns`
|
|
12405 * $(document).ready( function() {
|
|
12406 * $('#example').dataTable( {
|
|
12407 * "columns": [
|
|
12408 * null,
|
|
12409 * null,
|
|
12410 * { "orderDataType": "dom-text" },
|
|
12411 * { "orderDataType": "dom-text", "type": "numeric" },
|
|
12412 * { "orderDataType": "dom-select" },
|
|
12413 * { "orderDataType": "dom-checkbox" }
|
|
12414 * ]
|
|
12415 * } );
|
|
12416 * } );
|
|
12417 */
|
|
12418 "sSortDataType": "std",
|
|
12419
|
|
12420
|
|
12421 /**
|
|
12422 * The title of this column.
|
|
12423 * @type string
|
|
12424 * @default null <i>Derived from the 'TH' value for this column in the
|
|
12425 * original HTML table.</i>
|
|
12426 *
|
|
12427 * @name DataTable.defaults.column.title
|
|
12428 * @dtopt Columns
|
|
12429 *
|
|
12430 * @example
|
|
12431 * // Using `columnDefs`
|
|
12432 * $(document).ready( function() {
|
|
12433 * $('#example').dataTable( {
|
|
12434 * "columnDefs": [
|
|
12435 * { "title": "My column title", "targets": [ 0 ] }
|
|
12436 * ]
|
|
12437 * } );
|
|
12438 * } );
|
|
12439 *
|
|
12440 * @example
|
|
12441 * // Using `columns`
|
|
12442 * $(document).ready( function() {
|
|
12443 * $('#example').dataTable( {
|
|
12444 * "columns": [
|
|
12445 * { "title": "My column title" },
|
|
12446 * null,
|
|
12447 * null,
|
|
12448 * null,
|
|
12449 * null
|
|
12450 * ]
|
|
12451 * } );
|
|
12452 * } );
|
|
12453 */
|
|
12454 "sTitle": null,
|
|
12455
|
|
12456
|
|
12457 /**
|
|
12458 * The type allows you to specify how the data for this column will be
|
|
12459 * ordered. Four types (string, numeric, date and html (which will strip
|
|
12460 * HTML tags before ordering)) are currently available. Note that only date
|
|
12461 * formats understood by Javascript's Date() object will be accepted as type
|
|
12462 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
|
|
12463 * 'numeric', 'date' or 'html' (by default). Further types can be adding
|
|
12464 * through plug-ins.
|
|
12465 * @type string
|
|
12466 * @default null <i>Auto-detected from raw data</i>
|
|
12467 *
|
|
12468 * @name DataTable.defaults.column.type
|
|
12469 * @dtopt Columns
|
|
12470 *
|
|
12471 * @example
|
|
12472 * // Using `columnDefs`
|
|
12473 * $(document).ready( function() {
|
|
12474 * $('#example').dataTable( {
|
|
12475 * "columnDefs": [
|
|
12476 * { "type": "html", "targets": [ 0 ] }
|
|
12477 * ]
|
|
12478 * } );
|
|
12479 * } );
|
|
12480 *
|
|
12481 * @example
|
|
12482 * // Using `columns`
|
|
12483 * $(document).ready( function() {
|
|
12484 * $('#example').dataTable( {
|
|
12485 * "columns": [
|
|
12486 * { "type": "html" },
|
|
12487 * null,
|
|
12488 * null,
|
|
12489 * null,
|
|
12490 * null
|
|
12491 * ]
|
|
12492 * } );
|
|
12493 * } );
|
|
12494 */
|
|
12495 "sType": null,
|
|
12496
|
|
12497
|
|
12498 /**
|
|
12499 * Defining the width of the column, this parameter may take any CSS value
|
|
12500 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
|
|
12501 * been given a specific width through this interface ensuring that the table
|
|
12502 * remains readable.
|
|
12503 * @type string
|
|
12504 * @default null <i>Automatic</i>
|
|
12505 *
|
|
12506 * @name DataTable.defaults.column.width
|
|
12507 * @dtopt Columns
|
|
12508 *
|
|
12509 * @example
|
|
12510 * // Using `columnDefs`
|
|
12511 * $(document).ready( function() {
|
|
12512 * $('#example').dataTable( {
|
|
12513 * "columnDefs": [
|
|
12514 * { "width": "20%", "targets": [ 0 ] }
|
|
12515 * ]
|
|
12516 * } );
|
|
12517 * } );
|
|
12518 *
|
|
12519 * @example
|
|
12520 * // Using `columns`
|
|
12521 * $(document).ready( function() {
|
|
12522 * $('#example').dataTable( {
|
|
12523 * "columns": [
|
|
12524 * { "width": "20%" },
|
|
12525 * null,
|
|
12526 * null,
|
|
12527 * null,
|
|
12528 * null
|
|
12529 * ]
|
|
12530 * } );
|
|
12531 * } );
|
|
12532 */
|
|
12533 "sWidth": null
|
|
12534 };
|
|
12535
|
|
12536 _fnHungarianMap( DataTable.defaults.column );
|
|
12537
|
|
12538
|
|
12539
|
|
12540 /**
|
|
12541 * DataTables settings object - this holds all the information needed for a
|
|
12542 * given table, including configuration, data and current application of the
|
|
12543 * table options. DataTables does not have a single instance for each DataTable
|
|
12544 * with the settings attached to that instance, but rather instances of the
|
|
12545 * DataTable "class" are created on-the-fly as needed (typically by a
|
|
12546 * $().dataTable() call) and the settings object is then applied to that
|
|
12547 * instance.
|
|
12548 *
|
|
12549 * Note that this object is related to {@link DataTable.defaults} but this
|
|
12550 * one is the internal data store for DataTables's cache of columns. It should
|
|
12551 * NOT be manipulated outside of DataTables. Any configuration should be done
|
|
12552 * through the initialisation options.
|
|
12553 * @namespace
|
|
12554 * @todo Really should attach the settings object to individual instances so we
|
|
12555 * don't need to create new instances on each $().dataTable() call (if the
|
|
12556 * table already exists). It would also save passing oSettings around and
|
|
12557 * into every single function. However, this is a very significant
|
|
12558 * architecture change for DataTables and will almost certainly break
|
|
12559 * backwards compatibility with older installations. This is something that
|
|
12560 * will be done in 2.0.
|
|
12561 */
|
|
12562 DataTable.models.oSettings = {
|
|
12563 /**
|
|
12564 * Primary features of DataTables and their enablement state.
|
|
12565 * @namespace
|
|
12566 */
|
|
12567 "oFeatures": {
|
|
12568
|
|
12569 /**
|
|
12570 * Flag to say if DataTables should automatically try to calculate the
|
|
12571 * optimum table and columns widths (true) or not (false).
|
|
12572 * Note that this parameter will be set by the initialisation routine. To
|
|
12573 * set a default use {@link DataTable.defaults}.
|
|
12574 * @type boolean
|
|
12575 */
|
|
12576 "bAutoWidth": null,
|
|
12577
|
|
12578 /**
|
|
12579 * Delay the creation of TR and TD elements until they are actually
|
|
12580 * needed by a driven page draw. This can give a significant speed
|
|
12581 * increase for Ajax source and Javascript source data, but makes no
|
|
12582 * difference at all fro DOM and server-side processing tables.
|
|
12583 * Note that this parameter will be set by the initialisation routine. To
|
|
12584 * set a default use {@link DataTable.defaults}.
|
|
12585 * @type boolean
|
|
12586 */
|
|
12587 "bDeferRender": null,
|
|
12588
|
|
12589 /**
|
|
12590 * Enable filtering on the table or not. Note that if this is disabled
|
|
12591 * then there is no filtering at all on the table, including fnFilter.
|
|
12592 * To just remove the filtering input use sDom and remove the 'f' option.
|
|
12593 * Note that this parameter will be set by the initialisation routine. To
|
|
12594 * set a default use {@link DataTable.defaults}.
|
|
12595 * @type boolean
|
|
12596 */
|
|
12597 "bFilter": null,
|
|
12598
|
|
12599 /**
|
|
12600 * Table information element (the 'Showing x of y records' div) enable
|
|
12601 * flag.
|
|
12602 * Note that this parameter will be set by the initialisation routine. To
|
|
12603 * set a default use {@link DataTable.defaults}.
|
|
12604 * @type boolean
|
|
12605 */
|
|
12606 "bInfo": null,
|
|
12607
|
|
12608 /**
|
|
12609 * Present a user control allowing the end user to change the page size
|
|
12610 * when pagination is enabled.
|
|
12611 * Note that this parameter will be set by the initialisation routine. To
|
|
12612 * set a default use {@link DataTable.defaults}.
|
|
12613 * @type boolean
|
|
12614 */
|
|
12615 "bLengthChange": null,
|
|
12616
|
|
12617 /**
|
|
12618 * Pagination enabled or not. Note that if this is disabled then length
|
|
12619 * changing must also be disabled.
|
|
12620 * Note that this parameter will be set by the initialisation routine. To
|
|
12621 * set a default use {@link DataTable.defaults}.
|
|
12622 * @type boolean
|
|
12623 */
|
|
12624 "bPaginate": null,
|
|
12625
|
|
12626 /**
|
|
12627 * Processing indicator enable flag whenever DataTables is enacting a
|
|
12628 * user request - typically an Ajax request for server-side processing.
|
|
12629 * Note that this parameter will be set by the initialisation routine. To
|
|
12630 * set a default use {@link DataTable.defaults}.
|
|
12631 * @type boolean
|
|
12632 */
|
|
12633 "bProcessing": null,
|
|
12634
|
|
12635 /**
|
|
12636 * Server-side processing enabled flag - when enabled DataTables will
|
|
12637 * get all data from the server for every draw - there is no filtering,
|
|
12638 * sorting or paging done on the client-side.
|
|
12639 * Note that this parameter will be set by the initialisation routine. To
|
|
12640 * set a default use {@link DataTable.defaults}.
|
|
12641 * @type boolean
|
|
12642 */
|
|
12643 "bServerSide": null,
|
|
12644
|
|
12645 /**
|
|
12646 * Sorting enablement flag.
|
|
12647 * Note that this parameter will be set by the initialisation routine. To
|
|
12648 * set a default use {@link DataTable.defaults}.
|
|
12649 * @type boolean
|
|
12650 */
|
|
12651 "bSort": null,
|
|
12652
|
|
12653 /**
|
|
12654 * Multi-column sorting
|
|
12655 * Note that this parameter will be set by the initialisation routine. To
|
|
12656 * set a default use {@link DataTable.defaults}.
|
|
12657 * @type boolean
|
|
12658 */
|
|
12659 "bSortMulti": null,
|
|
12660
|
|
12661 /**
|
|
12662 * Apply a class to the columns which are being sorted to provide a
|
|
12663 * visual highlight or not. This can slow things down when enabled since
|
|
12664 * there is a lot of DOM interaction.
|
|
12665 * Note that this parameter will be set by the initialisation routine. To
|
|
12666 * set a default use {@link DataTable.defaults}.
|
|
12667 * @type boolean
|
|
12668 */
|
|
12669 "bSortClasses": null,
|
|
12670
|
|
12671 /**
|
|
12672 * State saving enablement flag.
|
|
12673 * Note that this parameter will be set by the initialisation routine. To
|
|
12674 * set a default use {@link DataTable.defaults}.
|
|
12675 * @type boolean
|
|
12676 */
|
|
12677 "bStateSave": null
|
|
12678 },
|
|
12679
|
|
12680
|
|
12681 /**
|
|
12682 * Scrolling settings for a table.
|
|
12683 * @namespace
|
|
12684 */
|
|
12685 "oScroll": {
|
|
12686 /**
|
|
12687 * When the table is shorter in height than sScrollY, collapse the
|
|
12688 * table container down to the height of the table (when true).
|
|
12689 * Note that this parameter will be set by the initialisation routine. To
|
|
12690 * set a default use {@link DataTable.defaults}.
|
|
12691 * @type boolean
|
|
12692 */
|
|
12693 "bCollapse": null,
|
|
12694
|
|
12695 /**
|
|
12696 * Width of the scrollbar for the web-browser's platform. Calculated
|
|
12697 * during table initialisation.
|
|
12698 * @type int
|
|
12699 * @default 0
|
|
12700 */
|
|
12701 "iBarWidth": 0,
|
|
12702
|
|
12703 /**
|
|
12704 * Viewport width for horizontal scrolling. Horizontal scrolling is
|
|
12705 * disabled if an empty string.
|
|
12706 * Note that this parameter will be set by the initialisation routine. To
|
|
12707 * set a default use {@link DataTable.defaults}.
|
|
12708 * @type string
|
|
12709 */
|
|
12710 "sX": null,
|
|
12711
|
|
12712 /**
|
|
12713 * Width to expand the table to when using x-scrolling. Typically you
|
|
12714 * should not need to use this.
|
|
12715 * Note that this parameter will be set by the initialisation routine. To
|
|
12716 * set a default use {@link DataTable.defaults}.
|
|
12717 * @type string
|
|
12718 * @deprecated
|
|
12719 */
|
|
12720 "sXInner": null,
|
|
12721
|
|
12722 /**
|
|
12723 * Viewport height for vertical scrolling. Vertical scrolling is disabled
|
|
12724 * if an empty string.
|
|
12725 * Note that this parameter will be set by the initialisation routine. To
|
|
12726 * set a default use {@link DataTable.defaults}.
|
|
12727 * @type string
|
|
12728 */
|
|
12729 "sY": null
|
|
12730 },
|
|
12731
|
|
12732 /**
|
|
12733 * Language information for the table.
|
|
12734 * @namespace
|
|
12735 * @extends DataTable.defaults.oLanguage
|
|
12736 */
|
|
12737 "oLanguage": {
|
|
12738 /**
|
|
12739 * Information callback function. See
|
|
12740 * {@link DataTable.defaults.fnInfoCallback}
|
|
12741 * @type function
|
|
12742 * @default null
|
|
12743 */
|
|
12744 "fnInfoCallback": null
|
|
12745 },
|
|
12746
|
|
12747 /**
|
|
12748 * Browser support parameters
|
|
12749 * @namespace
|
|
12750 */
|
|
12751 "oBrowser": {
|
|
12752 /**
|
|
12753 * Indicate if the browser incorrectly calculates width:100% inside a
|
|
12754 * scrolling element (IE6/7)
|
|
12755 * @type boolean
|
|
12756 * @default false
|
|
12757 */
|
|
12758 "bScrollOversize": false,
|
|
12759
|
|
12760 /**
|
|
12761 * Determine if the vertical scrollbar is on the right or left of the
|
|
12762 * scrolling container - needed for rtl language layout, although not
|
|
12763 * all browsers move the scrollbar (Safari).
|
|
12764 * @type boolean
|
|
12765 * @default false
|
|
12766 */
|
|
12767 "bScrollbarLeft": false
|
|
12768 },
|
|
12769
|
|
12770
|
|
12771 "ajax": null,
|
|
12772
|
|
12773
|
|
12774 /**
|
|
12775 * Array referencing the nodes which are used for the features. The
|
|
12776 * parameters of this object match what is allowed by sDom - i.e.
|
|
12777 * <ul>
|
|
12778 * <li>'l' - Length changing</li>
|
|
12779 * <li>'f' - Filtering input</li>
|
|
12780 * <li>'t' - The table!</li>
|
|
12781 * <li>'i' - Information</li>
|
|
12782 * <li>'p' - Pagination</li>
|
|
12783 * <li>'r' - pRocessing</li>
|
|
12784 * </ul>
|
|
12785 * @type array
|
|
12786 * @default []
|
|
12787 */
|
|
12788 "aanFeatures": [],
|
|
12789
|
|
12790 /**
|
|
12791 * Store data information - see {@link DataTable.models.oRow} for detailed
|
|
12792 * information.
|
|
12793 * @type array
|
|
12794 * @default []
|
|
12795 */
|
|
12796 "aoData": [],
|
|
12797
|
|
12798 /**
|
|
12799 * Array of indexes which are in the current display (after filtering etc)
|
|
12800 * @type array
|
|
12801 * @default []
|
|
12802 */
|
|
12803 "aiDisplay": [],
|
|
12804
|
|
12805 /**
|
|
12806 * Array of indexes for display - no filtering
|
|
12807 * @type array
|
|
12808 * @default []
|
|
12809 */
|
|
12810 "aiDisplayMaster": [],
|
|
12811
|
|
12812 /**
|
|
12813 * Store information about each column that is in use
|
|
12814 * @type array
|
|
12815 * @default []
|
|
12816 */
|
|
12817 "aoColumns": [],
|
|
12818
|
|
12819 /**
|
|
12820 * Store information about the table's header
|
|
12821 * @type array
|
|
12822 * @default []
|
|
12823 */
|
|
12824 "aoHeader": [],
|
|
12825
|
|
12826 /**
|
|
12827 * Store information about the table's footer
|
|
12828 * @type array
|
|
12829 * @default []
|
|
12830 */
|
|
12831 "aoFooter": [],
|
|
12832
|
|
12833 /**
|
|
12834 * Store the applied global search information in case we want to force a
|
|
12835 * research or compare the old search to a new one.
|
|
12836 * Note that this parameter will be set by the initialisation routine. To
|
|
12837 * set a default use {@link DataTable.defaults}.
|
|
12838 * @namespace
|
|
12839 * @extends DataTable.models.oSearch
|
|
12840 */
|
|
12841 "oPreviousSearch": {},
|
|
12842
|
|
12843 /**
|
|
12844 * Store the applied search for each column - see
|
|
12845 * {@link DataTable.models.oSearch} for the format that is used for the
|
|
12846 * filtering information for each column.
|
|
12847 * @type array
|
|
12848 * @default []
|
|
12849 */
|
|
12850 "aoPreSearchCols": [],
|
|
12851
|
|
12852 /**
|
|
12853 * Sorting that is applied to the table. Note that the inner arrays are
|
|
12854 * used in the following manner:
|
|
12855 * <ul>
|
|
12856 * <li>Index 0 - column number</li>
|
|
12857 * <li>Index 1 - current sorting direction</li>
|
|
12858 * </ul>
|
|
12859 * Note that this parameter will be set by the initialisation routine. To
|
|
12860 * set a default use {@link DataTable.defaults}.
|
|
12861 * @type array
|
|
12862 * @todo These inner arrays should really be objects
|
|
12863 */
|
|
12864 "aaSorting": null,
|
|
12865
|
|
12866 /**
|
|
12867 * Sorting that is always applied to the table (i.e. prefixed in front of
|
|
12868 * aaSorting).
|
|
12869 * Note that this parameter will be set by the initialisation routine. To
|
|
12870 * set a default use {@link DataTable.defaults}.
|
|
12871 * @type array
|
|
12872 * @default []
|
|
12873 */
|
|
12874 "aaSortingFixed": [],
|
|
12875
|
|
12876 /**
|
|
12877 * Classes to use for the striping of a table.
|
|
12878 * Note that this parameter will be set by the initialisation routine. To
|
|
12879 * set a default use {@link DataTable.defaults}.
|
|
12880 * @type array
|
|
12881 * @default []
|
|
12882 */
|
|
12883 "asStripeClasses": null,
|
|
12884
|
|
12885 /**
|
|
12886 * If restoring a table - we should restore its striping classes as well
|
|
12887 * @type array
|
|
12888 * @default []
|
|
12889 */
|
|
12890 "asDestroyStripes": [],
|
|
12891
|
|
12892 /**
|
|
12893 * If restoring a table - we should restore its width
|
|
12894 * @type int
|
|
12895 * @default 0
|
|
12896 */
|
|
12897 "sDestroyWidth": 0,
|
|
12898
|
|
12899 /**
|
|
12900 * Callback functions array for every time a row is inserted (i.e. on a draw).
|
|
12901 * @type array
|
|
12902 * @default []
|
|
12903 */
|
|
12904 "aoRowCallback": [],
|
|
12905
|
|
12906 /**
|
|
12907 * Callback functions for the header on each draw.
|
|
12908 * @type array
|
|
12909 * @default []
|
|
12910 */
|
|
12911 "aoHeaderCallback": [],
|
|
12912
|
|
12913 /**
|
|
12914 * Callback function for the footer on each draw.
|
|
12915 * @type array
|
|
12916 * @default []
|
|
12917 */
|
|
12918 "aoFooterCallback": [],
|
|
12919
|
|
12920 /**
|
|
12921 * Array of callback functions for draw callback functions
|
|
12922 * @type array
|
|
12923 * @default []
|
|
12924 */
|
|
12925 "aoDrawCallback": [],
|
|
12926
|
|
12927 /**
|
|
12928 * Array of callback functions for row created function
|
|
12929 * @type array
|
|
12930 * @default []
|
|
12931 */
|
|
12932 "aoRowCreatedCallback": [],
|
|
12933
|
|
12934 /**
|
|
12935 * Callback functions for just before the table is redrawn. A return of
|
|
12936 * false will be used to cancel the draw.
|
|
12937 * @type array
|
|
12938 * @default []
|
|
12939 */
|
|
12940 "aoPreDrawCallback": [],
|
|
12941
|
|
12942 /**
|
|
12943 * Callback functions for when the table has been initialised.
|
|
12944 * @type array
|
|
12945 * @default []
|
|
12946 */
|
|
12947 "aoInitComplete": [],
|
|
12948
|
|
12949
|
|
12950 /**
|
|
12951 * Callbacks for modifying the settings to be stored for state saving, prior to
|
|
12952 * saving state.
|
|
12953 * @type array
|
|
12954 * @default []
|
|
12955 */
|
|
12956 "aoStateSaveParams": [],
|
|
12957
|
|
12958 /**
|
|
12959 * Callbacks for modifying the settings that have been stored for state saving
|
|
12960 * prior to using the stored values to restore the state.
|
|
12961 * @type array
|
|
12962 * @default []
|
|
12963 */
|
|
12964 "aoStateLoadParams": [],
|
|
12965
|
|
12966 /**
|
|
12967 * Callbacks for operating on the settings object once the saved state has been
|
|
12968 * loaded
|
|
12969 * @type array
|
|
12970 * @default []
|
|
12971 */
|
|
12972 "aoStateLoaded": [],
|
|
12973
|
|
12974 /**
|
|
12975 * Cache the table ID for quick access
|
|
12976 * @type string
|
|
12977 * @default <i>Empty string</i>
|
|
12978 */
|
|
12979 "sTableId": "",
|
|
12980
|
|
12981 /**
|
|
12982 * The TABLE node for the main table
|
|
12983 * @type node
|
|
12984 * @default null
|
|
12985 */
|
|
12986 "nTable": null,
|
|
12987
|
|
12988 /**
|
|
12989 * Permanent ref to the thead element
|
|
12990 * @type node
|
|
12991 * @default null
|
|
12992 */
|
|
12993 "nTHead": null,
|
|
12994
|
|
12995 /**
|
|
12996 * Permanent ref to the tfoot element - if it exists
|
|
12997 * @type node
|
|
12998 * @default null
|
|
12999 */
|
|
13000 "nTFoot": null,
|
|
13001
|
|
13002 /**
|
|
13003 * Permanent ref to the tbody element
|
|
13004 * @type node
|
|
13005 * @default null
|
|
13006 */
|
|
13007 "nTBody": null,
|
|
13008
|
|
13009 /**
|
|
13010 * Cache the wrapper node (contains all DataTables controlled elements)
|
|
13011 * @type node
|
|
13012 * @default null
|
|
13013 */
|
|
13014 "nTableWrapper": null,
|
|
13015
|
|
13016 /**
|
|
13017 * Indicate if when using server-side processing the loading of data
|
|
13018 * should be deferred until the second draw.
|
|
13019 * Note that this parameter will be set by the initialisation routine. To
|
|
13020 * set a default use {@link DataTable.defaults}.
|
|
13021 * @type boolean
|
|
13022 * @default false
|
|
13023 */
|
|
13024 "bDeferLoading": false,
|
|
13025
|
|
13026 /**
|
|
13027 * Indicate if all required information has been read in
|
|
13028 * @type boolean
|
|
13029 * @default false
|
|
13030 */
|
|
13031 "bInitialised": false,
|
|
13032
|
|
13033 /**
|
|
13034 * Information about open rows. Each object in the array has the parameters
|
|
13035 * 'nTr' and 'nParent'
|
|
13036 * @type array
|
|
13037 * @default []
|
|
13038 */
|
|
13039 "aoOpenRows": [],
|
|
13040
|
|
13041 /**
|
|
13042 * Dictate the positioning of DataTables' control elements - see
|
|
13043 * {@link DataTable.model.oInit.sDom}.
|
|
13044 * Note that this parameter will be set by the initialisation routine. To
|
|
13045 * set a default use {@link DataTable.defaults}.
|
|
13046 * @type string
|
|
13047 * @default null
|
|
13048 */
|
|
13049 "sDom": null,
|
|
13050
|
|
13051 /**
|
|
13052 * Search delay (in mS)
|
|
13053 * @type integer
|
|
13054 * @default null
|
|
13055 */
|
|
13056 "searchDelay": null,
|
|
13057
|
|
13058 /**
|
|
13059 * Which type of pagination should be used.
|
|
13060 * Note that this parameter will be set by the initialisation routine. To
|
|
13061 * set a default use {@link DataTable.defaults}.
|
|
13062 * @type string
|
|
13063 * @default two_button
|
|
13064 */
|
|
13065 "sPaginationType": "two_button",
|
|
13066
|
|
13067 /**
|
|
13068 * The state duration (for `stateSave`) in seconds.
|
|
13069 * Note that this parameter will be set by the initialisation routine. To
|
|
13070 * set a default use {@link DataTable.defaults}.
|
|
13071 * @type int
|
|
13072 * @default 0
|
|
13073 */
|
|
13074 "iStateDuration": 0,
|
|
13075
|
|
13076 /**
|
|
13077 * Array of callback functions for state saving. Each array element is an
|
|
13078 * object with the following parameters:
|
|
13079 * <ul>
|
|
13080 * <li>function:fn - function to call. Takes two parameters, oSettings
|
|
13081 * and the JSON string to save that has been thus far created. Returns
|
|
13082 * a JSON string to be inserted into a json object
|
|
13083 * (i.e. '"param": [ 0, 1, 2]')</li>
|
|
13084 * <li>string:sName - name of callback</li>
|
|
13085 * </ul>
|
|
13086 * @type array
|
|
13087 * @default []
|
|
13088 */
|
|
13089 "aoStateSave": [],
|
|
13090
|
|
13091 /**
|
|
13092 * Array of callback functions for state loading. Each array element is an
|
|
13093 * object with the following parameters:
|
|
13094 * <ul>
|
|
13095 * <li>function:fn - function to call. Takes two parameters, oSettings
|
|
13096 * and the object stored. May return false to cancel state loading</li>
|
|
13097 * <li>string:sName - name of callback</li>
|
|
13098 * </ul>
|
|
13099 * @type array
|
|
13100 * @default []
|
|
13101 */
|
|
13102 "aoStateLoad": [],
|
|
13103
|
|
13104 /**
|
|
13105 * State that was saved. Useful for back reference
|
|
13106 * @type object
|
|
13107 * @default null
|
|
13108 */
|
|
13109 "oSavedState": null,
|
|
13110
|
|
13111 /**
|
|
13112 * State that was loaded. Useful for back reference
|
|
13113 * @type object
|
|
13114 * @default null
|
|
13115 */
|
|
13116 "oLoadedState": null,
|
|
13117
|
|
13118 /**
|
|
13119 * Source url for AJAX data for the table.
|
|
13120 * Note that this parameter will be set by the initialisation routine. To
|
|
13121 * set a default use {@link DataTable.defaults}.
|
|
13122 * @type string
|
|
13123 * @default null
|
|
13124 */
|
|
13125 "sAjaxSource": null,
|
|
13126
|
|
13127 /**
|
|
13128 * Property from a given object from which to read the table data from. This
|
|
13129 * can be an empty string (when not server-side processing), in which case
|
|
13130 * it is assumed an an array is given directly.
|
|
13131 * Note that this parameter will be set by the initialisation routine. To
|
|
13132 * set a default use {@link DataTable.defaults}.
|
|
13133 * @type string
|
|
13134 */
|
|
13135 "sAjaxDataProp": null,
|
|
13136
|
|
13137 /**
|
|
13138 * Note if draw should be blocked while getting data
|
|
13139 * @type boolean
|
|
13140 * @default true
|
|
13141 */
|
|
13142 "bAjaxDataGet": true,
|
|
13143
|
|
13144 /**
|
|
13145 * The last jQuery XHR object that was used for server-side data gathering.
|
|
13146 * This can be used for working with the XHR information in one of the
|
|
13147 * callbacks
|
|
13148 * @type object
|
|
13149 * @default null
|
|
13150 */
|
|
13151 "jqXHR": null,
|
|
13152
|
|
13153 /**
|
|
13154 * JSON returned from the server in the last Ajax request
|
|
13155 * @type object
|
|
13156 * @default undefined
|
|
13157 */
|
|
13158 "json": undefined,
|
|
13159
|
|
13160 /**
|
|
13161 * Data submitted as part of the last Ajax request
|
|
13162 * @type object
|
|
13163 * @default undefined
|
|
13164 */
|
|
13165 "oAjaxData": undefined,
|
|
13166
|
|
13167 /**
|
|
13168 * Function to get the server-side data.
|
|
13169 * Note that this parameter will be set by the initialisation routine. To
|
|
13170 * set a default use {@link DataTable.defaults}.
|
|
13171 * @type function
|
|
13172 */
|
|
13173 "fnServerData": null,
|
|
13174
|
|
13175 /**
|
|
13176 * Functions which are called prior to sending an Ajax request so extra
|
|
13177 * parameters can easily be sent to the server
|
|
13178 * @type array
|
|
13179 * @default []
|
|
13180 */
|
|
13181 "aoServerParams": [],
|
|
13182
|
|
13183 /**
|
|
13184 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
|
|
13185 * required).
|
|
13186 * Note that this parameter will be set by the initialisation routine. To
|
|
13187 * set a default use {@link DataTable.defaults}.
|
|
13188 * @type string
|
|
13189 */
|
|
13190 "sServerMethod": null,
|
|
13191
|
|
13192 /**
|
|
13193 * Format numbers for display.
|
|
13194 * Note that this parameter will be set by the initialisation routine. To
|
|
13195 * set a default use {@link DataTable.defaults}.
|
|
13196 * @type function
|
|
13197 */
|
|
13198 "fnFormatNumber": null,
|
|
13199
|
|
13200 /**
|
|
13201 * List of options that can be used for the user selectable length menu.
|
|
13202 * Note that this parameter will be set by the initialisation routine. To
|
|
13203 * set a default use {@link DataTable.defaults}.
|
|
13204 * @type array
|
|
13205 * @default []
|
|
13206 */
|
|
13207 "aLengthMenu": null,
|
|
13208
|
|
13209 /**
|
|
13210 * Counter for the draws that the table does. Also used as a tracker for
|
|
13211 * server-side processing
|
|
13212 * @type int
|
|
13213 * @default 0
|
|
13214 */
|
|
13215 "iDraw": 0,
|
|
13216
|
|
13217 /**
|
|
13218 * Indicate if a redraw is being done - useful for Ajax
|
|
13219 * @type boolean
|
|
13220 * @default false
|
|
13221 */
|
|
13222 "bDrawing": false,
|
|
13223
|
|
13224 /**
|
|
13225 * Draw index (iDraw) of the last error when parsing the returned data
|
|
13226 * @type int
|
|
13227 * @default -1
|
|
13228 */
|
|
13229 "iDrawError": -1,
|
|
13230
|
|
13231 /**
|
|
13232 * Paging display length
|
|
13233 * @type int
|
|
13234 * @default 10
|
|
13235 */
|
|
13236 "_iDisplayLength": 10,
|
|
13237
|
|
13238 /**
|
|
13239 * Paging start point - aiDisplay index
|
|
13240 * @type int
|
|
13241 * @default 0
|
|
13242 */
|
|
13243 "_iDisplayStart": 0,
|
|
13244
|
|
13245 /**
|
|
13246 * Server-side processing - number of records in the result set
|
|
13247 * (i.e. before filtering), Use fnRecordsTotal rather than
|
|
13248 * this property to get the value of the number of records, regardless of
|
|
13249 * the server-side processing setting.
|
|
13250 * @type int
|
|
13251 * @default 0
|
|
13252 * @private
|
|
13253 */
|
|
13254 "_iRecordsTotal": 0,
|
|
13255
|
|
13256 /**
|
|
13257 * Server-side processing - number of records in the current display set
|
|
13258 * (i.e. after filtering). Use fnRecordsDisplay rather than
|
|
13259 * this property to get the value of the number of records, regardless of
|
|
13260 * the server-side processing setting.
|
|
13261 * @type boolean
|
|
13262 * @default 0
|
|
13263 * @private
|
|
13264 */
|
|
13265 "_iRecordsDisplay": 0,
|
|
13266
|
|
13267 /**
|
|
13268 * Flag to indicate if jQuery UI marking and classes should be used.
|
|
13269 * Note that this parameter will be set by the initialisation routine. To
|
|
13270 * set a default use {@link DataTable.defaults}.
|
|
13271 * @type boolean
|
|
13272 */
|
|
13273 "bJUI": null,
|
|
13274
|
|
13275 /**
|
|
13276 * The classes to use for the table
|
|
13277 * @type object
|
|
13278 * @default {}
|
|
13279 */
|
|
13280 "oClasses": {},
|
|
13281
|
|
13282 /**
|
|
13283 * Flag attached to the settings object so you can check in the draw
|
|
13284 * callback if filtering has been done in the draw. Deprecated in favour of
|
|
13285 * events.
|
|
13286 * @type boolean
|
|
13287 * @default false
|
|
13288 * @deprecated
|
|
13289 */
|
|
13290 "bFiltered": false,
|
|
13291
|
|
13292 /**
|
|
13293 * Flag attached to the settings object so you can check in the draw
|
|
13294 * callback if sorting has been done in the draw. Deprecated in favour of
|
|
13295 * events.
|
|
13296 * @type boolean
|
|
13297 * @default false
|
|
13298 * @deprecated
|
|
13299 */
|
|
13300 "bSorted": false,
|
|
13301
|
|
13302 /**
|
|
13303 * Indicate that if multiple rows are in the header and there is more than
|
|
13304 * one unique cell per column, if the top one (true) or bottom one (false)
|
|
13305 * should be used for sorting / title by DataTables.
|
|
13306 * Note that this parameter will be set by the initialisation routine. To
|
|
13307 * set a default use {@link DataTable.defaults}.
|
|
13308 * @type boolean
|
|
13309 */
|
|
13310 "bSortCellsTop": null,
|
|
13311
|
|
13312 /**
|
|
13313 * Initialisation object that is used for the table
|
|
13314 * @type object
|
|
13315 * @default null
|
|
13316 */
|
|
13317 "oInit": null,
|
|
13318
|
|
13319 /**
|
|
13320 * Destroy callback functions - for plug-ins to attach themselves to the
|
|
13321 * destroy so they can clean up markup and events.
|
|
13322 * @type array
|
|
13323 * @default []
|
|
13324 */
|
|
13325 "aoDestroyCallback": [],
|
|
13326
|
|
13327
|
|
13328 /**
|
|
13329 * Get the number of records in the current record set, before filtering
|
|
13330 * @type function
|
|
13331 */
|
|
13332 "fnRecordsTotal": function ()
|
|
13333 {
|
|
13334 return _fnDataSource( this ) == 'ssp' ?
|
|
13335 this._iRecordsTotal * 1 :
|
|
13336 this.aiDisplayMaster.length;
|
|
13337 },
|
|
13338
|
|
13339 /**
|
|
13340 * Get the number of records in the current record set, after filtering
|
|
13341 * @type function
|
|
13342 */
|
|
13343 "fnRecordsDisplay": function ()
|
|
13344 {
|
|
13345 return _fnDataSource( this ) == 'ssp' ?
|
|
13346 this._iRecordsDisplay * 1 :
|
|
13347 this.aiDisplay.length;
|
|
13348 },
|
|
13349
|
|
13350 /**
|
|
13351 * Get the display end point - aiDisplay index
|
|
13352 * @type function
|
|
13353 */
|
|
13354 "fnDisplayEnd": function ()
|
|
13355 {
|
|
13356 var
|
|
13357 len = this._iDisplayLength,
|
|
13358 start = this._iDisplayStart,
|
|
13359 calc = start + len,
|
|
13360 records = this.aiDisplay.length,
|
|
13361 features = this.oFeatures,
|
|
13362 paginate = features.bPaginate;
|
|
13363
|
|
13364 if ( features.bServerSide ) {
|
|
13365 return paginate === false || len === -1 ?
|
|
13366 start + records :
|
|
13367 Math.min( start+len, this._iRecordsDisplay );
|
|
13368 }
|
|
13369 else {
|
|
13370 return ! paginate || calc>records || len===-1 ?
|
|
13371 records :
|
|
13372 calc;
|
|
13373 }
|
|
13374 },
|
|
13375
|
|
13376 /**
|
|
13377 * The DataTables object for this table
|
|
13378 * @type object
|
|
13379 * @default null
|
|
13380 */
|
|
13381 "oInstance": null,
|
|
13382
|
|
13383 /**
|
|
13384 * Unique identifier for each instance of the DataTables object. If there
|
|
13385 * is an ID on the table node, then it takes that value, otherwise an
|
|
13386 * incrementing internal counter is used.
|
|
13387 * @type string
|
|
13388 * @default null
|
|
13389 */
|
|
13390 "sInstance": null,
|
|
13391
|
|
13392 /**
|
|
13393 * tabindex attribute value that is added to DataTables control elements, allowing
|
|
13394 * keyboard navigation of the table and its controls.
|
|
13395 */
|
|
13396 "iTabIndex": 0,
|
|
13397
|
|
13398 /**
|
|
13399 * DIV container for the footer scrolling table if scrolling
|
|
13400 */
|
|
13401 "nScrollHead": null,
|
|
13402
|
|
13403 /**
|
|
13404 * DIV container for the footer scrolling table if scrolling
|
|
13405 */
|
|
13406 "nScrollFoot": null,
|
|
13407
|
|
13408 /**
|
|
13409 * Last applied sort
|
|
13410 * @type array
|
|
13411 * @default []
|
|
13412 */
|
|
13413 "aLastSort": [],
|
|
13414
|
|
13415 /**
|
|
13416 * Stored plug-in instances
|
|
13417 * @type object
|
|
13418 * @default {}
|
|
13419 */
|
|
13420 "oPlugins": {}
|
|
13421 };
|
|
13422
|
|
13423 /**
|
|
13424 * Extension object for DataTables that is used to provide all extension
|
|
13425 * options.
|
|
13426 *
|
|
13427 * Note that the `DataTable.ext` object is available through
|
|
13428 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
|
|
13429 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
|
|
13430 * @namespace
|
|
13431 * @extends DataTable.models.ext
|
|
13432 */
|
|
13433
|
|
13434
|
|
13435 /**
|
|
13436 * DataTables extensions
|
|
13437 *
|
|
13438 * This namespace acts as a collection area for plug-ins that can be used to
|
|
13439 * extend DataTables capabilities. Indeed many of the build in methods
|
|
13440 * use this method to provide their own capabilities (sorting methods for
|
|
13441 * example).
|
|
13442 *
|
|
13443 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
|
|
13444 * reasons
|
|
13445 *
|
|
13446 * @namespace
|
|
13447 */
|
|
13448 DataTable.ext = _ext = {
|
|
13449 /**
|
|
13450 * Element class names
|
|
13451 *
|
|
13452 * @type object
|
|
13453 * @default {}
|
|
13454 */
|
|
13455 classes: {},
|
|
13456
|
|
13457
|
|
13458 /**
|
|
13459 * Error reporting.
|
|
13460 *
|
|
13461 * How should DataTables report an error. Can take the value 'alert' or
|
|
13462 * 'throw'
|
|
13463 *
|
|
13464 * @type string
|
|
13465 * @default alert
|
|
13466 */
|
|
13467 errMode: "alert",
|
|
13468
|
|
13469
|
|
13470 /**
|
|
13471 * Feature plug-ins.
|
|
13472 *
|
|
13473 * This is an array of objects which describe the feature plug-ins that are
|
|
13474 * available to DataTables. These feature plug-ins are then available for
|
|
13475 * use through the `dom` initialisation option.
|
|
13476 *
|
|
13477 * Each feature plug-in is described by an object which must have the
|
|
13478 * following properties:
|
|
13479 *
|
|
13480 * * `fnInit` - function that is used to initialise the plug-in,
|
|
13481 * * `cFeature` - a character so the feature can be enabled by the `dom`
|
|
13482 * instillation option. This is case sensitive.
|
|
13483 *
|
|
13484 * The `fnInit` function has the following input parameters:
|
|
13485 *
|
|
13486 * 1. `{object}` DataTables settings object: see
|
|
13487 * {@link DataTable.models.oSettings}
|
|
13488 *
|
|
13489 * And the following return is expected:
|
|
13490 *
|
|
13491 * * {node|null} The element which contains your feature. Note that the
|
|
13492 * return may also be void if your plug-in does not require to inject any
|
|
13493 * DOM elements into DataTables control (`dom`) - for example this might
|
|
13494 * be useful when developing a plug-in which allows table control via
|
|
13495 * keyboard entry
|
|
13496 *
|
|
13497 * @type array
|
|
13498 *
|
|
13499 * @example
|
|
13500 * $.fn.dataTable.ext.features.push( {
|
|
13501 * "fnInit": function( oSettings ) {
|
|
13502 * return new TableTools( { "oDTSettings": oSettings } );
|
|
13503 * },
|
|
13504 * "cFeature": "T"
|
|
13505 * } );
|
|
13506 */
|
|
13507 feature: [],
|
|
13508
|
|
13509
|
|
13510 /**
|
|
13511 * Row searching.
|
|
13512 *
|
|
13513 * This method of searching is complimentary to the default type based
|
|
13514 * searching, and a lot more comprehensive as it allows you complete control
|
|
13515 * over the searching logic. Each element in this array is a function
|
|
13516 * (parameters described below) that is called for every row in the table,
|
|
13517 * and your logic decides if it should be included in the searching data set
|
|
13518 * or not.
|
|
13519 *
|
|
13520 * Searching functions have the following input parameters:
|
|
13521 *
|
|
13522 * 1. `{object}` DataTables settings object: see
|
|
13523 * {@link DataTable.models.oSettings}
|
|
13524 * 2. `{array|object}` Data for the row to be processed (same as the
|
|
13525 * original format that was passed in as the data source, or an array
|
|
13526 * from a DOM data source
|
|
13527 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
|
|
13528 * can be useful to retrieve the `TR` element if you need DOM interaction.
|
|
13529 *
|
|
13530 * And the following return is expected:
|
|
13531 *
|
|
13532 * * {boolean} Include the row in the searched result set (true) or not
|
|
13533 * (false)
|
|
13534 *
|
|
13535 * Note that as with the main search ability in DataTables, technically this
|
|
13536 * is "filtering", since it is subtractive. However, for consistency in
|
|
13537 * naming we call it searching here.
|
|
13538 *
|
|
13539 * @type array
|
|
13540 * @default []
|
|
13541 *
|
|
13542 * @example
|
|
13543 * // The following example shows custom search being applied to the
|
|
13544 * // fourth column (i.e. the data[3] index) based on two input values
|
|
13545 * // from the end-user, matching the data in a certain range.
|
|
13546 * $.fn.dataTable.ext.search.push(
|
|
13547 * function( settings, data, dataIndex ) {
|
|
13548 * var min = document.getElementById('min').value * 1;
|
|
13549 * var max = document.getElementById('max').value * 1;
|
|
13550 * var version = data[3] == "-" ? 0 : data[3]*1;
|
|
13551 *
|
|
13552 * if ( min == "" && max == "" ) {
|
|
13553 * return true;
|
|
13554 * }
|
|
13555 * else if ( min == "" && version < max ) {
|
|
13556 * return true;
|
|
13557 * }
|
|
13558 * else if ( min < version && "" == max ) {
|
|
13559 * return true;
|
|
13560 * }
|
|
13561 * else if ( min < version && version < max ) {
|
|
13562 * return true;
|
|
13563 * }
|
|
13564 * return false;
|
|
13565 * }
|
|
13566 * );
|
|
13567 */
|
|
13568 search: [],
|
|
13569
|
|
13570
|
|
13571 /**
|
|
13572 * Internal functions, exposed for used in plug-ins.
|
|
13573 *
|
|
13574 * Please note that you should not need to use the internal methods for
|
|
13575 * anything other than a plug-in (and even then, try to avoid if possible).
|
|
13576 * The internal function may change between releases.
|
|
13577 *
|
|
13578 * @type object
|
|
13579 * @default {}
|
|
13580 */
|
|
13581 internal: {},
|
|
13582
|
|
13583
|
|
13584 /**
|
|
13585 * Legacy configuration options. Enable and disable legacy options that
|
|
13586 * are available in DataTables.
|
|
13587 *
|
|
13588 * @type object
|
|
13589 */
|
|
13590 legacy: {
|
|
13591 /**
|
|
13592 * Enable / disable DataTables 1.9 compatible server-side processing
|
|
13593 * requests
|
|
13594 *
|
|
13595 * @type boolean
|
|
13596 * @default null
|
|
13597 */
|
|
13598 ajax: null
|
|
13599 },
|
|
13600
|
|
13601
|
|
13602 /**
|
|
13603 * Pagination plug-in methods.
|
|
13604 *
|
|
13605 * Each entry in this object is a function and defines which buttons should
|
|
13606 * be shown by the pagination rendering method that is used for the table:
|
|
13607 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
|
|
13608 * buttons are displayed in the document, while the functions here tell it
|
|
13609 * what buttons to display. This is done by returning an array of button
|
|
13610 * descriptions (what each button will do).
|
|
13611 *
|
|
13612 * Pagination types (the four built in options and any additional plug-in
|
|
13613 * options defined here) can be used through the `paginationType`
|
|
13614 * initialisation parameter.
|
|
13615 *
|
|
13616 * The functions defined take two parameters:
|
|
13617 *
|
|
13618 * 1. `{int} page` The current page index
|
|
13619 * 2. `{int} pages` The number of pages in the table
|
|
13620 *
|
|
13621 * Each function is expected to return an array where each element of the
|
|
13622 * array can be one of:
|
|
13623 *
|
|
13624 * * `first` - Jump to first page when activated
|
|
13625 * * `last` - Jump to last page when activated
|
|
13626 * * `previous` - Show previous page when activated
|
|
13627 * * `next` - Show next page when activated
|
|
13628 * * `{int}` - Show page of the index given
|
|
13629 * * `{array}` - A nested array containing the above elements to add a
|
|
13630 * containing 'DIV' element (might be useful for styling).
|
|
13631 *
|
|
13632 * Note that DataTables v1.9- used this object slightly differently whereby
|
|
13633 * an object with two functions would be defined for each plug-in. That
|
|
13634 * ability is still supported by DataTables 1.10+ to provide backwards
|
|
13635 * compatibility, but this option of use is now decremented and no longer
|
|
13636 * documented in DataTables 1.10+.
|
|
13637 *
|
|
13638 * @type object
|
|
13639 * @default {}
|
|
13640 *
|
|
13641 * @example
|
|
13642 * // Show previous, next and current page buttons only
|
|
13643 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
|
|
13644 * return [ 'previous', page, 'next' ];
|
|
13645 * };
|
|
13646 */
|
|
13647 pager: {},
|
|
13648
|
|
13649
|
|
13650 renderer: {
|
|
13651 pageButton: {},
|
|
13652 header: {}
|
|
13653 },
|
|
13654
|
|
13655
|
|
13656 /**
|
|
13657 * Ordering plug-ins - custom data source
|
|
13658 *
|
|
13659 * The extension options for ordering of data available here is complimentary
|
|
13660 * to the default type based ordering that DataTables typically uses. It
|
|
13661 * allows much greater control over the the data that is being used to
|
|
13662 * order a column, but is necessarily therefore more complex.
|
|
13663 *
|
|
13664 * This type of ordering is useful if you want to do ordering based on data
|
|
13665 * live from the DOM (for example the contents of an 'input' element) rather
|
|
13666 * than just the static string that DataTables knows of.
|
|
13667 *
|
|
13668 * The way these plug-ins work is that you create an array of the values you
|
|
13669 * wish to be ordering for the column in question and then return that
|
|
13670 * array. The data in the array much be in the index order of the rows in
|
|
13671 * the table (not the currently ordering order!). Which order data gathering
|
|
13672 * function is run here depends on the `dt-init columns.orderDataType`
|
|
13673 * parameter that is used for the column (if any).
|
|
13674 *
|
|
13675 * The functions defined take two parameters:
|
|
13676 *
|
|
13677 * 1. `{object}` DataTables settings object: see
|
|
13678 * {@link DataTable.models.oSettings}
|
|
13679 * 2. `{int}` Target column index
|
|
13680 *
|
|
13681 * Each function is expected to return an array:
|
|
13682 *
|
|
13683 * * `{array}` Data for the column to be ordering upon
|
|
13684 *
|
|
13685 * @type array
|
|
13686 *
|
|
13687 * @example
|
|
13688 * // Ordering using `input` node values
|
|
13689 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
|
|
13690 * {
|
|
13691 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
|
|
13692 * return $('input', td).val();
|
|
13693 * } );
|
|
13694 * }
|
|
13695 */
|
|
13696 order: {},
|
|
13697
|
|
13698
|
|
13699 /**
|
|
13700 * Type based plug-ins.
|
|
13701 *
|
|
13702 * Each column in DataTables has a type assigned to it, either by automatic
|
|
13703 * detection or by direct assignment using the `type` option for the column.
|
|
13704 * The type of a column will effect how it is ordering and search (plug-ins
|
|
13705 * can also make use of the column type if required).
|
|
13706 *
|
|
13707 * @namespace
|
|
13708 */
|
|
13709 type: {
|
|
13710 /**
|
|
13711 * Type detection functions.
|
|
13712 *
|
|
13713 * The functions defined in this object are used to automatically detect
|
|
13714 * a column's type, making initialisation of DataTables super easy, even
|
|
13715 * when complex data is in the table.
|
|
13716 *
|
|
13717 * The functions defined take two parameters:
|
|
13718 *
|
|
13719 * 1. `{*}` Data from the column cell to be analysed
|
|
13720 * 2. `{settings}` DataTables settings object. This can be used to
|
|
13721 * perform context specific type detection - for example detection
|
|
13722 * based on language settings such as using a comma for a decimal
|
|
13723 * place. Generally speaking the options from the settings will not
|
|
13724 * be required
|
|
13725 *
|
|
13726 * Each function is expected to return:
|
|
13727 *
|
|
13728 * * `{string|null}` Data type detected, or null if unknown (and thus
|
|
13729 * pass it on to the other type detection functions.
|
|
13730 *
|
|
13731 * @type array
|
|
13732 *
|
|
13733 * @example
|
|
13734 * // Currency type detection plug-in:
|
|
13735 * $.fn.dataTable.ext.type.detect.push(
|
|
13736 * function ( data, settings ) {
|
|
13737 * // Check the numeric part
|
|
13738 * if ( ! $.isNumeric( data.substring(1) ) ) {
|
|
13739 * return null;
|
|
13740 * }
|
|
13741 *
|
|
13742 * // Check prefixed by currency
|
|
13743 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) {
|
|
13744 * return 'currency';
|
|
13745 * }
|
|
13746 * return null;
|
|
13747 * }
|
|
13748 * );
|
|
13749 */
|
|
13750 detect: [],
|
|
13751
|
|
13752
|
|
13753 /**
|
|
13754 * Type based search formatting.
|
|
13755 *
|
|
13756 * The type based searching functions can be used to pre-format the
|
|
13757 * data to be search on. For example, it can be used to strip HTML
|
|
13758 * tags or to de-format telephone numbers for numeric only searching.
|
|
13759 *
|
|
13760 * Note that is a search is not defined for a column of a given type,
|
|
13761 * no search formatting will be performed.
|
|
13762 *
|
|
13763 * Pre-processing of searching data plug-ins - When you assign the sType
|
|
13764 * for a column (or have it automatically detected for you by DataTables
|
|
13765 * or a type detection plug-in), you will typically be using this for
|
|
13766 * custom sorting, but it can also be used to provide custom searching
|
|
13767 * by allowing you to pre-processing the data and returning the data in
|
|
13768 * the format that should be searched upon. This is done by adding
|
|
13769 * functions this object with a parameter name which matches the sType
|
|
13770 * for that target column. This is the corollary of <i>afnSortData</i>
|
|
13771 * for searching data.
|
|
13772 *
|
|
13773 * The functions defined take a single parameter:
|
|
13774 *
|
|
13775 * 1. `{*}` Data from the column cell to be prepared for searching
|
|
13776 *
|
|
13777 * Each function is expected to return:
|
|
13778 *
|
|
13779 * * `{string|null}` Formatted string that will be used for the searching.
|
|
13780 *
|
|
13781 * @type object
|
|
13782 * @default {}
|
|
13783 *
|
|
13784 * @example
|
|
13785 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
|
|
13786 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
|
|
13787 * }
|
|
13788 */
|
|
13789 search: {},
|
|
13790
|
|
13791
|
|
13792 /**
|
|
13793 * Type based ordering.
|
|
13794 *
|
|
13795 * The column type tells DataTables what ordering to apply to the table
|
|
13796 * when a column is sorted upon. The order for each type that is defined,
|
|
13797 * is defined by the functions available in this object.
|
|
13798 *
|
|
13799 * Each ordering option can be described by three properties added to
|
|
13800 * this object:
|
|
13801 *
|
|
13802 * * `{type}-pre` - Pre-formatting function
|
|
13803 * * `{type}-asc` - Ascending order function
|
|
13804 * * `{type}-desc` - Descending order function
|
|
13805 *
|
|
13806 * All three can be used together, only `{type}-pre` or only
|
|
13807 * `{type}-asc` and `{type}-desc` together. It is generally recommended
|
|
13808 * that only `{type}-pre` is used, as this provides the optimal
|
|
13809 * implementation in terms of speed, although the others are provided
|
|
13810 * for compatibility with existing Javascript sort functions.
|
|
13811 *
|
|
13812 * `{type}-pre`: Functions defined take a single parameter:
|
|
13813 *
|
|
13814 * 1. `{*}` Data from the column cell to be prepared for ordering
|
|
13815 *
|
|
13816 * And return:
|
|
13817 *
|
|
13818 * * `{*}` Data to be sorted upon
|
|
13819 *
|
|
13820 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
|
|
13821 * functions, taking two parameters:
|
|
13822 *
|
|
13823 * 1. `{*}` Data to compare to the second parameter
|
|
13824 * 2. `{*}` Data to compare to the first parameter
|
|
13825 *
|
|
13826 * And returning:
|
|
13827 *
|
|
13828 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
|
|
13829 * than the second parameter, ===0 if the two parameters are equal and
|
|
13830 * >0 if the first parameter should be sorted height than the second
|
|
13831 * parameter.
|
|
13832 *
|
|
13833 * @type object
|
|
13834 * @default {}
|
|
13835 *
|
|
13836 * @example
|
|
13837 * // Numeric ordering of formatted numbers with a pre-formatter
|
|
13838 * $.extend( $.fn.dataTable.ext.type.order, {
|
|
13839 * "string-pre": function(x) {
|
|
13840 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
|
|
13841 * return parseFloat( a );
|
|
13842 * }
|
|
13843 * } );
|
|
13844 *
|
|
13845 * @example
|
|
13846 * // Case-sensitive string ordering, with no pre-formatting method
|
|
13847 * $.extend( $.fn.dataTable.ext.order, {
|
|
13848 * "string-case-asc": function(x,y) {
|
|
13849 * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
|
13850 * },
|
|
13851 * "string-case-desc": function(x,y) {
|
|
13852 * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
|
|
13853 * }
|
|
13854 * } );
|
|
13855 */
|
|
13856 order: {}
|
|
13857 },
|
|
13858
|
|
13859 /**
|
|
13860 * Unique DataTables instance counter
|
|
13861 *
|
|
13862 * @type int
|
|
13863 * @private
|
|
13864 */
|
|
13865 _unique: 0,
|
|
13866
|
|
13867
|
|
13868 //
|
|
13869 // Depreciated
|
|
13870 // The following properties are retained for backwards compatiblity only.
|
|
13871 // The should not be used in new projects and will be removed in a future
|
|
13872 // version
|
|
13873 //
|
|
13874
|
|
13875 /**
|
|
13876 * Version check function.
|
|
13877 * @type function
|
|
13878 * @depreciated Since 1.10
|
|
13879 */
|
|
13880 fnVersionCheck: DataTable.fnVersionCheck,
|
|
13881
|
|
13882
|
|
13883 /**
|
|
13884 * Index for what 'this' index API functions should use
|
|
13885 * @type int
|
|
13886 * @deprecated Since v1.10
|
|
13887 */
|
|
13888 iApiIndex: 0,
|
|
13889
|
|
13890
|
|
13891 /**
|
|
13892 * jQuery UI class container
|
|
13893 * @type object
|
|
13894 * @deprecated Since v1.10
|
|
13895 */
|
|
13896 oJUIClasses: {},
|
|
13897
|
|
13898
|
|
13899 /**
|
|
13900 * Software version
|
|
13901 * @type string
|
|
13902 * @deprecated Since v1.10
|
|
13903 */
|
|
13904 sVersion: DataTable.version
|
|
13905 };
|
|
13906
|
|
13907
|
|
13908 //
|
|
13909 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
|
|
13910 //
|
|
13911 $.extend( _ext, {
|
|
13912 afnFiltering: _ext.search,
|
|
13913 aTypes: _ext.type.detect,
|
|
13914 ofnSearch: _ext.type.search,
|
|
13915 oSort: _ext.type.order,
|
|
13916 afnSortData: _ext.order,
|
|
13917 aoFeatures: _ext.feature,
|
|
13918 oApi: _ext.internal,
|
|
13919 oStdClasses: _ext.classes,
|
|
13920 oPagination: _ext.pager
|
|
13921 } );
|
|
13922
|
|
13923
|
|
13924 $.extend( DataTable.ext.classes, {
|
|
13925 "sTable": "dataTable",
|
|
13926 "sNoFooter": "no-footer",
|
|
13927
|
|
13928 /* Paging buttons */
|
|
13929 "sPageButton": "paginate_button",
|
|
13930 "sPageButtonActive": "current",
|
|
13931 "sPageButtonDisabled": "disabled",
|
|
13932
|
|
13933 /* Striping classes */
|
|
13934 "sStripeOdd": "odd",
|
|
13935 "sStripeEven": "even",
|
|
13936
|
|
13937 /* Empty row */
|
|
13938 "sRowEmpty": "dataTables_empty",
|
|
13939
|
|
13940 /* Features */
|
|
13941 "sWrapper": "dataTables_wrapper",
|
|
13942 "sFilter": "dataTables_filter",
|
|
13943 "sInfo": "dataTables_info",
|
|
13944 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
|
|
13945 "sLength": "dataTables_length",
|
|
13946 "sProcessing": "dataTables_processing",
|
|
13947
|
|
13948 /* Sorting */
|
|
13949 "sSortAsc": "sorting_asc",
|
|
13950 "sSortDesc": "sorting_desc",
|
|
13951 "sSortable": "sorting", /* Sortable in both directions */
|
|
13952 "sSortableAsc": "sorting_asc_disabled",
|
|
13953 "sSortableDesc": "sorting_desc_disabled",
|
|
13954 "sSortableNone": "sorting_disabled",
|
|
13955 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
|
|
13956
|
|
13957 /* Filtering */
|
|
13958 "sFilterInput": "",
|
|
13959
|
|
13960 /* Page length */
|
|
13961 "sLengthSelect": "",
|
|
13962
|
|
13963 /* Scrolling */
|
|
13964 "sScrollWrapper": "dataTables_scroll",
|
|
13965 "sScrollHead": "dataTables_scrollHead",
|
|
13966 "sScrollHeadInner": "dataTables_scrollHeadInner",
|
|
13967 "sScrollBody": "dataTables_scrollBody",
|
|
13968 "sScrollFoot": "dataTables_scrollFoot",
|
|
13969 "sScrollFootInner": "dataTables_scrollFootInner",
|
|
13970
|
|
13971 /* Misc */
|
|
13972 "sHeaderTH": "",
|
|
13973 "sFooterTH": "",
|
|
13974
|
|
13975 // Deprecated
|
|
13976 "sSortJUIAsc": "",
|
|
13977 "sSortJUIDesc": "",
|
|
13978 "sSortJUI": "",
|
|
13979 "sSortJUIAscAllowed": "",
|
|
13980 "sSortJUIDescAllowed": "",
|
|
13981 "sSortJUIWrapper": "",
|
|
13982 "sSortIcon": "",
|
|
13983 "sJUIHeader": "",
|
|
13984 "sJUIFooter": ""
|
|
13985 } );
|
|
13986
|
|
13987
|
|
13988 (function() {
|
|
13989
|
|
13990 // Reused strings for better compression. Closure compiler appears to have a
|
|
13991 // weird edge case where it is trying to expand strings rather than use the
|
|
13992 // variable version. This results in about 200 bytes being added, for very
|
|
13993 // little preference benefit since it this run on script load only.
|
|
13994 var _empty = '';
|
|
13995 _empty = '';
|
|
13996
|
|
13997 var _stateDefault = _empty + 'ui-state-default';
|
|
13998 var _sortIcon = _empty + 'css_right ui-icon ui-icon-';
|
|
13999 var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
|
|
14000
|
|
14001 $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
|
|
14002 /* Full numbers paging buttons */
|
|
14003 "sPageButton": "fg-button ui-button "+_stateDefault,
|
|
14004 "sPageButtonActive": "ui-state-disabled",
|
|
14005 "sPageButtonDisabled": "ui-state-disabled",
|
|
14006
|
|
14007 /* Features */
|
|
14008 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
|
|
14009 "ui-buttonset-multi paging_", /* Note that the type is postfixed */
|
|
14010
|
|
14011 /* Sorting */
|
|
14012 "sSortAsc": _stateDefault+" sorting_asc",
|
|
14013 "sSortDesc": _stateDefault+" sorting_desc",
|
|
14014 "sSortable": _stateDefault+" sorting",
|
|
14015 "sSortableAsc": _stateDefault+" sorting_asc_disabled",
|
|
14016 "sSortableDesc": _stateDefault+" sorting_desc_disabled",
|
|
14017 "sSortableNone": _stateDefault+" sorting_disabled",
|
|
14018 "sSortJUIAsc": _sortIcon+"triangle-1-n",
|
|
14019 "sSortJUIDesc": _sortIcon+"triangle-1-s",
|
|
14020 "sSortJUI": _sortIcon+"carat-2-n-s",
|
|
14021 "sSortJUIAscAllowed": _sortIcon+"carat-1-n",
|
|
14022 "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
|
|
14023 "sSortJUIWrapper": "DataTables_sort_wrapper",
|
|
14024 "sSortIcon": "DataTables_sort_icon",
|
|
14025
|
|
14026 /* Scrolling */
|
|
14027 "sScrollHead": "dataTables_scrollHead "+_stateDefault,
|
|
14028 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
|
|
14029
|
|
14030 /* Misc */
|
|
14031 "sHeaderTH": _stateDefault,
|
|
14032 "sFooterTH": _stateDefault,
|
|
14033 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
|
|
14034 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
|
|
14035 } );
|
|
14036
|
|
14037 }());
|
|
14038
|
|
14039
|
|
14040
|
|
14041 var extPagination = DataTable.ext.pager;
|
|
14042
|
|
14043 function _numbers ( page, pages ) {
|
|
14044 var
|
|
14045 numbers = [],
|
|
14046 buttons = extPagination.numbers_length,
|
|
14047 half = Math.floor( buttons / 2 ),
|
|
14048 i = 1;
|
|
14049
|
|
14050 if ( pages <= buttons ) {
|
|
14051 numbers = _range( 0, pages );
|
|
14052 }
|
|
14053 else if ( page <= half ) {
|
|
14054 numbers = _range( 0, buttons-2 );
|
|
14055 numbers.push( 'ellipsis' );
|
|
14056 numbers.push( pages-1 );
|
|
14057 }
|
|
14058 else if ( page >= pages - 1 - half ) {
|
|
14059 numbers = _range( pages-(buttons-2), pages );
|
|
14060 numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
|
|
14061 numbers.splice( 0, 0, 0 );
|
|
14062 }
|
|
14063 else {
|
|
14064 numbers = _range( page-1, page+2 );
|
|
14065 numbers.push( 'ellipsis' );
|
|
14066 numbers.push( pages-1 );
|
|
14067 numbers.splice( 0, 0, 'ellipsis' );
|
|
14068 numbers.splice( 0, 0, 0 );
|
|
14069 }
|
|
14070
|
|
14071 numbers.DT_el = 'span';
|
|
14072 return numbers;
|
|
14073 }
|
|
14074
|
|
14075
|
|
14076 $.extend( extPagination, {
|
|
14077 simple: function ( page, pages ) {
|
|
14078 return [ 'previous', 'next' ];
|
|
14079 },
|
|
14080
|
|
14081 full: function ( page, pages ) {
|
|
14082 return [ 'first', 'previous', 'next', 'last' ];
|
|
14083 },
|
|
14084
|
|
14085 simple_numbers: function ( page, pages ) {
|
|
14086 return [ 'previous', _numbers(page, pages), 'next' ];
|
|
14087 },
|
|
14088
|
|
14089 full_numbers: function ( page, pages ) {
|
|
14090 return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
|
|
14091 },
|
|
14092
|
|
14093 // For testing and plug-ins to use
|
|
14094 _numbers: _numbers,
|
|
14095 numbers_length: 7
|
|
14096 } );
|
|
14097
|
|
14098
|
|
14099 $.extend( true, DataTable.ext.renderer, {
|
|
14100 pageButton: {
|
|
14101 _: function ( settings, host, idx, buttons, page, pages ) {
|
|
14102 var classes = settings.oClasses;
|
|
14103 var lang = settings.oLanguage.oPaginate;
|
|
14104 var btnDisplay, btnClass, counter=0;
|
|
14105
|
|
14106 var attach = function( container, buttons ) {
|
|
14107 var i, ien, node, button;
|
|
14108 var clickHandler = function ( e ) {
|
|
14109 _fnPageChange( settings, e.data.action, true );
|
|
14110 };
|
|
14111
|
|
14112 for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
|
|
14113 button = buttons[i];
|
|
14114
|
|
14115 if ( $.isArray( button ) ) {
|
|
14116 var inner = $( '<'+(button.DT_el || 'div')+'/>' )
|
|
14117 .appendTo( container );
|
|
14118 attach( inner, button );
|
|
14119 }
|
|
14120 else {
|
|
14121 btnDisplay = '';
|
|
14122 btnClass = '';
|
|
14123
|
|
14124 switch ( button ) {
|
|
14125 case 'ellipsis':
|
|
14126 container.append('<span>…</span>');
|
|
14127 break;
|
|
14128
|
|
14129 case 'first':
|
|
14130 btnDisplay = lang.sFirst;
|
|
14131 btnClass = button + (page > 0 ?
|
|
14132 '' : ' '+classes.sPageButtonDisabled);
|
|
14133 break;
|
|
14134
|
|
14135 case 'previous':
|
|
14136 btnDisplay = lang.sPrevious;
|
|
14137 btnClass = button + (page > 0 ?
|
|
14138 '' : ' '+classes.sPageButtonDisabled);
|
|
14139 break;
|
|
14140
|
|
14141 case 'next':
|
|
14142 btnDisplay = lang.sNext;
|
|
14143 btnClass = button + (page < pages-1 ?
|
|
14144 '' : ' '+classes.sPageButtonDisabled);
|
|
14145 break;
|
|
14146
|
|
14147 case 'last':
|
|
14148 btnDisplay = lang.sLast;
|
|
14149 btnClass = button + (page < pages-1 ?
|
|
14150 '' : ' '+classes.sPageButtonDisabled);
|
|
14151 break;
|
|
14152
|
|
14153 default:
|
|
14154 btnDisplay = button + 1;
|
|
14155 btnClass = page === button ?
|
|
14156 classes.sPageButtonActive : '';
|
|
14157 break;
|
|
14158 }
|
|
14159
|
|
14160 if ( btnDisplay ) {
|
|
14161 node = $('<a>', {
|
|
14162 'class': classes.sPageButton+' '+btnClass,
|
|
14163 'aria-controls': settings.sTableId,
|
|
14164 'data-dt-idx': counter,
|
|
14165 'tabindex': settings.iTabIndex,
|
|
14166 'id': idx === 0 && typeof button === 'string' ?
|
|
14167 settings.sTableId +'_'+ button :
|
|
14168 null
|
|
14169 } )
|
|
14170 .html( btnDisplay )
|
|
14171 .appendTo( container );
|
|
14172
|
|
14173 _fnBindAction(
|
|
14174 node, {action: button}, clickHandler
|
|
14175 );
|
|
14176
|
|
14177 counter++;
|
|
14178 }
|
|
14179 }
|
|
14180 }
|
|
14181 };
|
|
14182
|
|
14183 // IE9 throws an 'unknown error' if document.activeElement is used
|
|
14184 // inside an iframe or frame. Try / catch the error. Not good for
|
|
14185 // accessibility, but neither are frames.
|
|
14186 try {
|
|
14187 // Because this approach is destroying and recreating the paging
|
|
14188 // elements, focus is lost on the select button which is bad for
|
|
14189 // accessibility. So we want to restore focus once the draw has
|
|
14190 // completed
|
|
14191 var activeEl = $(document.activeElement).data('dt-idx');
|
|
14192
|
|
14193 attach( $(host).empty(), buttons );
|
|
14194
|
|
14195 if ( activeEl !== null ) {
|
|
14196 $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
|
|
14197 }
|
|
14198 }
|
|
14199 catch (e) {}
|
|
14200 }
|
|
14201 }
|
|
14202 } );
|
|
14203
|
|
14204
|
|
14205
|
|
14206 // Built in type detection. See model.ext.aTypes for information about
|
|
14207 // what is required from this methods.
|
|
14208 $.extend( DataTable.ext.type.detect, [
|
|
14209 // Plain numbers - first since V8 detects some plain numbers as dates
|
|
14210 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
|
|
14211 function ( d, settings )
|
|
14212 {
|
|
14213 var decimal = settings.oLanguage.sDecimal;
|
|
14214 return _isNumber( d, decimal ) ? 'num'+decimal : null;
|
|
14215 },
|
|
14216
|
|
14217 // Dates (only those recognised by the browser's Date.parse)
|
|
14218 function ( d, settings )
|
|
14219 {
|
|
14220 // V8 will remove any unknown characters at the start and end of the
|
|
14221 // expression, leading to false matches such as `$245.12` or `10%` being
|
|
14222 // a valid date. See forum thread 18941 for detail.
|
|
14223 if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
|
|
14224 return null;
|
|
14225 }
|
|
14226 var parsed = Date.parse(d);
|
|
14227 return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
|
|
14228 },
|
|
14229
|
|
14230 // Formatted numbers
|
|
14231 function ( d, settings )
|
|
14232 {
|
|
14233 var decimal = settings.oLanguage.sDecimal;
|
|
14234 return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
|
|
14235 },
|
|
14236
|
|
14237 // HTML numeric
|
|
14238 function ( d, settings )
|
|
14239 {
|
|
14240 var decimal = settings.oLanguage.sDecimal;
|
|
14241 return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
|
|
14242 },
|
|
14243
|
|
14244 // HTML numeric, formatted
|
|
14245 function ( d, settings )
|
|
14246 {
|
|
14247 var decimal = settings.oLanguage.sDecimal;
|
|
14248 return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
|
|
14249 },
|
|
14250
|
|
14251 // HTML (this is strict checking - there must be html)
|
|
14252 function ( d, settings )
|
|
14253 {
|
|
14254 return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
|
|
14255 'html' : null;
|
|
14256 }
|
|
14257 ] );
|
|
14258
|
|
14259
|
|
14260
|
|
14261 // Filter formatting functions. See model.ext.ofnSearch for information about
|
|
14262 // what is required from these methods.
|
|
14263 //
|
|
14264 // Note that additional search methods are added for the html numbers and
|
|
14265 // html formatted numbers by `_addNumericSort()` when we know what the decimal
|
|
14266 // place is
|
|
14267
|
|
14268
|
|
14269 $.extend( DataTable.ext.type.search, {
|
|
14270 html: function ( data ) {
|
|
14271 return _empty(data) ?
|
|
14272 data :
|
|
14273 typeof data === 'string' ?
|
|
14274 data
|
|
14275 .replace( _re_new_lines, " " )
|
|
14276 .replace( _re_html, "" ) :
|
|
14277 '';
|
|
14278 },
|
|
14279
|
|
14280 string: function ( data ) {
|
|
14281 return _empty(data) ?
|
|
14282 data :
|
|
14283 typeof data === 'string' ?
|
|
14284 data.replace( _re_new_lines, " " ) :
|
|
14285 data;
|
|
14286 }
|
|
14287 } );
|
|
14288
|
|
14289
|
|
14290
|
|
14291 var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
|
|
14292 if ( d !== 0 && (!d || d === '-') ) {
|
|
14293 return -Infinity;
|
|
14294 }
|
|
14295
|
|
14296 // If a decimal place other than `.` is used, it needs to be given to the
|
|
14297 // function so we can detect it and replace with a `.` which is the only
|
|
14298 // decimal place Javascript recognises - it is not locale aware.
|
|
14299 if ( decimalPlace ) {
|
|
14300 d = _numToDecimal( d, decimalPlace );
|
|
14301 }
|
|
14302
|
|
14303 if ( d.replace ) {
|
|
14304 if ( re1 ) {
|
|
14305 d = d.replace( re1, '' );
|
|
14306 }
|
|
14307
|
|
14308 if ( re2 ) {
|
|
14309 d = d.replace( re2, '' );
|
|
14310 }
|
|
14311 }
|
|
14312
|
|
14313 return d * 1;
|
|
14314 };
|
|
14315
|
|
14316
|
|
14317 // Add the numeric 'deformatting' functions for sorting and search. This is done
|
|
14318 // in a function to provide an easy ability for the language options to add
|
|
14319 // additional methods if a non-period decimal place is used.
|
|
14320 function _addNumericSort ( decimalPlace ) {
|
|
14321 $.each(
|
|
14322 {
|
|
14323 // Plain numbers
|
|
14324 "num": function ( d ) {
|
|
14325 return __numericReplace( d, decimalPlace );
|
|
14326 },
|
|
14327
|
|
14328 // Formatted numbers
|
|
14329 "num-fmt": function ( d ) {
|
|
14330 return __numericReplace( d, decimalPlace, _re_formatted_numeric );
|
|
14331 },
|
|
14332
|
|
14333 // HTML numeric
|
|
14334 "html-num": function ( d ) {
|
|
14335 return __numericReplace( d, decimalPlace, _re_html );
|
|
14336 },
|
|
14337
|
|
14338 // HTML numeric, formatted
|
|
14339 "html-num-fmt": function ( d ) {
|
|
14340 return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
|
|
14341 }
|
|
14342 },
|
|
14343 function ( key, fn ) {
|
|
14344 // Add the ordering method
|
|
14345 _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
|
|
14346
|
|
14347 // For HTML types add a search formatter that will strip the HTML
|
|
14348 if ( key.match(/^html\-/) ) {
|
|
14349 _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
|
|
14350 }
|
|
14351 }
|
|
14352 );
|
|
14353 }
|
|
14354
|
|
14355
|
|
14356 // Default sort methods
|
|
14357 $.extend( _ext.type.order, {
|
|
14358 // Dates
|
|
14359 "date-pre": function ( d ) {
|
|
14360 return Date.parse( d ) || 0;
|
|
14361 },
|
|
14362
|
|
14363 // html
|
|
14364 "html-pre": function ( a ) {
|
|
14365 return _empty(a) ?
|
|
14366 '' :
|
|
14367 a.replace ?
|
|
14368 a.replace( /<.*?>/g, "" ).toLowerCase() :
|
|
14369 a+'';
|
|
14370 },
|
|
14371
|
|
14372 // string
|
|
14373 "string-pre": function ( a ) {
|
|
14374 // This is a little complex, but faster than always calling toString,
|
|
14375 // http://jsperf.com/tostring-v-check
|
|
14376 return _empty(a) ?
|
|
14377 '' :
|
|
14378 typeof a === 'string' ?
|
|
14379 a.toLowerCase() :
|
|
14380 ! a.toString ?
|
|
14381 '' :
|
|
14382 a.toString();
|
|
14383 },
|
|
14384
|
|
14385 // string-asc and -desc are retained only for compatibility with the old
|
|
14386 // sort methods
|
|
14387 "string-asc": function ( x, y ) {
|
|
14388 return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
|
14389 },
|
|
14390
|
|
14391 "string-desc": function ( x, y ) {
|
|
14392 return ((x < y) ? 1 : ((x > y) ? -1 : 0));
|
|
14393 }
|
|
14394 } );
|
|
14395
|
|
14396
|
|
14397 // Numeric sorting types - order doesn't matter here
|
|
14398 _addNumericSort( '' );
|
|
14399
|
|
14400
|
|
14401 $.extend( true, DataTable.ext.renderer, {
|
|
14402 header: {
|
|
14403 _: function ( settings, cell, column, classes ) {
|
|
14404 // No additional mark-up required
|
|
14405 // Attach a sort listener to update on sort - note that using the
|
|
14406 // `DT` namespace will allow the event to be removed automatically
|
|
14407 // on destroy, while the `dt` namespaced event is the one we are
|
|
14408 // listening for
|
|
14409 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
|
|
14410 if ( settings !== ctx ) { // need to check this this is the host
|
|
14411 return; // table, not a nested one
|
|
14412 }
|
|
14413
|
|
14414 var colIdx = column.idx;
|
|
14415
|
|
14416 cell
|
|
14417 .removeClass(
|
|
14418 column.sSortingClass +' '+
|
|
14419 classes.sSortAsc +' '+
|
|
14420 classes.sSortDesc
|
|
14421 )
|
|
14422 .addClass( columns[ colIdx ] == 'asc' ?
|
|
14423 classes.sSortAsc : columns[ colIdx ] == 'desc' ?
|
|
14424 classes.sSortDesc :
|
|
14425 column.sSortingClass
|
|
14426 );
|
|
14427 } );
|
|
14428 },
|
|
14429
|
|
14430 jqueryui: function ( settings, cell, column, classes ) {
|
|
14431 $('<div/>')
|
|
14432 .addClass( classes.sSortJUIWrapper )
|
|
14433 .append( cell.contents() )
|
|
14434 .append( $('<span/>')
|
|
14435 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
|
|
14436 )
|
|
14437 .appendTo( cell );
|
|
14438
|
|
14439 // Attach a sort listener to update on sort
|
|
14440 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
|
|
14441 if ( settings !== ctx ) {
|
|
14442 return;
|
|
14443 }
|
|
14444
|
|
14445 var colIdx = column.idx;
|
|
14446
|
|
14447 cell
|
|
14448 .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
|
|
14449 .addClass( columns[ colIdx ] == 'asc' ?
|
|
14450 classes.sSortAsc : columns[ colIdx ] == 'desc' ?
|
|
14451 classes.sSortDesc :
|
|
14452 column.sSortingClass
|
|
14453 );
|
|
14454
|
|
14455 cell
|
|
14456 .find( 'span.'+classes.sSortIcon )
|
|
14457 .removeClass(
|
|
14458 classes.sSortJUIAsc +" "+
|
|
14459 classes.sSortJUIDesc +" "+
|
|
14460 classes.sSortJUI +" "+
|
|
14461 classes.sSortJUIAscAllowed +" "+
|
|
14462 classes.sSortJUIDescAllowed
|
|
14463 )
|
|
14464 .addClass( columns[ colIdx ] == 'asc' ?
|
|
14465 classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
|
|
14466 classes.sSortJUIDesc :
|
|
14467 column.sSortingClassJUI
|
|
14468 );
|
|
14469 } );
|
|
14470 }
|
|
14471 }
|
|
14472 } );
|
|
14473
|
|
14474 /*
|
|
14475 * Public helper functions. These aren't used internally by DataTables, or
|
|
14476 * called by any of the options passed into DataTables, but they can be used
|
|
14477 * externally by developers working with DataTables. They are helper functions
|
|
14478 * to make working with DataTables a little bit easier.
|
|
14479 */
|
|
14480
|
|
14481 /**
|
|
14482 * Helpers for `columns.render`.
|
|
14483 *
|
|
14484 * The options defined here can be used with the `columns.render` initialisation
|
|
14485 * option to provide a display renderer. The following functions are defined:
|
|
14486 *
|
|
14487 * * `number` - Will format numeric data (defined by `columns.data`) for
|
|
14488 * display, retaining the original unformatted data for sorting and filtering.
|
|
14489 * It takes 4 parameters:
|
|
14490 * * `string` - Thousands grouping separator
|
|
14491 * * `string` - Decimal point indicator
|
|
14492 * * `integer` - Number of decimal points to show
|
|
14493 * * `string` (optional) - Prefix.
|
|
14494 *
|
|
14495 * @example
|
|
14496 * // Column definition using the number renderer
|
|
14497 * {
|
|
14498 * data: "salary",
|
|
14499 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
|
|
14500 * }
|
|
14501 *
|
|
14502 * @namespace
|
|
14503 */
|
|
14504 DataTable.render = {
|
|
14505 number: function ( thousands, decimal, precision, prefix ) {
|
|
14506 return {
|
|
14507 display: function ( d ) {
|
|
14508 var negative = d < 0 ? '-' : '';
|
|
14509 d = Math.abs( parseFloat( d ) );
|
|
14510
|
|
14511 var intPart = parseInt( d, 10 );
|
|
14512 var floatPart = precision ?
|
|
14513 decimal+(d - intPart).toFixed( precision ).substring( 2 ):
|
|
14514 '';
|
|
14515
|
|
14516 return negative + (prefix||'') +
|
|
14517 intPart.toString().replace(
|
|
14518 /\B(?=(\d{3})+(?!\d))/g, thousands
|
|
14519 ) +
|
|
14520 floatPart;
|
|
14521 }
|
|
14522 };
|
|
14523 }
|
|
14524 };
|
|
14525
|
|
14526
|
|
14527 /*
|
|
14528 * This is really a good bit rubbish this method of exposing the internal methods
|
|
14529 * publicly... - To be fixed in 2.0 using methods on the prototype
|
|
14530 */
|
|
14531
|
|
14532
|
|
14533 /**
|
|
14534 * Create a wrapper function for exporting an internal functions to an external API.
|
|
14535 * @param {string} fn API function name
|
|
14536 * @returns {function} wrapped function
|
|
14537 * @memberof DataTable#internal
|
|
14538 */
|
|
14539 function _fnExternApiFunc (fn)
|
|
14540 {
|
|
14541 return function() {
|
|
14542 var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
|
|
14543 Array.prototype.slice.call(arguments)
|
|
14544 );
|
|
14545 return DataTable.ext.internal[fn].apply( this, args );
|
|
14546 };
|
|
14547 }
|
|
14548
|
|
14549
|
|
14550 /**
|
|
14551 * Reference to internal functions for use by plug-in developers. Note that
|
|
14552 * these methods are references to internal functions and are considered to be
|
|
14553 * private. If you use these methods, be aware that they are liable to change
|
|
14554 * between versions.
|
|
14555 * @namespace
|
|
14556 */
|
|
14557 $.extend( DataTable.ext.internal, {
|
|
14558 _fnExternApiFunc: _fnExternApiFunc,
|
|
14559 _fnBuildAjax: _fnBuildAjax,
|
|
14560 _fnAjaxUpdate: _fnAjaxUpdate,
|
|
14561 _fnAjaxParameters: _fnAjaxParameters,
|
|
14562 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
|
|
14563 _fnAjaxDataSrc: _fnAjaxDataSrc,
|
|
14564 _fnAddColumn: _fnAddColumn,
|
|
14565 _fnColumnOptions: _fnColumnOptions,
|
|
14566 _fnAdjustColumnSizing: _fnAdjustColumnSizing,
|
|
14567 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
|
|
14568 _fnColumnIndexToVisible: _fnColumnIndexToVisible,
|
|
14569 _fnVisbleColumns: _fnVisbleColumns,
|
|
14570 _fnGetColumns: _fnGetColumns,
|
|
14571 _fnColumnTypes: _fnColumnTypes,
|
|
14572 _fnApplyColumnDefs: _fnApplyColumnDefs,
|
|
14573 _fnHungarianMap: _fnHungarianMap,
|
|
14574 _fnCamelToHungarian: _fnCamelToHungarian,
|
|
14575 _fnLanguageCompat: _fnLanguageCompat,
|
|
14576 _fnBrowserDetect: _fnBrowserDetect,
|
|
14577 _fnAddData: _fnAddData,
|
|
14578 _fnAddTr: _fnAddTr,
|
|
14579 _fnNodeToDataIndex: _fnNodeToDataIndex,
|
|
14580 _fnNodeToColumnIndex: _fnNodeToColumnIndex,
|
|
14581 _fnGetCellData: _fnGetCellData,
|
|
14582 _fnSetCellData: _fnSetCellData,
|
|
14583 _fnSplitObjNotation: _fnSplitObjNotation,
|
|
14584 _fnGetObjectDataFn: _fnGetObjectDataFn,
|
|
14585 _fnSetObjectDataFn: _fnSetObjectDataFn,
|
|
14586 _fnGetDataMaster: _fnGetDataMaster,
|
|
14587 _fnClearTable: _fnClearTable,
|
|
14588 _fnDeleteIndex: _fnDeleteIndex,
|
|
14589 _fnInvalidate: _fnInvalidate,
|
|
14590 _fnGetRowElements: _fnGetRowElements,
|
|
14591 _fnCreateTr: _fnCreateTr,
|
|
14592 _fnBuildHead: _fnBuildHead,
|
|
14593 _fnDrawHead: _fnDrawHead,
|
|
14594 _fnDraw: _fnDraw,
|
|
14595 _fnReDraw: _fnReDraw,
|
|
14596 _fnAddOptionsHtml: _fnAddOptionsHtml,
|
|
14597 _fnDetectHeader: _fnDetectHeader,
|
|
14598 _fnGetUniqueThs: _fnGetUniqueThs,
|
|
14599 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
|
|
14600 _fnFilterComplete: _fnFilterComplete,
|
|
14601 _fnFilterCustom: _fnFilterCustom,
|
|
14602 _fnFilterColumn: _fnFilterColumn,
|
|
14603 _fnFilter: _fnFilter,
|
|
14604 _fnFilterCreateSearch: _fnFilterCreateSearch,
|
|
14605 _fnEscapeRegex: _fnEscapeRegex,
|
|
14606 _fnFilterData: _fnFilterData,
|
|
14607 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
|
|
14608 _fnUpdateInfo: _fnUpdateInfo,
|
|
14609 _fnInfoMacros: _fnInfoMacros,
|
|
14610 _fnInitialise: _fnInitialise,
|
|
14611 _fnInitComplete: _fnInitComplete,
|
|
14612 _fnLengthChange: _fnLengthChange,
|
|
14613 _fnFeatureHtmlLength: _fnFeatureHtmlLength,
|
|
14614 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
|
|
14615 _fnPageChange: _fnPageChange,
|
|
14616 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
|
|
14617 _fnProcessingDisplay: _fnProcessingDisplay,
|
|
14618 _fnFeatureHtmlTable: _fnFeatureHtmlTable,
|
|
14619 _fnScrollDraw: _fnScrollDraw,
|
|
14620 _fnApplyToChildren: _fnApplyToChildren,
|
|
14621 _fnCalculateColumnWidths: _fnCalculateColumnWidths,
|
|
14622 _fnThrottle: _fnThrottle,
|
|
14623 _fnConvertToWidth: _fnConvertToWidth,
|
|
14624 _fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
|
|
14625 _fnGetWidestNode: _fnGetWidestNode,
|
|
14626 _fnGetMaxLenString: _fnGetMaxLenString,
|
|
14627 _fnStringToCss: _fnStringToCss,
|
|
14628 _fnScrollBarWidth: _fnScrollBarWidth,
|
|
14629 _fnSortFlatten: _fnSortFlatten,
|
|
14630 _fnSort: _fnSort,
|
|
14631 _fnSortAria: _fnSortAria,
|
|
14632 _fnSortListener: _fnSortListener,
|
|
14633 _fnSortAttachListener: _fnSortAttachListener,
|
|
14634 _fnSortingClasses: _fnSortingClasses,
|
|
14635 _fnSortData: _fnSortData,
|
|
14636 _fnSaveState: _fnSaveState,
|
|
14637 _fnLoadState: _fnLoadState,
|
|
14638 _fnSettingsFromNode: _fnSettingsFromNode,
|
|
14639 _fnLog: _fnLog,
|
|
14640 _fnMap: _fnMap,
|
|
14641 _fnBindAction: _fnBindAction,
|
|
14642 _fnCallbackReg: _fnCallbackReg,
|
|
14643 _fnCallbackFire: _fnCallbackFire,
|
|
14644 _fnLengthOverflow: _fnLengthOverflow,
|
|
14645 _fnRenderer: _fnRenderer,
|
|
14646 _fnDataSource: _fnDataSource,
|
|
14647 _fnRowAttributes: _fnRowAttributes,
|
|
14648 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
|
|
14649 // in 1.10, so this dead-end function is
|
|
14650 // added to prevent errors
|
|
14651 } );
|
|
14652
|
|
14653
|
|
14654 // jQuery access
|
|
14655 $.fn.dataTable = DataTable;
|
|
14656
|
|
14657 // Legacy aliases
|
|
14658 $.fn.dataTableSettings = DataTable.settings;
|
|
14659 $.fn.dataTableExt = DataTable.ext;
|
|
14660
|
|
14661 // With a capital `D` we return a DataTables API instance rather than a
|
|
14662 // jQuery object
|
|
14663 $.fn.DataTable = function ( opts ) {
|
|
14664 return $(this).dataTable( opts ).api();
|
|
14665 };
|
|
14666
|
|
14667 // All properties that are available to $.fn.dataTable should also be
|
|
14668 // available on $.fn.DataTable
|
|
14669 $.each( DataTable, function ( prop, val ) {
|
|
14670 $.fn.DataTable[ prop ] = val;
|
|
14671 } );
|
|
14672
|
|
14673
|
|
14674 // Information about events fired by DataTables - for documentation.
|
|
14675 /**
|
|
14676 * Draw event, fired whenever the table is redrawn on the page, at the same
|
|
14677 * point as fnDrawCallback. This may be useful for binding events or
|
|
14678 * performing calculations when the table is altered at all.
|
|
14679 * @name DataTable#draw.dt
|
|
14680 * @event
|
|
14681 * @param {event} e jQuery event object
|
|
14682 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14683 */
|
|
14684
|
|
14685 /**
|
|
14686 * Search event, fired when the searching applied to the table (using the
|
|
14687 * built-in global search, or column filters) is altered.
|
|
14688 * @name DataTable#search.dt
|
|
14689 * @event
|
|
14690 * @param {event} e jQuery event object
|
|
14691 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14692 */
|
|
14693
|
|
14694 /**
|
|
14695 * Page change event, fired when the paging of the table is altered.
|
|
14696 * @name DataTable#page.dt
|
|
14697 * @event
|
|
14698 * @param {event} e jQuery event object
|
|
14699 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14700 */
|
|
14701
|
|
14702 /**
|
|
14703 * Order event, fired when the ordering applied to the table is altered.
|
|
14704 * @name DataTable#order.dt
|
|
14705 * @event
|
|
14706 * @param {event} e jQuery event object
|
|
14707 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14708 */
|
|
14709
|
|
14710 /**
|
|
14711 * DataTables initialisation complete event, fired when the table is fully
|
|
14712 * drawn, including Ajax data loaded, if Ajax data is required.
|
|
14713 * @name DataTable#init.dt
|
|
14714 * @event
|
|
14715 * @param {event} e jQuery event object
|
|
14716 * @param {object} oSettings DataTables settings object
|
|
14717 * @param {object} json The JSON object request from the server - only
|
|
14718 * present if client-side Ajax sourced data is used</li></ol>
|
|
14719 */
|
|
14720
|
|
14721 /**
|
|
14722 * State save event, fired when the table has changed state a new state save
|
|
14723 * is required. This event allows modification of the state saving object
|
|
14724 * prior to actually doing the save, including addition or other state
|
|
14725 * properties (for plug-ins) or modification of a DataTables core property.
|
|
14726 * @name DataTable#stateSaveParams.dt
|
|
14727 * @event
|
|
14728 * @param {event} e jQuery event object
|
|
14729 * @param {object} oSettings DataTables settings object
|
|
14730 * @param {object} json The state information to be saved
|
|
14731 */
|
|
14732
|
|
14733 /**
|
|
14734 * State load event, fired when the table is loading state from the stored
|
|
14735 * data, but prior to the settings object being modified by the saved state
|
|
14736 * - allowing modification of the saved state is required or loading of
|
|
14737 * state for a plug-in.
|
|
14738 * @name DataTable#stateLoadParams.dt
|
|
14739 * @event
|
|
14740 * @param {event} e jQuery event object
|
|
14741 * @param {object} oSettings DataTables settings object
|
|
14742 * @param {object} json The saved state information
|
|
14743 */
|
|
14744
|
|
14745 /**
|
|
14746 * State loaded event, fired when state has been loaded from stored data and
|
|
14747 * the settings object has been modified by the loaded data.
|
|
14748 * @name DataTable#stateLoaded.dt
|
|
14749 * @event
|
|
14750 * @param {event} e jQuery event object
|
|
14751 * @param {object} oSettings DataTables settings object
|
|
14752 * @param {object} json The saved state information
|
|
14753 */
|
|
14754
|
|
14755 /**
|
|
14756 * Processing event, fired when DataTables is doing some kind of processing
|
|
14757 * (be it, order, searcg or anything else). It can be used to indicate to
|
|
14758 * the end user that there is something happening, or that something has
|
|
14759 * finished.
|
|
14760 * @name DataTable#processing.dt
|
|
14761 * @event
|
|
14762 * @param {event} e jQuery event object
|
|
14763 * @param {object} oSettings DataTables settings object
|
|
14764 * @param {boolean} bShow Flag for if DataTables is doing processing or not
|
|
14765 */
|
|
14766
|
|
14767 /**
|
|
14768 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
|
|
14769 * request to made to the server for new data. This event is called before
|
|
14770 * DataTables processed the returned data, so it can also be used to pre-
|
|
14771 * process the data returned from the server, if needed.
|
|
14772 *
|
|
14773 * Note that this trigger is called in `fnServerData`, if you override
|
|
14774 * `fnServerData` and which to use this event, you need to trigger it in you
|
|
14775 * success function.
|
|
14776 * @name DataTable#xhr.dt
|
|
14777 * @event
|
|
14778 * @param {event} e jQuery event object
|
|
14779 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14780 * @param {object} json JSON returned from the server
|
|
14781 *
|
|
14782 * @example
|
|
14783 * // Use a custom property returned from the server in another DOM element
|
|
14784 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
|
|
14785 * $('#status').html( json.status );
|
|
14786 * } );
|
|
14787 *
|
|
14788 * @example
|
|
14789 * // Pre-process the data returned from the server
|
|
14790 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
|
|
14791 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
|
|
14792 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
|
|
14793 * }
|
|
14794 * // Note no return - manipulate the data directly in the JSON object.
|
|
14795 * } );
|
|
14796 */
|
|
14797
|
|
14798 /**
|
|
14799 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
|
|
14800 * or passing the bDestroy:true parameter in the initialisation object. This
|
|
14801 * can be used to remove bound events, added DOM nodes, etc.
|
|
14802 * @name DataTable#destroy.dt
|
|
14803 * @event
|
|
14804 * @param {event} e jQuery event object
|
|
14805 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14806 */
|
|
14807
|
|
14808 /**
|
|
14809 * Page length change event, fired when number of records to show on each
|
|
14810 * page (the length) is changed.
|
|
14811 * @name DataTable#length.dt
|
|
14812 * @event
|
|
14813 * @param {event} e jQuery event object
|
|
14814 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14815 * @param {integer} len New length
|
|
14816 */
|
|
14817
|
|
14818 /**
|
|
14819 * Column sizing has changed.
|
|
14820 * @name DataTable#column-sizing.dt
|
|
14821 * @event
|
|
14822 * @param {event} e jQuery event object
|
|
14823 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14824 */
|
|
14825
|
|
14826 /**
|
|
14827 * Column visibility has changed.
|
|
14828 * @name DataTable#column-visibility.dt
|
|
14829 * @event
|
|
14830 * @param {event} e jQuery event object
|
|
14831 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
|
|
14832 * @param {int} column Column index
|
|
14833 * @param {bool} vis `false` if column now hidden, or `true` if visible
|
|
14834 */
|
|
14835
|
|
14836 return $.fn.dataTable;
|
|
14837 }));
|
|
14838
|
|
14839 }(window, document));
|
|
14840
|