2 * ©2008-2014 SpryMedia Ltd - datatables.net/license
7 * @description Paginate, search and order HTML tables
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.
14 * This source file is free software, available under the following license:
15 * MIT license - http://datatables.net/license
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.
21 * For details please refer to: http://www.datatables.net
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,_fnInvalidateRow,_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*/
27 (/** @lends <global> */function( window
, document
, undefined ) {
29 (function( factory
) {
32 if ( typeof define
=== 'function' && define
.amd
) {
33 // Define as an AMD module if possible
34 define( 'datatables', ['jquery'], factory
);
36 else if ( typeof exports
=== 'object' ) {
38 factory( require( 'jquery' ) );
40 else if ( jQuery
&& !jQuery
.fn
.dataTable
) {
41 // Define using browser globals otherwise
42 // Prevent multiple instantiations if the script is loaded twice
46 (/** @lends <global> */function( $ ) {
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).
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
61 * @param {object} [init={}] Configuration object for DataTables. Options
62 * are defined by {@link DataTable.defaults}
63 * @requires jQuery 1.7+
66 * // Basic initialisation
67 * $(document).ready( function {
68 * $('#example').dataTable();
72 * // Initialisation with configuration options - in this case, disable
73 * // pagination and sorting.
74 * $(document).ready( function {
75 * $('#example').dataTable( {
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.
98 // _selector_row_indexes
100 var _ext
; // DataTable.ext
101 var _Api
; // DataTable.Api
102 var _api_register
; // DataTable.Api.register
103 var _api_registerPlural
; // DataTable.Api.registerPlural
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\+\-]$/;
111 // Escape regular expression special characters
112 var _re_escape_regex
= new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
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;
119 var _empty = function ( d
) {
120 return !d
|| d
=== true || d
=== '-' ? true : false;
124 var _intVal = function ( s
) {
125 var integer
= parseInt( s
, 10 );
126 return !isNaN(integer
) && isFinite(s
) ? integer
: null;
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' );
136 return typeof num
=== 'string' && decimalPoint
!== '.' ?
137 num
.replace( /\./g, '' ).replace( _re_dic
[ decimalPoint
], '.' ) :
142 var _isNumber = function ( d
, decimalPoint
, formatted
) {
143 var strType
= typeof d
=== 'string';
145 if ( decimalPoint
&& strType
) {
146 d
= _numToDecimal( d
, decimalPoint
);
149 if ( formatted
&& strType
) {
150 d
= d
.replace( _re_formatted_numeric
, '' );
153 return _empty( d
) || (!isNaN( parseFloat(d
) ) && isFinite( d
));
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';
163 var _htmlNumeric = function ( d
, decimalPoint
, formatted
) {
168 var html
= _isHtml( d
);
171 _isNumber( _stripHtml( d
), decimalPoint
, formatted
) ?
177 var _pluck = function ( a
, prop
, prop2
) {
179 var i
=0, ien
=a
.length
;
181 // Could have the test in the loop for slightly smaller code, but speed
183 if ( prop2
!== undefined ) {
184 for ( ; i
<ien
; i
++ ) {
185 if ( a
[i
] && a
[i
][ prop
] ) {
186 out
.push( a
[i
][ prop
][ prop2
] );
191 for ( ; i
<ien
; i
++ ) {
193 out
.push( a
[i
][ prop
] );
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
)
207 var i
=0, ien
=order
.length
;
209 // Could have the test in the loop for slightly smaller code, but speed
211 if ( prop2
!== undefined ) {
212 for ( ; i
<ien
; i
++ ) {
213 out
.push( a
[ order
[i
] ][ prop
][ prop2
] );
217 for ( ; i
<ien
; i
++ ) {
218 out
.push( a
[ order
[i
] ][ prop
] );
226 var _range = function ( len
, start
)
231 if ( start
=== undefined ) {
240 for ( var i
=start
; i
<end
; i
++ ) {
248 var _stripHtml = function ( d
) {
249 return d
.replace( _re_html
, '' );
254 * Find the unique elements in a source array.
256 * @param {array} src Source array
257 * @return {array} Array of unique items
260 var _unique = function ( src
)
262 // A faster unique method is to use object keys to identify used values,
263 // but this doesn't work with arrays or objects, which we must also
264 // consider. See jsperf.com/compare-array-unique-versions/4 for more
272 again
: for ( i
=0 ; i
<ien
; i
++ ) {
275 for ( j
=0 ; j
<k
; j
++ ) {
276 if ( out
[j
] === val
) {
291 * Create a mapping object that allows camel case parameters to be looked up
292 * for their Hungarian counterparts. The mapping is stored in a private
293 * parameter called `_hungarianMap` which can be accessed on the source object.
295 * @memberof DataTable#oApi
297 function _fnHungarianMap ( o
)
300 hungarian
= 'a aa ai ao as b fn i m o s ',
305 $.each( o
, function (key
, val
) {
306 match
= key
.match(/^([^A-Z]+?)([A-Z])/);
308 if ( match
&& hungarian
.indexOf(match
[1]+' ') !== -1 )
310 newKey
= key
.replace( match
[0], match
[2].toLowerCase() );
313 if ( match
[1] === 'o' )
315 _fnHungarianMap( o
[key
] );
320 o
._hungarianMap
= map
;
325 * Convert from camel case parameters to Hungarian, based on a Hungarian map
326 * created by _fnHungarianMap.
327 * @param {object} src The model object which holds all parameters that can be
329 * @param {object} user The object to convert from camel case to Hungarian.
330 * @param {boolean} force When set to `true`, properties which already have a
331 * Hungarian value in the `user` object will be overwritten. Otherwise they
333 * @memberof DataTable#oApi
335 function _fnCamelToHungarian ( src
, user
, force
)
337 if ( ! src
._hungarianMap
) {
338 _fnHungarianMap( src
);
343 $.each( user
, function (key
, val
) {
344 hungarianKey
= src
._hungarianMap
[ key
];
346 if ( hungarianKey
!== undefined && (force
|| user
[hungarianKey
] === undefined) )
348 // For objects, we need to buzz down into the object to copy parameters
349 if ( hungarianKey
.charAt(0) === 'o' )
351 // Copy the camelCase options over to the hungarian
352 if ( ! user
[ hungarianKey
] ) {
353 user
[ hungarianKey
] = {};
355 $.extend( true, user
[hungarianKey
], user
[key
] );
357 _fnCamelToHungarian( src
[hungarianKey
], user
[hungarianKey
], force
);
360 user
[hungarianKey
] = user
[ key
];
368 * Language compatibility - when certain options are given, and others aren't, we
369 * need to duplicate the values over, in order to provide backwards compatibility
370 * with older language files.
371 * @param {object} oSettings dataTables settings object
372 * @memberof DataTable#oApi
374 function _fnLanguageCompat( lang
)
376 var defaults
= DataTable
.defaults
.oLanguage
;
377 var zeroRecords
= lang
.sZeroRecords
;
379 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
380 * sZeroRecords - assuming that is given.
382 if ( ! lang
.sEmptyTable
&& zeroRecords
&&
383 defaults
.sEmptyTable
=== "No data available in table" )
385 _fnMap( lang
, lang
, 'sZeroRecords', 'sEmptyTable' );
388 /* Likewise with loading records */
389 if ( ! lang
.sLoadingRecords
&& zeroRecords
&&
390 defaults
.sLoadingRecords
=== "Loading..." )
392 _fnMap( lang
, lang
, 'sZeroRecords', 'sLoadingRecords' );
395 // Old parameter name of the thousands separator mapped onto the new
396 if ( lang
.sInfoThousands
) {
397 lang
.sThousands
= lang
.sInfoThousands
;
400 var decimal = lang
.sDecimal
;
402 _addNumericSort( decimal );
408 * Map one parameter onto another
409 * @param {object} o Object to map
410 * @param {*} knew The new parameter name
411 * @param {*} old The old parameter name
413 var _fnCompatMap = function ( o
, knew
, old
) {
414 if ( o
[ knew
] !== undefined ) {
415 o
[ old
] = o
[ knew
];
421 * Provide backwards compatibility for the main DT options. Note that the new
422 * options are mapped onto the old parameters, so this is an external interface
424 * @param {object} init Object to map
426 function _fnCompatOpts ( init
)
428 _fnCompatMap( init
, 'ordering', 'bSort' );
429 _fnCompatMap( init
, 'orderMulti', 'bSortMulti' );
430 _fnCompatMap( init
, 'orderClasses', 'bSortClasses' );
431 _fnCompatMap( init
, 'orderCellsTop', 'bSortCellsTop' );
432 _fnCompatMap( init
, 'order', 'aaSorting' );
433 _fnCompatMap( init
, 'orderFixed', 'aaSortingFixed' );
434 _fnCompatMap( init
, 'paging', 'bPaginate' );
435 _fnCompatMap( init
, 'pagingType', 'sPaginationType' );
436 _fnCompatMap( init
, 'pageLength', 'iDisplayLength' );
437 _fnCompatMap( init
, 'searching', 'bFilter' );
439 // Column search objects are in an array, so it needs to be converted
440 // element by element
441 var searchCols
= init
.aoSearchCols
;
444 for ( var i
=0, ien
=searchCols
.length
; i
<ien
; i
++ ) {
445 if ( searchCols
[i
] ) {
446 _fnCamelToHungarian( DataTable
.models
.oSearch
, searchCols
[i
] );
454 * Provide backwards compatibility for column options. Note that the new options
455 * are mapped onto the old parameters, so this is an external interface change
457 * @param {object} init Object to map
459 function _fnCompatCols ( init
)
461 _fnCompatMap( init
, 'orderable', 'bSortable' );
462 _fnCompatMap( init
, 'orderData', 'aDataSort' );
463 _fnCompatMap( init
, 'orderSequence', 'asSorting' );
464 _fnCompatMap( init
, 'orderDataType', 'sortDataType' );
469 * Browser feature detection for capabilities, quirks
470 * @param {object} settings dataTables settings object
471 * @memberof DataTable#oApi
473 function _fnBrowserDetect( settings
)
475 var browser
= settings
.oBrowser
;
477 // Scrolling feature / quirks detection
480 position
: 'absolute',
490 position
: 'absolute',
497 $('<div class="test"/>')
506 var test
= n
.find('.test');
508 // IE6/7 will oversize a width 100% element inside a scrolling element, to
509 // include the width of the scrollbar, while other browsers ensure the inner
510 // element is contained without forcing scrolling
511 browser
.bScrollOversize
= test
[0].offsetWidth
=== 100;
513 // In rtl text layout, some browsers (most, but not all) will place the
514 // scrollbar on the left, rather than the right.
515 browser
.bScrollbarLeft
= test
.offset().left
!== 1;
522 * Array.prototype reduce[Right] method, used for browsers which don't support
523 * JS 1.6. Done this way to reduce code size, since we iterate either way
524 * @param {object} settings dataTables settings object
525 * @memberof DataTable#oApi
527 function _fnReduce ( that
, fn
, init
, start
, end
, inc
)
534 if ( init
!== undefined ) {
539 while ( i
!== end
) {
540 if ( ! that
.hasOwnProperty(i
) ) {
545 fn( value
, that
[i
], i
, that
) :
556 * Add a column to the list used for the table with default values
557 * @param {object} oSettings dataTables settings object
558 * @param {node} nTh The th element for this column
559 * @memberof DataTable#oApi
561 function _fnAddColumn( oSettings
, nTh
)
563 // Add column to aoColumns array
564 var oDefaults
= DataTable
.defaults
.column
;
565 var iCol
= oSettings
.aoColumns
.length
;
566 var oCol
= $.extend( {}, DataTable
.models
.oColumn
, oDefaults
, {
567 "nTh": nTh
? nTh
: document
.createElement('th'),
568 "sTitle": oDefaults
.sTitle
? oDefaults
.sTitle
: nTh
? nTh
.innerHTML
: '',
569 "aDataSort": oDefaults
.aDataSort
? oDefaults
.aDataSort
: [iCol
],
570 "mData": oDefaults
.mData
? oDefaults
.mData
: iCol
,
573 oSettings
.aoColumns
.push( oCol
);
575 // Add search object for column specific search. Note that the `searchCols[ iCol ]`
576 // passed into extend can be undefined. This allows the user to give a default
577 // with only some of the parameters defined, and also not give a default
578 var searchCols
= oSettings
.aoPreSearchCols
;
579 searchCols
[ iCol
] = $.extend( {}, DataTable
.models
.oSearch
, searchCols
[ iCol
] );
581 // Use the default column options function to initialise classes etc
582 _fnColumnOptions( oSettings
, iCol
, null );
587 * Apply options for a column
588 * @param {object} oSettings dataTables settings object
589 * @param {int} iCol column index to consider
590 * @param {object} oOptions object with sType, bVisible and bSearchable etc
591 * @memberof DataTable#oApi
593 function _fnColumnOptions( oSettings
, iCol
, oOptions
)
595 var oCol
= oSettings
.aoColumns
[ iCol
];
596 var oClasses
= oSettings
.oClasses
;
597 var th
= $(oCol
.nTh
);
599 // Try to get width information from the DOM. We can't get it from CSS
600 // as we'd need to parse the CSS stylesheet. `width` option can override
601 if ( ! oCol
.sWidthOrig
) {
603 oCol
.sWidthOrig
= th
.attr('width') || null;
606 var t
= (th
.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
608 oCol
.sWidthOrig
= t
[1];
612 /* User specified column options */
613 if ( oOptions
!== undefined && oOptions
!== null )
615 // Backwards compatibility
616 _fnCompatCols( oOptions
);
618 // Map camel case parameters to their Hungarian counterparts
619 _fnCamelToHungarian( DataTable
.defaults
.column
, oOptions
);
621 /* Backwards compatibility for mDataProp */
622 if ( oOptions
.mDataProp
!== undefined && !oOptions
.mData
)
624 oOptions
.mData
= oOptions
.mDataProp
;
627 if ( oOptions
.sType
)
629 oCol
._sManualType
= oOptions
.sType
;
632 // `class` is a reserved word in Javascript, so we need to provide
633 // the ability to use a valid name for the camel case input
634 if ( oOptions
.className
&& ! oOptions
.sClass
)
636 oOptions
.sClass
= oOptions
.className
;
639 $.extend( oCol
, oOptions
);
640 _fnMap( oCol
, oOptions
, "sWidth", "sWidthOrig" );
642 /* iDataSort to be applied (backwards compatibility), but aDataSort will take
643 * priority if defined
645 if ( typeof oOptions
.iDataSort
=== 'number' )
647 oCol
.aDataSort
= [ oOptions
.iDataSort
];
649 _fnMap( oCol
, oOptions
, "aDataSort" );
652 /* Cache the data get and set functions for speed */
653 var mDataSrc
= oCol
.mData
;
654 var mData
= _fnGetObjectDataFn( mDataSrc
);
655 var mRender
= oCol
.mRender
? _fnGetObjectDataFn( oCol
.mRender
) : null;
657 var attrTest = function( src
) {
658 return typeof src
=== 'string' && src
.indexOf('@') !== -1;
660 oCol
._bAttrSrc
= $.isPlainObject( mDataSrc
) && (
661 attrTest(mDataSrc
.sort
) || attrTest(mDataSrc
.type
) || attrTest(mDataSrc
.filter
)
664 oCol
.fnGetData = function (rowData
, type
, meta
) {
665 var innerData
= mData( rowData
, type
, undefined, meta
);
667 return mRender
&& type
?
668 mRender( innerData
, type
, rowData
, meta
) :
671 oCol
.fnSetData = function ( rowData
, val
, meta
) {
672 return _fnSetObjectDataFn( mDataSrc
)( rowData
, val
, meta
);
675 // Indicate if DataTables should read DOM data as an object or array
676 // Used in _fnGetRowElements
677 if ( typeof mDataSrc
!== 'number' ) {
678 oSettings
._rowReadObject
= true;
681 /* Feature sorting overrides column specific when off */
682 if ( !oSettings
.oFeatures
.bSort
)
684 oCol
.bSortable
= false;
685 th
.addClass( oClasses
.sSortableNone
); // Have to add class here as order event isn't called
688 /* Check that the class assignment is correct for sorting */
689 var bAsc
= $.inArray('asc', oCol
.asSorting
) !== -1;
690 var bDesc
= $.inArray('desc', oCol
.asSorting
) !== -1;
691 if ( !oCol
.bSortable
|| (!bAsc
&& !bDesc
) )
693 oCol
.sSortingClass
= oClasses
.sSortableNone
;
694 oCol
.sSortingClassJUI
= "";
696 else if ( bAsc
&& !bDesc
)
698 oCol
.sSortingClass
= oClasses
.sSortableAsc
;
699 oCol
.sSortingClassJUI
= oClasses
.sSortJUIAscAllowed
;
701 else if ( !bAsc
&& bDesc
)
703 oCol
.sSortingClass
= oClasses
.sSortableDesc
;
704 oCol
.sSortingClassJUI
= oClasses
.sSortJUIDescAllowed
;
708 oCol
.sSortingClass
= oClasses
.sSortable
;
709 oCol
.sSortingClassJUI
= oClasses
.sSortJUI
;
715 * Adjust the table column widths for new data. Note: you would probably want to
716 * do a redraw after calling this function!
717 * @param {object} settings dataTables settings object
718 * @memberof DataTable#oApi
720 function _fnAdjustColumnSizing ( settings
)
722 /* Not interested in doing column width calculation if auto-width is disabled */
723 if ( settings
.oFeatures
.bAutoWidth
!== false )
725 var columns
= settings
.aoColumns
;
727 _fnCalculateColumnWidths( settings
);
728 for ( var i
=0 , iLen
=columns
.length
; i
<iLen
; i
++ )
730 columns
[i
].nTh
.style
.width
= columns
[i
].sWidth
;
734 var scroll
= settings
.oScroll
;
735 if ( scroll
.sY
!== '' || scroll
.sX
!== '')
737 _fnScrollDraw( settings
);
740 _fnCallbackFire( settings
, null, 'column-sizing', [settings
] );
745 * Covert the index of a visible column to the index in the data array (take account
747 * @param {object} oSettings dataTables settings object
748 * @param {int} iMatch Visible column index to lookup
749 * @returns {int} i the data index
750 * @memberof DataTable#oApi
752 function _fnVisibleToColumnIndex( oSettings
, iMatch
)
754 var aiVis
= _fnGetColumns( oSettings
, 'bVisible' );
756 return typeof aiVis
[iMatch
] === 'number' ?
763 * Covert the index of an index in the data array and convert it to the visible
764 * column index (take account of hidden columns)
765 * @param {int} iMatch Column index to lookup
766 * @param {object} oSettings dataTables settings object
767 * @returns {int} i the data index
768 * @memberof DataTable#oApi
770 function _fnColumnIndexToVisible( oSettings
, iMatch
)
772 var aiVis
= _fnGetColumns( oSettings
, 'bVisible' );
773 var iPos
= $.inArray( iMatch
, aiVis
);
775 return iPos
!== -1 ? iPos
: null;
780 * Get the number of visible columns
781 * @param {object} oSettings dataTables settings object
782 * @returns {int} i the number of visible columns
783 * @memberof DataTable#oApi
785 function _fnVisbleColumns( oSettings
)
787 return _fnGetColumns( oSettings
, 'bVisible' ).length
;
792 * Get an array of column indexes that match a given property
793 * @param {object} oSettings dataTables settings object
794 * @param {string} sParam Parameter in aoColumns to look for - typically
795 * bVisible or bSearchable
796 * @returns {array} Array of indexes with matched properties
797 * @memberof DataTable#oApi
799 function _fnGetColumns( oSettings
, sParam
)
803 $.map( oSettings
.aoColumns
, function(val
, i
) {
814 * Calculate the 'type' of a column
815 * @param {object} settings dataTables settings object
816 * @memberof DataTable#oApi
818 function _fnColumnTypes ( settings
)
820 var columns
= settings
.aoColumns
;
821 var data
= settings
.aoData
;
822 var types
= DataTable
.ext
.type
.detect
;
823 var i
, ien
, j
, jen
, k
, ken
;
824 var col
, cell
, detectedType
, cache
;
826 // For each column, spin over the
827 for ( i
=0, ien
=columns
.length
; i
<ien
; i
++ ) {
831 if ( ! col
.sType
&& col
._sManualType
) {
832 col
.sType
= col
._sManualType
;
834 else if ( ! col
.sType
) {
835 for ( j
=0, jen
=types
.length
; j
<jen
; j
++ ) {
836 for ( k
=0, ken
=data
.length
; k
<ken
; k
++ ) {
837 // Use a cache array so we only need to get the type data
838 // from the formatter once (when using multiple detectors)
839 if ( cache
[k
] === undefined ) {
840 cache
[k
] = _fnGetCellData( settings
, k
, i
, 'type' );
843 detectedType
= types
[j
]( cache
[k
], settings
);
845 // Doesn't match, so break early, since this type can't
846 // apply to this column. Also, HTML is a special case since
847 // it is so similar to `string`. Just a single match is
848 // needed for a column to be html type
849 if ( ! detectedType
|| detectedType
=== 'html' ) {
854 // Type is valid for all data points in the column - use this
856 if ( detectedType
) {
857 col
.sType
= detectedType
;
862 // Fall back - if no type was detected, always use string
864 col
.sType
= 'string';
872 * Take the column definitions and static columns arrays and calculate how
873 * they relate to column indexes. The callback function will then apply the
874 * definition found for a column to a suitable configuration object.
875 * @param {object} oSettings dataTables settings object
876 * @param {array} aoColDefs The aoColumnDefs array that is to be applied
877 * @param {array} aoCols The aoColumns array that defines columns individually
878 * @param {function} fn Callback function - takes two parameters, the calculated
879 * column index and the definition for that column.
880 * @memberof DataTable#oApi
882 function _fnApplyColumnDefs( oSettings
, aoColDefs
, aoCols
, fn
)
884 var i
, iLen
, j
, jLen
, k
, kLen
, def
;
885 var columns
= oSettings
.aoColumns
;
887 // Column definitions with aTargets
890 /* Loop over the definitions array - loop in reverse so first instance has priority */
891 for ( i
=aoColDefs
.length
-1 ; i
>=0 ; i
-- )
895 /* Each definition can target multiple columns, as it is an array */
896 var aTargets
= def
.targets
!== undefined ?
900 if ( ! $.isArray( aTargets
) )
902 aTargets
= [ aTargets
];
905 for ( j
=0, jLen
=aTargets
.length
; j
<jLen
; j
++ )
907 if ( typeof aTargets
[j
] === 'number' && aTargets
[j
] >= 0 )
909 /* Add columns that we don't yet know about */
910 while( columns
.length
<= aTargets
[j
] )
912 _fnAddColumn( oSettings
);
915 /* Integer, basic index */
916 fn( aTargets
[j
], def
);
918 else if ( typeof aTargets
[j
] === 'number' && aTargets
[j
] < 0 )
920 /* Negative integer, right to left column counting */
921 fn( columns
.length
+aTargets
[j
], def
);
923 else if ( typeof aTargets
[j
] === 'string' )
925 /* Class name matching on TH element */
926 for ( k
=0, kLen
=columns
.length
; k
<kLen
; k
++ )
928 if ( aTargets
[j
] == "_all" ||
929 $(columns
[k
].nTh
).hasClass( aTargets
[j
] ) )
939 // Statically defined columns array
942 for ( i
=0, iLen
=aoCols
.length
; i
<iLen
; i
++ )
950 * Add a data array to the table, creating DOM node etc. This is the parallel to
951 * _fnGatherData, but for adding rows from a Javascript source, rather than a
953 * @param {object} oSettings dataTables settings object
954 * @param {array} aData data array to be added
955 * @param {node} [nTr] TR element to add to the table - optional. If not given,
956 * DataTables will create a row automatically
957 * @param {array} [anTds] Array of TD|TH elements for the row - must be given
959 * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
960 * @memberof DataTable#oApi
962 function _fnAddData ( oSettings
, aDataIn
, nTr
, anTds
)
964 /* Create the object for storing information about this new row */
965 var iRow
= oSettings
.aoData
.length
;
966 var oData
= $.extend( true, {}, DataTable
.models
.oRow
, {
967 src
: nTr
? 'dom' : 'data'
970 oData
._aData
= aDataIn
;
971 oSettings
.aoData
.push( oData
);
973 /* Create the cells */
975 var columns
= oSettings
.aoColumns
;
976 for ( var i
=0, iLen
=columns
.length
; i
<iLen
; i
++ )
978 // When working with a row, the data source object must be populated. In
979 // all other cases, the data source object is already populated, so we
980 // don't overwrite it, which might break bindings etc
982 _fnSetCellData( oSettings
, iRow
, i
, _fnGetCellData( oSettings
, iRow
, i
) );
984 columns
[i
].sType
= null;
987 /* Add to the display array */
988 oSettings
.aiDisplayMaster
.push( iRow
);
990 /* Create the DOM information, or register it if already present */
991 if ( nTr
|| ! oSettings
.oFeatures
.bDeferRender
)
993 _fnCreateTr( oSettings
, iRow
, nTr
, anTds
);
1001 * Add one or more TR elements to the table. Generally we'd expect to
1002 * use this for reading data from a DOM sourced table, but it could be
1003 * used for an TR element. Note that if a TR is given, it is used (i.e.
1004 * it is not cloned).
1005 * @param {object} settings dataTables settings object
1006 * @param {array|node|jQuery} trs The TR element(s) to add to the table
1007 * @returns {array} Array of indexes for the added rows
1008 * @memberof DataTable#oApi
1010 function _fnAddTr( settings
, trs
)
1014 // Allow an individual node to be passed in
1015 if ( ! (trs
instanceof $) ) {
1019 return trs
.map( function (i
, el
) {
1020 row
= _fnGetRowElements( settings
, el
);
1021 return _fnAddData( settings
, row
.data
, el
, row
.cells
);
1027 * Take a TR element and convert it to an index in aoData
1028 * @param {object} oSettings dataTables settings object
1029 * @param {node} n the TR element to find
1030 * @returns {int} index if the node is found, null if not
1031 * @memberof DataTable#oApi
1033 function _fnNodeToDataIndex( oSettings
, n
)
1035 return (n
._DT_RowIndex
!==undefined) ? n
._DT_RowIndex
: null;
1040 * Take a TD element and convert it into a column data index (not the visible index)
1041 * @param {object} oSettings dataTables settings object
1042 * @param {int} iRow The row number the TD/TH can be found in
1043 * @param {node} n The TD/TH element to find
1044 * @returns {int} index if the node is found, -1 if not
1045 * @memberof DataTable#oApi
1047 function _fnNodeToColumnIndex( oSettings
, iRow
, n
)
1049 return $.inArray( n
, oSettings
.aoData
[ iRow
].anCells
);
1054 * Get the data for a given cell from the internal cache, taking into account data mapping
1055 * @param {object} settings dataTables settings object
1056 * @param {int} rowIdx aoData row id
1057 * @param {int} colIdx Column index
1058 * @param {string} type data get type ('display', 'type' 'filter' 'sort')
1059 * @returns {*} Cell data
1060 * @memberof DataTable#oApi
1062 function _fnGetCellData( settings
, rowIdx
, colIdx
, type
)
1064 var draw
= settings
.iDraw
;
1065 var col
= settings
.aoColumns
[colIdx
];
1066 var rowData
= settings
.aoData
[rowIdx
]._aData
;
1067 var defaultContent
= col
.sDefaultContent
;
1068 var cellData
= col
.fnGetData( rowData
, type
, {
1074 if ( cellData
=== undefined ) {
1075 if ( settings
.iDrawError
!= draw
&& defaultContent
=== null ) {
1076 _fnLog( settings
, 0, "Requested unknown parameter "+
1077 (typeof col
.mData
=='function' ? '{function}' : "'"+col
.mData
+"'")+
1078 " for row "+rowIdx
, 4 );
1079 settings
.iDrawError
= draw
;
1081 return defaultContent
;
1084 /* When the data source is null, we can use default column data */
1085 if ( (cellData
=== rowData
|| cellData
=== null) && defaultContent
!== null ) {
1086 cellData
= defaultContent
;
1088 else if ( typeof cellData
=== 'function' ) {
1089 // If the data source is a function, then we run it and use the return,
1090 // executing in the scope of the data object (for instances)
1091 return cellData
.call( rowData
);
1094 if ( cellData
=== null && type
== 'display' ) {
1102 * Set the value for a specific cell, into the internal data cache
1103 * @param {object} settings dataTables settings object
1104 * @param {int} rowIdx aoData row id
1105 * @param {int} colIdx Column index
1106 * @param {*} val Value to set
1107 * @memberof DataTable#oApi
1109 function _fnSetCellData( settings
, rowIdx
, colIdx
, val
)
1111 var col
= settings
.aoColumns
[colIdx
];
1112 var rowData
= settings
.aoData
[rowIdx
]._aData
;
1114 col
.fnSetData( rowData
, val
, {
1122 // Private variable that is used to match action syntax in the data property object
1123 var __reArray
= /\[.*?\]$/;
1124 var __reFn
= /\(\)$/;
1127 * Split string on periods, taking into account escaped periods
1128 * @param {string} str String to split
1129 * @return {array} Split string
1131 function _fnSplitObjNotation( str
)
1133 return $.map( str
.match(/(\\.|[^\.])+/g), function ( s
) {
1134 return s
.replace(/\\./g, '.');
1140 * Return a function that can be used to get data from a source object, taking
1141 * into account the ability to use nested objects as a source
1142 * @param {string|int|function} mSource The data source for the object
1143 * @returns {function} Data get function
1144 * @memberof DataTable#oApi
1146 function _fnGetObjectDataFn( mSource
)
1148 if ( $.isPlainObject( mSource
) )
1150 /* Build an object of get functions, and wrap them in a single call */
1152 $.each( mSource
, function (key
, val
) {
1154 o
[key
] = _fnGetObjectDataFn( val
);
1158 return function (data
, type
, row
, meta
) {
1159 var t
= o
[type
] || o
._
;
1160 return t
!== undefined ?
1161 t(data
, type
, row
, meta
) :
1165 else if ( mSource
=== null )
1167 /* Give an empty string for rendering / sorting etc */
1168 return function (data
) { // type, row and meta also passed, but not used
1172 else if ( typeof mSource
=== 'function' )
1174 return function (data
, type
, row
, meta
) {
1175 return mSource( data
, type
, row
, meta
);
1178 else if ( typeof mSource
=== 'string' && (mSource
.indexOf('.') !== -1 ||
1179 mSource
.indexOf('[') !== -1 || mSource
.indexOf('(') !== -1) )
1181 /* If there is a . in the source string then the data source is in a
1182 * nested object so we loop over the data for each level to get the next
1183 * level down. On each loop we test for undefined, and if found immediately
1184 * return. This allows entire objects to be missing and sDefaultContent to
1185 * be used if defined, rather than throwing an error
1187 var fetchData = function (data
, type
, src
) {
1188 var arrayNotation
, funcNotation
, out
, innerSrc
;
1192 var a
= _fnSplitObjNotation( src
);
1194 for ( var i
=0, iLen
=a
.length
; i
<iLen
; i
++ )
1196 // Check if we are dealing with special notation
1197 arrayNotation
= a
[i
].match(__reArray
);
1198 funcNotation
= a
[i
].match(__reFn
);
1200 if ( arrayNotation
)
1203 a
[i
] = a
[i
].replace(__reArray
, '');
1205 // Condition allows simply [] to be passed in
1206 if ( a
[i
] !== "" ) {
1207 data
= data
[ a
[i
] ];
1211 // Get the remainder of the nested object to get
1213 innerSrc
= a
.join('.');
1215 // Traverse each entry in the array getting the properties requested
1216 for ( var j
=0, jLen
=data
.length
; j
<jLen
; j
++ ) {
1217 out
.push( fetchData( data
[j
], type
, innerSrc
) );
1220 // If a string is given in between the array notation indicators, that
1221 // is used to join the strings together, otherwise an array is returned
1222 var join
= arrayNotation
[0].substring(1, arrayNotation
[0].length
-1);
1223 data
= (join
==="") ? out
: out
.join(join
);
1225 // The inner call to fetchData has already traversed through the remainder
1226 // of the source requested, so we exit from the loop
1229 else if ( funcNotation
)
1232 a
[i
] = a
[i
].replace(__reFn
, '');
1233 data
= data
[ a
[i
] ]();
1237 if ( data
=== null || data
[ a
[i
] ] === undefined )
1241 data
= data
[ a
[i
] ];
1248 return function (data
, type
) { // row and meta also passed, but not used
1249 return fetchData( data
, type
, mSource
);
1254 /* Array or flat object mapping */
1255 return function (data
, type
) { // row and meta also passed, but not used
1256 return data
[mSource
];
1263 * Return a function that can be used to set data from a source object, taking
1264 * into account the ability to use nested objects as a source
1265 * @param {string|int|function} mSource The data source for the object
1266 * @returns {function} Data set function
1267 * @memberof DataTable#oApi
1269 function _fnSetObjectDataFn( mSource
)
1271 if ( $.isPlainObject( mSource
) )
1273 /* Unlike get, only the underscore (global) option is used for for
1274 * setting data since we don't know the type here. This is why an object
1275 * option is not documented for `mData` (which is read/write), but it is
1276 * for `mRender` which is read only.
1278 return _fnSetObjectDataFn( mSource
._
);
1280 else if ( mSource
=== null )
1282 /* Nothing to do when the data source is null */
1283 return function () {};
1285 else if ( typeof mSource
=== 'function' )
1287 return function (data
, val
, meta
) {
1288 mSource( data
, 'set', val
, meta
);
1291 else if ( typeof mSource
=== 'string' && (mSource
.indexOf('.') !== -1 ||
1292 mSource
.indexOf('[') !== -1 || mSource
.indexOf('(') !== -1) )
1294 /* Like the get, we need to get data from a nested object */
1295 var setData = function (data
, val
, src
) {
1296 var a
= _fnSplitObjNotation( src
), b
;
1297 var aLast
= a
[a
.length
-1];
1298 var arrayNotation
, funcNotation
, o
, innerSrc
;
1300 for ( var i
=0, iLen
=a
.length
-1 ; i
<iLen
; i
++ )
1302 // Check if we are dealing with an array notation request
1303 arrayNotation
= a
[i
].match(__reArray
);
1304 funcNotation
= a
[i
].match(__reFn
);
1306 if ( arrayNotation
)
1308 a
[i
] = a
[i
].replace(__reArray
, '');
1311 // Get the remainder of the nested object to set so we can recurse
1314 innerSrc
= b
.join('.');
1316 // Traverse each entry in the array setting the properties requested
1317 for ( var j
=0, jLen
=val
.length
; j
<jLen
; j
++ )
1320 setData( o
, val
[j
], innerSrc
);
1321 data
[ a
[i
] ].push( o
);
1324 // The inner call to setData has already traversed through the remainder
1325 // of the source and has set the data, thus we can exit here
1328 else if ( funcNotation
)
1331 a
[i
] = a
[i
].replace(__reFn
, '');
1332 data
= data
[ a
[i
] ]( val
);
1335 // If the nested object doesn't currently exist - since we are
1336 // trying to set the value - create it
1337 if ( data
[ a
[i
] ] === null || data
[ a
[i
] ] === undefined )
1341 data
= data
[ a
[i
] ];
1344 // Last item in the input - i.e, the actual set
1345 if ( aLast
.match(__reFn
) )
1348 data
= data
[ aLast
.replace(__reFn
, '') ]( val
);
1352 // If array notation is used, we just want to strip it and use the property name
1353 // and assign the value. If it isn't used, then we get the result we want anyway
1354 data
[ aLast
.replace(__reArray
, '') ] = val
;
1358 return function (data
, val
) { // meta is also passed in, but not used
1359 return setData( data
, val
, mSource
);
1364 /* Array or flat object mapping */
1365 return function (data
, val
) { // meta is also passed in, but not used
1366 data
[mSource
] = val
;
1373 * Return an array with the full table data
1374 * @param {object} oSettings dataTables settings object
1375 * @returns array {array} aData Master data array
1376 * @memberof DataTable#oApi
1378 function _fnGetDataMaster ( settings
)
1380 return _pluck( settings
.aoData
, '_aData' );
1386 * @param {object} oSettings dataTables settings object
1387 * @memberof DataTable#oApi
1389 function _fnClearTable( settings
)
1391 settings
.aoData
.length
= 0;
1392 settings
.aiDisplayMaster
.length
= 0;
1393 settings
.aiDisplay
.length
= 0;
1398 * Take an array of integers (index array) and remove a target integer (value - not
1400 * @param {array} a Index array to target
1401 * @param {int} iTarget value to find
1402 * @memberof DataTable#oApi
1404 function _fnDeleteIndex( a
, iTarget
, splice
)
1406 var iTargetIndex
= -1;
1408 for ( var i
=0, iLen
=a
.length
; i
<iLen
; i
++ )
1410 if ( a
[i
] == iTarget
)
1414 else if ( a
[i
] > iTarget
)
1420 if ( iTargetIndex
!= -1 && splice
=== undefined )
1422 a
.splice( iTargetIndex
, 1 );
1428 * Mark cached data as invalid such that a re-read of the data will occur when
1429 * the cached data is next requested. Also update from the data source object.
1431 * @param {object} settings DataTables settings object
1432 * @param {int} rowIdx Row index to invalidate
1433 * @memberof DataTable#oApi
1435 * @todo For the modularisation of v1.11 this will need to become a callback, so
1436 * the sort and filter methods can subscribe to it. That will required
1437 * initialisation options for sorting, which is why it is not already baked in
1439 function _fnInvalidateRow( settings
, rowIdx
, src
, column
)
1441 var row
= settings
.aoData
[ rowIdx
];
1444 // Are we reading last data from DOM or the data object?
1445 if ( src
=== 'dom' || ((! src
|| src
=== 'auto') && row
.src
=== 'dom') ) {
1446 // Read the data from the DOM
1447 row
._aData
= _fnGetRowElements( settings
, row
).data
;
1450 // Reading from data object, update the DOM
1451 var cells
= row
.anCells
;
1455 for ( i
=0, ien
=cells
.length
; i
<ien
; i
++ ) {
1458 // This is very frustrating, but in IE if you just write directly
1459 // to innerHTML, and elements that are overwritten are GC'ed,
1460 // even if there is a reference to them elsewhere
1461 while ( cell
.childNodes
.length
) {
1462 cell
.removeChild( cell
.firstChild
);
1465 cells
[i
].innerHTML
= _fnGetCellData( settings
, rowIdx
, i
, 'display' );
1470 row
._aSortData
= null;
1471 row
._aFilterData
= null;
1473 // Invalidate the type for a specific column (if given) or all columns since
1474 // the data might have changed
1475 var cols
= settings
.aoColumns
;
1476 if ( column
!== undefined ) {
1477 cols
[ column
].sType
= null;
1480 for ( i
=0, ien
=cols
.length
; i
<ien
; i
++ ) {
1481 cols
[i
].sType
= null;
1485 // Update DataTables special `DT_*` attributes for the row
1486 _fnRowAttributes( row
);
1491 * Build a data source object from an HTML row, reading the contents of the
1492 * cells that are in the row.
1494 * @param {object} settings DataTables settings object
1495 * @param {node|object} TR element from which to read data or existing row
1496 * object from which to re-read the data from the cells
1497 * @returns {object} Object with two parameters: `data` the data read, in
1498 * document order, and `cells` and array of nodes (they can be useful to the
1499 * caller, so rather than needing a second traversal to get them, just return
1501 * @memberof DataTable#oApi
1503 function _fnGetRowElements( settings
, row
)
1507 td
= row
.firstChild
,
1508 name
, col
, o
, i
=0, contents
,
1509 columns
= settings
.aoColumns
,
1510 objectRead
= settings
._rowReadObject
;
1512 var d
= objectRead
? {} : [];
1514 var attr = function ( str
, td
) {
1515 if ( typeof str
=== 'string' ) {
1516 var idx
= str
.indexOf('@');
1519 var attr
= str
.substring( idx
+1 );
1520 var setter
= _fnSetObjectDataFn( str
);
1521 setter( d
, td
.getAttribute( attr
) );
1526 var cellProcess = function ( cell
) {
1528 contents
= $.trim(cell
.innerHTML
);
1530 if ( col
&& col
._bAttrSrc
) {
1531 var setter
= _fnSetObjectDataFn( col
.mData
._
);
1532 setter( d
, contents
);
1534 attr( col
.mData
.sort
, cell
);
1535 attr( col
.mData
.type
, cell
);
1536 attr( col
.mData
.filter
, cell
);
1539 // Depending on the `data` option for the columns the data can be
1540 // read to either an object or an array.
1542 if ( ! col
._setter
) {
1543 // Cache the setter function
1544 col
._setter
= _fnSetObjectDataFn( col
.mData
);
1546 col
._setter( d
, contents
);
1557 // `tr` element passed in
1559 name
= td
.nodeName
.toUpperCase();
1561 if ( name
== "TD" || name
== "TH" ) {
1566 td
= td
.nextSibling
;
1570 // Existing row object passed in
1573 for ( var j
=0, jen
=tds
.length
; j
<jen
; j
++ ) {
1574 cellProcess( tds
[j
] );
1584 * Create a new TR element (and it's TD children) for a row
1585 * @param {object} oSettings dataTables settings object
1586 * @param {int} iRow Row to consider
1587 * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1588 * DataTables will create a row automatically
1589 * @param {array} [anTds] Array of TD|TH elements for the row - must be given
1591 * @memberof DataTable#oApi
1593 function _fnCreateTr ( oSettings
, iRow
, nTrIn
, anTds
)
1596 row
= oSettings
.aoData
[iRow
],
1597 rowData
= row
._aData
,
1602 if ( row
.nTr
=== null )
1604 nTr
= nTrIn
|| document
.createElement('tr');
1607 row
.anCells
= cells
;
1609 /* Use a private property on the node to allow reserve mapping from the node
1610 * to the aoData array for fast look up
1612 nTr
._DT_RowIndex
= iRow
;
1614 /* Special parameters can be given by the data source to be used on the row */
1615 _fnRowAttributes( row
);
1617 /* Process each column */
1618 for ( i
=0, iLen
=oSettings
.aoColumns
.length
; i
<iLen
; i
++ )
1620 oCol
= oSettings
.aoColumns
[i
];
1622 nTd
= nTrIn
? anTds
[i
] : document
.createElement( oCol
.sCellType
);
1625 // Need to create the HTML if new, or if a rendering function is defined
1626 if ( !nTrIn
|| oCol
.mRender
|| oCol
.mData
!== i
)
1628 nTd
.innerHTML
= _fnGetCellData( oSettings
, iRow
, i
, 'display' );
1631 /* Add user defined class */
1634 nTd
.className
+= ' '+oCol
.sClass
;
1637 // Visibility - add or remove as required
1638 if ( oCol
.bVisible
&& ! nTrIn
)
1640 nTr
.appendChild( nTd
);
1642 else if ( ! oCol
.bVisible
&& nTrIn
)
1644 nTd
.parentNode
.removeChild( nTd
);
1647 if ( oCol
.fnCreatedCell
)
1649 oCol
.fnCreatedCell
.call( oSettings
.oInstance
,
1650 nTd
, _fnGetCellData( oSettings
, iRow
, i
), rowData
, iRow
, i
1655 _fnCallbackFire( oSettings
, 'aoRowCreatedCallback', null, [nTr
, rowData
, iRow
] );
1658 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1660 row
.nTr
.setAttribute( 'role', 'row' );
1665 * Add attributes to a row based on the special `DT_*` parameters in a data
1667 * @param {object} DataTables row object for the row to be modified
1668 * @memberof DataTable#oApi
1670 function _fnRowAttributes( row
)
1673 var data
= row
._aData
;
1676 if ( data
.DT_RowId
) {
1677 tr
.id
= data
.DT_RowId
;
1680 if ( data
.DT_RowClass
) {
1681 // Remove any classes added by DT_RowClass before
1682 var a
= data
.DT_RowClass
.split(' ');
1683 row
.__rowc
= row
.__rowc
?
1684 _unique( row
.__rowc
.concat( a
) ) :
1688 .removeClass( row
.__rowc
.join(' ') )
1689 .addClass( data
.DT_RowClass
);
1692 if ( data
.DT_RowData
) {
1693 $(tr
).data( data
.DT_RowData
);
1700 * Create the HTML header for the table
1701 * @param {object} oSettings dataTables settings object
1702 * @memberof DataTable#oApi
1704 function _fnBuildHead( oSettings
)
1706 var i
, ien
, cell
, row
, column
;
1707 var thead
= oSettings
.nTHead
;
1708 var tfoot
= oSettings
.nTFoot
;
1709 var createHeader
= $('th, td', thead
).length
=== 0;
1710 var classes
= oSettings
.oClasses
;
1711 var columns
= oSettings
.aoColumns
;
1713 if ( createHeader
) {
1714 row
= $('<tr/>').appendTo( thead
);
1717 for ( i
=0, ien
=columns
.length
; i
<ien
; i
++ ) {
1718 column
= columns
[i
];
1719 cell
= $( column
.nTh
).addClass( column
.sClass
);
1721 if ( createHeader
) {
1722 cell
.appendTo( row
);
1725 // 1.11 move into sorting
1726 if ( oSettings
.oFeatures
.bSort
) {
1727 cell
.addClass( column
.sSortingClass
);
1729 if ( column
.bSortable
!== false ) {
1731 .attr( 'tabindex', oSettings
.iTabIndex
)
1732 .attr( 'aria-controls', oSettings
.sTableId
);
1734 _fnSortAttachListener( oSettings
, column
.nTh
, i
);
1738 if ( column
.sTitle
!= cell
.html() ) {
1739 cell
.html( column
.sTitle
);
1742 _fnRenderer( oSettings
, 'header' )(
1743 oSettings
, cell
, column
, classes
1747 if ( createHeader
) {
1748 _fnDetectHeader( oSettings
.aoHeader
, thead
);
1751 /* ARIA role for the rows */
1752 $(thead
).find('>tr').attr('role', 'row');
1754 /* Deal with the footer - add classes if required */
1755 $(thead
).find('>tr>th, >tr>td').addClass( classes
.sHeaderTH
);
1756 $(tfoot
).find('>tr>th, >tr>td').addClass( classes
.sFooterTH
);
1758 // Cache the footer cells. Note that we only take the cells from the first
1759 // row in the footer. If there is more than one row the user wants to
1760 // interact with, they need to use the table().foot() method. Note also this
1761 // allows cells to be used for multiple columns using colspan
1762 if ( tfoot
!== null ) {
1763 var cells
= oSettings
.aoFooter
[0];
1765 for ( i
=0, ien
=cells
.length
; i
<ien
; i
++ ) {
1766 column
= columns
[i
];
1767 column
.nTf
= cells
[i
].cell
;
1769 if ( column
.sClass
) {
1770 $(column
.nTf
).addClass( column
.sClass
);
1778 * Draw the header (or footer) element based on the column visibility states. The
1779 * methodology here is to use the layout array from _fnDetectHeader, modified for
1780 * the instantaneous column visibility, to construct the new layout. The grid is
1781 * traversed over cell at a time in a rows x columns grid fashion, although each
1782 * cell insert can cover multiple elements in the grid - which is tracks using the
1783 * aApplied array. Cell inserts in the grid will only occur where there isn't
1784 * already a cell in that position.
1785 * @param {object} oSettings dataTables settings object
1786 * @param array {objects} aoSource Layout array from _fnDetectHeader
1787 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1788 * @memberof DataTable#oApi
1790 function _fnDrawHead( oSettings
, aoSource
, bIncludeHidden
)
1792 var i
, iLen
, j
, jLen
, k
, kLen
, n
, nLocalTr
;
1795 var iColumns
= oSettings
.aoColumns
.length
;
1796 var iRowspan
, iColspan
;
1803 if ( bIncludeHidden
=== undefined )
1805 bIncludeHidden
= false;
1808 /* Make a copy of the master layout array, but without the visible columns in it */
1809 for ( i
=0, iLen
=aoSource
.length
; i
<iLen
; i
++ )
1811 aoLocal
[i
] = aoSource
[i
].slice();
1812 aoLocal
[i
].nTr
= aoSource
[i
].nTr
;
1814 /* Remove any columns which are currently hidden */
1815 for ( j
=iColumns
-1 ; j
>=0 ; j
-- )
1817 if ( !oSettings
.aoColumns
[j
].bVisible
&& !bIncludeHidden
)
1819 aoLocal
[i
].splice( j
, 1 );
1823 /* Prep the applied array - it needs an element for each row */
1824 aApplied
.push( [] );
1827 for ( i
=0, iLen
=aoLocal
.length
; i
<iLen
; i
++ )
1829 nLocalTr
= aoLocal
[i
].nTr
;
1831 /* All cells are going to be replaced, so empty out the row */
1834 while( (n
= nLocalTr
.firstChild
) )
1836 nLocalTr
.removeChild( n
);
1840 for ( j
=0, jLen
=aoLocal
[i
].length
; j
<jLen
; j
++ )
1845 /* Check to see if there is already a cell (row/colspan) covering our target
1846 * insert point. If there is, then there is nothing to do.
1848 if ( aApplied
[i
][j
] === undefined )
1850 nLocalTr
.appendChild( aoLocal
[i
][j
].cell
);
1853 /* Expand the cell to cover as many rows as needed */
1854 while ( aoLocal
[i
+iRowspan
] !== undefined &&
1855 aoLocal
[i
][j
].cell
== aoLocal
[i
+iRowspan
][j
].cell
)
1857 aApplied
[i
+iRowspan
][j
] = 1;
1861 /* Expand the cell to cover as many columns as needed */
1862 while ( aoLocal
[i
][j
+iColspan
] !== undefined &&
1863 aoLocal
[i
][j
].cell
== aoLocal
[i
][j
+iColspan
].cell
)
1865 /* Must update the applied array over the rows for the columns */
1866 for ( k
=0 ; k
<iRowspan
; k
++ )
1868 aApplied
[i
+k
][j
+iColspan
] = 1;
1873 /* Do the actual expansion in the DOM */
1874 $(aoLocal
[i
][j
].cell
)
1875 .attr('rowspan', iRowspan
)
1876 .attr('colspan', iColspan
);
1884 * Insert the required TR nodes into the table for display
1885 * @param {object} oSettings dataTables settings object
1886 * @memberof DataTable#oApi
1888 function _fnDraw( oSettings
)
1890 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1891 var aPreDraw
= _fnCallbackFire( oSettings
, 'aoPreDrawCallback', 'preDraw', [oSettings
] );
1892 if ( $.inArray( false, aPreDraw
) !== -1 )
1894 _fnProcessingDisplay( oSettings
, false );
1901 var asStripeClasses
= oSettings
.asStripeClasses
;
1902 var iStripes
= asStripeClasses
.length
;
1903 var iOpenRows
= oSettings
.aoOpenRows
.length
;
1904 var oLang
= oSettings
.oLanguage
;
1905 var iInitDisplayStart
= oSettings
.iInitDisplayStart
;
1906 var bServerSide
= _fnDataSource( oSettings
) == 'ssp';
1907 var aiDisplay
= oSettings
.aiDisplay
;
1909 oSettings
.bDrawing
= true;
1911 /* Check and see if we have an initial draw position from state saving */
1912 if ( iInitDisplayStart
!== undefined && iInitDisplayStart
!== -1 )
1914 oSettings
._iDisplayStart
= bServerSide
?
1916 iInitDisplayStart
>= oSettings
.fnRecordsDisplay() ?
1920 oSettings
.iInitDisplayStart
= -1;
1923 var iDisplayStart
= oSettings
._iDisplayStart
;
1924 var iDisplayEnd
= oSettings
.fnDisplayEnd();
1926 /* Server-side processing draw intercept */
1927 if ( oSettings
.bDeferLoading
)
1929 oSettings
.bDeferLoading
= false;
1931 _fnProcessingDisplay( oSettings
, false );
1933 else if ( !bServerSide
)
1937 else if ( !oSettings
.bDestroying
&& !_fnAjaxUpdate( oSettings
) )
1942 if ( aiDisplay
.length
!== 0 )
1944 var iStart
= bServerSide
? 0 : iDisplayStart
;
1945 var iEnd
= bServerSide
? oSettings
.aoData
.length
: iDisplayEnd
;
1947 for ( var j
=iStart
; j
<iEnd
; j
++ )
1949 var iDataIndex
= aiDisplay
[j
];
1950 var aoData
= oSettings
.aoData
[ iDataIndex
];
1951 if ( aoData
.nTr
=== null )
1953 _fnCreateTr( oSettings
, iDataIndex
);
1956 var nRow
= aoData
.nTr
;
1958 /* Remove the old striping classes and then add the new one */
1959 if ( iStripes
!== 0 )
1961 var sStripe
= asStripeClasses
[ iRowCount
% iStripes
];
1962 if ( aoData
._sRowStripe
!= sStripe
)
1964 $(nRow
).removeClass( aoData
._sRowStripe
).addClass( sStripe
);
1965 aoData
._sRowStripe
= sStripe
;
1969 // Row callback functions - might want to manipulate the row
1970 // iRowCount and j are not currently documented. Are they at all
1972 _fnCallbackFire( oSettings
, 'aoRowCallback', null,
1973 [nRow
, aoData
._aData
, iRowCount
, j
] );
1975 anRows
.push( nRow
);
1981 /* Table is empty - create a row with an empty message in it */
1982 var sZero
= oLang
.sZeroRecords
;
1983 if ( oSettings
.iDraw
== 1 && _fnDataSource( oSettings
) == 'ajax' )
1985 sZero
= oLang
.sLoadingRecords
;
1987 else if ( oLang
.sEmptyTable
&& oSettings
.fnRecordsTotal() === 0 )
1989 sZero
= oLang
.sEmptyTable
;
1992 anRows
[ 0 ] = $( '<tr/>', { 'class': iStripes
? asStripeClasses
[0] : '' } )
1993 .append( $('<td />', {
1995 'colSpan': _fnVisbleColumns( oSettings
),
1996 'class': oSettings
.oClasses
.sRowEmpty
1997 } ).html( sZero
) )[0];
2000 /* Header and footer callbacks */
2001 _fnCallbackFire( oSettings
, 'aoHeaderCallback', 'header', [ $(oSettings
.nTHead
).children('tr')[0],
2002 _fnGetDataMaster( oSettings
), iDisplayStart
, iDisplayEnd
, aiDisplay
] );
2004 _fnCallbackFire( oSettings
, 'aoFooterCallback', 'footer', [ $(oSettings
.nTFoot
).children('tr')[0],
2005 _fnGetDataMaster( oSettings
), iDisplayStart
, iDisplayEnd
, aiDisplay
] );
2007 var body
= $(oSettings
.nTBody
);
2009 body
.children().detach();
2010 body
.append( $(anRows
) );
2012 /* Call all required callback functions for the end of a draw */
2013 _fnCallbackFire( oSettings
, 'aoDrawCallback', 'draw', [oSettings
] );
2015 /* Draw is complete, sorting and filtering must be as well */
2016 oSettings
.bSorted
= false;
2017 oSettings
.bFiltered
= false;
2018 oSettings
.bDrawing
= false;
2023 * Redraw the table - taking account of the various features which are enabled
2024 * @param {object} oSettings dataTables settings object
2025 * @param {boolean} [holdPosition] Keep the current paging position. By default
2026 * the paging is reset to the first page
2027 * @memberof DataTable#oApi
2029 function _fnReDraw( settings
, holdPosition
)
2032 features
= settings
.oFeatures
,
2033 sort
= features
.bSort
,
2034 filter
= features
.bFilter
;
2037 _fnSort( settings
);
2041 _fnFilterComplete( settings
, settings
.oPreviousSearch
);
2044 // No filtering, so we want to just use the display master
2045 settings
.aiDisplay
= settings
.aiDisplayMaster
.slice();
2048 if ( holdPosition
!== true ) {
2049 settings
._iDisplayStart
= 0;
2052 // Let any modules know about the draw hold position state (used by
2053 // scrolling internally)
2054 settings
._drawHold
= holdPosition
;
2056 _fnDraw( settings
);
2058 settings
._drawHold
= false;
2063 * Add the options to the page HTML for the table
2064 * @param {object} oSettings dataTables settings object
2065 * @memberof DataTable#oApi
2067 function _fnAddOptionsHtml ( oSettings
)
2069 var classes
= oSettings
.oClasses
;
2070 var table
= $(oSettings
.nTable
);
2071 var holding
= $('<div/>').insertBefore( table
); // Holding element for speed
2072 var features
= oSettings
.oFeatures
;
2074 // All DataTables are wrapped in a div
2075 var insert
= $('<div/>', {
2076 id
: oSettings
.sTableId
+'_wrapper',
2077 'class': classes
.sWrapper
+ (oSettings
.nTFoot
? '' : ' '+classes
.sNoFooter
)
2080 oSettings
.nHolding
= holding
[0];
2081 oSettings
.nTableWrapper
= insert
[0];
2082 oSettings
.nTableReinsertBefore
= oSettings
.nTable
.nextSibling
;
2084 /* Loop over the user set positioning and place the elements as needed */
2085 var aDom
= oSettings
.sDom
.split('');
2086 var featureNode
, cOption
, nNewNode
, cNext
, sAttr
, j
;
2087 for ( var i
=0 ; i
<aDom
.length
; i
++ )
2092 if ( cOption
== '<' )
2094 /* New container div */
2095 nNewNode
= $('<div/>')[0];
2097 /* Check to see if we should append an id and/or a class name to the container */
2099 if ( cNext == "'" || cNext == '"' )
2103 while ( aDom[i+j] != cNext )
2109 /* Replace jQuery UI constants @todo depreciated */
2112 sAttr
= classes
.sJUIHeader
;
2114 else if ( sAttr
== "F" )
2116 sAttr
= classes
.sJUIFooter
;
2119 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2120 * breaks the string into parts and applies them as needed
2122 if ( sAttr
.indexOf('.') != -1 )
2124 var aSplit
= sAttr
.split('.');
2125 nNewNode
.id
= aSplit
[0].substr(1, aSplit
[0].length
-1);
2126 nNewNode
.className
= aSplit
[1];
2128 else if ( sAttr
.charAt(0) == "#" )
2130 nNewNode
.id
= sAttr
.substr(1, sAttr
.length
-1);
2134 nNewNode
.className
= sAttr
;
2137 i
+= j
; /* Move along the position array */
2140 insert
.append( nNewNode
);
2141 insert
= $(nNewNode
);
2143 else if ( cOption
== '>' )
2145 /* End container div */
2146 insert
= insert
.parent();
2148 // @todo Move options into their own plugins?
2149 else if ( cOption
== 'l' && features
.bPaginate
&& features
.bLengthChange
)
2152 featureNode
= _fnFeatureHtmlLength( oSettings
);
2154 else if ( cOption
== 'f' && features
.bFilter
)
2157 featureNode
= _fnFeatureHtmlFilter( oSettings
);
2159 else if ( cOption
== 'r' && features
.bProcessing
)
2162 featureNode
= _fnFeatureHtmlProcessing( oSettings
);
2164 else if ( cOption
== 't' )
2167 featureNode
= _fnFeatureHtmlTable( oSettings
);
2169 else if ( cOption
== 'i' && features
.bInfo
)
2172 featureNode
= _fnFeatureHtmlInfo( oSettings
);
2174 else if ( cOption
== 'p' && features
.bPaginate
)
2177 featureNode
= _fnFeatureHtmlPaginate( oSettings
);
2179 else if ( DataTable
.ext
.feature
.length
!== 0 )
2181 /* Plug-in features */
2182 var aoFeatures
= DataTable
.ext
.feature
;
2183 for ( var k
=0, kLen
=aoFeatures
.length
; k
<kLen
; k
++ )
2185 if ( cOption
== aoFeatures
[k
].cFeature
)
2187 featureNode
= aoFeatures
[k
].fnInit( oSettings
);
2193 /* Add to the 2D features array */
2196 var aanFeatures
= oSettings
.aanFeatures
;
2198 if ( ! aanFeatures
[cOption
] )
2200 aanFeatures
[cOption
] = [];
2203 aanFeatures
[cOption
].push( featureNode
);
2204 insert
.append( featureNode
);
2208 /* Built our DOM structure - replace the holding div with what we want */
2209 holding
.replaceWith( insert
);
2214 * Use the DOM source to create up an array of header cells. The idea here is to
2215 * create a layout grid (array) of rows x columns, which contains a reference
2216 * to the cell that that point in the grid (regardless of col/rowspan), such that
2217 * any column / row could be removed and the new grid constructed
2218 * @param array {object} aLayout Array to store the calculated layout in
2219 * @param {node} nThead The header/footer element for the table
2220 * @memberof DataTable#oApi
2222 function _fnDetectHeader ( aLayout
, nThead
)
2224 var nTrs
= $(nThead
).children('tr');
2226 var i
, k
, l
, iLen
, jLen
, iColShifted
, iColumn
, iColspan
, iRowspan
;
2228 var fnShiftCol = function ( a
, i
, j
) {
2236 aLayout
.splice( 0, aLayout
.length
);
2238 /* We know how many rows there are in the layout - so prep it */
2239 for ( i
=0, iLen
=nTrs
.length
; i
<iLen
; i
++ )
2244 /* Calculate a layout array */
2245 for ( i
=0, iLen
=nTrs
.length
; i
<iLen
; i
++ )
2250 /* For every cell in the row... */
2251 nCell
= nTr
.firstChild
;
2253 if ( nCell
.nodeName
.toUpperCase() == "TD" ||
2254 nCell
.nodeName
.toUpperCase() == "TH" )
2256 /* Get the col and rowspan attributes from the DOM and sanitise them */
2257 iColspan
= nCell
.getAttribute('colspan') * 1;
2258 iRowspan
= nCell
.getAttribute('rowspan') * 1;
2259 iColspan
= (!iColspan
|| iColspan
===0 || iColspan
===1) ? 1 : iColspan
;
2260 iRowspan
= (!iRowspan
|| iRowspan
===0 || iRowspan
===1) ? 1 : iRowspan
;
2262 /* There might be colspan cells already in this row, so shift our target
2265 iColShifted
= fnShiftCol( aLayout
, i
, iColumn
);
2267 /* Cache calculation for unique columns */
2268 bUnique
= iColspan
=== 1 ? true : false;
2270 /* If there is col / rowspan, copy the information into the layout grid */
2271 for ( l
=0 ; l
<iColspan
; l
++ )
2273 for ( k
=0 ; k
<iRowspan
; k
++ )
2275 aLayout
[i
+k
][iColShifted
+l
] = {
2279 aLayout
[i
+k
].nTr
= nTr
;
2283 nCell
= nCell
.nextSibling
;
2290 * Get an array of unique th elements, one for each column
2291 * @param {object} oSettings dataTables settings object
2292 * @param {node} nHeader automatically detect the layout from this node - optional
2293 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2294 * @returns array {node} aReturn list of unique th's
2295 * @memberof DataTable#oApi
2297 function _fnGetUniqueThs ( oSettings
, nHeader
, aLayout
)
2302 aLayout
= oSettings
.aoHeader
;
2306 _fnDetectHeader( aLayout
, nHeader
);
2310 for ( var i
=0, iLen
=aLayout
.length
; i
<iLen
; i
++ )
2312 for ( var j
=0, jLen
=aLayout
[i
].length
; j
<jLen
; j
++ )
2314 if ( aLayout
[i
][j
].unique
&&
2315 (!aReturn
[j
] || !oSettings
.bSortCellsTop
) )
2317 aReturn
[j
] = aLayout
[i
][j
].cell
;
2328 * Create an Ajax call based on the table's settings, taking into account that
2329 * parameters can have multiple forms, and backwards compatibility.
2331 * @param {object} oSettings dataTables settings object
2332 * @param {array} data Data to send to the server, required by
2333 * DataTables - may be augmented by developer callbacks
2334 * @param {function} fn Callback function to run when data is obtained
2336 function _fnBuildAjax( oSettings
, data
, fn
)
2338 // Compatibility with 1.9-, allow fnServerData and event to manipulate
2339 _fnCallbackFire( oSettings
, 'aoServerParams', 'serverParams', [data
] );
2341 // Convert to object based for 1.10+ if using the old array scheme which can
2342 // come from server-side processing or serverParams
2343 if ( data
&& $.isArray(data
) ) {
2345 var rbracket
= /(.*?)\[\]$/;
2347 $.each( data
, function (key
, val
) {
2348 var match
= val
.name
.match(rbracket
);
2351 // Support for arrays
2352 var name
= match
[0];
2354 if ( ! tmp
[ name
] ) {
2357 tmp
[ name
].push( val
.value
);
2360 tmp
[val
.name
] = val
.value
;
2367 var ajax
= oSettings
.ajax
;
2368 var instance
= oSettings
.oInstance
;
2370 if ( $.isPlainObject( ajax
) && ajax
.data
)
2372 ajaxData
= ajax
.data
;
2374 var newData
= $.isFunction( ajaxData
) ?
2375 ajaxData( data
) : // fn can manipulate data or return an object
2376 ajaxData
; // object or array to merge
2378 // If the function returned an object, use that alone
2379 data
= $.isFunction( ajaxData
) && newData
?
2381 $.extend( true, data
, newData
);
2383 // Remove the data property as we've resolved it already and don't want
2384 // jQuery to do it again (it is restored at the end of the function)
2390 "success": function (json
) {
2391 var error
= json
.error
|| json
.sError
;
2393 oSettings
.oApi
._fnLog( oSettings
, 0, error
);
2396 oSettings
.json
= json
;
2397 _fnCallbackFire( oSettings
, null, 'xhr', [oSettings
, json
] );
2402 "type": oSettings
.sServerMethod
,
2403 "error": function (xhr
, error
, thrown
) {
2404 var log
= oSettings
.oApi
._fnLog
;
2406 if ( error
== "parsererror" ) {
2407 log( oSettings
, 0, 'Invalid JSON response', 1 );
2409 else if ( xhr
.readyState
=== 4 ) {
2410 log( oSettings
, 0, 'Ajax error', 7 );
2413 _fnProcessingDisplay( oSettings
, false );
2417 // Store the data submitted for the API
2418 oSettings
.oAjaxData
= data
;
2420 // Allow plug-ins and external processes to modify the data
2421 _fnCallbackFire( oSettings
, null, 'preXhr', [oSettings
, data
] );
2423 if ( oSettings
.fnServerData
)
2425 // DataTables 1.9- compatibility
2426 oSettings
.fnServerData
.call( instance
,
2427 oSettings
.sAjaxSource
,
2428 $.map( data
, function (val
, key
) { // Need to convert back to 1.9 trad format
2429 return { name
: key
, value
: val
};
2435 else if ( oSettings
.sAjaxSource
|| typeof ajax
=== 'string' )
2437 // DataTables 1.9- compatibility
2438 oSettings
.jqXHR
= $.ajax( $.extend( baseAjax
, {
2439 url
: ajax
|| oSettings
.sAjaxSource
2442 else if ( $.isFunction( ajax
) )
2444 // Is a function - let the caller define what needs to be done
2445 oSettings
.jqXHR
= ajax
.call( instance
, data
, fn
, oSettings
);
2449 // Object to extend the base settings
2450 oSettings
.jqXHR
= $.ajax( $.extend( baseAjax
, ajax
) );
2452 // Restore for next time around
2453 ajax
.data
= ajaxData
;
2459 * Update the table using an Ajax call
2460 * @param {object} settings dataTables settings object
2461 * @returns {boolean} Block the table drawing or not
2462 * @memberof DataTable#oApi
2464 function _fnAjaxUpdate( settings
)
2466 if ( settings
.bAjaxDataGet
) {
2468 _fnProcessingDisplay( settings
, true );
2472 _fnAjaxParameters( settings
),
2474 _fnAjaxUpdateDraw( settings
, json
);
2485 * Build up the parameters in an object needed for a server-side processing
2486 * request. Note that this is basically done twice, is different ways - a modern
2487 * method which is used by default in DataTables 1.10 which uses objects and
2488 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2489 * the sAjaxSource option is used in the initialisation, or the legacyAjax
2491 * @param {object} oSettings dataTables settings object
2492 * @returns {bool} block the table drawing or not
2493 * @memberof DataTable#oApi
2495 function _fnAjaxParameters( settings
)
2498 columns
= settings
.aoColumns
,
2499 columnCount
= columns
.length
,
2500 features
= settings
.oFeatures
,
2501 preSearch
= settings
.oPreviousSearch
,
2502 preColSearch
= settings
.aoPreSearchCols
,
2503 i
, data
= [], dataProp
, column
, columnSearch
,
2504 sort
= _fnSortFlatten( settings
),
2505 displayStart
= settings
._iDisplayStart
,
2506 displayLength
= features
.bPaginate
!== false ?
2507 settings
._iDisplayLength
:
2510 var param = function ( name
, value
) {
2511 data
.push( { 'name': name
, 'value': value
} );
2514 // DataTables 1.9- compatible method
2515 param( 'sEcho', settings
.iDraw
);
2516 param( 'iColumns', columnCount
);
2517 param( 'sColumns', _pluck( columns
, 'sName' ).join(',') );
2518 param( 'iDisplayStart', displayStart
);
2519 param( 'iDisplayLength', displayLength
);
2521 // DataTables 1.10+ method
2523 draw
: settings
.iDraw
,
2526 start
: displayStart
,
2527 length
: displayLength
,
2529 value
: preSearch
.sSearch
,
2530 regex
: preSearch
.bRegex
2534 for ( i
=0 ; i
<columnCount
; i
++ ) {
2535 column
= columns
[i
];
2536 columnSearch
= preColSearch
[i
];
2537 dataProp
= typeof column
.mData
=="function" ? 'function' : column
.mData
;
2542 searchable
: column
.bSearchable
,
2543 orderable
: column
.bSortable
,
2545 value
: columnSearch
.sSearch
,
2546 regex
: columnSearch
.bRegex
2550 param( "mDataProp_"+i
, dataProp
);
2552 if ( features
.bFilter
) {
2553 param( 'sSearch_'+i
, columnSearch
.sSearch
);
2554 param( 'bRegex_'+i
, columnSearch
.bRegex
);
2555 param( 'bSearchable_'+i
, column
.bSearchable
);
2558 if ( features
.bSort
) {
2559 param( 'bSortable_'+i
, column
.bSortable
);
2563 if ( features
.bFilter
) {
2564 param( 'sSearch', preSearch
.sSearch
);
2565 param( 'bRegex', preSearch
.bRegex
);
2568 if ( features
.bSort
) {
2569 $.each( sort
, function ( i
, val
) {
2570 d
.order
.push( { column
: val
.col
, dir
: val
.dir
} );
2572 param( 'iSortCol_'+i
, val
.col
);
2573 param( 'sSortDir_'+i
, val
.dir
);
2576 param( 'iSortingCols', sort
.length
);
2579 // If the legacy.ajax parameter is null, then we automatically decide which
2580 // form to use, based on sAjaxSource
2581 var legacy
= DataTable
.ext
.legacy
.ajax
;
2582 if ( legacy
=== null ) {
2583 return settings
.sAjaxSource
? data
: d
;
2586 // Otherwise, if legacy has been specified then we use that to decide on the
2588 return legacy
? data
: d
;
2593 * Data the data from the server (nuking the old) and redraw the table
2594 * @param {object} oSettings dataTables settings object
2595 * @param {object} json json data return from the server.
2596 * @param {string} json.sEcho Tracking flag for DataTables to match requests
2597 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2598 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2599 * @param {array} json.aaData The data to display on this page
2600 * @param {string} [json.sColumns] Column ordering (sName, comma separated)
2601 * @memberof DataTable#oApi
2603 function _fnAjaxUpdateDraw ( settings
, json
)
2605 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2607 var compat = function ( old
, modern
) {
2608 return json
[old
] !== undefined ? json
[old
] : json
[modern
];
2611 var draw
= compat( 'sEcho', 'draw' );
2612 var recordsTotal
= compat( 'iTotalRecords', 'recordsTotal' );
2613 var rocordsFiltered
= compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2616 // Protect against out of sequence returns
2617 if ( draw
*1 < settings
.iDraw
) {
2620 settings
.iDraw
= draw
* 1;
2623 _fnClearTable( settings
);
2624 settings
._iRecordsTotal
= parseInt(recordsTotal
, 10);
2625 settings
._iRecordsDisplay
= parseInt(rocordsFiltered
, 10);
2627 var data
= _fnAjaxDataSrc( settings
, json
);
2628 for ( var i
=0, ien
=data
.length
; i
<ien
; i
++ ) {
2629 _fnAddData( settings
, data
[i
] );
2631 settings
.aiDisplay
= settings
.aiDisplayMaster
.slice();
2633 settings
.bAjaxDataGet
= false;
2634 _fnDraw( settings
);
2636 if ( ! settings
._bInitComplete
) {
2637 _fnInitComplete( settings
, json
);
2640 settings
.bAjaxDataGet
= true;
2641 _fnProcessingDisplay( settings
, false );
2646 * Get the data from the JSON data source to use for drawing a table. Using
2647 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2648 * source object, or from a processing function.
2649 * @param {object} oSettings dataTables settings object
2650 * @param {object} json Data source object / array from the server
2651 * @return {array} Array of data to use
2653 function _fnAjaxDataSrc ( oSettings
, json
)
2655 var dataSrc
= $.isPlainObject( oSettings
.ajax
) && oSettings
.ajax
.dataSrc
!== undefined ?
2656 oSettings
.ajax
.dataSrc
:
2657 oSettings
.sAjaxDataProp
; // Compatibility with 1.9-.
2659 // Compatibility with 1.9-. In order to read from aaData, check if the
2660 // default has been changed, if not, check for aaData
2661 if ( dataSrc
=== 'data' ) {
2662 return json
.aaData
|| json
[dataSrc
];
2665 return dataSrc
!== "" ?
2666 _fnGetObjectDataFn( dataSrc
)( json
) :
2672 * Generate the node required for filtering text
2673 * @returns {node} Filter control element
2674 * @param {object} oSettings dataTables settings object
2675 * @memberof DataTable#oApi
2677 function _fnFeatureHtmlFilter ( settings
)
2679 var classes
= settings
.oClasses
;
2680 var tableId
= settings
.sTableId
;
2681 var language
= settings
.oLanguage
;
2682 var previousSearch
= settings
.oPreviousSearch
;
2683 var features
= settings
.aanFeatures
;
2684 var input
= '<input type="search" class="'+classes
.sFilterInput
+'"/>';
2686 var str
= language
.sSearch
;
2687 str
= str
.match(/_INPUT_/) ?
2688 str
.replace('_INPUT_', input
) :
2691 var filter
= $('<div/>', {
2692 'id': ! features
.f
? tableId
+'_filter' : null,
2693 'class': classes
.sFilter
2695 .append( $('<label/>' ).append( str
) );
2697 var searchFn = function() {
2698 /* Update all other filter input elements for the new display */
2700 var val
= !this.value
? "" : this.value
; // mental IE8 fix :-(
2702 /* Now do the filter */
2703 if ( val
!= previousSearch
.sSearch
) {
2704 _fnFilterComplete( settings
, {
2706 "bRegex": previousSearch
.bRegex
,
2707 "bSmart": previousSearch
.bSmart
,
2708 "bCaseInsensitive": previousSearch
.bCaseInsensitive
2711 // Need to redraw, without resorting
2712 settings
._iDisplayStart
= 0;
2713 _fnDraw( settings
);
2717 var searchDelay
= settings
.searchDelay
!== null ?
2718 settings
.searchDelay
:
2719 _fnDataSource( settings
) === 'ssp' ?
2723 var jqFilter
= $('input', filter
)
2724 .val( previousSearch
.sSearch
)
2725 .attr( 'placeholder', language
.sSearchPlaceholder
)
2727 'keyup.DT search.DT input.DT paste.DT cut.DT',
2729 _fnThrottle( searchFn
, searchDelay
) :
2732 .bind( 'keypress.DT', function(e
) {
2733 /* Prevent form submission */
2734 if ( e
.keyCode
== 13 ) {
2738 .attr('aria-controls', tableId
);
2740 // Update the input elements whenever the table is filtered
2741 $(settings
.nTable
).on( 'search.dt.DT', function ( ev
, s
) {
2742 if ( settings
=== s
) {
2743 // IE9 throws an 'unknown error' if document.activeElement is used
2744 // inside an iframe or frame...
2746 if ( jqFilter
[0] !== document
.activeElement
) {
2747 jqFilter
.val( previousSearch
.sSearch
);
2759 * Filter the table using both the global filter and column based filtering
2760 * @param {object} oSettings dataTables settings object
2761 * @param {object} oSearch search information
2762 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2763 * @memberof DataTable#oApi
2765 function _fnFilterComplete ( oSettings
, oInput
, iForce
)
2767 var oPrevSearch
= oSettings
.oPreviousSearch
;
2768 var aoPrevSearch
= oSettings
.aoPreSearchCols
;
2769 var fnSaveFilter = function ( oFilter
) {
2770 /* Save the filtering values */
2771 oPrevSearch
.sSearch
= oFilter
.sSearch
;
2772 oPrevSearch
.bRegex
= oFilter
.bRegex
;
2773 oPrevSearch
.bSmart
= oFilter
.bSmart
;
2774 oPrevSearch
.bCaseInsensitive
= oFilter
.bCaseInsensitive
;
2776 var fnRegex = function ( o
) {
2777 // Backwards compatibility with the bEscapeRegex option
2778 return o
.bEscapeRegex
!== undefined ? !o
.bEscapeRegex
: o
.bRegex
;
2781 // Resolve any column types that are unknown due to addition or invalidation
2782 // @todo As per sort - can this be moved into an event handler?
2783 _fnColumnTypes( oSettings
);
2785 /* In server-side processing all filtering is done by the server, so no point hanging around here */
2786 if ( _fnDataSource( oSettings
) != 'ssp' )
2789 _fnFilter( oSettings
, oInput
.sSearch
, iForce
, fnRegex(oInput
), oInput
.bSmart
, oInput
.bCaseInsensitive
);
2790 fnSaveFilter( oInput
);
2792 /* Now do the individual column filter */
2793 for ( var i
=0 ; i
<aoPrevSearch
.length
; i
++ )
2795 _fnFilterColumn( oSettings
, aoPrevSearch
[i
].sSearch
, i
, fnRegex(aoPrevSearch
[i
]),
2796 aoPrevSearch
[i
].bSmart
, aoPrevSearch
[i
].bCaseInsensitive
);
2799 /* Custom filtering */
2800 _fnFilterCustom( oSettings
);
2804 fnSaveFilter( oInput
);
2807 /* Tell the draw function we have been filtering */
2808 oSettings
.bFiltered
= true;
2809 _fnCallbackFire( oSettings
, null, 'search', [oSettings
] );
2814 * Apply custom filtering functions
2815 * @param {object} oSettings dataTables settings object
2816 * @memberof DataTable#oApi
2818 function _fnFilterCustom( settings
)
2820 var filters
= DataTable
.ext
.search
;
2821 var displayRows
= settings
.aiDisplay
;
2824 for ( var i
=0, ien
=filters
.length
; i
<ien
; i
++ ) {
2827 // Loop over each row and see if it should be included
2828 for ( var j
=0, jen
=displayRows
.length
; j
<jen
; j
++ ) {
2829 rowIdx
= displayRows
[ j
];
2830 row
= settings
.aoData
[ rowIdx
];
2832 if ( filters
[i
]( settings
, row
._aFilterData
, rowIdx
, row
._aData
, j
) ) {
2833 rows
.push( rowIdx
);
2837 // So the array reference doesn't break set the results into the
2839 displayRows
.length
= 0;
2840 displayRows
.push
.apply( displayRows
, rows
);
2846 * Filter the table on a per-column basis
2847 * @param {object} oSettings dataTables settings object
2848 * @param {string} sInput string to filter on
2849 * @param {int} iColumn column to filter
2850 * @param {bool} bRegex treat search string as a regular expression or not
2851 * @param {bool} bSmart use smart filtering or not
2852 * @param {bool} bCaseInsensitive Do case insenstive matching or not
2853 * @memberof DataTable#oApi
2855 function _fnFilterColumn ( settings
, searchStr
, colIdx
, regex
, smart
, caseInsensitive
)
2857 if ( searchStr
=== '' ) {
2862 var display
= settings
.aiDisplay
;
2863 var rpSearch
= _fnFilterCreateSearch( searchStr
, regex
, smart
, caseInsensitive
);
2865 for ( var i
=display
.length
-1 ; i
>=0 ; i
-- ) {
2866 data
= settings
.aoData
[ display
[i
] ]._aFilterData
[ colIdx
];
2868 if ( ! rpSearch
.test( data
) ) {
2869 display
.splice( i
, 1 );
2876 * Filter the data table based on user input and draw the table
2877 * @param {object} settings dataTables settings object
2878 * @param {string} input string to filter on
2879 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
2880 * @param {bool} regex treat as a regular expression or not
2881 * @param {bool} smart perform smart filtering or not
2882 * @param {bool} caseInsensitive Do case insenstive matching or not
2883 * @memberof DataTable#oApi
2885 function _fnFilter( settings
, input
, force
, regex
, smart
, caseInsensitive
)
2887 var rpSearch
= _fnFilterCreateSearch( input
, regex
, smart
, caseInsensitive
);
2888 var prevSearch
= settings
.oPreviousSearch
.sSearch
;
2889 var displayMaster
= settings
.aiDisplayMaster
;
2890 var display
, invalidated
, i
;
2892 // Need to take account of custom filtering functions - always filter
2893 if ( DataTable
.ext
.search
.length
!== 0 ) {
2897 // Check if any of the rows were invalidated
2898 invalidated
= _fnFilterData( settings
);
2900 // If the input is blank - we just want the full data set
2901 if ( input
.length
<= 0 ) {
2902 settings
.aiDisplay
= displayMaster
.slice();
2905 // New search - start from the master array
2908 prevSearch
.length
> input
.length
||
2909 input
.indexOf(prevSearch
) !== 0 ||
2910 settings
.bSorted
// On resort, the display master needs to be
2911 // re-filtered since indexes will have changed
2913 settings
.aiDisplay
= displayMaster
.slice();
2916 // Search the display array
2917 display
= settings
.aiDisplay
;
2919 for ( i
=display
.length
-1 ; i
>=0 ; i
-- ) {
2920 if ( ! rpSearch
.test( settings
.aoData
[ display
[i
] ]._sFilterRow
) ) {
2921 display
.splice( i
, 1 );
2929 * Build a regular expression object suitable for searching a table
2930 * @param {string} sSearch string to search for
2931 * @param {bool} bRegex treat as a regular expression or not
2932 * @param {bool} bSmart perform smart filtering or not
2933 * @param {bool} bCaseInsensitive Do case insensitive matching or not
2934 * @returns {RegExp} constructed object
2935 * @memberof DataTable#oApi
2937 function _fnFilterCreateSearch( search
, regex
, smart
, caseInsensitive
)
2941 _fnEscapeRegex( search
);
2944 /* For smart filtering we want to allow the search to work regardless of
2945 * word order. We also want double quoted text to be preserved, so word
2946 * order is important - a la google. So this is what we want to
2949 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
2951 var a
= $.map( search
.match( /"[^"]+"|[^ ]+/g ) || '', function ( word
) {
2952 if ( word
.charAt(0) === '"' ) {
2953 var m
= word
.match( /^"(.*)"$/ );
2954 word
= m
? m
[1] : word
;
2957 return word
.replace('"', '');
2960 search
= '^(?=.*?'+a
.join( ')(?=.*?' )+').*$';
2963 return new RegExp( search
, caseInsensitive
? 'i' : '' );
2968 * scape a string such that it can be used in a regular expression
2969 * @param {string} sVal string to escape
2970 * @returns {string} escaped string
2971 * @memberof DataTable#oApi
2973 function _fnEscapeRegex ( sVal
)
2975 return sVal
.replace( _re_escape_regex
, '\\$1' );
2980 var __filter_div
= $('<div>')[0];
2981 var __filter_div_textContent
= __filter_div
.textContent
!== undefined;
2983 // Update the filtering data for each row if needed (by invalidation or first run)
2984 function _fnFilterData ( settings
)
2986 var columns
= settings
.aoColumns
;
2988 var i
, j
, ien
, jen
, filterData
, cellData
, row
;
2989 var fomatters
= DataTable
.ext
.type
.search
;
2990 var wasInvalidated
= false;
2992 for ( i
=0, ien
=settings
.aoData
.length
; i
<ien
; i
++ ) {
2993 row
= settings
.aoData
[i
];
2995 if ( ! row
._aFilterData
) {
2998 for ( j
=0, jen
=columns
.length
; j
<jen
; j
++ ) {
2999 column
= columns
[j
];
3001 if ( column
.bSearchable
) {
3002 cellData
= _fnGetCellData( settings
, i
, j
, 'filter' );
3004 if ( fomatters
[ column
.sType
] ) {
3005 cellData
= fomatters
[ column
.sType
]( cellData
);
3008 // Search in DataTables 1.10 is string based. In 1.11 this
3009 // should be altered to also allow strict type checking.
3010 if ( cellData
=== null ) {
3014 if ( typeof cellData
!== 'string' && cellData
.toString
) {
3015 cellData
= cellData
.toString();
3022 // If it looks like there is an HTML entity in the string,
3023 // attempt to decode it so sorting works as expected. Note that
3024 // we could use a single line of jQuery to do this, but the DOM
3025 // method used here is much faster http://jsperf.com/html-decode
3026 if ( cellData
.indexOf
&& cellData
.indexOf('&') !== -1 ) {
3027 __filter_div
.innerHTML
= cellData
;
3028 cellData
= __filter_div_textContent
?
3029 __filter_div
.textContent
:
3030 __filter_div
.innerText
;
3033 if ( cellData
.replace
) {
3034 cellData
= cellData
.replace(/[\r\n]/g, '');
3037 filterData
.push( cellData
);
3040 row
._aFilterData
= filterData
;
3041 row
._sFilterRow
= filterData
.join(' ');
3042 wasInvalidated
= true;
3046 return wasInvalidated
;
3051 * Convert from the internal Hungarian notation to camelCase for external
3053 * @param {object} obj Object to convert
3054 * @returns {object} Inverted object
3055 * @memberof DataTable#oApi
3057 function _fnSearchToCamel ( obj
)
3060 search
: obj
.sSearch
,
3063 caseInsensitive
: obj
.bCaseInsensitive
3070 * Convert from camelCase notation to the internal Hungarian. We could use the
3071 * Hungarian convert function here, but this is cleaner
3072 * @param {object} obj Object to convert
3073 * @returns {object} Inverted object
3074 * @memberof DataTable#oApi
3076 function _fnSearchToHung ( obj
)
3079 sSearch
: obj
.search
,
3082 bCaseInsensitive
: obj
.caseInsensitive
3087 * Generate the node required for the info display
3088 * @param {object} oSettings dataTables settings object
3089 * @returns {node} Information element
3090 * @memberof DataTable#oApi
3092 function _fnFeatureHtmlInfo ( settings
)
3095 tid
= settings
.sTableId
,
3096 nodes
= settings
.aanFeatures
.i
,
3098 'class': settings
.oClasses
.sInfo
,
3099 'id': ! nodes
? tid
+'_info' : null
3103 // Update display on each draw
3104 settings
.aoDrawCallback
.push( {
3105 "fn": _fnUpdateInfo
,
3106 "sName": "information"
3110 .attr( 'role', 'status' )
3111 .attr( 'aria-live', 'polite' );
3113 // Table is described by our info div
3114 $(settings
.nTable
).attr( 'aria-describedby', tid
+'_info' );
3122 * Update the information elements in the display
3123 * @param {object} settings dataTables settings object
3124 * @memberof DataTable#oApi
3126 function _fnUpdateInfo ( settings
)
3128 /* Show information about the table */
3129 var nodes
= settings
.aanFeatures
.i
;
3130 if ( nodes
.length
=== 0 ) {
3135 lang
= settings
.oLanguage
,
3136 start
= settings
._iDisplayStart
+1,
3137 end
= settings
.fnDisplayEnd(),
3138 max
= settings
.fnRecordsTotal(),
3139 total
= settings
.fnRecordsDisplay(),
3144 if ( total
!== max
) {
3145 /* Record set after filtering */
3146 out
+= ' ' + lang
.sInfoFiltered
;
3149 // Convert the macros
3150 out
+= lang
.sInfoPostFix
;
3151 out
= _fnInfoMacros( settings
, out
);
3153 var callback
= lang
.fnInfoCallback
;
3154 if ( callback
!== null ) {
3155 out
= callback
.call( settings
.oInstance
,
3156 settings
, start
, end
, max
, total
, out
3160 $(nodes
).html( out
);
3164 function _fnInfoMacros ( settings
, str
)
3166 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3169 formatter
= settings
.fnFormatNumber
,
3170 start
= settings
._iDisplayStart
+1,
3171 len
= settings
._iDisplayLength
,
3172 vis
= settings
.fnRecordsDisplay(),
3176 replace(/_START_/g, formatter
.call( settings
, start
) ).
3177 replace(/_END_/g, formatter
.call( settings
, settings
.fnDisplayEnd() ) ).
3178 replace(/_MAX_/g, formatter
.call( settings
, settings
.fnRecordsTotal() ) ).
3179 replace(/_TOTAL_/g, formatter
.call( settings
, vis
) ).
3180 replace(/_PAGE_/g, formatter
.call( settings
, all
? 1 : Math
.ceil( start
/ len
) ) ).
3181 replace(/_PAGES_/g, formatter
.call( settings
, all
? 1 : Math
.ceil( vis
/ len
) ) );
3187 * Draw the table for the first time, adding all required features
3188 * @param {object} settings dataTables settings object
3189 * @memberof DataTable#oApi
3191 function _fnInitialise ( settings
)
3193 var i
, iLen
, iAjaxStart
=settings
.iInitDisplayStart
;
3194 var columns
= settings
.aoColumns
, column
;
3195 var features
= settings
.oFeatures
;
3197 /* Ensure that the table data is fully initialised */
3198 if ( ! settings
.bInitialised
) {
3199 setTimeout( function(){ _fnInitialise( settings
); }, 200 );
3203 /* Show the display HTML options */
3204 _fnAddOptionsHtml( settings
);
3206 /* Build and draw the header / footer for the table */
3207 _fnBuildHead( settings
);
3208 _fnDrawHead( settings
, settings
.aoHeader
);
3209 _fnDrawHead( settings
, settings
.aoFooter
);
3211 /* Okay to show that something is going on now */
3212 _fnProcessingDisplay( settings
, true );
3214 /* Calculate sizes for columns */
3215 if ( features
.bAutoWidth
) {
3216 _fnCalculateColumnWidths( settings
);
3219 for ( i
=0, iLen
=columns
.length
; i
<iLen
; i
++ ) {
3220 column
= columns
[i
];
3222 if ( column
.sWidth
) {
3223 column
.nTh
.style
.width
= _fnStringToCss( column
.sWidth
);
3227 // If there is default sorting required - let's do it. The sort function
3228 // will do the drawing for us. Otherwise we draw the table regardless of the
3229 // Ajax source - this allows the table to look initialised for Ajax sourcing
3230 // data (show 'loading' message possibly)
3231 _fnReDraw( settings
);
3233 // Server-side processing init complete is done by _fnAjaxUpdateDraw
3234 var dataSrc
= _fnDataSource( settings
);
3235 if ( dataSrc
!= 'ssp' ) {
3236 // if there is an ajax source load the data
3237 if ( dataSrc
== 'ajax' ) {
3238 _fnBuildAjax( settings
, [], function(json
) {
3239 var aData
= _fnAjaxDataSrc( settings
, json
);
3241 // Got the data - add it to the table
3242 for ( i
=0 ; i
<aData
.length
; i
++ ) {
3243 _fnAddData( settings
, aData
[i
] );
3246 // Reset the init display for cookie saving. We've already done
3247 // a filter, and therefore cleared it before. So we need to make
3248 // it appear 'fresh'
3249 settings
.iInitDisplayStart
= iAjaxStart
;
3251 _fnReDraw( settings
);
3253 _fnProcessingDisplay( settings
, false );
3254 _fnInitComplete( settings
, json
);
3258 _fnProcessingDisplay( settings
, false );
3259 _fnInitComplete( settings
);
3266 * Draw the table for the first time, adding all required features
3267 * @param {object} oSettings dataTables settings object
3268 * @param {object} [json] JSON from the server that completed the table, if using Ajax source
3269 * with client-side processing (optional)
3270 * @memberof DataTable#oApi
3272 function _fnInitComplete ( settings
, json
)
3274 settings
._bInitComplete
= true;
3276 // On an Ajax load we now have data and therefore want to apply the column
3279 _fnAdjustColumnSizing( settings
);
3282 _fnCallbackFire( settings
, 'aoInitComplete', 'init', [settings
, json
] );
3286 function _fnLengthChange ( settings
, val
)
3288 var len
= parseInt( val
, 10 );
3289 settings
._iDisplayLength
= len
;
3291 _fnLengthOverflow( settings
);
3293 // Fire length change event
3294 _fnCallbackFire( settings
, null, 'length', [settings
, len
] );
3299 * Generate the node required for user display length changing
3300 * @param {object} settings dataTables settings object
3301 * @returns {node} Display length feature node
3302 * @memberof DataTable#oApi
3304 function _fnFeatureHtmlLength ( settings
)
3307 classes
= settings
.oClasses
,
3308 tableId
= settings
.sTableId
,
3309 menu
= settings
.aLengthMenu
,
3310 d2
= $.isArray( menu
[0] ),
3311 lengths
= d2
? menu
[0] : menu
,
3312 language
= d2
? menu
[1] : menu
;
3314 var select
= $('<select/>', {
3315 'name': tableId
+'_length',
3316 'aria-controls': tableId
,
3317 'class': classes
.sLengthSelect
3320 for ( var i
=0, ien
=lengths
.length
; i
<ien
; i
++ ) {
3321 select
[0][ i
] = new Option( language
[i
], lengths
[i
] );
3324 var div
= $('<div><label/></div>').addClass( classes
.sLength
);
3325 if ( ! settings
.aanFeatures
.l
) {
3326 div
[0].id
= tableId
+'_length';
3329 div
.children().append(
3330 settings
.oLanguage
.sLengthMenu
.replace( '_MENU_', select
[0].outerHTML
)
3333 // Can't use `select` variable as user might provide their own and the
3334 // reference is broken by the use of outerHTML
3336 .val( settings
._iDisplayLength
)
3337 .bind( 'change.DT', function(e
) {
3338 _fnLengthChange( settings
, $(this).val() );
3339 _fnDraw( settings
);
3342 // Update node value whenever anything changes the table's length
3343 $(settings
.nTable
).bind( 'length.dt.DT', function (e
, s
, len
) {
3344 if ( settings
=== s
) {
3345 $('select', div
).val( len
);
3354 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3355 * Note that most of the paging logic is done in
3356 * DataTable.ext.pager
3360 * Generate the node required for default pagination
3361 * @param {object} oSettings dataTables settings object
3362 * @returns {node} Pagination feature node
3363 * @memberof DataTable#oApi
3365 function _fnFeatureHtmlPaginate ( settings
)
3368 type
= settings
.sPaginationType
,
3369 plugin
= DataTable
.ext
.pager
[ type
],
3370 modern
= typeof plugin
=== 'function',
3371 redraw = function( settings
) {
3372 _fnDraw( settings
);
3374 node
= $('<div/>').addClass( settings
.oClasses
.sPaging
+ type
)[0],
3375 features
= settings
.aanFeatures
;
3378 plugin
.fnInit( settings
, node
, redraw
);
3381 /* Add a draw callback for the pagination on first instance, to update the paging display */
3384 node
.id
= settings
.sTableId
+'_paginate';
3386 settings
.aoDrawCallback
.push( {
3387 "fn": function( settings
) {
3390 start
= settings
._iDisplayStart
,
3391 len
= settings
._iDisplayLength
,
3392 visRecords
= settings
.fnRecordsDisplay(),
3394 page
= all
? 0 : Math
.ceil( start
/ len
),
3395 pages
= all
? 1 : Math
.ceil( visRecords
/ len
),
3396 buttons
= plugin(page
, pages
),
3399 for ( i
=0, ien
=features
.p
.length
; i
<ien
; i
++ ) {
3400 _fnRenderer( settings
, 'pageButton' )(
3401 settings
, features
.p
[i
], i
, buttons
, page
, pages
3406 plugin
.fnUpdate( settings
, redraw
);
3409 "sName": "pagination"
3418 * Alter the display settings to change the page
3419 * @param {object} settings DataTables settings object
3420 * @param {string|int} action Paging action to take: "first", "previous",
3421 * "next" or "last" or page number to jump to (integer)
3422 * @param [bool] redraw Automatically draw the update or not
3423 * @returns {bool} true page has changed, false - no change
3424 * @memberof DataTable#oApi
3426 function _fnPageChange ( settings
, action
, redraw
)
3429 start
= settings
._iDisplayStart
,
3430 len
= settings
._iDisplayLength
,
3431 records
= settings
.fnRecordsDisplay();
3433 if ( records
=== 0 || len
=== -1 )
3437 else if ( typeof action
=== "number" )
3439 start
= action
* len
;
3441 if ( start
> records
)
3446 else if ( action
== "first" )
3450 else if ( action
== "previous" )
3461 else if ( action
== "next" )
3463 if ( start
+ len
< records
)
3468 else if ( action
== "last" )
3470 start
= Math
.floor( (records
-1) / len
) * len
;
3474 _fnLog( settings
, 0, "Unknown paging action: "+action
, 5 );
3477 var changed
= settings
._iDisplayStart
!== start
;
3478 settings
._iDisplayStart
= start
;
3481 _fnCallbackFire( settings
, null, 'page', [settings
] );
3484 _fnDraw( settings
);
3494 * Generate the node required for the processing node
3495 * @param {object} settings dataTables settings object
3496 * @returns {node} Processing element
3497 * @memberof DataTable#oApi
3499 function _fnFeatureHtmlProcessing ( settings
)
3501 return $('<div/>', {
3502 'id': ! settings
.aanFeatures
.r
? settings
.sTableId
+'_processing' : null,
3503 'class': settings
.oClasses
.sProcessing
3505 .html( settings
.oLanguage
.sProcessing
)
3506 .insertBefore( settings
.nTable
)[0];
3511 * Display or hide the processing indicator
3512 * @param {object} settings dataTables settings object
3513 * @param {bool} show Show the processing indicator (true) or not (false)
3514 * @memberof DataTable#oApi
3516 function _fnProcessingDisplay ( settings
, show
)
3518 if ( settings
.oFeatures
.bProcessing
) {
3519 $(settings
.aanFeatures
.r
).css( 'display', show
? 'block' : 'none' );
3522 _fnCallbackFire( settings
, null, 'processing', [settings
, show
] );
3526 * Add any control elements for the table - specifically scrolling
3527 * @param {object} settings dataTables settings object
3528 * @returns {node} Node to add to the DOM
3529 * @memberof DataTable#oApi
3531 function _fnFeatureHtmlTable ( settings
)
3533 var table
= $(settings
.nTable
);
3535 // Add the ARIA grid role to the table
3536 table
.attr( 'role', 'grid' );
3538 // Scrolling from here on in
3539 var scroll
= settings
.oScroll
;
3541 if ( scroll
.sX
=== '' && scroll
.sY
=== '' ) {
3542 return settings
.nTable
;
3545 var scrollX
= scroll
.sX
;
3546 var scrollY
= scroll
.sY
;
3547 var classes
= settings
.oClasses
;
3548 var caption
= table
.children('caption');
3549 var captionSide
= caption
.length
? caption
[0]._captionSide
: null;
3550 var headerClone
= $( table
[0].cloneNode(false) );
3551 var footerClone
= $( table
[0].cloneNode(false) );
3552 var footer
= table
.children('tfoot');
3553 var _div
= '<div/>';
3554 var size = function ( s
) {
3555 return !s
? null : _fnStringToCss( s
);
3558 // This is fairly messy, but with x scrolling enabled, if the table has a
3559 // width attribute, regardless of any width applied using the column width
3560 // options, the browser will shrink or grow the table as needed to fit into
3561 // that 100%. That would make the width options useless. So we remove it.
3562 // This is okay, under the assumption that width:100% is applied to the
3563 // table in CSS (it is in the default stylesheet) which will set the table
3564 // width as appropriate (the attribute and css behave differently...)
3565 if ( scroll
.sX
&& table
.attr('width') === '100%' ) {
3566 table
.removeAttr('width');
3569 if ( ! footer
.length
) {
3574 * The HTML structure that we want to generate in this function is:
3577 * div - scroll head inner
3578 * table - scroll head table
3581 * table - table (master table)
3582 * thead - thead clone for sizing
3585 * div - scroll foot inner
3586 * table - scroll foot table
3589 var scroller
= $( _div
, { 'class': classes
.sScrollWrapper
} )
3591 $(_div
, { 'class': classes
.sScrollHead
} )
3594 position
: 'relative',
3596 width
: scrollX
? size(scrollX
) : '100%'
3599 $(_div
, { 'class': classes
.sScrollHeadInner
} )
3601 'box-sizing': 'content-box',
3602 width
: scroll
.sXInner
|| '100%'
3607 .css( 'margin-left', 0 )
3609 table
.children('thead')
3613 .append( captionSide
=== 'top' ? caption
: null )
3616 $(_div
, { 'class': classes
.sScrollBody
} )
3619 height
: size( scrollY
),
3620 width
: size( scrollX
)
3627 $(_div
, { 'class': classes
.sScrollFoot
} )
3631 width
: scrollX
? size(scrollX
) : '100%'
3634 $(_div
, { 'class': classes
.sScrollFootInner
} )
3638 .css( 'margin-left', 0 )
3640 table
.children('tfoot')
3644 .append( captionSide
=== 'bottom' ? caption
: null )
3648 var children
= scroller
.children();
3649 var scrollHead
= children
[0];
3650 var scrollBody
= children
[1];
3651 var scrollFoot
= footer
? children
[2] : null;
3653 // When the body is scrolled, then we also want to scroll the headers
3655 $(scrollBody
).scroll( function (e
) {
3656 var scrollLeft
= this.scrollLeft
;
3658 scrollHead
.scrollLeft
= scrollLeft
;
3661 scrollFoot
.scrollLeft
= scrollLeft
;
3666 settings
.nScrollHead
= scrollHead
;
3667 settings
.nScrollBody
= scrollBody
;
3668 settings
.nScrollFoot
= scrollFoot
;
3670 // On redraw - align columns
3671 settings
.aoDrawCallback
.push( {
3672 "fn": _fnScrollDraw
,
3673 "sName": "scrolling"
3682 * Update the header, footer and body tables for resizing - i.e. column
3685 * Welcome to the most horrible function DataTables. The process that this
3686 * function follows is basically:
3687 * 1. Re-create the table inside the scrolling div
3688 * 2. Take live measurements from the DOM
3689 * 3. Apply the measurements to align the columns
3692 * @param {object} settings dataTables settings object
3693 * @memberof DataTable#oApi
3695 function _fnScrollDraw ( settings
)
3697 // Given that this is such a monster function, a lot of variables are use
3698 // to try and keep the minimised size as small as possible
3700 scroll
= settings
.oScroll
,
3701 scrollX
= scroll
.sX
,
3702 scrollXInner
= scroll
.sXInner
,
3703 scrollY
= scroll
.sY
,
3704 barWidth
= scroll
.iBarWidth
,
3705 divHeader
= $(settings
.nScrollHead
),
3706 divHeaderStyle
= divHeader
[0].style
,
3707 divHeaderInner
= divHeader
.children('div'),
3708 divHeaderInnerStyle
= divHeaderInner
[0].style
,
3709 divHeaderTable
= divHeaderInner
.children('table'),
3710 divBodyEl
= settings
.nScrollBody
,
3711 divBody
= $(divBodyEl
),
3712 divBodyStyle
= divBodyEl
.style
,
3713 divFooter
= $(settings
.nScrollFoot
),
3714 divFooterInner
= divFooter
.children('div'),
3715 divFooterTable
= divFooterInner
.children('table'),
3716 header
= $(settings
.nTHead
),
3717 table
= $(settings
.nTable
),
3719 tableStyle
= tableEl
.style
,
3720 footer
= settings
.nTFoot
? $(settings
.nTFoot
) : null,
3721 browser
= settings
.oBrowser
,
3722 ie67
= browser
.bScrollOversize
,
3723 headerTrgEls
, footerTrgEls
,
3724 headerSrcEls
, footerSrcEls
,
3725 headerCopy
, footerCopy
,
3726 headerWidths
=[], footerWidths
=[],
3728 idx
, correction
, sanityWidth
,
3729 zeroOut = function(nSizer
) {
3730 var style
= nSizer
.style
;
3731 style
.paddingTop
= "0";
3732 style
.paddingBottom
= "0";
3733 style
.borderTopWidth
= "0";
3734 style
.borderBottomWidth
= "0";
3739 * 1. Re-create the table inside the scrolling div
3742 // Remove the old minimised thead and tfoot elements in the inner table
3743 table
.children('thead, tfoot').remove();
3745 // Clone the current header and footer elements and then place it into the inner table
3746 headerCopy
= header
.clone().prependTo( table
);
3747 headerTrgEls
= header
.find('tr'); // original header is in its own table
3748 headerSrcEls
= headerCopy
.find('tr');
3749 headerCopy
.find('th, td').removeAttr('tabindex');
3752 footerCopy
= footer
.clone().prependTo( table
);
3753 footerTrgEls
= footer
.find('tr'); // the original tfoot is in its own table and must be sized
3754 footerSrcEls
= footerCopy
.find('tr');
3759 * 2. Take live measurements from the DOM - do not alter the DOM itself!
3762 // Remove old sizing and apply the calculated column widths
3763 // Get the unique column headers in the newly created (cloned) header. We want to apply the
3764 // calculated sizes to this header
3767 divBodyStyle
.width
= '100%';
3768 divHeader
[0].style
.width
= '100%';
3771 $.each( _fnGetUniqueThs( settings
, headerCopy
), function ( i
, el
) {
3772 idx
= _fnVisibleToColumnIndex( settings
, i
);
3773 el
.style
.width
= settings
.aoColumns
[idx
].sWidth
;
3777 _fnApplyToChildren( function(n
) {
3782 // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3783 // will end up forcing the scrollbar to appear, making our measurements wrong for when we
3784 // then hide it (end of this function), so add the header height to the body scroller.
3785 if ( scroll
.bCollapse
&& scrollY
!== "" ) {
3786 divBodyStyle
.height
= (divBody
[0].offsetHeight
+ header
[0].offsetHeight
)+"px";
3789 // Size the table as a whole
3790 sanityWidth
= table
.outerWidth();
3791 if ( scrollX
=== "" ) {
3793 tableStyle
.width
= "100%";
3795 // IE7 will make the width of the table when 100% include the scrollbar
3796 // - which is shouldn't. When there is a scrollbar we need to take this
3798 if ( ie67
&& (table
.find('tbody').height() > divBodyEl
.offsetHeight
||
3799 divBody
.css('overflow-y') == "scroll")
3801 tableStyle
.width
= _fnStringToCss( table
.outerWidth() - barWidth
);
3807 if ( scrollXInner
!== "" ) {
3808 // x scroll inner has been given - use it
3809 tableStyle
.width
= _fnStringToCss(scrollXInner
);
3811 else if ( sanityWidth
== divBody
.width() && divBody
.height() < table
.height() ) {
3812 // There is y-scrolling - try to take account of the y scroll bar
3813 tableStyle
.width
= _fnStringToCss( sanityWidth
-barWidth
);
3814 if ( table
.outerWidth() > sanityWidth
-barWidth
) {
3815 // Not possible to take account of it
3816 tableStyle
.width
= _fnStringToCss( sanityWidth
);
3820 // When all else fails
3821 tableStyle
.width
= _fnStringToCss( sanityWidth
);
3825 // Recalculate the sanity width - now that we've applied the required width,
3826 // before it was a temporary variable. This is required because the column
3827 // width calculation is done before this table DOM is created.
3828 sanityWidth
= table
.outerWidth();
3830 // Hidden header should have zero height, so remove padding and borders. Then
3831 // set the width based on the real headers
3833 // Apply all styles in one pass
3834 _fnApplyToChildren( zeroOut
, headerSrcEls
);
3836 // Read all widths in next pass
3837 _fnApplyToChildren( function(nSizer
) {
3838 headerContent
.push( nSizer
.innerHTML
);
3839 headerWidths
.push( _fnStringToCss( $(nSizer
).css('width') ) );
3842 // Apply all widths in final pass
3843 _fnApplyToChildren( function(nToSize
, i
) {
3844 nToSize
.style
.width
= headerWidths
[i
];
3847 $(headerSrcEls
).height(0);
3849 /* Same again with the footer if we have one */
3852 _fnApplyToChildren( zeroOut
, footerSrcEls
);
3854 _fnApplyToChildren( function(nSizer
) {
3855 footerWidths
.push( _fnStringToCss( $(nSizer
).css('width') ) );
3858 _fnApplyToChildren( function(nToSize
, i
) {
3859 nToSize
.style
.width
= footerWidths
[i
];
3862 $(footerSrcEls
).height(0);
3867 * 3. Apply the measurements
3870 // "Hide" the header and footer that we used for the sizing. We need to keep
3871 // the content of the cell so that the width applied to the header and body
3872 // both match, but we want to hide it completely. We want to also fix their
3873 // width to what they currently are
3874 _fnApplyToChildren( function(nSizer
, i
) {
3875 nSizer
.innerHTML
= '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent
[i
]+'</div>';
3876 nSizer
.style
.width
= headerWidths
[i
];
3881 _fnApplyToChildren( function(nSizer
, i
) {
3882 nSizer
.innerHTML
= "";
3883 nSizer
.style
.width
= footerWidths
[i
];
3887 // Sanity check that the table is of a sensible width. If not then we are going to get
3888 // misalignment - try to prevent this by not allowing the table to shrink below its min width
3889 if ( table
.outerWidth() < sanityWidth
)
3891 // The min width depends upon if we have a vertical scrollbar visible or not */
3892 correction
= ((divBodyEl
.scrollHeight
> divBodyEl
.offsetHeight
||
3893 divBody
.css('overflow-y') == "scroll")) ?
3894 sanityWidth
+barWidth
:
3897 // IE6/7 are a law unto themselves...
3898 if ( ie67
&& (divBodyEl
.scrollHeight
>
3899 divBodyEl
.offsetHeight
|| divBody
.css('overflow-y') == "scroll")
3901 tableStyle
.width
= _fnStringToCss( correction
-barWidth
);
3904 // And give the user a warning that we've stopped the table getting too small
3905 if ( scrollX
=== "" || scrollXInner
!== "" ) {
3906 _fnLog( settings
, 1, 'Possible column misalignment', 6 );
3911 correction
= '100%';
3914 // Apply to the container elements
3915 divBodyStyle
.width
= _fnStringToCss( correction
);
3916 divHeaderStyle
.width
= _fnStringToCss( correction
);
3919 settings
.nScrollFoot
.style
.width
= _fnStringToCss( correction
);
3927 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
3928 * the scrollbar height from the visible display, rather than adding it on. We need to
3929 * set the height in order to sort this. Don't want to do it in any other browsers.
3932 divBodyStyle
.height
= _fnStringToCss( tableEl
.offsetHeight
+barWidth
);
3936 if ( scrollY
&& scroll
.bCollapse
) {
3937 divBodyStyle
.height
= _fnStringToCss( scrollY
);
3939 var iExtra
= (scrollX
&& tableEl
.offsetWidth
> divBodyEl
.offsetWidth
) ?
3943 if ( tableEl
.offsetHeight
< divBodyEl
.offsetHeight
) {
3944 divBodyStyle
.height
= _fnStringToCss( tableEl
.offsetHeight
+iExtra
);
3948 /* Finally set the width's of the header and footer tables */
3949 var iOuterWidth
= table
.outerWidth();
3950 divHeaderTable
[0].style
.width
= _fnStringToCss( iOuterWidth
);
3951 divHeaderInnerStyle
.width
= _fnStringToCss( iOuterWidth
);
3953 // Figure out if there are scrollbar present - if so then we need a the header and footer to
3954 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
3955 var bScrolling
= table
.height() > divBodyEl
.clientHeight
|| divBody
.css('overflow-y') == "scroll";
3956 var padding
= 'padding' + (browser
.bScrollbarLeft
? 'Left' : 'Right' );
3957 divHeaderInnerStyle
[ padding
] = bScrolling
? barWidth
+"px" : "0px";
3960 divFooterTable
[0].style
.width
= _fnStringToCss( iOuterWidth
);
3961 divFooterInner
[0].style
.width
= _fnStringToCss( iOuterWidth
);
3962 divFooterInner
[0].style
[padding
] = bScrolling
? barWidth
+"px" : "0px";
3965 /* Adjust the position of the header in case we loose the y-scrollbar */
3968 // If sorting or filtering has occurred, jump the scrolling back to the top
3969 // only if we aren't holding the position
3970 if ( (settings
.bSorted
|| settings
.bFiltered
) && ! settings
._drawHold
) {
3971 divBodyEl
.scrollTop
= 0;
3978 * Apply a given function to the display child nodes of an element array (typically
3979 * TD children of TR rows
3980 * @param {function} fn Method to apply to the objects
3981 * @param array {nodes} an1 List of elements to look through for display children
3982 * @param array {nodes} an2 Another list (identical structure to the first) - optional
3983 * @memberof DataTable#oApi
3985 function _fnApplyToChildren( fn
, an1
, an2
)
3987 var index
=0, i
=0, iLen
=an1
.length
;
3990 while ( i
< iLen
) {
3991 nNode1
= an1
[i
].firstChild
;
3992 nNode2
= an2
? an2
[i
].firstChild
: null;
3995 if ( nNode1
.nodeType
=== 1 ) {
3997 fn( nNode1
, nNode2
, index
);
4000 fn( nNode1
, index
);
4006 nNode1
= nNode1
.nextSibling
;
4007 nNode2
= an2
? nNode2
.nextSibling
: null;
4016 var __re_html_remove
= /<.*?>/g;
4020 * Calculate the width of columns for the table
4021 * @param {object} oSettings dataTables settings object
4022 * @memberof DataTable#oApi
4024 function _fnCalculateColumnWidths ( oSettings
)
4027 table
= oSettings
.nTable
,
4028 columns
= oSettings
.aoColumns
,
4029 scroll
= oSettings
.oScroll
,
4030 scrollY
= scroll
.sY
,
4031 scrollX
= scroll
.sX
,
4032 scrollXInner
= scroll
.sXInner
,
4033 columnCount
= columns
.length
,
4034 visibleColumns
= _fnGetColumns( oSettings
, 'bVisible' ),
4035 headerCells
= $('th', oSettings
.nTHead
),
4036 tableWidthAttr
= table
.getAttribute('width'),
4037 tableContainer
= table
.parentNode
,
4039 i
, column
, columnIdx
, width
, outerWidth
;
4041 /* Convert any user input sizes into pixel sizes */
4042 for ( i
=0 ; i
<visibleColumns
.length
; i
++ ) {
4043 column
= columns
[ visibleColumns
[i
] ];
4045 if ( column
.sWidth
!== null ) {
4046 column
.sWidth
= _fnConvertToWidth( column
.sWidthOrig
, tableContainer
);
4052 /* If the number of columns in the DOM equals the number that we have to
4053 * process in DataTables, then we can use the offsets that are created by
4054 * the web- browser. No custom sizes can be set in order for this to happen,
4055 * nor scrolling used
4057 if ( ! userInputs
&& ! scrollX
&& ! scrollY
&&
4058 columnCount
== _fnVisbleColumns( oSettings
) &&
4059 columnCount
== headerCells
.length
4061 for ( i
=0 ; i
<columnCount
; i
++ ) {
4062 columns
[i
].sWidth
= _fnStringToCss( headerCells
.eq(i
).width() );
4067 // Otherwise construct a single row table with the widest node in the
4068 // data, assign any user defined widths, then insert it into the DOM and
4069 // allow the browser to do all the hard work of calculating table widths
4070 var tmpTable
= $(table
).clone() // don't use cloneNode - IE8 will remove events on the main table
4072 .css( 'visibility', 'hidden' )
4074 .append( $(oSettings
.nTHead
).clone( false ) )
4075 .append( $(oSettings
.nTFoot
).clone( false ) )
4076 .append( $('<tbody><tr/></tbody>') );
4078 // Remove any assigned widths from the footer (from scrolling)
4079 tmpTable
.find('tfoot th, tfoot td').css('width', '');
4081 var tr
= tmpTable
.find( 'tbody tr' );
4083 // Apply custom sizing to the cloned header
4084 headerCells
= _fnGetUniqueThs( oSettings
, tmpTable
.find('thead')[0] );
4086 for ( i
=0 ; i
<visibleColumns
.length
; i
++ ) {
4087 column
= columns
[ visibleColumns
[i
] ];
4089 headerCells
[i
].style
.width
= column
.sWidthOrig
!== null && column
.sWidthOrig
!== '' ?
4090 _fnStringToCss( column
.sWidthOrig
) :
4094 // Find the widest cell for each column and put it into the table
4095 if ( oSettings
.aoData
.length
) {
4096 for ( i
=0 ; i
<visibleColumns
.length
; i
++ ) {
4097 columnIdx
= visibleColumns
[i
];
4098 column
= columns
[ columnIdx
];
4100 $( _fnGetWidestNode( oSettings
, columnIdx
) )
4102 .append( column
.sContentPadding
)
4107 // Table has been built, attach to the document so we can work with it
4108 tmpTable
.appendTo( tableContainer
);
4110 // When scrolling (X or Y) we want to set the width of the table as
4111 // appropriate. However, when not scrolling leave the table width as it
4112 // is. This results in slightly different, but I think correct behaviour
4113 if ( scrollX
&& scrollXInner
) {
4114 tmpTable
.width( scrollXInner
);
4116 else if ( scrollX
) {
4117 tmpTable
.css( 'width', 'auto' );
4119 if ( tmpTable
.width() < tableContainer
.offsetWidth
) {
4120 tmpTable
.width( tableContainer
.offsetWidth
);
4123 else if ( scrollY
) {
4124 tmpTable
.width( tableContainer
.offsetWidth
);
4126 else if ( tableWidthAttr
) {
4127 tmpTable
.width( tableWidthAttr
);
4130 // Take into account the y scrollbar
4131 _fnScrollingWidthAdjust( oSettings
, tmpTable
[0] );
4133 // Browsers need a bit of a hand when a width is assigned to any columns
4134 // when x-scrolling as they tend to collapse the table to the min-width,
4135 // even if we sent the column widths. So we need to keep track of what
4136 // the table width should be by summing the user given values, and the
4142 for ( i
=0 ; i
<visibleColumns
.length
; i
++ ) {
4143 column
= columns
[ visibleColumns
[i
] ];
4144 outerWidth
= $(headerCells
[i
]).outerWidth();
4146 total
+= column
.sWidthOrig
=== null ?
4148 parseInt( column
.sWidth
, 10 ) + outerWidth
- $(headerCells
[i
]).width();
4151 tmpTable
.width( _fnStringToCss( total
) );
4152 table
.style
.width
= _fnStringToCss( total
);
4155 // Get the width of each column in the constructed table
4156 for ( i
=0 ; i
<visibleColumns
.length
; i
++ ) {
4157 column
= columns
[ visibleColumns
[i
] ];
4158 width
= $(headerCells
[i
]).width();
4161 column
.sWidth
= _fnStringToCss( width
);
4165 table
.style
.width
= _fnStringToCss( tmpTable
.css('width') );
4167 // Finished with the table - ditch it
4171 // If there is a width attr, we want to attach an event listener which
4172 // allows the table sizing to automatically adjust when the window is
4173 // resized. Use the width attr rather than CSS, since we can't know if the
4174 // CSS is a relative value or absolute - DOM read is always px.
4175 if ( tableWidthAttr
) {
4176 table
.style
.width
= _fnStringToCss( tableWidthAttr
);
4179 if ( (tableWidthAttr
|| scrollX
) && ! oSettings
._reszEvt
) {
4180 $(window
).bind('resize.DT-'+oSettings
.sInstance
, _fnThrottle( function () {
4181 _fnAdjustColumnSizing( oSettings
);
4184 oSettings
._reszEvt
= true;
4190 * Throttle the calls to a function. Arguments and context are maintained for
4191 * the throttled function
4192 * @param {function} fn Function to be called
4193 * @param {int} [freq=200] call frequency in mS
4194 * @returns {function} wrapped function
4195 * @memberof DataTable#oApi
4197 function _fnThrottle( fn
, freq
) {
4199 frequency
= freq
!== undefined ? freq
: 200,
4203 return function () {
4209 if ( last
&& now
< last
+ frequency
) {
4210 clearTimeout( timer
);
4212 timer
= setTimeout( function () {
4214 fn
.apply( that
, args
);
4219 fn
.apply( that
, args
);
4229 * Convert a CSS unit width to pixels (e.g. 2em)
4230 * @param {string} width width to be converted
4231 * @param {node} parent parent to get the with for (required for relative widths) - optional
4232 * @returns {int} width in pixels
4233 * @memberof DataTable#oApi
4235 function _fnConvertToWidth ( width
, parent
)
4242 .css( 'width', _fnStringToCss( width
) )
4243 .appendTo( parent
|| document
.body
);
4245 var val
= n
[0].offsetWidth
;
4253 * Adjust a table's width to take account of vertical scroll bar
4254 * @param {object} oSettings dataTables settings object
4255 * @param {node} n table node
4256 * @memberof DataTable#oApi
4259 function _fnScrollingWidthAdjust ( settings
, n
)
4261 var scroll
= settings
.oScroll
;
4263 if ( scroll
.sX
|| scroll
.sY
) {
4264 // When y-scrolling only, we want to remove the width of the scroll bar
4265 // so the table + scroll bar will fit into the area available, otherwise
4266 // we fix the table at its current size with no adjustment
4267 var correction
= ! scroll
.sX
? scroll
.iBarWidth
: 0;
4268 n
.style
.width
= _fnStringToCss( $(n
).outerWidth() - correction
);
4274 * Get the widest node
4275 * @param {object} settings dataTables settings object
4276 * @param {int} colIdx column of interest
4277 * @returns {node} widest table node
4278 * @memberof DataTable#oApi
4280 function _fnGetWidestNode( settings
, colIdx
)
4282 var idx
= _fnGetMaxLenString( settings
, colIdx
);
4287 var data
= settings
.aoData
[ idx
];
4288 return ! data
.nTr
? // Might not have been created when deferred rendering
4289 $('<td/>').html( _fnGetCellData( settings
, idx
, colIdx
, 'display' ) )[0] :
4290 data
.anCells
[ colIdx
];
4295 * Get the maximum strlen for each data column
4296 * @param {object} settings dataTables settings object
4297 * @param {int} colIdx column of interest
4298 * @returns {string} max string length for each column
4299 * @memberof DataTable#oApi
4301 function _fnGetMaxLenString( settings
, colIdx
)
4303 var s
, max
=-1, maxIdx
= -1;
4305 for ( var i
=0, ien
=settings
.aoData
.length
; i
<ien
; i
++ ) {
4306 s
= _fnGetCellData( settings
, i
, colIdx
, 'display' )+'';
4307 s
= s
.replace( __re_html_remove
, '' );
4309 if ( s
.length
> max
) {
4320 * Append a CSS unit (only if required) to a string
4321 * @param {string} value to css-ify
4322 * @returns {string} value with css unit
4323 * @memberof DataTable#oApi
4325 function _fnStringToCss( s
)
4331 if ( typeof s
== 'number' ) {
4337 // Check it has a unit character already
4338 return s
.match(/\d$/) ?
4345 * Get the width of a scroll bar in this browser being used
4346 * @returns {int} width in pixels
4347 * @memberof DataTable#oApi
4349 function _fnScrollBarWidth ()
4351 // On first run a static variable is set, since this is only needed once.
4352 // Subsequent runs will just use the previously calculated value
4353 if ( ! DataTable
.__scrollbarWidth
) {
4354 var inner
= $('<p/>').css( {
4360 var outer
= $('<div/>')
4362 position
: 'absolute',
4369 visibility
: 'hidden'
4372 .appendTo( 'body' );
4374 var w1
= inner
.offsetWidth
;
4375 outer
.css( 'overflow', 'scroll' );
4376 var w2
= inner
.offsetWidth
;
4379 w2
= outer
[0].clientWidth
;
4384 DataTable
.__scrollbarWidth
= w1
- w2
;
4387 return DataTable
.__scrollbarWidth
;
4392 function _fnSortFlatten ( settings
)
4398 aoColumns
= settings
.aoColumns
,
4399 aDataSort
, iCol
, sType
, srcCol
,
4400 fixed
= settings
.aaSortingFixed
,
4401 fixedObj
= $.isPlainObject( fixed
),
4403 add = function ( a
) {
4404 if ( a
.length
&& ! $.isArray( a
[0] ) ) {
4406 nestedSort
.push( a
);
4410 nestedSort
.push
.apply( nestedSort
, a
);
4414 // Build the sort array, with pre-fix and post-fix options if they have been
4416 if ( $.isArray( fixed
) ) {
4420 if ( fixedObj
&& fixed
.pre
) {
4424 add( settings
.aaSorting
);
4426 if (fixedObj
&& fixed
.post
) {
4430 for ( i
=0 ; i
<nestedSort
.length
; i
++ )
4432 srcCol
= nestedSort
[i
][0];
4433 aDataSort
= aoColumns
[ srcCol
].aDataSort
;
4435 for ( k
=0, kLen
=aDataSort
.length
; k
<kLen
; k
++ )
4437 iCol
= aDataSort
[k
];
4438 sType
= aoColumns
[ iCol
].sType
|| 'string';
4440 if ( nestedSort
[i
]._idx
=== undefined ) {
4441 nestedSort
[i
]._idx
= $.inArray( nestedSort
[i
][1], aoColumns
[iCol
].asSorting
);
4447 dir
: nestedSort
[i
][1],
4448 index
: nestedSort
[i
]._idx
,
4450 formatter
: DataTable
.ext
.type
.order
[ sType
+"-pre" ]
4459 * Change the order of the table
4460 * @param {object} oSettings dataTables settings object
4461 * @memberof DataTable#oApi
4462 * @todo This really needs split up!
4464 function _fnSort ( oSettings
)
4467 i
, ien
, iLen
, j
, jLen
, k
, kLen
,
4470 oExtSort
= DataTable
.ext
.type
.order
,
4471 aoData
= oSettings
.aoData
,
4472 aoColumns
= oSettings
.aoColumns
,
4473 aDataSort
, data
, iCol
, sType
, oSort
,
4476 displayMaster
= oSettings
.aiDisplayMaster
,
4479 // Resolve any column types that are unknown due to addition or invalidation
4480 // @todo Can this be moved into a 'data-ready' handler which is called when
4481 // data is going to be used in the table?
4482 _fnColumnTypes( oSettings
);
4484 aSort
= _fnSortFlatten( oSettings
);
4486 for ( i
=0, ien
=aSort
.length
; i
<ien
; i
++ ) {
4489 // Track if we can use the fast sort algorithm
4490 if ( sortCol
.formatter
) {
4494 // Load the data needed for the sort, for each cell
4495 _fnSortData( oSettings
, sortCol
.col
);
4498 /* No sorting required if server-side or no sorting array */
4499 if ( _fnDataSource( oSettings
) != 'ssp' && aSort
.length
!== 0 )
4501 // Create a value - key array of the current row positions such that we can use their
4502 // current position during the sort, if values match, in order to perform stable sorting
4503 for ( i
=0, iLen
=displayMaster
.length
; i
<iLen
; i
++ ) {
4504 aiOrig
[ displayMaster
[i
] ] = i
;
4507 /* Do the sort - here we want multi-column sorting based on a given data source (column)
4508 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4509 * follow on it's own, but this is what we want (example two column sorting):
4510 * fnLocalSorting = function(a,b){
4512 * iTest = oSort['string-asc']('data11', 'data12');
4515 * iTest = oSort['numeric-desc']('data21', 'data22');
4518 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4520 * Basically we have a test for each sorting column, if the data in that column is equal,
4521 * test the next column. If all columns match, then we use a numeric sort on the row
4522 * positions in the original data array to provide a stable sort.
4524 * Note - I know it seems excessive to have two sorting methods, but the first is around
4525 * 15% faster, so the second is only maintained for backwards compatibility with sorting
4526 * methods which do not have a pre-sort formatting function.
4528 if ( formatters
=== aSort
.length
) {
4529 // All sort types have formatting functions
4530 displayMaster
.sort( function ( a
, b
) {
4532 x
, y
, k
, test
, sort
,
4534 dataA
= aoData
[a
]._aSortData
,
4535 dataB
= aoData
[b
]._aSortData
;
4537 for ( k
=0 ; k
<len
; k
++ ) {
4540 x
= dataA
[ sort
.col
];
4541 y
= dataB
[ sort
.col
];
4543 test
= x
<y
? -1 : x
>y
? 1 : 0;
4545 return sort
.dir
=== 'asc' ? test
: -test
;
4551 return x
<y
? -1 : x
>y
? 1 : 0;
4555 // Depreciated - remove in 1.11 (providing a plug-in option)
4556 // Not all sort types have formatting methods, so we have to call their sorting
4558 displayMaster
.sort( function ( a
, b
) {
4560 x
, y
, k
, l
, test
, sort
, fn
,
4562 dataA
= aoData
[a
]._aSortData
,
4563 dataB
= aoData
[b
]._aSortData
;
4565 for ( k
=0 ; k
<len
; k
++ ) {
4568 x
= dataA
[ sort
.col
];
4569 y
= dataB
[ sort
.col
];
4571 fn
= oExtSort
[ sort
.type
+"-"+sort
.dir
] || oExtSort
[ "string-"+sort
.dir
];
4580 return x
<y
? -1 : x
>y
? 1 : 0;
4585 /* Tell the draw function that we have sorted the data */
4586 oSettings
.bSorted
= true;
4590 function _fnSortAria ( settings
)
4594 var columns
= settings
.aoColumns
;
4595 var aSort
= _fnSortFlatten( settings
);
4596 var oAria
= settings
.oLanguage
.oAria
;
4598 // ARIA attributes - need to loop all columns, to update all (removing old
4599 // attributes as needed)
4600 for ( var i
=0, iLen
=columns
.length
; i
<iLen
; i
++ )
4602 var col
= columns
[i
];
4603 var asSorting
= col
.asSorting
;
4604 var sTitle
= col
.sTitle
.replace( /<.*?>/g, "" );
4607 // IE7 is throwing an error when setting these properties with jQuery's
4608 // attr() and removeAttr() methods...
4609 th
.removeAttribute('aria-sort');
4611 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4612 if ( col
.bSortable
) {
4613 if ( aSort
.length
> 0 && aSort
[0].col
== i
) {
4614 th
.setAttribute('aria-sort', aSort
[0].dir
=="asc" ? "ascending" : "descending" );
4615 nextSort
= asSorting
[ aSort
[0].index
+1 ] || asSorting
[0];
4618 nextSort
= asSorting
[0];
4621 label
= sTitle
+ ( nextSort
=== "asc" ?
4622 oAria
.sSortAscending
:
4623 oAria
.sSortDescending
4630 th
.setAttribute('aria-label', label
);
4636 * Function to run on user sort request
4637 * @param {object} settings dataTables settings object
4638 * @param {node} attachTo node to attach the handler to
4639 * @param {int} colIdx column sorting index
4640 * @param {boolean} [append=false] Append the requested sort to the existing
4641 * sort if true (i.e. multi-column sort)
4642 * @param {function} [callback] callback function
4643 * @memberof DataTable#oApi
4645 function _fnSortListener ( settings
, colIdx
, append
, callback
)
4647 var col
= settings
.aoColumns
[ colIdx
];
4648 var sorting
= settings
.aaSorting
;
4649 var asSorting
= col
.asSorting
;
4651 var next = function ( a
, overflow
) {
4653 if ( idx
=== undefined ) {
4654 idx
= $.inArray( a
[1], asSorting
);
4657 return idx
+1 < asSorting
.length
?
4664 // Convert to 2D array if needed
4665 if ( typeof sorting
[0] === 'number' ) {
4666 sorting
= settings
.aaSorting
= [ sorting
];
4669 // If appending the sort then we are multi-column sorting
4670 if ( append
&& settings
.oFeatures
.bSortMulti
) {
4671 // Are we already doing some kind of sort on this column?
4672 var sortIdx
= $.inArray( colIdx
, _pluck(sorting
, '0') );
4674 if ( sortIdx
!== -1 ) {
4675 // Yes, modify the sort
4676 nextSortIdx
= next( sorting
[sortIdx
], true );
4678 if ( nextSortIdx
=== null ) {
4679 sorting
.splice( sortIdx
, 1 );
4682 sorting
[sortIdx
][1] = asSorting
[ nextSortIdx
];
4683 sorting
[sortIdx
]._idx
= nextSortIdx
;
4687 // No sort on this column yet
4688 sorting
.push( [ colIdx
, asSorting
[0], 0 ] );
4689 sorting
[sorting
.length
-1]._idx
= 0;
4692 else if ( sorting
.length
&& sorting
[0][0] == colIdx
) {
4693 // Single column - already sorting on this column, modify the sort
4694 nextSortIdx
= next( sorting
[0] );
4697 sorting
[0][1] = asSorting
[ nextSortIdx
];
4698 sorting
[0]._idx
= nextSortIdx
;
4701 // Single column - sort only on this column
4703 sorting
.push( [ colIdx
, asSorting
[0] ] );
4704 sorting
[0]._idx
= 0;
4707 // Run the sort by calling a full redraw
4708 _fnReDraw( settings
);
4710 // callback used for async user interaction
4711 if ( typeof callback
== 'function' ) {
4712 callback( settings
);
4718 * Attach a sort handler (click) to a node
4719 * @param {object} settings dataTables settings object
4720 * @param {node} attachTo node to attach the handler to
4721 * @param {int} colIdx column sorting index
4722 * @param {function} [callback] callback function
4723 * @memberof DataTable#oApi
4725 function _fnSortAttachListener ( settings
, attachTo
, colIdx
, callback
)
4727 var col
= settings
.aoColumns
[ colIdx
];
4729 _fnBindAction( attachTo
, {}, function (e
) {
4730 /* If the column is not sortable - don't to anything */
4731 if ( col
.bSortable
=== false ) {
4735 // If processing is enabled use a timeout to allow the processing
4736 // display to be shown - otherwise to it synchronously
4737 if ( settings
.oFeatures
.bProcessing
) {
4738 _fnProcessingDisplay( settings
, true );
4740 setTimeout( function() {
4741 _fnSortListener( settings
, colIdx
, e
.shiftKey
, callback
);
4743 // In server-side processing, the draw callback will remove the
4744 // processing display
4745 if ( _fnDataSource( settings
) !== 'ssp' ) {
4746 _fnProcessingDisplay( settings
, false );
4751 _fnSortListener( settings
, colIdx
, e
.shiftKey
, callback
);
4758 * Set the sorting classes on table's body, Note: it is safe to call this function
4759 * when bSort and bSortClasses are false
4760 * @param {object} oSettings dataTables settings object
4761 * @memberof DataTable#oApi
4763 function _fnSortingClasses( settings
)
4765 var oldSort
= settings
.aLastSort
;
4766 var sortClass
= settings
.oClasses
.sSortColumn
;
4767 var sort
= _fnSortFlatten( settings
);
4768 var features
= settings
.oFeatures
;
4771 if ( features
.bSort
&& features
.bSortClasses
) {
4772 // Remove old sorting classes
4773 for ( i
=0, ien
=oldSort
.length
; i
<ien
; i
++ ) {
4774 colIdx
= oldSort
[i
].src
;
4776 // Remove column sorting
4777 $( _pluck( settings
.aoData
, 'anCells', colIdx
) )
4778 .removeClass( sortClass
+ (i
<2 ? i
+1 : 3) );
4781 // Add new column sorting
4782 for ( i
=0, ien
=sort
.length
; i
<ien
; i
++ ) {
4783 colIdx
= sort
[i
].src
;
4785 $( _pluck( settings
.aoData
, 'anCells', colIdx
) )
4786 .addClass( sortClass
+ (i
<2 ? i
+1 : 3) );
4790 settings
.aLastSort
= sort
;
4794 // Get the data to sort a column, be it from cache, fresh (populating the
4795 // cache), or from a sort formatter
4796 function _fnSortData( settings
, idx
)
4798 // Custom sorting function - provided by the sort data type
4799 var column
= settings
.aoColumns
[ idx
];
4800 var customSort
= DataTable
.ext
.order
[ column
.sSortDataType
];
4804 customData
= customSort
.call( settings
.oInstance
, settings
, idx
,
4805 _fnColumnIndexToVisible( settings
, idx
)
4809 // Use / populate cache
4811 var formatter
= DataTable
.ext
.type
.order
[ column
.sType
+"-pre" ];
4813 for ( var i
=0, ien
=settings
.aoData
.length
; i
<ien
; i
++ ) {
4814 row
= settings
.aoData
[i
];
4816 if ( ! row
._aSortData
) {
4817 row
._aSortData
= [];
4820 if ( ! row
._aSortData
[idx
] || customSort
) {
4821 cellData
= customSort
?
4822 customData
[i
] : // If there was a custom sort function, use data from there
4823 _fnGetCellData( settings
, i
, idx
, 'sort' );
4825 row
._aSortData
[ idx
] = formatter
?
4826 formatter( cellData
) :
4835 * Save the state of a table
4836 * @param {object} oSettings dataTables settings object
4837 * @memberof DataTable#oApi
4839 function _fnSaveState ( settings
)
4841 if ( !settings
.oFeatures
.bStateSave
|| settings
.bDestroying
)
4846 /* Store the interesting variables */
4849 start
: settings
._iDisplayStart
,
4850 length
: settings
._iDisplayLength
,
4851 order
: $.extend( true, [], settings
.aaSorting
),
4852 search
: _fnSearchToCamel( settings
.oPreviousSearch
),
4853 columns
: $.map( settings
.aoColumns
, function ( col
, i
) {
4855 visible
: col
.bVisible
,
4856 search
: _fnSearchToCamel( settings
.aoPreSearchCols
[i
] )
4861 _fnCallbackFire( settings
, "aoStateSaveParams", 'stateSaveParams', [settings
, state
] );
4863 settings
.oSavedState
= state
;
4864 settings
.fnStateSaveCallback
.call( settings
.oInstance
, settings
, state
);
4869 * Attempt to load a saved table state
4870 * @param {object} oSettings dataTables settings object
4871 * @param {object} oInit DataTables init object so we can override settings
4872 * @memberof DataTable#oApi
4874 function _fnLoadState ( settings
, oInit
)
4877 var columns
= settings
.aoColumns
;
4879 if ( ! settings
.oFeatures
.bStateSave
) {
4883 var state
= settings
.fnStateLoadCallback
.call( settings
.oInstance
, settings
);
4884 if ( ! state
|| ! state
.time
) {
4888 /* Allow custom and plug-in manipulation functions to alter the saved data set and
4889 * cancelling of loading by returning false
4891 var abStateLoad
= _fnCallbackFire( settings
, 'aoStateLoadParams', 'stateLoadParams', [settings
, state
] );
4892 if ( $.inArray( false, abStateLoad
) !== -1 ) {
4896 /* Reject old data */
4897 var duration
= settings
.iStateDuration
;
4898 if ( duration
> 0 && state
.time
< +new Date() - (duration
*1000) ) {
4902 // Number of columns have changed - all bets are off, no restore of settings
4903 if ( columns
.length
!== state
.columns
.length
) {
4907 // Store the saved state so it might be accessed at any time
4908 settings
.oLoadedState
= $.extend( true, {}, state
);
4910 // Restore key features - todo - for 1.11 this needs to be done by
4911 // subscribed events
4912 settings
._iDisplayStart
= state
.start
;
4913 settings
.iInitDisplayStart
= state
.start
;
4914 settings
._iDisplayLength
= state
.length
;
4915 settings
.aaSorting
= [];
4918 $.each( state
.order
, function ( i
, col
) {
4919 settings
.aaSorting
.push( col
[0] >= columns
.length
?
4926 $.extend( settings
.oPreviousSearch
, _fnSearchToHung( state
.search
) );
4929 for ( i
=0, ien
=state
.columns
.length
; i
<ien
; i
++ ) {
4930 var col
= state
.columns
[i
];
4933 columns
[i
].bVisible
= col
.visible
;
4936 $.extend( settings
.aoPreSearchCols
[i
], _fnSearchToHung( col
.search
) );
4939 _fnCallbackFire( settings
, 'aoStateLoaded', 'stateLoaded', [settings
, state
] );
4944 * Return the settings object for a particular table
4945 * @param {node} table table we are using as a dataTable
4946 * @returns {object} Settings object - or null if not found
4947 * @memberof DataTable#oApi
4949 function _fnSettingsFromNode ( table
)
4951 var settings
= DataTable
.settings
;
4952 var idx
= $.inArray( table
, _pluck( settings
, 'nTable' ) );
4961 * Log an error message
4962 * @param {object} settings dataTables settings object
4963 * @param {int} level log error messages, or display them to the user
4964 * @param {string} msg error message
4965 * @param {int} tn Technical note id to get more information about the error.
4966 * @memberof DataTable#oApi
4968 function _fnLog( settings
, level
, msg
, tn
)
4970 msg
= 'DataTables warning: '+
4971 (settings
!==null ? 'table id='+settings
.sTableId
+' - ' : '')+msg
;
4974 msg
+= '. For more information about this error, please see '+
4975 'http://datatables.net/tn/'+tn
;
4979 // Backwards compatibility pre 1.10
4980 var ext
= DataTable
.ext
;
4981 var type
= ext
.sErrMode
|| ext
.errMode
;
4983 if ( type
== 'alert' ) {
4987 throw new Error(msg
);
4990 else if ( window
.console
&& console
.log
) {
4997 * See if a property is defined on one object, if so assign it to the other object
4998 * @param {object} ret target object
4999 * @param {object} src source object
5000 * @param {string} name property
5001 * @param {string} [mappedName] name to map too - optional, name used if not given
5002 * @memberof DataTable#oApi
5004 function _fnMap( ret
, src
, name
, mappedName
)
5006 if ( $.isArray( name
) ) {
5007 $.each( name
, function (i
, val
) {
5008 if ( $.isArray( val
) ) {
5009 _fnMap( ret
, src
, val
[0], val
[1] );
5012 _fnMap( ret
, src
, val
);
5019 if ( mappedName
=== undefined ) {
5023 if ( src
[name
] !== undefined ) {
5024 ret
[mappedName
] = src
[name
];
5030 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
5031 * shallow copy arrays. The reason we need to do this, is that we don't want to
5032 * deep copy array init values (such as aaSorting) since the dev wouldn't be
5033 * able to override them, but we do want to deep copy arrays.
5034 * @param {object} out Object to extend
5035 * @param {object} extender Object from which the properties will be applied to
5037 * @param {boolean} breakRefs If true, then arrays will be sliced to take an
5038 * independent copy with the exception of the `data` or `aaData` parameters
5039 * if they are present. This is so you can pass in a collection to
5040 * DataTables and have that used as your data source without breaking the
5042 * @returns {object} out Reference, just for convenience - out === the return.
5043 * @memberof DataTable#oApi
5044 * @todo This doesn't take account of arrays inside the deep copied objects.
5046 function _fnExtend( out
, extender
, breakRefs
)
5050 for ( var prop
in extender
) {
5051 if ( extender
.hasOwnProperty(prop
) ) {
5052 val
= extender
[prop
];
5054 if ( $.isPlainObject( val
) ) {
5055 if ( ! $.isPlainObject( out
[prop
] ) ) {
5058 $.extend( true, out
[prop
], val
);
5060 else if ( breakRefs
&& prop
!== 'data' && prop
!== 'aaData' && $.isArray(val
) ) {
5061 out
[prop
] = val
.slice();
5074 * Bind an event handers to allow a click or return key to activate the callback.
5075 * This is good for accessibility since a return on the keyboard will have the
5076 * same effect as a click, if the element has focus.
5077 * @param {element} n Element to bind the action to
5078 * @param {object} oData Data object to pass to the triggered function
5079 * @param {function} fn Callback function for when the event is triggered
5080 * @memberof DataTable#oApi
5082 function _fnBindAction( n
, oData
, fn
)
5085 .bind( 'click.DT', oData
, function (e
) {
5086 n
.blur(); // Remove focus outline for mouse users
5089 .bind( 'keypress.DT', oData
, function (e
){
5090 if ( e
.which
=== 13 ) {
5095 .bind( 'selectstart.DT', function () {
5096 /* Take the brutal approach to cancelling text selection */
5103 * Register a callback function. Easily allows a callback function to be added to
5104 * an array store of callback functions that can then all be called together.
5105 * @param {object} oSettings dataTables settings object
5106 * @param {string} sStore Name of the array storage for the callbacks in oSettings
5107 * @param {function} fn Function to be called back
5108 * @param {string} sName Identifying name for the callback (i.e. a label)
5109 * @memberof DataTable#oApi
5111 function _fnCallbackReg( oSettings
, sStore
, fn
, sName
)
5115 oSettings
[sStore
].push( {
5124 * Fire callback functions and trigger events. Note that the loop over the
5125 * callback array store is done backwards! Further note that you do not want to
5126 * fire off triggers in time sensitive applications (for example cell creation)
5128 * @param {object} settings dataTables settings object
5129 * @param {string} callbackArr Name of the array storage for the callbacks in
5131 * @param {string} event Name of the jQuery custom event to trigger. If null no
5133 * @param {array} args Array of arguments to pass to the callback function /
5135 * @memberof DataTable#oApi
5137 function _fnCallbackFire( settings
, callbackArr
, e
, args
)
5141 if ( callbackArr
) {
5142 ret
= $.map( settings
[callbackArr
].slice().reverse(), function (val
, i
) {
5143 return val
.fn
.apply( settings
.oInstance
, args
);
5148 $(settings
.nTable
).trigger( e
+'.dt', args
);
5155 function _fnLengthOverflow ( settings
)
5158 start
= settings
._iDisplayStart
,
5159 end
= settings
.fnDisplayEnd(),
5160 len
= settings
._iDisplayLength
;
5162 /* If we have space to show extra rows (backing up from the end point - then do so */
5168 if ( len
=== -1 || start
< 0 )
5173 settings
._iDisplayStart
= start
;
5177 function _fnRenderer( settings
, type
)
5179 var renderer
= settings
.renderer
;
5180 var host
= DataTable
.ext
.renderer
[type
];
5182 if ( $.isPlainObject( renderer
) && renderer
[type
] ) {
5183 // Specific renderer for this type. If available use it, otherwise use
5185 return host
[renderer
[type
]] || host
._
;
5187 else if ( typeof renderer
=== 'string' ) {
5188 // Common renderer - if there is one available for this type use it,
5189 // otherwise use the default
5190 return host
[renderer
] || host
._
;
5199 * Detect the data source being used for the table. Used to simplify the code
5200 * a little (ajax) and to make it compress a little smaller.
5202 * @param {object} settings dataTables settings object
5203 * @returns {string} Data source
5204 * @memberof DataTable#oApi
5206 function _fnDataSource ( settings
)
5208 if ( settings
.oFeatures
.bServerSide
) {
5211 else if ( settings
.ajax
|| settings
.sAjaxSource
) {
5218 DataTable = function( options
)
5221 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5222 * return the resulting jQuery object.
5223 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5224 * @param {object} [oOpts] Optional parameters for modifying the rows to be included
5225 * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5226 * criterion ("applied") or all TR elements (i.e. no filter).
5227 * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5228 * Can be either 'current', whereby the current sorting of the table is used, or
5229 * 'original' whereby the original order the data was read into the table is used.
5230 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5231 * ("current") or not ("all"). If 'current' is given, then order is assumed to be
5232 * 'current' and filter is 'applied', regardless of what they might be given as.
5233 * @returns {object} jQuery object, filtered by the given selector.
5235 * @deprecated Since v1.10
5238 * $(document).ready(function() {
5239 * var oTable = $('#example').dataTable();
5241 * // Highlight every second row
5242 * oTable.$('tr:odd').css('backgroundColor', 'blue');
5246 * $(document).ready(function() {
5247 * var oTable = $('#example').dataTable();
5249 * // Filter to rows with 'Webkit' in them, add a background colour and then
5250 * // remove the filter, thus highlighting the 'Webkit' rows only.
5251 * oTable.fnFilter('Webkit');
5252 * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5253 * oTable.fnFilter('');
5256 this.$ = function ( sSelector
, oOpts
)
5258 return this.api(true).$( sSelector
, oOpts
);
5263 * Almost identical to $ in operation, but in this case returns the data for the matched
5264 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5265 * rather than any descendants, so the data can be obtained for the row/cell. If matching
5266 * rows are found, the data returned is the original data array/object that was used to
5267 * create the row (or a generated array if from a DOM source).
5269 * This method is often useful in-combination with $ where both functions are given the
5270 * same parameters and the array indexes will match identically.
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 elements that meet the current filter
5274 * criterion ("applied") or all elements (i.e. no filter).
5275 * @param {string} [oOpts.order=current] Order of the data 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 {array} Data for the matched elements. If any elements, as a result of the
5282 * selector, were not TR, TD or TH elements in the DataTable, they will have a null
5283 * entry in the array.
5285 * @deprecated Since v1.10
5288 * $(document).ready(function() {
5289 * var oTable = $('#example').dataTable();
5291 * // Get the data from the first row in the table
5292 * var data = oTable._('tr:first');
5294 * // Do something useful with the data
5295 * alert( "First cell is: "+data[0] );
5299 * $(document).ready(function() {
5300 * var oTable = $('#example').dataTable();
5302 * // Filter to 'Webkit' and get all data for
5303 * oTable.fnFilter('Webkit');
5304 * var data = oTable._('tr', {"search": "applied"});
5306 * // Do something with the data
5307 * alert( data.length+" rows matched the search" );
5310 this._ = function ( sSelector
, oOpts
)
5312 return this.api(true).rows( sSelector
, oOpts
).data();
5317 * Create a DataTables Api instance, with the currently selected tables for
5318 * the Api's context.
5319 * @param {boolean} [traditional=false] Set the API instance's context to be
5320 * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5321 * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5322 * or if all tables captured in the jQuery object should be used.
5323 * @return {DataTables.Api}
5325 this.api = function ( traditional
)
5327 return traditional
?
5329 _fnSettingsFromNode( this[ _ext
.iApiIndex
] )
5336 * Add a single new row or multiple rows of data to the table. Please note
5337 * that this is suitable for client-side processing only - if you are using
5338 * server-side processing (i.e. "bServerSide": true), then to add data, you
5339 * must add it to the data source, i.e. the server-side, through an Ajax call.
5340 * @param {array|object} data The data to be added to the table. This can be:
5342 * <li>1D array of data - add a single row with the data provided</li>
5343 * <li>2D array of arrays - add multiple rows in a single call</li>
5344 * <li>object - data object when using <i>mData</i></li>
5345 * <li>array of objects - multiple data objects when using <i>mData</i></li>
5347 * @param {bool} [redraw=true] redraw the table or not
5348 * @returns {array} An array of integers, representing the list of indexes in
5349 * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5352 * @deprecated Since v1.10
5355 * // Global var for counter
5358 * $(document).ready(function() {
5359 * $('#example').dataTable();
5362 * function fnClickAddRow() {
5363 * $('#example').dataTable().fnAddData( [
5373 this.fnAddData = function( data
, redraw
)
5375 var api
= this.api( true );
5377 /* Check if we want to add multiple rows or not */
5378 var rows
= $.isArray(data
) && ( $.isArray(data
[0]) || $.isPlainObject(data
[0]) ) ?
5379 api
.rows
.add( data
) :
5380 api
.row
.add( data
);
5382 if ( redraw
=== undefined || redraw
) {
5386 return rows
.flatten().toArray();
5391 * This function will make DataTables recalculate the column sizes, based on the data
5392 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5393 * through the sWidth parameter). This can be useful when the width of the table's
5394 * parent element changes (for example a window resize).
5395 * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5397 * @deprecated Since v1.10
5400 * $(document).ready(function() {
5401 * var oTable = $('#example').dataTable( {
5402 * "sScrollY": "200px",
5403 * "bPaginate": false
5406 * $(window).bind('resize', function () {
5407 * oTable.fnAdjustColumnSizing();
5411 this.fnAdjustColumnSizing = function ( bRedraw
)
5413 var api
= this.api( true ).columns
.adjust();
5414 var settings
= api
.settings()[0];
5415 var scroll
= settings
.oScroll
;
5417 if ( bRedraw
=== undefined || bRedraw
) {
5420 else if ( scroll
.sX
!== "" || scroll
.sY
!== "" ) {
5421 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5422 _fnScrollDraw( settings
);
5428 * Quickly and simply clear a table
5429 * @param {bool} [bRedraw=true] redraw the table or not
5431 * @deprecated Since v1.10
5434 * $(document).ready(function() {
5435 * var oTable = $('#example').dataTable();
5437 * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5438 * oTable.fnClearTable();
5441 this.fnClearTable = function( bRedraw
)
5443 var api
= this.api( true ).clear();
5445 if ( bRedraw
=== undefined || bRedraw
) {
5452 * The exact opposite of 'opening' a row, this function will close any rows which
5453 * are currently 'open'.
5454 * @param {node} nTr the table row to 'close'
5455 * @returns {int} 0 on success, or 1 if failed (can't find the row)
5457 * @deprecated Since v1.10
5460 * $(document).ready(function() {
5463 * // 'open' an information row when a row is clicked on
5464 * $('#example tbody tr').click( function () {
5465 * if ( oTable.fnIsOpen(this) ) {
5466 * oTable.fnClose( this );
5468 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
5472 * oTable = $('#example').dataTable();
5475 this.fnClose = function( nTr
)
5477 this.api( true ).row( nTr
).child
.hide();
5482 * Remove a row for the table
5483 * @param {mixed} target The index of the row from aoData to be deleted, or
5484 * the TR element you want to delete
5485 * @param {function|null} [callBack] Callback function
5486 * @param {bool} [redraw=true] Redraw the table or not
5487 * @returns {array} The row that was deleted
5489 * @deprecated Since v1.10
5492 * $(document).ready(function() {
5493 * var oTable = $('#example').dataTable();
5495 * // Immediately remove the first row
5496 * oTable.fnDeleteRow( 0 );
5499 this.fnDeleteRow = function( target
, callback
, redraw
)
5501 var api
= this.api( true );
5502 var rows
= api
.rows( target
);
5503 var settings
= rows
.settings()[0];
5504 var data
= settings
.aoData
[ rows
[0][0] ];
5509 callback
.call( this, settings
, data
);
5512 if ( redraw
=== undefined || redraw
) {
5521 * Restore the table to it's original state in the DOM by removing all of DataTables
5522 * enhancements, alterations to the DOM structure of the table and event listeners.
5523 * @param {boolean} [remove=false] Completely remove the table from the DOM
5525 * @deprecated Since v1.10
5528 * $(document).ready(function() {
5529 * // This example is fairly pointless in reality, but shows how fnDestroy can be used
5530 * var oTable = $('#example').dataTable();
5531 * oTable.fnDestroy();
5534 this.fnDestroy = function ( remove
)
5536 this.api( true ).destroy( remove
);
5542 * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5544 * @deprecated Since v1.10
5547 * $(document).ready(function() {
5548 * var oTable = $('#example').dataTable();
5550 * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5554 this.fnDraw = function( complete
)
5556 // Note that this isn't an exact match to the old call to _fnDraw - it takes
5557 // into account the new data, but can old position.
5558 this.api( true ).draw( ! complete
);
5563 * Filter the input based on data
5564 * @param {string} sInput String to filter the table on
5565 * @param {int|null} [iColumn] Column to limit filtering to
5566 * @param {bool} [bRegex=false] Treat as regular expression or not
5567 * @param {bool} [bSmart=true] Perform smart filtering or not
5568 * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5569 * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5571 * @deprecated Since v1.10
5574 * $(document).ready(function() {
5575 * var oTable = $('#example').dataTable();
5577 * // Sometime later - filter...
5578 * oTable.fnFilter( 'test string' );
5581 this.fnFilter = function( sInput
, iColumn
, bRegex
, bSmart
, bShowGlobal
, bCaseInsensitive
)
5583 var api
= this.api( true );
5585 if ( iColumn
=== null || iColumn
=== undefined ) {
5586 api
.search( sInput
, bRegex
, bSmart
, bCaseInsensitive
);
5589 api
.column( iColumn
).search( sInput
, bRegex
, bSmart
, bCaseInsensitive
);
5597 * Get the data for the whole table, an individual row or an individual cell based on the
5598 * provided parameters.
5599 * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5600 * a TR node then the data source for the whole row will be returned. If given as a
5601 * TD/TH cell node then iCol will be automatically calculated and the data for the
5602 * cell returned. If given as an integer, then this is treated as the aoData internal
5603 * data index for the row (see fnGetPosition) and the data for that row used.
5604 * @param {int} [col] Optional column index that you want the data of.
5605 * @returns {array|object|string} If mRow is undefined, then the data for all rows is
5606 * returned. If mRow is defined, just data for that row, and is iCol is
5607 * defined, only data for the designated cell is returned.
5609 * @deprecated Since v1.10
5613 * $(document).ready(function() {
5614 * oTable = $('#example').dataTable();
5616 * oTable.$('tr').click( function () {
5617 * var data = oTable.fnGetData( this );
5618 * // ... do something with the array / object of data for the row
5623 * // Individual cell data
5624 * $(document).ready(function() {
5625 * oTable = $('#example').dataTable();
5627 * oTable.$('td').click( function () {
5628 * var sData = oTable.fnGetData( this );
5629 * alert( 'The cell clicked on had the value of '+sData );
5633 this.fnGetData = function( src
, col
)
5635 var api
= this.api( true );
5637 if ( src
!== undefined ) {
5638 var type
= src
.nodeName
? src
.nodeName
.toLowerCase() : '';
5640 return col
!== undefined || type
== 'td' || type
== 'th' ?
5641 api
.cell( src
, col
).data() :
5642 api
.row( src
).data() || null;
5645 return api
.data().toArray();
5650 * Get an array of the TR nodes that are used in the table's body. Note that you will
5651 * typically want to use the '$' API method in preference to this as it is more
5653 * @param {int} [iRow] Optional row index for the TR element you want
5654 * @returns {array|node} If iRow is undefined, returns an array of all TR elements
5655 * in the table's body, or iRow is defined, just the TR element requested.
5657 * @deprecated Since v1.10
5660 * $(document).ready(function() {
5661 * var oTable = $('#example').dataTable();
5663 * // Get the nodes from the table
5664 * var nNodes = oTable.fnGetNodes( );
5667 this.fnGetNodes = function( iRow
)
5669 var api
= this.api( true );
5671 return iRow
!== undefined ?
5672 api
.row( iRow
).node() :
5673 api
.rows().nodes().flatten().toArray();
5678 * Get the array indexes of a particular cell from it's DOM element
5679 * and column index including hidden columns
5680 * @param {node} node this can either be a TR, TD or TH in the table's body
5681 * @returns {int} If nNode is given as a TR, then a single index is returned, or
5682 * if given as a cell, an array of [row index, column index (visible),
5683 * column index (all)] is given.
5685 * @deprecated Since v1.10
5688 * $(document).ready(function() {
5689 * $('#example tbody td').click( function () {
5690 * // Get the position of the current data from the node
5691 * var aPos = oTable.fnGetPosition( this );
5693 * // Get the data array for this row
5694 * var aData = oTable.fnGetData( aPos[0] );
5696 * // Update the data array and return the value
5697 * aData[ aPos[1] ] = 'clicked';
5698 * this.innerHTML = 'clicked';
5701 * // Init DataTables
5702 * oTable = $('#example').dataTable();
5705 this.fnGetPosition = function( node
)
5707 var api
= this.api( true );
5708 var nodeName
= node
.nodeName
.toUpperCase();
5710 if ( nodeName
== 'TR' ) {
5711 return api
.row( node
).index();
5713 else if ( nodeName
== 'TD' || nodeName
== 'TH' ) {
5714 var cell
= api
.cell( node
).index();
5727 * Check to see if a row is 'open' or not.
5728 * @param {node} nTr the table row to check
5729 * @returns {boolean} true if the row is currently open, false otherwise
5731 * @deprecated Since v1.10
5734 * $(document).ready(function() {
5737 * // 'open' an information row when a row is clicked on
5738 * $('#example tbody tr').click( function () {
5739 * if ( oTable.fnIsOpen(this) ) {
5740 * oTable.fnClose( this );
5742 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
5746 * oTable = $('#example').dataTable();
5749 this.fnIsOpen = function( nTr
)
5751 return this.api( true ).row( nTr
).child
.isShown();
5756 * This function will place a new row directly after a row which is currently
5757 * on display on the page, with the HTML contents that is passed into the
5758 * function. This can be used, for example, to ask for confirmation that a
5759 * particular record should be deleted.
5760 * @param {node} nTr The table row to 'open'
5761 * @param {string|node|jQuery} mHtml The HTML to put into the row
5762 * @param {string} sClass Class to give the new TD cell
5763 * @returns {node} The row opened. Note that if the table row passed in as the
5764 * first parameter, is not found in the table, this method will silently
5767 * @deprecated Since v1.10
5770 * $(document).ready(function() {
5773 * // 'open' an information row when a row is clicked on
5774 * $('#example tbody tr').click( function () {
5775 * if ( oTable.fnIsOpen(this) ) {
5776 * oTable.fnClose( this );
5778 * oTable.fnOpen( this, "Temporary row opened", "info_row" );
5782 * oTable = $('#example').dataTable();
5785 this.fnOpen = function( nTr
, mHtml
, sClass
)
5787 return this.api( true )
5789 .child( mHtml
, sClass
)
5796 * Change the pagination - provides the internal logic for pagination in a simple API
5797 * function. With this function you can have a DataTables table go to the next,
5798 * previous, first or last pages.
5799 * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5800 * or page number to jump to (integer), note that page 0 is the first page.
5801 * @param {bool} [bRedraw=true] Redraw the table or not
5803 * @deprecated Since v1.10
5806 * $(document).ready(function() {
5807 * var oTable = $('#example').dataTable();
5808 * oTable.fnPageChange( 'next' );
5811 this.fnPageChange = function ( mAction
, bRedraw
)
5813 var api
= this.api( true ).page( mAction
);
5815 if ( bRedraw
=== undefined || bRedraw
) {
5822 * Show a particular column
5823 * @param {int} iCol The column whose display should be changed
5824 * @param {bool} bShow Show (true) or hide (false) the column
5825 * @param {bool} [bRedraw=true] Redraw the table or not
5827 * @deprecated Since v1.10
5830 * $(document).ready(function() {
5831 * var oTable = $('#example').dataTable();
5833 * // Hide the second column after initialisation
5834 * oTable.fnSetColumnVis( 1, false );
5837 this.fnSetColumnVis = function ( iCol
, bShow
, bRedraw
)
5839 var api
= this.api( true ).column( iCol
).visible( bShow
);
5841 if ( bRedraw
=== undefined || bRedraw
) {
5842 api
.columns
.adjust().draw();
5848 * Get the settings for a particular table for external manipulation
5849 * @returns {object} DataTables settings object. See
5850 * {@link DataTable.models.oSettings}
5852 * @deprecated Since v1.10
5855 * $(document).ready(function() {
5856 * var oTable = $('#example').dataTable();
5857 * var oSettings = oTable.fnSettings();
5859 * // Show an example parameter from the settings
5860 * alert( oSettings._iDisplayStart );
5863 this.fnSettings = function()
5865 return _fnSettingsFromNode( this[_ext
.iApiIndex
] );
5870 * Sort the table by a particular column
5871 * @param {int} iCol the data index to sort on. Note that this will not match the
5872 * 'display index' if you have hidden data entries
5874 * @deprecated Since v1.10
5877 * $(document).ready(function() {
5878 * var oTable = $('#example').dataTable();
5880 * // Sort immediately with columns 0 and 1
5881 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
5884 this.fnSort = function( aaSort
)
5886 this.api( true ).order( aaSort
).draw();
5891 * Attach a sort listener to an element for a given column
5892 * @param {node} nNode the element to attach the sort listener to
5893 * @param {int} iColumn the column that a click on this node will sort on
5894 * @param {function} [fnCallback] callback function when sort is run
5896 * @deprecated Since v1.10
5899 * $(document).ready(function() {
5900 * var oTable = $('#example').dataTable();
5902 * // Sort on column 1, when 'sorter' is clicked on
5903 * oTable.fnSortListener( document.getElementById('sorter'), 1 );
5906 this.fnSortListener = function( nNode
, iColumn
, fnCallback
)
5908 this.api( true ).order
.listener( nNode
, iColumn
, fnCallback
);
5913 * Update a table cell or row - this method will accept either a single value to
5914 * update the cell with, an array of values with one element for each column or
5915 * an object in the same format as the original data source. The function is
5916 * self-referencing in order to make the multi column updates easier.
5917 * @param {object|array|string} mData Data to update the cell/row with
5918 * @param {node|int} mRow TR element you want to update or the aoData index
5919 * @param {int} [iColumn] The column to update, give as null or undefined to
5920 * update a whole row.
5921 * @param {bool} [bRedraw=true] Redraw the table or not
5922 * @param {bool} [bAction=true] Perform pre-draw actions or not
5923 * @returns {int} 0 on success, 1 on error
5925 * @deprecated Since v1.10
5928 * $(document).ready(function() {
5929 * var oTable = $('#example').dataTable();
5930 * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
5931 * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
5934 this.fnUpdate = function( mData
, mRow
, iColumn
, bRedraw
, bAction
)
5936 var api
= this.api( true );
5938 if ( iColumn
=== undefined || iColumn
=== null ) {
5939 api
.row( mRow
).data( mData
);
5942 api
.cell( mRow
, iColumn
).data( mData
);
5945 if ( bAction
=== undefined || bAction
) {
5946 api
.columns
.adjust();
5949 if ( bRedraw
=== undefined || bRedraw
) {
5957 * Provide a common method for plug-ins to check the version of DataTables being used, in order
5958 * to ensure compatibility.
5959 * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
5960 * formats "X" and "X.Y" are also acceptable.
5961 * @returns {boolean} true if this version of DataTables is greater or equal to the required
5962 * version, or false if this version of DataTales is not suitable
5965 * @deprecated Since v1.10
5968 * $(document).ready(function() {
5969 * var oTable = $('#example').dataTable();
5970 * alert( oTable.fnVersionCheck( '1.9.0' ) );
5973 this.fnVersionCheck
= _ext
.fnVersionCheck
;
5977 var emptyInit
= options
=== undefined;
5978 var len
= this.length
;
5984 this.oApi
= this.internal = _ext
.internal;
5986 // Extend with old style plug-in API methods
5987 for ( var fn
in DataTable
.ext
.internal ) {
5989 this[fn
] = _fnExternApiFunc(fn
);
5993 this.each(function() {
5994 // For each initialisation we want to give it a clean initialisation
5995 // object that can be bashed around
5997 var oInit
= len
> 1 ? // optimisation for single table case
5998 _fnExtend( o
, options
, true ) :
6001 /*global oInit,_that,emptyInit*/
6002 var i
=0, iLen
, j
, jLen
, k
, kLen
;
6003 var sId
= this.getAttribute( 'id' );
6004 var bInitHandedOff
= false;
6005 var defaults
= DataTable
.defaults
;
6009 if ( this.nodeName
.toLowerCase() != 'table' )
6011 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName
+')', 2 );
6015 /* Backwards compatibility for the defaults */
6016 _fnCompatOpts( defaults
);
6017 _fnCompatCols( defaults
.column
);
6019 /* Convert the camel-case defaults to Hungarian */
6020 _fnCamelToHungarian( defaults
, defaults
, true );
6021 _fnCamelToHungarian( defaults
.column
, defaults
.column
, true );
6023 /* Setting up the initialisation object */
6024 _fnCamelToHungarian( defaults
, oInit
);
6026 /* Check to see if we are re-initialising a table */
6027 var allSettings
= DataTable
.settings
;
6028 for ( i
=0, iLen
=allSettings
.length
; i
<iLen
; i
++ )
6030 /* Base check on table node */
6031 if ( allSettings
[i
].nTable
== this )
6033 var bRetrieve
= oInit
.bRetrieve
!== undefined ? oInit
.bRetrieve
: defaults
.bRetrieve
;
6034 var bDestroy
= oInit
.bDestroy
!== undefined ? oInit
.bDestroy
: defaults
.bDestroy
;
6036 if ( emptyInit
|| bRetrieve
)
6038 return allSettings
[i
].oInstance
;
6040 else if ( bDestroy
)
6042 allSettings
[i
].oInstance
.fnDestroy();
6047 _fnLog( allSettings
[i
], 0, 'Cannot reinitialise DataTable', 3 );
6052 /* If the element we are initialising has the same ID as a table which was previously
6053 * initialised, but the table nodes don't match (from before) then we destroy the old
6054 * instance by simply deleting it. This is under the assumption that the table has been
6055 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6057 if ( allSettings
[i
].sTableId
== this.id
)
6059 allSettings
.splice( i
, 1 );
6064 /* Ensure the table has an ID - required for accessibility */
6065 if ( sId
=== null || sId
=== "" )
6067 sId
= "DataTables_Table_"+(DataTable
.ext
._unique
++);
6071 /* Create the settings object for this table and set some of the default parameters */
6072 var oSettings
= $.extend( true, {}, DataTable
.models
.oSettings
, {
6074 "oApi": _that
.internal,
6076 "sDestroyWidth": $(this)[0].style
.width
,
6080 allSettings
.push( oSettings
);
6082 // Need to add the instance after the instance after the settings object has been added
6083 // to the settings array, so we can self reference the table instance if more than one
6084 oSettings
.oInstance
= (_that
.length
===1) ? _that
: $(this).dataTable();
6086 // Backwards compatibility, before we apply all the defaults
6087 _fnCompatOpts( oInit
);
6089 if ( oInit
.oLanguage
)
6091 _fnLanguageCompat( oInit
.oLanguage
);
6094 // If the length menu is given, but the init display length is not, use the length menu
6095 if ( oInit
.aLengthMenu
&& ! oInit
.iDisplayLength
)
6097 oInit
.iDisplayLength
= $.isArray( oInit
.aLengthMenu
[0] ) ?
6098 oInit
.aLengthMenu
[0][0] : oInit
.aLengthMenu
[0];
6101 // Apply the defaults and init options to make a single init object will all
6102 // options defined from defaults and instance options.
6103 oInit
= _fnExtend( $.extend( true, {}, defaults
), oInit
);
6106 // Map the initialisation options onto the settings object
6107 _fnMap( oSettings
.oFeatures
, oInit
, [
6120 _fnMap( oSettings
, oInit
, [
6136 "fnStateLoadCallback",
6137 "fnStateSaveCallback",
6140 [ "iCookieDuration", "iStateDuration" ], // backwards compat
6141 [ "oSearch", "oPreviousSearch" ],
6142 [ "aoSearchCols", "aoPreSearchCols" ],
6143 [ "iDisplayLength", "_iDisplayLength" ],
6144 [ "bJQueryUI", "bJUI" ]
6146 _fnMap( oSettings
.oScroll
, oInit
, [
6147 [ "sScrollX", "sX" ],
6148 [ "sScrollXInner", "sXInner" ],
6149 [ "sScrollY", "sY" ],
6150 [ "bScrollCollapse", "bCollapse" ]
6152 _fnMap( oSettings
.oLanguage
, oInit
, "fnInfoCallback" );
6154 /* Callback functions which are array driven */
6155 _fnCallbackReg( oSettings
, 'aoDrawCallback', oInit
.fnDrawCallback
, 'user' );
6156 _fnCallbackReg( oSettings
, 'aoServerParams', oInit
.fnServerParams
, 'user' );
6157 _fnCallbackReg( oSettings
, 'aoStateSaveParams', oInit
.fnStateSaveParams
, 'user' );
6158 _fnCallbackReg( oSettings
, 'aoStateLoadParams', oInit
.fnStateLoadParams
, 'user' );
6159 _fnCallbackReg( oSettings
, 'aoStateLoaded', oInit
.fnStateLoaded
, 'user' );
6160 _fnCallbackReg( oSettings
, 'aoRowCallback', oInit
.fnRowCallback
, 'user' );
6161 _fnCallbackReg( oSettings
, 'aoRowCreatedCallback', oInit
.fnCreatedRow
, 'user' );
6162 _fnCallbackReg( oSettings
, 'aoHeaderCallback', oInit
.fnHeaderCallback
, 'user' );
6163 _fnCallbackReg( oSettings
, 'aoFooterCallback', oInit
.fnFooterCallback
, 'user' );
6164 _fnCallbackReg( oSettings
, 'aoInitComplete', oInit
.fnInitComplete
, 'user' );
6165 _fnCallbackReg( oSettings
, 'aoPreDrawCallback', oInit
.fnPreDrawCallback
, 'user' );
6167 var oClasses
= oSettings
.oClasses
;
6169 // @todo Remove in 1.11
6170 if ( oInit
.bJQueryUI
)
6172 /* Use the JUI classes object for display. You could clone the oStdClasses object if
6173 * you want to have multiple tables with multiple independent classes
6175 $.extend( oClasses
, DataTable
.ext
.oJUIClasses
, oInit
.oClasses
);
6177 if ( oInit
.sDom
=== defaults
.sDom
&& defaults
.sDom
=== "lfrtip" )
6179 /* Set the DOM to use a layout suitable for jQuery UI's theming */
6180 oSettings
.sDom
= '<"H"lfr>t<"F"ip>';
6183 if ( ! oSettings
.renderer
) {
6184 oSettings
.renderer
= 'jqueryui';
6186 else if ( $.isPlainObject( oSettings
.renderer
) && ! oSettings
.renderer
.header
) {
6187 oSettings
.renderer
.header
= 'jqueryui';
6192 $.extend( oClasses
, DataTable
.ext
.classes
, oInit
.oClasses
);
6194 $(this).addClass( oClasses
.sTable
);
6196 /* Calculate the scroll bar width and cache it for use later on */
6197 if ( oSettings
.oScroll
.sX
!== "" || oSettings
.oScroll
.sY
!== "" )
6199 oSettings
.oScroll
.iBarWidth
= _fnScrollBarWidth();
6201 if ( oSettings
.oScroll
.sX
=== true ) { // Easy initialisation of x-scrolling
6202 oSettings
.oScroll
.sX
= '100%';
6205 if ( oSettings
.iInitDisplayStart
=== undefined )
6207 /* Display start point, taking into account the save saving */
6208 oSettings
.iInitDisplayStart
= oInit
.iDisplayStart
;
6209 oSettings
._iDisplayStart
= oInit
.iDisplayStart
;
6212 if ( oInit
.iDeferLoading
!== null )
6214 oSettings
.bDeferLoading
= true;
6215 var tmp
= $.isArray( oInit
.iDeferLoading
);
6216 oSettings
._iRecordsDisplay
= tmp
? oInit
.iDeferLoading
[0] : oInit
.iDeferLoading
;
6217 oSettings
._iRecordsTotal
= tmp
? oInit
.iDeferLoading
[1] : oInit
.iDeferLoading
;
6220 /* Language definitions */
6221 if ( oInit
.oLanguage
.sUrl
!== "" )
6223 /* Get the language definitions from a file - because this Ajax call makes the language
6224 * get async to the remainder of this function we use bInitHandedOff to indicate that
6225 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6227 oSettings
.oLanguage
.sUrl
= oInit
.oLanguage
.sUrl
;
6228 $.getJSON( oSettings
.oLanguage
.sUrl
, null, function( json
) {
6229 _fnLanguageCompat( json
);
6230 _fnCamelToHungarian( defaults
.oLanguage
, json
);
6231 $.extend( true, oSettings
.oLanguage
, oInit
.oLanguage
, json
);
6232 _fnInitialise( oSettings
);
6234 bInitHandedOff
= true;
6238 $.extend( true, oSettings
.oLanguage
, oInit
.oLanguage
);
6245 if ( oInit
.asStripeClasses
=== null )
6247 oSettings
.asStripeClasses
=[
6248 oClasses
.sStripeOdd
,
6249 oClasses
.sStripeEven
6253 /* Remove row stripe classes if they are already on the table row */
6254 var stripeClasses
= oSettings
.asStripeClasses
;
6255 var rowOne
= $('tbody tr:eq(0)', this);
6256 if ( $.inArray( true, $.map( stripeClasses
, function(el
, i
) {
6257 return rowOne
.hasClass(el
);
6259 $('tbody tr', this).removeClass( stripeClasses
.join(' ') );
6260 oSettings
.asDestroyStripes
= stripeClasses
.slice();
6265 * See if we should load columns automatically or use defined ones
6269 var nThead
= this.getElementsByTagName('thead');
6270 if ( nThead
.length
!== 0 )
6272 _fnDetectHeader( oSettings
.aoHeader
, nThead
[0] );
6273 anThs
= _fnGetUniqueThs( oSettings
);
6276 /* If not given a column array, generate one with nulls */
6277 if ( oInit
.aoColumns
=== null )
6280 for ( i
=0, iLen
=anThs
.length
; i
<iLen
; i
++ )
6282 aoColumnsInit
.push( null );
6287 aoColumnsInit
= oInit
.aoColumns
;
6290 /* Add the columns */
6291 for ( i
=0, iLen
=aoColumnsInit
.length
; i
<iLen
; i
++ )
6293 _fnAddColumn( oSettings
, anThs
? anThs
[i
] : null );
6296 /* Apply the column definitions */
6297 _fnApplyColumnDefs( oSettings
, oInit
.aoColumnDefs
, aoColumnsInit
, function (iCol
, oDef
) {
6298 _fnColumnOptions( oSettings
, iCol
, oDef
);
6301 /* HTML5 attribute detection - build an mData object automatically if the
6302 * attributes are found
6304 if ( rowOne
.length
) {
6305 var a = function ( cell
, name
) {
6306 return cell
.getAttribute( 'data-'+name
) ? name
: null;
6309 $.each( _fnGetRowElements( oSettings
, rowOne
[0] ).cells
, function (i
, cell
) {
6310 var col
= oSettings
.aoColumns
[i
];
6312 if ( col
.mData
=== i
) {
6313 var sort
= a( cell
, 'sort' ) || a( cell
, 'order' );
6314 var filter
= a( cell
, 'filter' ) || a( cell
, 'search' );
6316 if ( sort
!== null || filter
!== null ) {
6319 sort
: sort
!== null ? i
+'.@data-'+sort
: undefined,
6320 type
: sort
!== null ? i
+'.@data-'+sort
: undefined,
6321 filter
: filter
!== null ? i
+'.@data-'+filter
: undefined
6324 _fnColumnOptions( oSettings
, i
);
6330 var features
= oSettings
.oFeatures
;
6332 /* Must be done after everything which can be overridden by the state saving! */
6333 if ( oInit
.bStateSave
)
6335 features
.bStateSave
= true;
6336 _fnLoadState( oSettings
, oInit
);
6337 _fnCallbackReg( oSettings
, 'aoDrawCallback', _fnSaveState
, 'state_save' );
6343 * @todo For modularisation (1.11) this needs to do into a sort start up handler
6346 // If aaSorting is not defined, then we use the first indicator in asSorting
6347 // in case that has been altered, so the default sort reflects that option
6348 if ( oInit
.aaSorting
=== undefined )
6350 var sorting
= oSettings
.aaSorting
;
6351 for ( i
=0, iLen
=sorting
.length
; i
<iLen
; i
++ )
6353 sorting
[i
][1] = oSettings
.aoColumns
[ i
].asSorting
[0];
6357 /* Do a first pass on the sorting classes (allows any size changes to be taken into
6358 * account, and also will apply sorting disabled classes if disabled
6360 _fnSortingClasses( oSettings
);
6362 if ( features
.bSort
)
6364 _fnCallbackReg( oSettings
, 'aoDrawCallback', function () {
6365 if ( oSettings
.bSorted
) {
6366 var aSort
= _fnSortFlatten( oSettings
);
6367 var sortedColumns
= {};
6369 $.each( aSort
, function (i
, val
) {
6370 sortedColumns
[ val
.src
] = val
.dir
;
6373 _fnCallbackFire( oSettings
, null, 'order', [oSettings
, aSort
, sortedColumns
] );
6374 _fnSortAria( oSettings
);
6379 _fnCallbackReg( oSettings
, 'aoDrawCallback', function () {
6380 if ( oSettings
.bSorted
|| _fnDataSource( oSettings
) === 'ssp' || features
.bDeferRender
) {
6381 _fnSortingClasses( oSettings
);
6388 * Cache the header, body and footer as required, creating them if needed
6391 /* Browser support detection */
6392 _fnBrowserDetect( oSettings
);
6394 // Work around for Webkit bug 83867 - store the caption-side before removing from doc
6395 var captions
= $(this).children('caption').each( function () {
6396 this._captionSide
= $(this).css('caption-side');
6399 var thead
= $(this).children('thead');
6400 if ( thead
.length
=== 0 )
6402 thead
= $('<thead/>').appendTo(this);
6404 oSettings
.nTHead
= thead
[0];
6406 var tbody
= $(this).children('tbody');
6407 if ( tbody
.length
=== 0 )
6409 tbody
= $('<tbody/>').appendTo(this);
6411 oSettings
.nTBody
= tbody
[0];
6413 var tfoot
= $(this).children('tfoot');
6414 if ( tfoot
.length
=== 0 && captions
.length
> 0 && (oSettings
.oScroll
.sX
!== "" || oSettings
.oScroll
.sY
!== "") )
6416 // If we are a scrolling table, and no footer has been given, then we need to create
6417 // a tfoot element for the caption element to be appended to
6418 tfoot
= $('<tfoot/>').appendTo(this);
6421 if ( tfoot
.length
=== 0 || tfoot
.children().length
=== 0 ) {
6422 $(this).addClass( oClasses
.sNoFooter
);
6424 else if ( tfoot
.length
> 0 ) {
6425 oSettings
.nTFoot
= tfoot
[0];
6426 _fnDetectHeader( oSettings
.aoFooter
, oSettings
.nTFoot
);
6429 /* Check if there is data passing into the constructor */
6432 for ( i
=0 ; i
<oInit
.aaData
.length
; i
++ )
6434 _fnAddData( oSettings
, oInit
.aaData
[ i
] );
6437 else if ( oSettings
.bDeferLoading
|| _fnDataSource( oSettings
) == 'dom' )
6439 /* Grab the data from the page - only do this when deferred loading or no Ajax
6440 * source since there is no point in reading the DOM data if we are then going
6441 * to replace it with Ajax data
6443 _fnAddTr( oSettings
, $(oSettings
.nTBody
).children('tr') );
6446 /* Copy the data index array */
6447 oSettings
.aiDisplay
= oSettings
.aiDisplayMaster
.slice();
6449 /* Initialisation complete - table can be drawn */
6450 oSettings
.bInitialised
= true;
6452 /* Check if we need to initialise the table (it might not have been handed off to the
6453 * language processor)
6455 if ( bInitHandedOff
=== false )
6457 _fnInitialise( oSettings
);
6467 * Computed structure of the DataTables API, defined by the options passed to
6468 * `DataTable.Api.register()` when building the API.
6470 * The structure is built in order to speed creation and extension of the Api
6471 * objects since the extensions are effectively pre-parsed.
6473 * The array is an array of objects with the following structure, where this
6474 * base array represents the Api prototype base:
6478 * name: 'data' -- string - Property name
6479 * val: function () {}, -- function - Api method (or undefined if just an object
6480 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
6481 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
6486 * methodExt: [ ... ],
6490 * val: function () {},
6491 * methodExt: [ ... ],
6502 var __apiStruct
= [];
6506 * `Array.prototype` reference.
6511 var __arrayProto
= Array
.prototype;
6515 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6516 * take several different forms for ease of use.
6518 * Each of the input parameter types will be converted to a DataTables settings
6519 * object where possible.
6521 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
6524 * * `string` - jQuery selector. Any DataTables' matching the given selector
6525 * with be found and used.
6526 * * `node` - `TABLE` node which has already been formed into a DataTable.
6527 * * `jQuery` - A jQuery object of `TABLE` nodes.
6528 * * `object` - DataTables settings object
6529 * * `DataTables.Api` - API instance
6530 * @return {array|null} Matching DataTables settings objects. `null` or
6531 * `undefined` is returned if no matching DataTable is found.
6534 var _toSettings = function ( mixed
)
6537 var settings
= DataTable
.settings
;
6538 var tables
= $.map( settings
, function (el
, i
) {
6545 else if ( mixed
.nTable
&& mixed
.oApi
) {
6546 // DataTables settings object
6549 else if ( mixed
.nodeName
&& mixed
.nodeName
.toLowerCase() === 'table' ) {
6551 idx
= $.inArray( mixed
, tables
);
6552 return idx
!== -1 ? [ settings
[idx
] ] : null;
6554 else if ( mixed
&& typeof mixed
.settings
=== 'function' ) {
6555 return mixed
.settings().toArray();
6557 else if ( typeof mixed
=== 'string' ) {
6561 else if ( mixed
instanceof $ ) {
6562 // jQuery object (also DataTables instance)
6567 return jq
.map( function(i
) {
6568 idx
= $.inArray( this, tables
);
6569 return idx
!== -1 ? settings
[idx
] : null;
6576 * DataTables API class - used to control and interface with one or more
6577 * DataTables enhanced tables.
6579 * The API class is heavily based on jQuery, presenting a chainable interface
6580 * that you can use to interact with tables. Each instance of the API class has
6581 * a "context" - i.e. the tables that it will operate on. This could be a single
6582 * table, all tables on a page or a sub-set thereof.
6584 * Additionally the API is designed to allow you to easily work with the data in
6585 * the tables, retrieving and manipulating it as required. This is done by
6586 * presenting the API class as an array like interface. The contents of the
6587 * array depend upon the actions requested by each method (for example
6588 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6589 * return an array of objects or arrays depending upon your table's
6590 * configuration). The API object has a number of array like methods (`push`,
6591 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6592 * `unique` etc) to assist your working with the data held in a table.
6594 * Most methods (those which return an Api instance) are chainable, which means
6595 * the return from a method call also has all of the methods available that the
6596 * top level object had. For example, these two calls are equivalent:
6599 * api.row.add( {...} );
6603 * api.row.add( {...} ).draw();
6605 * @class DataTable.Api
6606 * @param {array|object|string|jQuery} context DataTable identifier. This is
6607 * used to define which DataTables enhanced tables this API will operate on.
6610 * * `string` - jQuery selector. Any DataTables' matching the given selector
6611 * with be found and used.
6612 * * `node` - `TABLE` node which has already been formed into a DataTable.
6613 * * `jQuery` - A jQuery object of `TABLE` nodes.
6614 * * `object` - DataTables settings object
6615 * @param {array} [data] Data to initialise the Api instance with.
6618 * // Direct initialisation during DataTables construction
6619 * var api = $('#example').DataTable();
6622 * // Initialisation using a DataTables jQuery object
6623 * var api = $('#example').dataTable().api();
6626 * // Initialisation as a constructor
6627 * var api = new $.fn.DataTable.Api( 'table.dataTable' );
6629 _Api = function ( context
, data
)
6631 if ( ! this instanceof _Api
) {
6632 throw 'DT API must be constructed as a new object';
6633 // or should it do the 'new' for the caller?
6634 // return new _Api.apply( this, arguments );
6638 var ctxSettings = function ( o
) {
6639 var a
= _toSettings( o
);
6641 settings
.push
.apply( settings
, a
);
6645 if ( $.isArray( context
) ) {
6646 for ( var i
=0, ien
=context
.length
; i
<ien
; i
++ ) {
6647 ctxSettings( context
[i
] );
6651 ctxSettings( context
);
6654 // Remove duplicates
6655 this.context
= _unique( settings
);
6659 this.push
.apply( this, data
.toArray
? data
.toArray() : data
);
6669 _Api
.extend( this, this, __apiStruct
);
6672 DataTable
.Api
= _Api
;
6674 _Api
.prototype = /** @lends DataTables.Api */{
6676 * Return a new Api instance, comprised of the data held in the current
6677 * instance, join with the other array(s) and/or value(s).
6679 * An alias for `Array.prototype.concat`.
6682 * @param {*} value1 Arrays and/or values to concatenate.
6683 * @param {*} [...] Additional arrays and/or values to concatenate.
6684 * @returns {DataTables.Api} New API instance, comprising of the combined
6687 concat
: __arrayProto
.concat
,
6690 context
: [], // array of table settings objects
6693 each: function ( fn
)
6695 for ( var i
=0, ien
=this.length
; i
<ien
; i
++ ) {
6696 fn
.call( this, this[i
], i
, this );
6703 eq: function ( idx
)
6705 var ctx
= this.context
;
6707 return ctx
.length
> idx
?
6708 new _Api( ctx
[idx
], this[idx
] ) :
6713 filter: function ( fn
)
6717 if ( __arrayProto
.filter
) {
6718 a
= __arrayProto
.filter
.call( this, fn
, this );
6721 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6722 for ( var i
=0, ien
=this.length
; i
<ien
; i
++ ) {
6723 if ( fn
.call( this, this[i
], i
, this ) ) {
6729 return new _Api( this.context
, a
);
6733 flatten: function ()
6736 return new _Api( this.context
, a
.concat
.apply( a
, this.toArray() ) );
6740 join
: __arrayProto
.join
,
6743 indexOf
: __arrayProto
.indexOf
|| function (obj
, start
)
6745 for ( var i
=(start
|| 0), ien
=this.length
; i
<ien
; i
++ ) {
6746 if ( this[i
] === obj
) {
6753 // Internal only at the moment - relax?
6754 iterator: function ( flatten
, type
, fn
) {
6758 context
= this.context
,
6760 selector
= this.selector
;
6762 // Argument shifting
6763 if ( typeof flatten
=== 'string' ) {
6769 for ( i
=0, ien
=context
.length
; i
<ien
; i
++ ) {
6770 var apiInst
= new _Api( context
[i
] );
6772 if ( type
=== 'table' ) {
6773 ret
= fn
.call( apiInst
, context
[i
], i
);
6775 if ( ret
!== undefined ) {
6779 else if ( type
=== 'columns' || type
=== 'rows' ) {
6780 // this has same length as context - one entry for each table
6781 ret
= fn
.call( apiInst
, context
[i
], this[i
], i
);
6783 if ( ret
!== undefined ) {
6787 else if ( type
=== 'column' || type
=== 'column-rows' || type
=== 'row' || type
=== 'cell' ) {
6788 // columns and rows share the same structure.
6789 // 'this' is an array of column indexes for each context
6792 if ( type
=== 'column-rows' ) {
6793 rows
= _selector_row_indexes( context
[i
], selector
.opts
);
6796 for ( j
=0, jen
=items
.length
; j
<jen
; j
++ ) {
6799 if ( type
=== 'cell' ) {
6800 ret
= fn
.call( apiInst
, context
[i
], item
.row
, item
.column
, i
, j
);
6803 ret
= fn
.call( apiInst
, context
[i
], item
, i
, j
, rows
);
6806 if ( ret
!== undefined ) {
6814 var api
= new _Api( context
, flatten
? a
.concat
.apply( [], a
) : a
);
6815 var apiSelector
= api
.selector
;
6816 apiSelector
.rows
= selector
.rows
;
6817 apiSelector
.cols
= selector
.cols
;
6818 apiSelector
.opts
= selector
.opts
;
6825 lastIndexOf
: __arrayProto
.lastIndexOf
|| function (obj
, start
)
6828 return this.indexOf
.apply( this.toArray
.reverse(), arguments
);
6835 map: function ( fn
)
6839 if ( __arrayProto
.map
) {
6840 a
= __arrayProto
.map
.call( this, fn
, this );
6843 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6844 for ( var i
=0, ien
=this.length
; i
<ien
; i
++ ) {
6845 a
.push( fn
.call( this, this[i
], i
) );
6849 return new _Api( this.context
, a
);
6853 pluck: function ( prop
)
6855 return this.map( function ( el
) {
6860 pop
: __arrayProto
.pop
,
6863 push
: __arrayProto
.push
,
6866 // Does not return an API instance
6867 reduce
: __arrayProto
.reduce
|| function ( fn
, init
)
6869 return _fnReduce( this, fn
, init
, 0, this.length
, 1 );
6873 reduceRight
: __arrayProto
.reduceRight
|| function ( fn
, init
)
6875 return _fnReduce( this, fn
, init
, this.length
-1, -1, -1 );
6879 reverse
: __arrayProto
.reverse
,
6882 // Object with rows, columns and opts
6886 shift
: __arrayProto
.shift
,
6889 sort
: __arrayProto
.sort
, // ? name - order?
6892 splice
: __arrayProto
.splice
,
6895 toArray: function ()
6897 return __arrayProto
.slice
.call( this );
6907 toJQuery: function ()
6915 return new _Api( this.context
, _unique(this) );
6919 unshift
: __arrayProto
.unshift
6923 _Api
.extend = function ( scope
, obj
, ext
)
6925 // Only extend API instances and static properties of the API
6926 if ( ! obj
|| ( ! (obj
instanceof _Api
) && ! obj
.__dt_wrapper
) ) {
6934 methodScoping = function ( scope
, fn
, struc
) {
6935 return function () {
6936 var ret
= fn
.apply( scope
, arguments
);
6939 _Api
.extend( ret
, ret
, struc
.methodExt
);
6944 for ( i
=0, ien
=ext
.length
; i
<ien
; i
++ ) {
6948 obj
[ struct
.name
] = typeof struct
.val
=== 'function' ?
6949 methodScoping( scope
, struct
.val
, struct
) :
6950 $.isPlainObject( struct
.val
) ?
6954 obj
[ struct
.name
].__dt_wrapper
= true;
6956 // Property extension
6957 _Api
.extend( scope
, obj
[ struct
.name
], struct
.propExt
);
6962 // @todo - Is there need for an augment function?
6963 // _Api.augment = function ( inst, name )
6965 // // Find src object in the structure from the name
6966 // var parts = name.split('.');
6968 // _Api.extend( inst, obj );
6974 // name: 'data' -- string - Property name
6975 // val: function () {}, -- function - Api method (or undefined if just an object
6976 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
6977 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
6982 // methodExt: [ ... ],
6986 // val: function () {},
6987 // methodExt: [ ... ],
6995 _Api
.register
= _api_register = function ( name
, val
)
6997 if ( $.isArray( name
) ) {
6998 for ( var j
=0, jen
=name
.length
; j
<jen
; j
++ ) {
6999 _Api
.register( name
[j
], val
);
7006 heir
= name
.split('.'),
7007 struct
= __apiStruct
,
7010 var find = function ( src
, name
) {
7011 for ( var i
=0, ien
=src
.length
; i
<ien
; i
++ ) {
7012 if ( src
[i
].name
=== name
) {
7019 for ( i
=0, ien
=heir
.length
; i
<ien
; i
++ ) {
7020 method
= heir
[i
].indexOf('()') !== -1;
7022 heir
[i
].replace('()', '') :
7025 var src
= find( struct
, key
);
7036 if ( i
=== ien
-1 ) {
7048 _Api
.registerPlural
= _api_registerPlural = function ( pluralName
, singularName
, val
) {
7049 _Api
.register( pluralName
, val
);
7051 _Api
.register( singularName
, function () {
7052 var ret
= val
.apply( this, arguments
);
7054 if ( ret
=== this ) {
7055 // Returned item is the API instance that was passed in, return it
7058 else if ( ret
instanceof _Api
) {
7059 // New API instance returned, want the value from the first item
7060 // in the returned array for the singular result.
7062 $.isArray( ret
[0] ) ?
7063 new _Api( ret
.context
, ret
[0] ) : // Array results are 'enhanced'
7068 // Non-API return - just fire it back
7075 * Selector for HTML tables. Apply the given selector to the give array of
7076 * DataTables settings objects.
7078 * @param {string|integer} [selector] jQuery selector string or integer
7079 * @param {array} Array of DataTables settings objects to be filtered
7083 var __table_selector = function ( selector
, a
)
7085 // Integer is used to pick out a table by index
7086 if ( typeof selector
=== 'number' ) {
7087 return [ a
[ selector
] ];
7090 // Perform a jQuery selector on the table nodes
7091 var nodes
= $.map( a
, function (el
, i
) {
7097 .map( function (i
) {
7098 // Need to translate back from the table node to the settings
7099 var idx
= $.inArray( this, nodes
);
7108 * Context selector for the API's context (i.e. the tables the API instance
7111 * @name DataTable.Api#tables
7112 * @param {string|integer} [selector] Selector to pick which tables the iterator
7113 * should operate on. If not given, all tables in the current context are
7114 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7115 * select multiple tables or as an integer to select a single table.
7116 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7118 _api_register( 'tables()', function ( selector
) {
7119 // A new instance is created if there was a selector specified
7121 new _Api( __table_selector( selector
, this.context
) ) :
7126 _api_register( 'table()', function ( selector
) {
7127 var tables
= this.tables( selector
);
7128 var ctx
= tables
.context
;
7130 // Truncate to the first matched table
7132 new _Api( ctx
[0] ) :
7137 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7138 return this.iterator( 'table', function ( ctx
) {
7144 _api_registerPlural( 'tables().body()', 'table().body()' , function () {
7145 return this.iterator( 'table', function ( ctx
) {
7151 _api_registerPlural( 'tables().header()', 'table().header()' , function () {
7152 return this.iterator( 'table', function ( ctx
) {
7158 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7159 return this.iterator( 'table', function ( ctx
) {
7165 _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7166 return this.iterator( 'table', function ( ctx
) {
7167 return ctx
.nTableWrapper
;
7174 * Redraw the tables in the current context.
7176 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7177 * position. A full re-sort and re-filter is performed when this method is
7178 * called, which is why the pagination reset is the default action.
7179 * @returns {DataTables.Api} this
7181 _api_register( 'draw()', function ( resetPaging
) {
7182 return this.iterator( 'table', function ( settings
) {
7183 _fnReDraw( settings
, resetPaging
===false );
7190 * Get the current page index.
7192 * @return {integer} Current page index (zero based)
7194 * Set the current page.
7196 * Note that if you attempt to show a page which does not exist, DataTables will
7197 * not throw an error, but rather reset the paging.
7199 * @param {integer|string} action The paging action to take. This can be one of:
7200 * * `integer` - The page index to jump to
7201 * * `string` - An action to take:
7202 * * `first` - Jump to first page.
7203 * * `next` - Jump to the next page
7204 * * `previous` - Jump to previous page
7205 * * `last` - Jump to the last page.
7206 * @returns {DataTables.Api} this
7208 _api_register( 'page()', function ( action
) {
7209 if ( action
=== undefined ) {
7210 return this.page
.info().page
; // not an expensive call
7213 // else, have an action to take on all tables
7214 return this.iterator( 'table', function ( settings
) {
7215 _fnPageChange( settings
, action
);
7221 * Paging information for the first table in the current context.
7223 * If you require paging information for another table, use the `table()` method
7224 * with a suitable selector.
7226 * @return {object} Object with the following properties set:
7227 * * `page` - Current page index (zero based - i.e. the first page is `0`)
7228 * * `pages` - Total number of pages
7229 * * `start` - Display index for the first record shown on the current page
7230 * * `end` - Display index for the last record shown on the current page
7231 * * `length` - Display length (number of records). Note that generally `start
7232 * + length = end`, but this is not always true, for example if there are
7233 * only 2 records to show on the final page, with a length of 10.
7234 * * `recordsTotal` - Full data set length
7235 * * `recordsDisplay` - Data set length once the current filtering criterion
7238 _api_register( 'page.info()', function ( action
) {
7239 if ( this.context
.length
=== 0 ) {
7244 settings
= this.context
[0],
7245 start
= settings
._iDisplayStart
,
7246 len
= settings
._iDisplayLength
,
7247 visRecords
= settings
.fnRecordsDisplay(),
7251 "page": all
? 0 : Math
.floor( start
/ len
),
7252 "pages": all
? 1 : Math
.ceil( visRecords
/ len
),
7254 "end": settings
.fnDisplayEnd(),
7256 "recordsTotal": settings
.fnRecordsTotal(),
7257 "recordsDisplay": visRecords
7263 * Get the current page length.
7265 * @return {integer} Current page length. Note `-1` indicates that all records
7268 * Set the current page length.
7270 * @param {integer} Page length to set. Use `-1` to show all records.
7271 * @returns {DataTables.Api} this
7273 _api_register( 'page.len()', function ( len
) {
7274 // Note that we can't call this function 'length()' because `length`
7275 // is a Javascript property of functions which defines how many arguments
7276 // the function expects.
7277 if ( len
=== undefined ) {
7278 return this.context
.length
!== 0 ?
7279 this.context
[0]._iDisplayLength
:
7283 // else, set the page length
7284 return this.iterator( 'table', function ( settings
) {
7285 _fnLengthChange( settings
, len
);
7291 var __reload = function ( settings
, holdPosition
, callback
) {
7292 if ( _fnDataSource( settings
) == 'ssp' ) {
7293 _fnReDraw( settings
, holdPosition
);
7297 _fnProcessingDisplay( settings
, true );
7299 _fnBuildAjax( settings
, [], function( json
) {
7300 _fnClearTable( settings
);
7302 var data
= _fnAjaxDataSrc( settings
, json
);
7303 for ( var i
=0, ien
=data
.length
; i
<ien
; i
++ ) {
7304 _fnAddData( settings
, data
[i
] );
7307 _fnReDraw( settings
, holdPosition
);
7308 _fnProcessingDisplay( settings
, false );
7312 // Use the draw event to trigger a callback, regardless of if it is an async
7315 var api
= new _Api( settings
);
7317 api
.one( 'draw', function () {
7318 callback( api
.ajax
.json() );
7325 * Get the JSON response from the last Ajax request that DataTables made to the
7326 * server. Note that this returns the JSON from the first table in the current
7329 * @return {object} JSON received from the server.
7331 _api_register( 'ajax.json()', function () {
7332 var ctx
= this.context
;
7334 if ( ctx
.length
> 0 ) {
7338 // else return undefined;
7343 * Get the data submitted in the last Ajax request
7345 _api_register( 'ajax.params()', function () {
7346 var ctx
= this.context
;
7348 if ( ctx
.length
> 0 ) {
7349 return ctx
[0].oAjaxData
;
7352 // else return undefined;
7357 * Reload tables from the Ajax data source. Note that this function will
7358 * automatically re-draw the table when the remote data has been loaded.
7360 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7361 * position. A full re-sort and re-filter is performed when this method is
7362 * called, which is why the pagination reset is the default action.
7363 * @returns {DataTables.Api} this
7365 _api_register( 'ajax.reload()', function ( callback
, resetPaging
) {
7366 return this.iterator( 'table', function (settings
) {
7367 __reload( settings
, resetPaging
===false, callback
);
7373 * Get the current Ajax URL. Note that this returns the URL from the first
7374 * table in the current context.
7376 * @return {string} Current Ajax source URL
7378 * Set the Ajax URL. Note that this will set the URL for all tables in the
7381 * @param {string} url URL to set.
7382 * @returns {DataTables.Api} this
7384 _api_register( 'ajax.url()', function ( url
) {
7385 var ctx
= this.context
;
7387 if ( url
=== undefined ) {
7389 if ( ctx
.length
=== 0 ) {
7395 $.isPlainObject( ctx
.ajax
) ?
7402 return this.iterator( 'table', function ( settings
) {
7403 if ( $.isPlainObject( settings
.ajax
) ) {
7404 settings
.ajax
.url
= url
;
7407 settings
.ajax
= url
;
7409 // No need to consider sAjaxSource here since DataTables gives priority
7410 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7411 // value of `sAjaxSource` redundant.
7417 * Load data from the newly set Ajax URL. Note that this method is only
7418 * available when `ajax.url()` is used to set a URL. Additionally, this method
7419 * has the same effect as calling `ajax.reload()` but is provided for
7420 * convenience when setting a new URL. Like `ajax.reload()` it will
7421 * automatically redraw the table once the remote data has been loaded.
7423 * @returns {DataTables.Api} this
7425 _api_register( 'ajax.url().load()', function ( callback
, resetPaging
) {
7426 // Same as a reload, but makes sense to present it for easy access after a
7428 return this.iterator( 'table', function ( ctx
) {
7429 __reload( ctx
, resetPaging
===false, callback
);
7436 var _selector_run = function ( selector
, select
)
7441 selectorType
= typeof selector
;
7443 // Can't just check for isArray here, as an API or jQuery instance might be
7444 // given with their array like look
7445 if ( ! selector
|| selectorType
=== 'string' || selectorType
=== 'function' || selector
.length
=== undefined ) {
7446 selector
= [ selector
];
7449 for ( i
=0, ien
=selector
.length
; i
<ien
; i
++ ) {
7450 a
= selector
[i
] && selector
[i
].split
?
7451 selector
[i
].split(',') :
7454 for ( j
=0, jen
=a
.length
; j
<jen
; j
++ ) {
7455 res
= select( typeof a
[j
] === 'string' ? $.trim(a
[j
]) : a
[j
] );
7457 if ( res
&& res
.length
) {
7458 out
.push
.apply( out
, res
);
7467 var _selector_opts = function ( opts
)
7473 // Backwards compatibility for 1.9- which used the terminology filter rather
7475 if ( opts
.filter
&& ! opts
.search
) {
7476 opts
.search
= opts
.filter
;
7480 search
: opts
.search
|| 'none',
7481 order
: opts
.order
|| 'current',
7482 page
: opts
.page
|| 'all'
7487 var _selector_first = function ( inst
)
7489 // Reduce the API instance to the first item found
7490 for ( var i
=0, ien
=inst
.length
; i
<ien
; i
++ ) {
7491 if ( inst
[i
].length
> 0 ) {
7492 // Assign the first element to the first item in the instance
7493 // and truncate the instance and context
7496 inst
.context
= [ inst
.context
[i
] ];
7502 // Not found - return an empty instance
7508 var _selector_row_indexes = function ( settings
, opts
)
7512 displayFiltered
= settings
.aiDisplay
,
7513 displayMaster
= settings
.aiDisplayMaster
;
7516 search
= opts
.search
, // none, applied, removed
7517 order
= opts
.order
, // applied, current, index (original - compatibility with 1.9)
7518 page
= opts
.page
; // all, current
7520 if ( _fnDataSource( settings
) == 'ssp' ) {
7521 // In server-side processing mode, most options are irrelevant since
7522 // rows not shown don't exist and the index order is the applied order
7523 // Removed is a special case - for consistency just return an empty
7525 return search
=== 'removed' ?
7527 _range( 0, displayMaster
.length
);
7529 else if ( page
== 'current' ) {
7530 // Current page implies that order=current and fitler=applied, since it is
7531 // fairly senseless otherwise, regardless of what order and search actually
7533 for ( i
=settings
._iDisplayStart
, ien
=settings
.fnDisplayEnd() ; i
<ien
; i
++ ) {
7534 a
.push( displayFiltered
[i
] );
7537 else if ( order
== 'current' || order
== 'applied' ) {
7538 a
= search
== 'none' ?
7539 displayMaster
.slice() : // no search
7540 search
== 'applied' ?
7541 displayFiltered
.slice() : // applied search
7542 $.map( displayMaster
, function (el
, i
) { // removed search
7543 return $.inArray( el
, displayFiltered
) === -1 ? el
: null;
7546 else if ( order
== 'index' || order
== 'original' ) {
7547 for ( i
=0, ien
=settings
.aoData
.length
; i
<ien
; i
++ ) {
7548 if ( search
== 'none' ) {
7551 else { // applied | removed
7552 tmp
= $.inArray( i
, displayFiltered
);
7554 if ((tmp
=== -1 && search
== 'removed') ||
7555 (tmp
>= 0 && search
== 'applied') )
7567 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7570 * {} - no selector - use all available rows
7571 * {integer} - row aoData index
7573 * {string} - jQuery selector to apply to the TR elements
7574 * {array} - jQuery array of nodes, or simply an array of TR nodes
7579 var __row_selector = function ( settings
, selector
, opts
)
7581 return _selector_run( selector
, function ( sel
) {
7582 var selInt
= _intVal( sel
);
7585 // Short cut - selector is a number and no options provided (default is
7586 // all records, so no need to check if the index is in there, since it
7587 // must be - dev error if the index doesn't exist).
7588 if ( selInt
!== null && ! opts
) {
7592 var rows
= _selector_row_indexes( settings
, opts
);
7594 if ( selInt
!== null && $.inArray( selInt
, rows
) !== -1 ) {
7595 // Selector - integer
7603 // Get nodes in the order from the `rows` array
7604 var nodes
= _pluck_order( settings
.aoData
, rows
, 'nTr' );
7606 // Selector - function
7607 if ( typeof sel
=== 'function' ) {
7608 return $.map( rows
, function (idx
) {
7609 var row
= settings
.aoData
[ idx
];
7610 return sel( idx
, row
._aData
, row
.nTr
) ? idx
: null;
7615 if ( sel
.nodeName
) {
7616 if ( $.inArray( sel
, nodes
) !== -1 ) {
7617 return [ sel
._DT_RowIndex
];// sel is a TR node that is in the table
7618 // and DataTables adds a prop for fast lookup
7622 // Selector - jQuery selector string, array of nodes or jQuery object/
7623 // As jQuery's .filter() allows jQuery objects to be passed in filter,
7624 // it also allows arrays, so this will cope with all three options
7628 return this._DT_RowIndex
;
7638 _api_register( 'rows()', function ( selector
, opts
) {
7639 // argument shifting
7640 if ( selector
=== undefined ) {
7643 else if ( $.isPlainObject( selector
) ) {
7648 opts
= _selector_opts( opts
);
7650 var inst
= this.iterator( 'table', function ( settings
) {
7651 return __row_selector( settings
, selector
, opts
);
7654 // Want argument shifting here and in __row_selector?
7655 inst
.selector
.rows
= selector
;
7656 inst
.selector
.opts
= opts
;
7662 _api_register( 'rows().nodes()', function () {
7663 return this.iterator( 'row', function ( settings
, row
) {
7664 return settings
.aoData
[ row
].nTr
|| undefined;
7668 _api_register( 'rows().data()', function () {
7669 return this.iterator( true, 'rows', function ( settings
, rows
) {
7670 return _pluck_order( settings
.aoData
, rows
, '_aData' );
7674 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type
) {
7675 return this.iterator( 'row', function ( settings
, row
) {
7676 var r
= settings
.aoData
[ row
];
7677 return type
=== 'search' ? r
._aFilterData
: r
._aSortData
;
7681 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src
) {
7682 return this.iterator( 'row', function ( settings
, row
) {
7683 _fnInvalidateRow( settings
, row
, src
);
7687 _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7688 return this.iterator( 'row', function ( settings
, row
) {
7693 _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7696 return this.iterator( 'row', function ( settings
, row
, thatIdx
) {
7697 var data
= settings
.aoData
;
7699 data
.splice( row
, 1 );
7701 // Update the _DT_RowIndex parameter on all rows in the table
7702 for ( var i
=0, ien
=data
.length
; i
<ien
; i
++ ) {
7703 if ( data
[i
].nTr
!== null ) {
7704 data
[i
].nTr
._DT_RowIndex
= i
;
7708 // Remove the target row from the search array
7709 var displayIndex
= $.inArray( row
, settings
.aiDisplay
);
7711 // Delete from the display arrays
7712 _fnDeleteIndex( settings
.aiDisplayMaster
, row
);
7713 _fnDeleteIndex( settings
.aiDisplay
, row
);
7714 _fnDeleteIndex( that
[ thatIdx
], row
, false ); // maintain local indexes
7716 // Check for an 'overflow' they case for displaying the table
7717 _fnLengthOverflow( settings
);
7722 _api_register( 'rows.add()', function ( rows
) {
7723 var newRows
= this.iterator( 'table', function ( settings
) {
7727 for ( i
=0, ien
=rows
.length
; i
<ien
; i
++ ) {
7730 if ( row
.nodeName
&& row
.nodeName
.toUpperCase() === 'TR' ) {
7731 out
.push( _fnAddTr( settings
, row
)[0] );
7734 out
.push( _fnAddData( settings
, row
) );
7741 // Return an Api.rows() extended instance, so rows().nodes() etc can be used
7742 var modRows
= this.rows( -1 );
7744 modRows
.push
.apply( modRows
, newRows
.toArray() );
7756 _api_register( 'row()', function ( selector
, opts
) {
7757 return _selector_first( this.rows( selector
, opts
) );
7761 _api_register( 'row().data()', function ( data
) {
7762 var ctx
= this.context
;
7764 if ( data
=== undefined ) {
7766 return ctx
.length
&& this.length
?
7767 ctx
[0].aoData
[ this[0] ]._aData
:
7772 ctx
[0].aoData
[ this[0] ]._aData
= data
;
7774 // Automatically invalidate
7775 _fnInvalidateRow( ctx
[0], this[0], 'data' );
7781 _api_register( 'row().node()', function () {
7782 var ctx
= this.context
;
7784 return ctx
.length
&& this.length
?
7785 ctx
[0].aoData
[ this[0] ].nTr
|| null :
7790 _api_register( 'row.add()', function ( row
) {
7791 // Allow a jQuery object to be passed in - only a single row is added from
7792 // it though - the first element in the set
7793 if ( row
instanceof $ && row
.length
) {
7797 var rows
= this.iterator( 'table', function ( settings
) {
7798 if ( row
.nodeName
&& row
.nodeName
.toUpperCase() === 'TR' ) {
7799 return _fnAddTr( settings
, row
)[0];
7801 return _fnAddData( settings
, row
);
7804 // Return an Api.rows() extended instance, with the newly added row selected
7805 return this.row( rows
[0] );
7810 var __details_add = function ( ctx
, row
, data
, klass
)
7812 // Convert to array of TR elements
7814 var addRow = function ( r
, k
) {
7815 // If we get a TR element, then just add it directly - up to the dev
7816 // to add the correct number of columns etc
7817 if ( r
.nodeName
&& r
.nodeName
.toLowerCase() === 'tr' ) {
7821 // Otherwise create a row with a wrapper
7822 var created
= $('<tr><td/></tr>').addClass( k
);
7826 [0].colSpan
= _fnVisbleColumns( ctx
);
7828 rows
.push( created
[0] );
7832 if ( $.isArray( data
) || data
instanceof $ ) {
7833 for ( var i
=0, ien
=data
.length
; i
<ien
; i
++ ) {
7834 addRow( data
[i
], klass
);
7838 addRow( data
, klass
);
7841 if ( row
._details
) {
7842 row
._details
.remove();
7845 row
._details
= $(rows
);
7847 // If the children were already shown, that state should be retained
7848 if ( row
._detailsShow
) {
7849 row
._details
.insertAfter( row
.nTr
);
7854 var __details_remove = function ( api
, idx
)
7856 var ctx
= api
.context
;
7859 var row
= ctx
[0].aoData
[ idx
!== undefined ? idx
: api
[0] ];
7861 if ( row
._details
) {
7862 row
._details
.remove();
7864 row
._detailsShow
= undefined;
7865 row
._details
= undefined;
7871 var __details_display = function ( api
, show
) {
7872 var ctx
= api
.context
;
7874 if ( ctx
.length
&& api
.length
) {
7875 var row
= ctx
[0].aoData
[ api
[0] ];
7877 if ( row
._details
) {
7878 row
._detailsShow
= show
;
7881 row
._details
.insertAfter( row
.nTr
);
7884 row
._details
.detach();
7887 __details_events( ctx
[0] );
7893 var __details_events = function ( settings
)
7895 var api
= new _Api( settings
);
7896 var namespace = '.dt.DT_details';
7897 var drawEvent
= 'draw'+namespace;
7898 var colvisEvent
= 'column-visibility'+namespace;
7899 var destroyEvent
= 'destroy'+namespace;
7900 var data
= settings
.aoData
;
7902 api
.off( drawEvent
+' '+ colvisEvent
+' '+ destroyEvent
);
7904 if ( _pluck( data
, '_details' ).length
> 0 ) {
7905 // On each draw, insert the required elements into the document
7906 api
.on( drawEvent
, function ( e
, ctx
) {
7907 if ( settings
!== ctx
) {
7911 api
.rows( {page
:'current'} ).eq(0).each( function (idx
) {
7912 // Internal data grab
7913 var row
= data
[ idx
];
7915 if ( row
._detailsShow
) {
7916 row
._details
.insertAfter( row
.nTr
);
7921 // Column visibility change - update the colspan
7922 api
.on( colvisEvent
, function ( e
, ctx
, idx
, vis
) {
7923 if ( settings
!== ctx
) {
7927 // Update the colspan for the details rows (note, only if it already has
7929 var row
, visible
= _fnVisbleColumns( ctx
);
7931 for ( var i
=0, ien
=data
.length
; i
<ien
; i
++ ) {
7934 if ( row
._details
) {
7935 row
._details
.children('td[colspan]').attr('colspan', visible
);
7940 // Table destroyed - nuke any child rows
7941 api
.on( destroyEvent
, function ( e
, ctx
) {
7942 if ( settings
!== ctx
) {
7946 for ( var i
=0, ien
=data
.length
; i
<ien
; i
++ ) {
7947 if ( data
[i
]._details
) {
7948 __details_remove( api
, i
);
7955 // Strings for the method names to help minification
7957 var _child_obj
= _emp
+'row().child';
7958 var _child_mth
= _child_obj
+'()';
7963 // jQuery or array of any of the above
7964 _api_register( _child_mth
, function ( data
, klass
) {
7965 var ctx
= this.context
;
7967 if ( data
=== undefined ) {
7969 return ctx
.length
&& this.length
?
7970 ctx
[0].aoData
[ this[0] ]._details
:
7973 else if ( data
=== true ) {
7977 else if ( data
=== false ) {
7979 __details_remove( this );
7981 else if ( ctx
.length
&& this.length
) {
7983 __details_add( ctx
[0], ctx
[0].aoData
[ this[0] ], data
, klass
);
7991 _child_obj
+'.show()',
7992 _child_mth
+'.show()' // only when `child()` was called with parameters (without
7993 ], function ( show
) { // it returns an object and this method is not executed)
7994 __details_display( this, true );
8000 _child_obj
+'.hide()',
8001 _child_mth
+'.hide()' // only when `child()` was called with parameters (without
8002 ], function () { // it returns an object and this method is not executed)
8003 __details_display( this, false );
8009 _child_obj
+'.remove()',
8010 _child_mth
+'.remove()' // only when `child()` was called with parameters (without
8011 ], function () { // it returns an object and this method is not executed)
8012 __details_remove( this );
8017 _api_register( _child_obj
+'.isShown()', function () {
8018 var ctx
= this.context
;
8020 if ( ctx
.length
&& this.length
) {
8021 // _detailsShown as false or undefined will fall through to return false
8022 return ctx
[0].aoData
[ this[0] ]._detailsShow
|| false;
8029 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8032 * {integer} - column index (>=0 count from left, <0 count from right)
8033 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
8034 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
8035 * "{string}:name" - column name
8036 * "{string}" - jQuery selector on column header nodes
8040 // can be an array of these items, comma separated list, or an array of comma
8043 var __re_column_selector
= /^(.+):(name|visIdx|visible)$/;
8046 // r1 and r2 are redundant - but it means that the parameters match for the
8047 // iterator callback in columns().data()
8048 var __columnData = function ( settings
, column
, r1
, r2
, rows
) {
8050 for ( var row
=0, ien
=rows
.length
; row
<ien
; row
++ ) {
8051 a
.push( _fnGetCellData( settings
, rows
[row
], column
) );
8057 var __column_selector = function ( settings
, selector
, opts
)
8060 columns
= settings
.aoColumns
,
8061 names
= _pluck( columns
, 'sName' ),
8062 nodes
= _pluck( columns
, 'nTh' );
8064 return _selector_run( selector
, function ( s
) {
8065 var selInt
= _intVal( s
);
8069 return _range( columns
.length
);
8073 if ( selInt
!== null ) {
8074 return [ selInt
>= 0 ?
8075 selInt
: // Count from left
8076 columns
.length
+ selInt
// Count from right (+ because its a negative value)
8080 // Selector = function
8081 if ( typeof s
=== 'function' ) {
8082 var rows
= _selector_row_indexes( settings
, opts
);
8084 return $.map( columns
, function (col
, idx
) {
8087 __columnData( settings
, idx
, 0, 0, rows
),
8093 // jQuery or string selector
8094 var match
= typeof s
=== 'string' ?
8095 s
.match( __re_column_selector
) :
8099 switch( match
[2] ) {
8102 var idx
= parseInt( match
[1], 10 );
8103 // Visible index given, convert to column index
8105 // Counting from the right
8106 var visColumns
= $.map( columns
, function (col
,i
) {
8107 return col
.bVisible
? i
: null;
8109 return [ visColumns
[ visColumns
.length
+ idx
] ];
8111 // Counting from the left
8112 return [ _fnVisibleToColumnIndex( settings
, idx
) ];
8115 // match by name. `names` is column index complete and in order
8116 return $.map( names
, function (name
, i
) {
8117 return name
=== match
[1] ? i
: null;
8122 // jQuery selector on the TH elements for the columns
8126 return $.inArray( this, nodes
); // `nodes` is column index complete and in order
8134 var __setColumnVis = function ( settings
, column
, vis
, recalc
) {
8136 cols
= settings
.aoColumns
,
8137 col
= cols
[ column
],
8138 data
= settings
.aoData
,
8139 row
, cells
, i
, ien
, tr
;
8142 if ( vis
=== undefined ) {
8143 return col
.bVisible
;
8148 if ( col
.bVisible
=== vis
) {
8154 // Need to decide if we should use appendChild or insertBefore
8155 var insertBefore
= $.inArray( true, _pluck(cols
, 'bVisible'), column
+1 );
8157 for ( i
=0, ien
=data
.length
; i
<ien
; i
++ ) {
8159 cells
= data
[i
].anCells
;
8162 // insertBefore can act like appendChild if 2nd arg is null
8163 tr
.insertBefore( cells
[ column
], cells
[ insertBefore
] || null );
8169 $( _pluck( settings
.aoData
, 'anCells', column
) ).detach();
8174 _fnDrawHead( settings
, settings
.aoHeader
);
8175 _fnDrawHead( settings
, settings
.aoFooter
);
8177 if ( recalc
=== undefined || recalc
) {
8178 // Automatically adjust column sizing
8179 _fnAdjustColumnSizing( settings
);
8181 // Realign columns for scrolling
8182 if ( settings
.oScroll
.sX
|| settings
.oScroll
.sY
) {
8183 _fnScrollDraw( settings
);
8187 _fnCallbackFire( settings
, null, 'column-visibility', [settings
, column
, vis
] );
8189 _fnSaveState( settings
);
8196 _api_register( 'columns()', function ( selector
, opts
) {
8197 // argument shifting
8198 if ( selector
=== undefined ) {
8201 else if ( $.isPlainObject( selector
) ) {
8206 opts
= _selector_opts( opts
);
8208 var inst
= this.iterator( 'table', function ( settings
) {
8209 return __column_selector( settings
, selector
, opts
);
8212 // Want argument shifting here and in _row_selector?
8213 inst
.selector
.cols
= selector
;
8214 inst
.selector
.opts
= opts
;
8223 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector
, opts
) {
8224 return this.iterator( 'column', function ( settings
, column
) {
8225 return settings
.aoColumns
[column
].nTh
;
8233 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector
, opts
) {
8234 return this.iterator( 'column', function ( settings
, column
) {
8235 return settings
.aoColumns
[column
].nTf
;
8243 _api_registerPlural( 'columns().data()', 'column().data()', function () {
8244 return this.iterator( 'column-rows', __columnData
);
8248 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8249 return this.iterator( 'column', function ( settings
, column
) {
8250 return settings
.aoColumns
[column
].mData
;
8255 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type
) {
8256 return this.iterator( 'column-rows', function ( settings
, column
, i
, j
, rows
) {
8257 return _pluck_order( settings
.aoData
, rows
,
8258 type
=== 'search' ? '_aFilterData' : '_aSortData', column
8264 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8265 return this.iterator( 'column-rows', function ( settings
, column
, i
, j
, rows
) {
8266 return _pluck_order( settings
.aoData
, rows
, 'anCells', column
) ;
8272 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis
, calc
) {
8273 return this.iterator( 'column', function ( settings
, column
) {
8274 return vis
=== undefined ?
8275 settings
.aoColumns
[ column
].bVisible
:
8276 __setColumnVis( settings
, column
, vis
, calc
);
8282 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type
) {
8283 return this.iterator( 'column', function ( settings
, column
) {
8284 return type
=== 'visible' ?
8285 _fnColumnIndexToVisible( settings
, column
) :
8291 // _api_register( 'columns().show()', function () {
8292 // var selector = this.selector;
8293 // return this.columns( selector.cols, selector.opts ).visible( true );
8297 // _api_register( 'columns().hide()', function () {
8298 // var selector = this.selector;
8299 // return this.columns( selector.cols, selector.opts ).visible( false );
8304 _api_register( 'columns.adjust()', function () {
8305 return this.iterator( 'table', function ( settings
) {
8306 _fnAdjustColumnSizing( settings
);
8311 // Convert from one column index type, to another type
8312 _api_register( 'column.index()', function ( type
, idx
) {
8313 if ( this.context
.length
!== 0 ) {
8314 var ctx
= this.context
[0];
8316 if ( type
=== 'fromVisible' || type
=== 'toData' ) {
8317 return _fnVisibleToColumnIndex( ctx
, idx
);
8319 else if ( type
=== 'fromData' || type
=== 'toVisible' ) {
8320 return _fnColumnIndexToVisible( ctx
, idx
);
8326 _api_register( 'column()', function ( selector
, opts
) {
8327 return _selector_first( this.columns( selector
, opts
) );
8333 var __cell_selector = function ( settings
, selector
, opts
)
8335 var data
= settings
.aoData
;
8336 var rows
= _selector_row_indexes( settings
, opts
);
8337 var cells
= _pluck_order( data
, rows
, 'anCells' );
8338 var allCells
= $( [].concat
.apply([], cells
) );
8340 var columns
= settings
.aoColumns
.length
;
8341 var a
, i
, ien
, j
, o
, host
;
8343 return _selector_run( selector
, function ( s
) {
8344 var fnSelector
= typeof s
=== 'function';
8346 if ( s
=== null || s
=== undefined || fnSelector
) {
8347 // All cells and function selectors
8350 for ( i
=0, ien
=rows
.length
; i
<ien
; i
++ ) {
8353 for ( j
=0 ; j
<columns
; j
++ ) {
8360 // Selector - function
8361 host
= settings
.aoData
[ row
];
8363 if ( s( o
, _fnGetCellData(settings
, row
, j
), host
.anCells
[j
] ) ) {
8378 if ( $.isPlainObject( s
) ) {
8382 // Selector - jQuery filtered cells
8385 .map( function (i
, el
) {
8386 row
= el
.parentNode
._DT_RowIndex
;
8390 column
: $.inArray( el
, data
[ row
].anCells
)
8400 _api_register( 'cells()', function ( rowSelector
, columnSelector
, opts
) {
8401 // Argument shifting
8402 if ( $.isPlainObject( rowSelector
) ) {
8404 if ( typeof rowSelector
.row
!== undefined ) {
8405 opts
= columnSelector
;
8406 columnSelector
= null;
8413 if ( $.isPlainObject( columnSelector
) ) {
8414 opts
= columnSelector
;
8415 columnSelector
= null;
8419 if ( columnSelector
=== null || columnSelector
=== undefined ) {
8420 return this.iterator( 'table', function ( settings
) {
8421 return __cell_selector( settings
, rowSelector
, _selector_opts( opts
) );
8425 // Row + column selector
8426 var columns
= this.columns( columnSelector
, opts
);
8427 var rows
= this.rows( rowSelector
, opts
);
8428 var a
, i
, ien
, j
, jen
;
8430 var cells
= this.iterator( 'table', function ( settings
, idx
) {
8433 for ( i
=0, ien
=rows
[idx
].length
; i
<ien
; i
++ ) {
8434 for ( j
=0, jen
=columns
[idx
].length
; j
<jen
; j
++ ) {
8437 column
: columns
[idx
][j
]
8445 $.extend( cells
.selector
, {
8446 cols
: columnSelector
,
8455 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8456 return this.iterator( 'cell', function ( settings
, row
, column
) {
8457 return settings
.aoData
[ row
].anCells
[ column
];
8462 _api_register( 'cells().data()', function () {
8463 return this.iterator( 'cell', function ( settings
, row
, column
) {
8464 return _fnGetCellData( settings
, row
, column
);
8469 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type
) {
8470 type
= type
=== 'search' ? '_aFilterData' : '_aSortData';
8472 return this.iterator( 'cell', function ( settings
, row
, column
) {
8473 return settings
.aoData
[ row
][ type
][ column
];
8478 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type
) {
8479 return this.iterator( 'cell', function ( settings
, row
, column
) {
8480 return _fnGetCellData( settings
, row
, column
, type
);
8485 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8486 return this.iterator( 'cell', function ( settings
, row
, column
) {
8490 columnVisible
: _fnColumnIndexToVisible( settings
, column
)
8497 'cells().invalidate()',
8498 'cell().invalidate()'
8499 ], function ( src
) {
8500 var selector
= this.selector
;
8502 // Use the rows method of the instance to perform the invalidation, rather
8503 // than doing it here. This avoids needing to handle duplicate rows from
8505 this.rows( selector
.rows
, selector
.opts
).invalidate( src
);
8513 _api_register( 'cell()', function ( rowSelector
, columnSelector
, opts
) {
8514 return _selector_first( this.cells( rowSelector
, columnSelector
, opts
) );
8519 _api_register( 'cell().data()', function ( data
) {
8520 var ctx
= this.context
;
8523 if ( data
=== undefined ) {
8525 return ctx
.length
&& cell
.length
?
8526 _fnGetCellData( ctx
[0], cell
[0].row
, cell
[0].column
) :
8531 _fnSetCellData( ctx
[0], cell
[0].row
, cell
[0].column
, data
);
8532 _fnInvalidateRow( ctx
[0], cell
[0].row
, 'data', cell
[0].column
);
8540 * Get current ordering (sorting) that has been applied to the table.
8542 * @returns {array} 2D array containing the sorting information for the first
8543 * table in the current context. Each element in the parent array represents
8544 * a column being sorted upon (i.e. multi-sorting with two columns would have
8545 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8546 * the column index that the sorting condition applies to, the second is the
8547 * direction of the sort (`desc` or `asc`) and, optionally, the third is the
8548 * index of the sorting order from the `column.sorting` initialisation array.
8550 * Set the ordering for the table.
8552 * @param {integer} order Column index to sort upon.
8553 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8554 * @returns {DataTables.Api} this
8556 * Set the ordering for the table.
8558 * @param {array} order 1D array of sorting information to be applied.
8559 * @param {array} [...] Optional additional sorting conditions
8560 * @returns {DataTables.Api} this
8562 * Set the ordering for the table.
8564 * @param {array} order 2D array of sorting information to be applied.
8565 * @returns {DataTables.Api} this
8567 _api_register( 'order()', function ( order
, dir
) {
8568 var ctx
= this.context
;
8570 if ( order
=== undefined ) {
8572 return ctx
.length
!== 0 ?
8578 if ( typeof order
=== 'number' ) {
8579 // Simple column / direction passed in
8580 order
= [ [ order
, dir
] ];
8582 else if ( ! $.isArray( order
[0] ) ) {
8583 // Arguments passed in (list of 1D arrays)
8584 order
= Array
.prototype.slice
.call( arguments
);
8586 // otherwise a 2D array was passed in
8588 return this.iterator( 'table', function ( settings
) {
8589 settings
.aaSorting
= order
.slice();
8595 * Attach a sort listener to an element for a given column
8597 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8598 * listener to. This can take the form of a single DOM node, a jQuery
8599 * collection of nodes or a jQuery selector which will identify the node(s).
8600 * @param {integer} column the column that a click on this node will sort on
8601 * @param {function} [callback] callback function when sort is run
8602 * @returns {DataTables.Api} this
8604 _api_register( 'order.listener()', function ( node
, column
, callback
) {
8605 return this.iterator( 'table', function ( settings
) {
8606 _fnSortAttachListener( settings
, node
, column
, callback
);
8611 // Order by the selected column(s)
8613 'columns().order()',
8615 ], function ( dir
) {
8618 return this.iterator( 'table', function ( settings
, i
) {
8621 $.each( that
[i
], function (j
, col
) {
8622 sort
.push( [ col
, dir
] );
8625 settings
.aaSorting
= sort
;
8631 _api_register( 'search()', function ( input
, regex
, smart
, caseInsen
) {
8632 var ctx
= this.context
;
8634 if ( input
=== undefined ) {
8636 return ctx
.length
!== 0 ?
8637 ctx
[0].oPreviousSearch
.sSearch
:
8642 return this.iterator( 'table', function ( settings
) {
8643 if ( ! settings
.oFeatures
.bFilter
) {
8647 _fnFilterComplete( settings
, $.extend( {}, settings
.oPreviousSearch
, {
8648 "sSearch": input
+"",
8649 "bRegex": regex
=== null ? false : regex
,
8650 "bSmart": smart
=== null ? true : smart
,
8651 "bCaseInsensitive": caseInsen
=== null ? true : caseInsen
8657 _api_registerPlural(
8658 'columns().search()',
8659 'column().search()',
8660 function ( input
, regex
, smart
, caseInsen
) {
8661 return this.iterator( 'column', function ( settings
, column
) {
8662 var preSearch
= settings
.aoPreSearchCols
;
8664 if ( input
=== undefined ) {
8666 return preSearch
[ column
].sSearch
;
8670 if ( ! settings
.oFeatures
.bFilter
) {
8674 $.extend( preSearch
[ column
], {
8675 "sSearch": input
+"",
8676 "bRegex": regex
=== null ? false : regex
,
8677 "bSmart": smart
=== null ? true : smart
,
8678 "bCaseInsensitive": caseInsen
=== null ? true : caseInsen
8681 _fnFilterComplete( settings
, settings
.oPreviousSearch
, 1 );
8690 _api_register( 'state()', function () {
8691 return this.context
.length
?
8692 this.context
[0].oSavedState
:
8697 _api_register( 'state.clear()', function () {
8698 return this.iterator( 'table', function ( settings
) {
8699 // Save an empty object
8700 settings
.fnStateSaveCallback
.call( settings
.oInstance
, settings
, {} );
8705 _api_register( 'state.loaded()', function () {
8706 return this.context
.length
?
8707 this.context
[0].oLoadedState
:
8712 _api_register( 'state.save()', function () {
8713 return this.iterator( 'table', function ( settings
) {
8714 _fnSaveState( settings
);
8721 * Provide a common method for plug-ins to check the version of DataTables being
8722 * used, in order to ensure compatibility.
8724 * @param {string} version Version string to check for, in the format "X.Y.Z".
8725 * Note that the formats "X" and "X.Y" are also acceptable.
8726 * @returns {boolean} true if this version of DataTables is greater or equal to
8727 * the required version, or false if this version of DataTales is not
8733 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8735 DataTable
.versionCheck
= DataTable
.fnVersionCheck = function( version
)
8737 var aThis
= DataTable
.version
.split('.');
8738 var aThat
= version
.split('.');
8741 for ( var i
=0, iLen
=aThat
.length
; i
<iLen
; i
++ ) {
8742 iThis
= parseInt( aThis
[i
], 10 ) || 0;
8743 iThat
= parseInt( aThat
[i
], 10 ) || 0;
8745 // Parts are the same, keep comparing
8746 if (iThis
=== iThat
) {
8750 // Parts are different, return immediately
8751 return iThis
> iThat
;
8759 * Check if a `<table>` node is a DataTable table already or not.
8761 * @param {node|jquery|string} table Table node, jQuery object or jQuery
8762 * selector for the table to test. Note that if more than more than one
8763 * table is passed on, only the first will be checked
8764 * @returns {boolean} true the table given is a DataTable, or false otherwise
8769 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8770 * $('#example').dataTable();
8773 DataTable
.isDataTable
= DataTable
.fnIsDataTable = function ( table
)
8775 var t
= $(table
).get(0);
8778 $.each( DataTable
.settings
, function (i
, o
) {
8779 if ( o
.nTable
=== t
|| o
.nScrollHead
=== t
|| o
.nScrollFoot
=== t
) {
8789 * Get all DataTable tables that have been initialised - optionally you can
8790 * select to get only currently visible tables.
8792 * @param {boolean} [visible=false] Flag to indicate if you want all (default)
8793 * or visible tables only.
8794 * @returns {array} Array of `table` nodes (not DataTable instances) which are
8800 * $.each( $.fn.dataTable.tables(true), function () {
8801 * $(table).DataTable().columns.adjust();
8804 DataTable
.tables
= DataTable
.fnTables = function ( visible
)
8806 return $.map( DataTable
.settings
, function (o
) {
8807 if ( !visible
|| (visible
&& $(o
.nTable
).is(':visible')) ) {
8815 * DataTables utility methods
8817 * This namespace provides helper methods that DataTables uses internally to
8818 * create a DataTable, but which are not exclusively used only for DataTables.
8819 * These methods can be used by extension authors to save the duplication of
8826 * Throttle the calls to a function. Arguments and context are maintained
8827 * for the throttled function.
8829 * @param {function} fn Function to be called
8830 * @param {integer} freq Call frequency in mS
8831 * @return {function} Wrapped function
8833 throttle
: _fnThrottle
8838 * Convert from camel case parameters to Hungarian notation. This is made public
8839 * for the extensions to provide the same ability as DataTables core to accept
8840 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
8843 * @param {object} src The model object which holds all parameters that can be
8845 * @param {object} user The object to convert from camel case to Hungarian.
8846 * @param {boolean} force When set to `true`, properties which already have a
8847 * Hungarian value in the `user` object will be overwritten. Otherwise they
8850 DataTable
.camelToHungarian
= _fnCamelToHungarian
;
8857 _api_register( '$()', function ( selector
, opts
) {
8859 rows
= this.rows( opts
).nodes(), // Get all rows
8862 return $( [].concat(
8863 jqRows
.filter( selector
).toArray(),
8864 jqRows
.find( selector
).toArray()
8869 // jQuery functions to operate on the tables
8870 $.each( [ 'on', 'one', 'off' ], function (i
, key
) {
8871 _api_register( key
+'()', function ( /* event, handler */ ) {
8872 var args
= Array
.prototype.slice
.call(arguments
);
8874 // Add the `dt` namespace automatically if it isn't already present
8875 if ( ! args
[0].match(/\.dt\b/) ) {
8879 var inst
= $( this.tables().nodes() );
8880 inst
[key
].apply( inst
, args
);
8886 _api_register( 'clear()', function () {
8887 return this.iterator( 'table', function ( settings
) {
8888 _fnClearTable( settings
);
8893 _api_register( 'settings()', function () {
8894 return new _Api( this.context
, this.context
);
8898 _api_register( 'data()', function () {
8899 return this.iterator( 'table', function ( settings
) {
8900 return _pluck( settings
.aoData
, '_aData' );
8905 _api_register( 'destroy()', function ( remove
) {
8906 remove
= remove
|| false;
8908 return this.iterator( 'table', function ( settings
) {
8909 var orig
= settings
.nTableWrapper
.parentNode
;
8910 var classes
= settings
.oClasses
;
8911 var table
= settings
.nTable
;
8912 var tbody
= settings
.nTBody
;
8913 var thead
= settings
.nTHead
;
8914 var tfoot
= settings
.nTFoot
;
8915 var jqTable
= $(table
);
8916 var jqTbody
= $(tbody
);
8917 var jqWrapper
= $(settings
.nTableWrapper
);
8918 var rows
= $.map( settings
.aoData
, function (r
) { return r
.nTr
; } );
8921 // Flag to note that the table is currently being destroyed - no action
8923 settings
.bDestroying
= true;
8925 // Fire off the destroy callbacks for plug-ins etc
8926 _fnCallbackFire( settings
, "aoDestroyCallback", "destroy", [settings
] );
8928 // If not being removed from the document, make all columns visible
8930 new _Api( settings
).columns().visible( true );
8933 // Blitz all `DT` namespaced events (these are internal events, the
8934 // lowercase, `dt` events are user subscribed and they are responsible
8935 // for removing them
8936 jqWrapper
.unbind('.DT').find(':not(tbody *)').unbind('.DT');
8937 $(window
).unbind('.DT-'+settings
.sInstance
);
8939 // When scrolling we had to break the table up - restore it
8940 if ( table
!= thead
.parentNode
) {
8941 jqTable
.children('thead').detach();
8942 jqTable
.append( thead
);
8945 if ( tfoot
&& table
!= tfoot
.parentNode
) {
8946 jqTable
.children('tfoot').detach();
8947 jqTable
.append( tfoot
);
8950 // Remove the DataTables generated nodes, events and classes
8954 settings
.aaSorting
= [];
8955 settings
.aaSortingFixed
= [];
8956 _fnSortingClasses( settings
);
8958 $( rows
).removeClass( settings
.asStripeClasses
.join(' ') );
8960 $('th, td', thead
).removeClass( classes
.sSortable
+' '+
8961 classes
.sSortableAsc
+' '+classes
.sSortableDesc
+' '+classes
.sSortableNone
8964 if ( settings
.bJUI
) {
8965 $('th span.'+classes
.sSortIcon
+ ', td span.'+classes
.sSortIcon
, thead
).detach();
8966 $('th, td', thead
).each( function () {
8967 var wrapper
= $('div.'+classes
.sSortJUIWrapper
, this);
8968 $(this).append( wrapper
.contents() );
8973 if ( ! remove
&& orig
) {
8974 // insertBefore acts like appendChild if !arg[1]
8975 orig
.insertBefore( table
, settings
.nTableReinsertBefore
);
8978 // Add the TR elements back into the table in their original order
8979 jqTbody
.children().detach();
8980 jqTbody
.append( rows
);
8982 // Restore the width of the original table - was read from the style property,
8983 // so we can restore directly to that
8985 .css( 'width', settings
.sDestroyWidth
)
8986 .removeClass( classes
.sTable
);
8988 // If the were originally stripe classes - then we add them back here.
8989 // Note this is not fool proof (for example if not all rows had stripe
8990 // classes - but it's a good effort without getting carried away
8991 ien
= settings
.asDestroyStripes
.length
;
8994 jqTbody
.children().each( function (i
) {
8995 $(this).addClass( settings
.asDestroyStripes
[i
% ien
] );
8999 /* Remove the settings object from the settings array */
9000 var idx
= $.inArray( settings
, DataTable
.settings
);
9002 DataTable
.settings
.splice( idx
, 1 );
9009 * Version string for plug-ins to check compatibility. Allowed format is
9010 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9011 * only for non-release builds. See http://semver.org/ for more information.
9014 * @default Version number
9016 DataTable
.version
= "1.10.3";
9019 * Private data store, containing all of the settings objects that are
9020 * created for the tables on a given page.
9022 * Note that the `DataTable.settings` object is aliased to
9023 * `jQuery.fn.dataTableExt` through which it may be accessed and
9024 * manipulated, or `jQuery.fn.dataTable.settings`.
9030 DataTable
.settings
= [];
9033 * Object models container, for the various models that DataTables has
9034 * available to it. These models define the objects that are used to hold
9035 * the active state and configuration of the table.
9038 DataTable
.models
= {};
9043 * Template object for the way in which DataTables holds information about
9044 * search information for the global filter and individual column filters.
9047 DataTable
.models
.oSearch
= {
9049 * Flag to indicate if the filtering should be case insensitive or not
9053 "bCaseInsensitive": true,
9056 * Applied search term
9058 * @default <i>Empty string</i>
9063 * Flag to indicate if the search term should be interpreted as a
9064 * regular expression (true) or not (false) and therefore and special
9065 * regex characters escaped.
9072 * Flag to indicate if DataTables is to use its smart filtering or not.
9083 * Template object for the way in which DataTables holds information about
9084 * each individual row. This is the object format used for the settings
9088 DataTable
.models
.oRow
= {
9090 * TR element for the row
9097 * Array of TD elements for each row. This is null until the row has been
9105 * Data object from the original data source for the row. This is either
9106 * an array if using the traditional form of DataTables, or an object if
9107 * using mData options. The exact type will depend on the passed in
9108 * data from the data source, or will be an array if using DOM a data
9110 * @type array|object
9116 * Sorting data cache - this array is ostensibly the same length as the
9117 * number of columns (although each index is generated only as it is
9118 * needed), and holds the data that is used for sorting each column in the
9119 * row. We do this cache generation at the start of the sort in order that
9120 * the formatting of the sort data need be done only once for each cell
9121 * per sort. This array should not be read from or written to by anything
9122 * other than the master sorting methods.
9130 * Per cell filtering data cache. As per the sort data cache, used to
9131 * increase the performance of the filtering in DataTables
9136 "_aFilterData": null,
9139 * Filtering data cache. This is the same as the cell filtering cache, but
9140 * in this case a string rather than an array. This is easily computed with
9141 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9142 * needed on every search (memory traded for performance)
9147 "_sFilterRow": null,
9150 * Cache of the class name that DataTables has applied to the row, so we
9151 * can quickly look at this variable rather than needing to do a DOM check
9152 * on className for the nTr property.
9154 * @default <i>Empty string</i>
9160 * Denote if the original data source was from the DOM, or the data source
9161 * object. This is used for invalidating data, so DataTables can
9162 * automatically read data from the original source, unless uninstructed
9173 * Template object for the column information object in DataTables. This object
9174 * is held in the settings aoColumns array and contains all the information that
9175 * DataTables needs about each individual column.
9177 * Note that this object is related to {@link DataTable.defaults.column}
9178 * but this one is the internal data store for DataTables's cache of columns.
9179 * It should NOT be manipulated outside of DataTables. Any configuration should
9180 * be done through the initialisation options.
9183 DataTable
.models
.oColumn
= {
9185 * Column index. This could be worked out on-the-fly with $.inArray, but it
9186 * is faster to just hold it as a variable
9193 * A list of the columns that sorting should occur on when this column
9194 * is sorted. That this property is an array allows multi-column sorting
9195 * to be defined for a column (for example first name / last name columns
9196 * would benefit from this). The values are integers pointing to the
9197 * columns to be sorted on (typically it will be a single integer pointing
9198 * at itself, but that doesn't need to be the case).
9204 * Define the sorting directions that are applied to the column, in sequence
9205 * as the column is repeatedly sorted upon - i.e. the first value is used
9206 * as the sorting direction when the column if first sorted (clicked on).
9207 * Sort it again (click again) and it will move on to the next index.
9208 * Repeat until loop.
9214 * Flag to indicate if the column is searchable, and thus should be included
9215 * in the filtering or not.
9218 "bSearchable": null,
9221 * Flag to indicate if the column is sortable or not.
9227 * Flag to indicate if the column is currently visible in the table or not
9233 * Store for manual type assignment using the `column.type` option. This
9234 * is held in store so we can manipulate the column's `sType` property.
9239 "_sManualType": null,
9242 * Flag to indicate if HTML5 data attributes should be used as the data
9243 * source for filtering or sorting. True is either are.
9251 * Developer definable function that is called whenever a cell is created (Ajax source,
9252 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9253 * allowing you to modify the DOM element (add background colour for example) when the
9254 * element is available.
9256 * @param {element} nTd The TD node that has been created
9257 * @param {*} sData The Data for the cell
9258 * @param {array|object} oData The data for the whole row
9259 * @param {int} iRow The row index for the aoData data store
9262 "fnCreatedCell": null,
9265 * Function to get data from a cell in a column. You should <b>never</b>
9266 * access data directly through _aData internally in DataTables - always use
9267 * the method attached to this property. It allows mData to function as
9268 * required. This function is automatically assigned by the column
9269 * initialisation method
9271 * @param {array|object} oData The data array/object for the array
9272 * (i.e. aoData[]._aData)
9273 * @param {string} sSpecific The specific data type you want to get -
9274 * 'display', 'type' 'filter' 'sort'
9275 * @returns {*} The data for the cell from the given row's data
9281 * Function to set data for a cell in the column. You should <b>never</b>
9282 * set the data directly to _aData internally in DataTables - always use
9283 * this method. It allows mData to function as required. This function
9284 * is automatically assigned by the column initialisation method
9286 * @param {array|object} oData The data array/object for the array
9287 * (i.e. aoData[]._aData)
9288 * @param {*} sValue Value to set
9294 * Property to read the value for the cells in the column from the data
9295 * source array / object. If null, then the default content is used, if a
9296 * function is given then the return from the function is used.
9297 * @type function|int|string|null
9303 * Partner property to mData which is used (only when defined) to get
9304 * the data - i.e. it is basically the same as mData, but without the
9305 * 'set' option, and also the data fed to it is the result from mData.
9306 * This is the rendering method to match the data method of mData.
9307 * @type function|int|string|null
9313 * Unique header TH/TD element for this column - this is what the sorting
9314 * listener is attached to (if sorting is enabled.)
9321 * Unique footer TH/TD element for this column (if there is one). Not used
9322 * in DataTables as such, but can be used for plug-ins to reference the
9323 * footer for each column.
9330 * The class to apply to all TD elements in the table's TBODY for the column
9337 * When DataTables calculates the column widths to assign to each column,
9338 * it finds the longest string in each column and then constructs a
9339 * temporary table and reads the widths from that. The problem with this
9340 * is that "mmm" is much wider then "iiii", but the latter is a longer
9341 * string - thus the calculation can go wrong (doing it properly and putting
9342 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9343 * a "work around" we provide this option. It will append its value to the
9344 * text that is found to be the longest string for the column - i.e. padding.
9347 "sContentPadding": null,
9350 * Allows a default value to be given for a column's data, and will be used
9351 * whenever a null data source is encountered (this can be because mData
9352 * is set to null, or because the data source itself is null).
9356 "sDefaultContent": null,
9359 * Name for the column, allowing reference to the column by name as well as
9360 * by index (needs a lookup to work by name).
9366 * Custom sorting data type - defines which of the available plug-ins in
9367 * afnSortData the custom sorting will use - if any is defined.
9371 "sSortDataType": 'std',
9374 * Class to be applied to the header element when sorting on this column
9378 "sSortingClass": null,
9381 * Class to be applied to the header element when sorting on this column -
9382 * when jQuery UI theming is used.
9386 "sSortingClassJUI": null,
9389 * Title of the column - what is seen in the TH element (nTh).
9395 * Column sorting and filtering type
9402 * Width of the column
9409 * Width of the column when it was first "encountered"
9418 * Developer note: The properties of the object below are given in Hungarian
9419 * notation, that was used as the interface for DataTables prior to v1.10, however
9420 * from v1.10 onwards the primary interface is camel case. In order to avoid
9421 * breaking backwards compatibility utterly with this change, the Hungarian
9422 * version is still, internally the primary interface, but is is not documented
9423 * - hence the @name tags in each doc comment. This allows a Javascript function
9424 * to create a map from Hungarian notation to camel case (going the other direction
9425 * would require each property to be listed, which would at around 3K to the size
9426 * of DataTables, while this method is about a 0.5K hit.
9428 * Ultimately this does pave the way for Hungarian notation to be dropped
9429 * completely, but that is a massive amount of work and will break current
9430 * installs (therefore is on-hold until v2).
9434 * Initialisation options that can be given to DataTables at initialisation
9438 DataTable
.defaults
= {
9440 * An array of data to use for the table, passed in at initialisation which
9441 * will be used in preference to any data which is already in the DOM. This is
9442 * particularly useful for constructing tables purely in Javascript, for
9443 * example with a custom Ajax call.
9448 * @name DataTable.defaults.data
9451 * // Using a 2D array data source
9452 * $(document).ready( function () {
9453 * $('#example').dataTable( {
9455 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9456 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9459 * { "title": "Engine" },
9460 * { "title": "Browser" },
9461 * { "title": "Platform" },
9462 * { "title": "Version" },
9463 * { "title": "Grade" }
9469 * // Using an array of objects as a data source (`data`)
9470 * $(document).ready( function () {
9471 * $('#example').dataTable( {
9474 * "engine": "Trident",
9475 * "browser": "Internet Explorer 4.0",
9476 * "platform": "Win 95+",
9481 * "engine": "Trident",
9482 * "browser": "Internet Explorer 5.0",
9483 * "platform": "Win 95+",
9489 * { "title": "Engine", "data": "engine" },
9490 * { "title": "Browser", "data": "browser" },
9491 * { "title": "Platform", "data": "platform" },
9492 * { "title": "Version", "data": "version" },
9493 * { "title": "Grade", "data": "grade" }
9502 * If ordering is enabled, then DataTables will perform a first pass sort on
9503 * initialisation. You can define which column(s) the sort is performed
9504 * upon, and the sorting direction, with this variable. The `sorting` array
9505 * should contain an array for each column to be sorted initially containing
9506 * the column's index and a direction string ('asc' or 'desc').
9508 * @default [[0,'asc']]
9511 * @name DataTable.defaults.order
9514 * // Sort by 3rd column first, and then 4th column
9515 * $(document).ready( function() {
9516 * $('#example').dataTable( {
9517 * "order": [[2,'asc'], [3,'desc']]
9521 * // No initial sorting
9522 * $(document).ready( function() {
9523 * $('#example').dataTable( {
9528 "aaSorting": [[0,'asc']],
9532 * This parameter is basically identical to the `sorting` parameter, but
9533 * cannot be overridden by user interaction with the table. What this means
9534 * is that you could have a column (visible or hidden) which the sorting
9535 * will always be forced on first - any sorting after that (from the user)
9536 * will then be performed as required. This can be useful for grouping rows
9542 * @name DataTable.defaults.orderFixed
9545 * $(document).ready( function() {
9546 * $('#example').dataTable( {
9547 * "orderFixed": [[0,'asc']]
9551 "aaSortingFixed": [],
9555 * DataTables can be instructed to load data to display in the table from a
9556 * Ajax source. This option defines how that Ajax call is made and where to.
9558 * The `ajax` property has three different modes of operation, depending on
9559 * how it is defined. These are:
9561 * * `string` - Set the URL from where the data should be loaded from.
9562 * * `object` - Define properties for `jQuery.ajax`.
9563 * * `function` - Custom data get function
9568 * As a string, the `ajax` property simply defines the URL from which
9569 * DataTables will load data.
9574 * As an object, the parameters in the object are passed to
9575 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9576 * of the Ajax request. DataTables has a number of default parameters which
9577 * you can override using this option. Please refer to the jQuery
9578 * documentation for a full description of the options available, although
9579 * the following parameters provide additional options in DataTables or
9580 * require special consideration:
9582 * * `data` - As with jQuery, `data` can be provided as an object, but it
9583 * can also be used as a function to manipulate the data DataTables sends
9584 * to the server. The function takes a single parameter, an object of
9585 * parameters with the values that DataTables has readied for sending. An
9586 * object may be returned which will be merged into the DataTables
9587 * defaults, or you can add the items to the object that was passed in and
9588 * not return anything from the function. This supersedes `fnServerParams`
9589 * from DataTables 1.9-.
9591 * * `dataSrc` - By default DataTables will look for the property `data` (or
9592 * `aaData` for compatibility with DataTables 1.9-) when obtaining data
9593 * from an Ajax source or for server-side processing - this parameter
9594 * allows that property to be changed. You can use Javascript dotted
9595 * object notation to get a data source for multiple levels of nesting, or
9596 * it my be used as a function. As a function it takes a single parameter,
9597 * the JSON returned from the server, which can be manipulated as
9598 * required, with the returned value being that used by DataTables as the
9599 * data source for the table. This supersedes `sAjaxDataProp` from
9602 * * `success` - Should not be overridden it is used internally in
9603 * DataTables. To manipulate / transform the data returned by the server
9604 * use `ajax.dataSrc`, or use `ajax` as a function (see below).
9609 * As a function, making the Ajax call is left up to yourself allowing
9610 * complete control of the Ajax request. Indeed, if desired, a method other
9611 * than Ajax could be used to obtain the required data, such as Web storage
9612 * or an AIR database.
9614 * The function is given four parameters and no return is required. The
9617 * 1. _object_ - Data to send to the server
9618 * 2. _function_ - Callback function that must be executed when the required
9619 * data has been obtained. That data should be passed into the callback
9620 * as the only parameter
9621 * 3. _object_ - DataTables settings object for the table
9623 * Note that this supersedes `fnServerData` from DataTables 1.9-.
9625 * @type string|object|function
9629 * @name DataTable.defaults.ajax
9633 * // Get JSON data from a file via Ajax.
9634 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9635 * $('#example').dataTable( {
9636 * "ajax": "data.json"
9640 * // Get JSON data from a file via Ajax, using `dataSrc` to change
9641 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9642 * $('#example').dataTable( {
9644 * "url": "data.json",
9645 * "dataSrc": "tableData"
9650 * // Get JSON data from a file via Ajax, using `dataSrc` to read data
9651 * // from a plain array rather than an array in an object
9652 * $('#example').dataTable( {
9654 * "url": "data.json",
9660 * // Manipulate the data returned from the server - add a link to data
9661 * // (note this can, should, be done using `render` for the column - this
9662 * // is just a simple example of how the data can be manipulated).
9663 * $('#example').dataTable( {
9665 * "url": "data.json",
9666 * "dataSrc": function ( json ) {
9667 * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9668 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9676 * // Add data to the request
9677 * $('#example').dataTable( {
9679 * "url": "data.json",
9680 * "data": function ( d ) {
9682 * "extra_search": $('#extra').val()
9689 * // Send request as POST
9690 * $('#example').dataTable( {
9692 * "url": "data.json",
9698 * // Get the data from localStorage (could interface with a form for
9699 * // adding, editing and removing rows).
9700 * $('#example').dataTable( {
9701 * "ajax": function (data, callback, settings) {
9703 * JSON.parse( localStorage.getItem('dataTablesData') )
9712 * This parameter allows you to readily specify the entries in the length drop
9713 * down menu that DataTables shows when pagination is enabled. It can be
9714 * either a 1D array of options which will be used for both the displayed
9715 * option and the value, or a 2D array which will use the array in the first
9716 * position as the value, and the array in the second position as the
9717 * displayed options (useful for language strings such as 'All').
9719 * Note that the `pageLength` property will be automatically set to the
9720 * first value given in this array, unless `pageLength` is also provided.
9722 * @default [ 10, 25, 50, 100 ]
9725 * @name DataTable.defaults.lengthMenu
9728 * $(document).ready( function() {
9729 * $('#example').dataTable( {
9730 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9734 "aLengthMenu": [ 10, 25, 50, 100 ],
9738 * The `columns` option in the initialisation parameter allows you to define
9739 * details about the way individual columns behave. For a full list of
9740 * column options that can be set, please see
9741 * {@link DataTable.defaults.column}. Note that if you use `columns` to
9742 * define your columns, you must have an entry in the array for every single
9743 * column that you have in your table (these can be null if you don't which
9744 * to specify any options).
9747 * @name DataTable.defaults.column
9752 * Very similar to `columns`, `columnDefs` allows you to target a specific
9753 * column, multiple columns, or all columns, using the `targets` property of
9754 * each object in the array. This allows great flexibility when creating
9755 * tables, as the `columnDefs` arrays can be of any length, targeting the
9756 * columns you specifically want. `columnDefs` may use any of the column
9757 * options available: {@link DataTable.defaults.column}, but it _must_
9758 * have `targets` defined in each object in the array. Values in the `targets`
9761 * <li>a string - class name will be matched on the TH for the column</li>
9762 * <li>0 or a positive integer - column index counting from the left</li>
9763 * <li>a negative integer - column index counting from the right</li>
9764 * <li>the string "_all" - all columns (i.e. assign a default)</li>
9768 * @name DataTable.defaults.columnDefs
9770 "aoColumnDefs": null,
9774 * Basically the same as `search`, this parameter defines the individual column
9775 * filtering state at initialisation time. The array must be of the same size
9776 * as the number of columns, and each element be an object with the parameters
9777 * `search` and `escapeRegex` (the latter is optional). 'null' is also
9778 * accepted and the default will be used.
9783 * @name DataTable.defaults.searchCols
9786 * $(document).ready( function() {
9787 * $('#example').dataTable( {
9790 * { "search": "My filter" },
9792 * { "search": "^[0-9]", "escapeRegex": false }
9801 * An array of CSS classes that should be applied to displayed rows. This
9802 * array may be of any length, and DataTables will apply each class
9803 * sequentially, looping when required.
9805 * @default null <i>Will take the values determined by the `oClasses.stripe*`
9809 * @name DataTable.defaults.stripeClasses
9812 * $(document).ready( function() {
9813 * $('#example').dataTable( {
9814 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
9818 "asStripeClasses": null,
9822 * Enable or disable automatic column width calculation. This can be disabled
9823 * as an optimisation (it takes some time to calculate the widths) if the
9824 * tables widths are passed in using `columns`.
9829 * @name DataTable.defaults.autoWidth
9832 * $(document).ready( function () {
9833 * $('#example').dataTable( {
9834 * "autoWidth": false
9842 * Deferred rendering can provide DataTables with a huge speed boost when you
9843 * are using an Ajax or JS data source for the table. This option, when set to
9844 * true, will cause DataTables to defer the creation of the table elements for
9845 * each row until they are needed for a draw - saving a significant amount of
9851 * @name DataTable.defaults.deferRender
9854 * $(document).ready( function() {
9855 * $('#example').dataTable( {
9856 * "ajax": "sources/arrays.txt",
9857 * "deferRender": true
9861 "bDeferRender": false,
9865 * Replace a DataTable which matches the given selector and replace it with
9866 * one which has the properties of the new initialisation object passed. If no
9867 * table matches the selector, then the new DataTable will be constructed as
9873 * @name DataTable.defaults.destroy
9876 * $(document).ready( function() {
9877 * $('#example').dataTable( {
9878 * "srollY": "200px",
9882 * // Some time later....
9883 * $('#example').dataTable( {
9893 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
9894 * that it allows the end user to input multiple words (space separated) and
9895 * will match a row containing those words, even if not in the order that was
9896 * specified (this allow matching across multiple columns). Note that if you
9897 * wish to use filtering in DataTables this must remain 'true' - to remove the
9898 * default filtering input box and retain filtering abilities, please use
9899 * {@link DataTable.defaults.dom}.
9904 * @name DataTable.defaults.searching
9907 * $(document).ready( function () {
9908 * $('#example').dataTable( {
9909 * "searching": false
9917 * Enable or disable the table information display. This shows information
9918 * about the data that is currently visible on the page, including information
9919 * about filtered data if that action is being performed.
9924 * @name DataTable.defaults.info
9927 * $(document).ready( function () {
9928 * $('#example').dataTable( {
9937 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
9938 * slightly different and additional mark-up from what DataTables has
9939 * traditionally used).
9944 * @name DataTable.defaults.jQueryUI
9947 * $(document).ready( function() {
9948 * $('#example').dataTable( {
9957 * Allows the end user to select the size of a formatted page from a select
9958 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
9963 * @name DataTable.defaults.lengthChange
9966 * $(document).ready( function () {
9967 * $('#example').dataTable( {
9968 * "lengthChange": false
9972 "bLengthChange": true,
9976 * Enable or disable pagination.
9981 * @name DataTable.defaults.paging
9984 * $(document).ready( function () {
9985 * $('#example').dataTable( {
9994 * Enable or disable the display of a 'processing' indicator when the table is
9995 * being processed (e.g. a sort). This is particularly useful for tables with
9996 * large amounts of data where it can take a noticeable amount of time to sort
10002 * @name DataTable.defaults.processing
10005 * $(document).ready( function () {
10006 * $('#example').dataTable( {
10007 * "processing": true
10011 "bProcessing": false,
10015 * Retrieve the DataTables object for the given selector. Note that if the
10016 * table has already been initialised, this parameter will cause DataTables
10017 * to simply return the object that has already been set up - it will not take
10018 * account of any changes you might have made to the initialisation object
10019 * passed to DataTables (setting this parameter to true is an acknowledgement
10020 * that you understand this). `destroy` can be used to reinitialise a table if
10026 * @name DataTable.defaults.retrieve
10029 * $(document).ready( function() {
10034 * function initTable ()
10036 * return $('#example').dataTable( {
10037 * "scrollY": "200px",
10038 * "paginate": false,
10043 * function tableActions ()
10045 * var table = initTable();
10046 * // perform API operations with oTable
10049 "bRetrieve": false,
10053 * When vertical (y) scrolling is enabled, DataTables will force the height of
10054 * the table's viewport to the given height at all times (useful for layout).
10055 * However, this can look odd when filtering data down to a small data set,
10056 * and the footer is left "floating" further down. This parameter (when
10057 * enabled) will cause DataTables to collapse the table's viewport down when
10058 * the result set will fit within the given Y height.
10063 * @name DataTable.defaults.scrollCollapse
10066 * $(document).ready( function() {
10067 * $('#example').dataTable( {
10068 * "scrollY": "200",
10069 * "scrollCollapse": true
10073 "bScrollCollapse": false,
10077 * Configure DataTables to use server-side processing. Note that the
10078 * `ajax` parameter must also be given in order to give DataTables a
10079 * source to obtain the required data for each draw.
10084 * @dtopt Server-side
10085 * @name DataTable.defaults.serverSide
10088 * $(document).ready( function () {
10089 * $('#example').dataTable( {
10090 * "serverSide": true,
10091 * "ajax": "xhr.php"
10095 "bServerSide": false,
10099 * Enable or disable sorting of columns. Sorting of individual columns can be
10100 * disabled by the `sortable` option for each column.
10105 * @name DataTable.defaults.ordering
10108 * $(document).ready( function () {
10109 * $('#example').dataTable( {
10110 * "ordering": false
10118 * Enable or display DataTables' ability to sort multiple columns at the
10119 * same time (activated by shift-click by the user).
10124 * @name DataTable.defaults.orderMulti
10127 * // Disable multiple column sorting ability
10128 * $(document).ready( function () {
10129 * $('#example').dataTable( {
10130 * "orderMulti": false
10134 "bSortMulti": true,
10138 * Allows control over whether DataTables should use the top (true) unique
10139 * cell that is found for a single column, or the bottom (false - default).
10140 * This is useful when using complex headers.
10145 * @name DataTable.defaults.orderCellsTop
10148 * $(document).ready( function() {
10149 * $('#example').dataTable( {
10150 * "orderCellsTop": true
10154 "bSortCellsTop": false,
10158 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10159 * `sorting\_3` to the columns which are currently being sorted on. This is
10160 * presented as a feature switch as it can increase processing time (while
10161 * classes are removed and added) so for large data sets you might want to
10167 * @name DataTable.defaults.orderClasses
10170 * $(document).ready( function () {
10171 * $('#example').dataTable( {
10172 * "orderClasses": false
10176 "bSortClasses": true,
10180 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10181 * used to save table display information such as pagination information,
10182 * display length, filtering and sorting. As such when the end user reloads
10183 * the page the display display will match what thy had previously set up.
10185 * Due to the use of `localStorage` the default state saving is not supported
10186 * in IE6 or 7. If state saving is required in those browsers, use
10187 * `stateSaveCallback` to provide a storage solution such as cookies.
10192 * @name DataTable.defaults.stateSave
10195 * $(document).ready( function () {
10196 * $('#example').dataTable( {
10197 * "stateSave": true
10201 "bStateSave": false,
10205 * This function is called when a TR element is created (and all TD child
10206 * elements have been inserted), or registered if using a DOM source, allowing
10207 * manipulation of the TR element (adding classes etc).
10209 * @param {node} row "TR" element for the current row
10210 * @param {array} data Raw data array for this row
10211 * @param {int} dataIndex The index of this row in the internal aoData array
10214 * @name DataTable.defaults.createdRow
10217 * $(document).ready( function() {
10218 * $('#example').dataTable( {
10219 * "createdRow": function( row, data, dataIndex ) {
10220 * // Bold the grade for all 'A' grade browsers
10221 * if ( data[4] == "A" )
10223 * $('td:eq(4)', row).html( '<b>A</b>' );
10229 "fnCreatedRow": null,
10233 * This function is called on every 'draw' event, and allows you to
10234 * dynamically modify any aspect you want about the created DOM.
10236 * @param {object} settings DataTables settings object
10239 * @name DataTable.defaults.drawCallback
10242 * $(document).ready( function() {
10243 * $('#example').dataTable( {
10244 * "drawCallback": function( settings ) {
10245 * alert( 'DataTables has redrawn the table' );
10250 "fnDrawCallback": null,
10254 * Identical to fnHeaderCallback() but for the table footer this function
10255 * allows you to modify the table footer on every 'draw' event.
10257 * @param {node} foot "TR" element for the footer
10258 * @param {array} data Full table data (as derived from the original HTML)
10259 * @param {int} start Index for the current display starting point in the
10261 * @param {int} end Index for the current display ending point in the
10263 * @param {array int} display Index array to translate the visual position
10264 * to the full data array
10267 * @name DataTable.defaults.footerCallback
10270 * $(document).ready( function() {
10271 * $('#example').dataTable( {
10272 * "footerCallback": function( tfoot, data, start, end, display ) {
10273 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10278 "fnFooterCallback": null,
10282 * When rendering large numbers in the information element for the table
10283 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10284 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10285 * rendered as "1,000,000") to help readability for the end user. This
10286 * function will override the default method DataTables uses.
10289 * @param {int} toFormat number to be formatted
10290 * @returns {string} formatted string for DataTables to show the number
10293 * @name DataTable.defaults.formatNumber
10296 * // Format a number using a single quote for the separator (note that
10297 * // this can also be done with the language.thousands option)
10298 * $(document).ready( function() {
10299 * $('#example').dataTable( {
10300 * "formatNumber": function ( toFormat ) {
10301 * return toFormat.toString().replace(
10302 * /\B(?=(\d{3})+(?!\d))/g, "'"
10308 "fnFormatNumber": function ( toFormat
) {
10309 return toFormat
.toString().replace(
10310 /\B(?=(\d{3})+(?!\d))/g,
10311 this.oLanguage
.sThousands
10317 * This function is called on every 'draw' event, and allows you to
10318 * dynamically modify the header row. This can be used to calculate and
10319 * display useful information about the table.
10321 * @param {node} head "TR" element for the header
10322 * @param {array} data Full table data (as derived from the original HTML)
10323 * @param {int} start Index for the current display starting point in the
10325 * @param {int} end Index for the current display ending point in the
10327 * @param {array int} display Index array to translate the visual position
10328 * to the full data array
10331 * @name DataTable.defaults.headerCallback
10334 * $(document).ready( function() {
10335 * $('#example').dataTable( {
10336 * "fheaderCallback": function( head, data, start, end, display ) {
10337 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10342 "fnHeaderCallback": null,
10346 * The information element can be used to convey information about the current
10347 * state of the table. Although the internationalisation options presented by
10348 * DataTables are quite capable of dealing with most customisations, there may
10349 * be times where you wish to customise the string further. This callback
10350 * allows you to do exactly that.
10352 * @param {object} oSettings DataTables settings object
10353 * @param {int} start Starting position in data for the draw
10354 * @param {int} end End position in data for the draw
10355 * @param {int} max Total number of rows in the table (regardless of
10357 * @param {int} total Total number of rows in the data set, after filtering
10358 * @param {string} pre The string that DataTables has formatted using it's
10360 * @returns {string} The string to be displayed in the information element.
10363 * @name DataTable.defaults.infoCallback
10366 * $('#example').dataTable( {
10367 * "infoCallback": function( settings, start, end, max, total, pre ) {
10368 * return start +" to "+ end;
10372 "fnInfoCallback": null,
10376 * Called when the table has been initialised. Normally DataTables will
10377 * initialise sequentially and there will be no need for this function,
10378 * however, this does not hold true when using external language information
10379 * since that is obtained using an async XHR call.
10381 * @param {object} settings DataTables settings object
10382 * @param {object} json The JSON object request from the server - only
10383 * present if client-side Ajax sourced data is used
10386 * @name DataTable.defaults.initComplete
10389 * $(document).ready( function() {
10390 * $('#example').dataTable( {
10391 * "initComplete": function(settings, json) {
10392 * alert( 'DataTables has finished its initialisation.' );
10397 "fnInitComplete": null,
10401 * Called at the very start of each table draw and can be used to cancel the
10402 * draw by returning false, any other return (including undefined) results in
10403 * the full draw occurring).
10405 * @param {object} settings DataTables settings object
10406 * @returns {boolean} False will cancel the draw, anything else (including no
10407 * return) will allow it to complete.
10410 * @name DataTable.defaults.preDrawCallback
10413 * $(document).ready( function() {
10414 * $('#example').dataTable( {
10415 * "preDrawCallback": function( settings ) {
10416 * if ( $('#test').val() == 1 ) {
10423 "fnPreDrawCallback": null,
10427 * This function allows you to 'post process' each row after it have been
10428 * generated for each table draw, but before it is rendered on screen. This
10429 * function might be used for setting the row class name etc.
10431 * @param {node} row "TR" element for the current row
10432 * @param {array} data Raw data array for this row
10433 * @param {int} displayIndex The display index for the current table draw
10434 * @param {int} displayIndexFull The index of the data in the full list of
10435 * rows (after filtering)
10438 * @name DataTable.defaults.rowCallback
10441 * $(document).ready( function() {
10442 * $('#example').dataTable( {
10443 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10444 * // Bold the grade for all 'A' grade browsers
10445 * if ( data[4] == "A" ) {
10446 * $('td:eq(4)', row).html( '<b>A</b>' );
10452 "fnRowCallback": null,
10456 * __Deprecated__ The functionality provided by this parameter has now been
10457 * superseded by that provided through `ajax`, which should be used instead.
10459 * This parameter allows you to override the default function which obtains
10460 * the data from the server so something more suitable for your application.
10461 * For example you could use POST data, or pull information from a Gears or
10465 * @param {string} source HTTP source to obtain the data from (`ajax`)
10466 * @param {array} data A key/value pair object containing the data to send
10468 * @param {function} callback to be called on completion of the data get
10469 * process that will draw the data on the page.
10470 * @param {object} settings DataTables settings object
10473 * @dtopt Server-side
10474 * @name DataTable.defaults.serverData
10476 * @deprecated 1.10. Please use `ajax` for this functionality now.
10478 "fnServerData": null,
10482 * __Deprecated__ The functionality provided by this parameter has now been
10483 * superseded by that provided through `ajax`, which should be used instead.
10485 * It is often useful to send extra data to the server when making an Ajax
10486 * request - for example custom filtering information, and this callback
10487 * function makes it trivial to send extra information to the server. The
10488 * passed in parameter is the data set that has been constructed by
10489 * DataTables, and you can add to this or modify it as you require.
10491 * @param {array} data Data array (array of objects which are name/value
10492 * pairs) that has been constructed by DataTables and will be sent to the
10493 * server. In the case of Ajax sourced data with server-side processing
10494 * this will be an empty array, for server-side processing there will be a
10495 * significant number of parameters!
10496 * @returns {undefined} Ensure that you modify the data array passed in,
10497 * as this is passed by reference.
10500 * @dtopt Server-side
10501 * @name DataTable.defaults.serverParams
10503 * @deprecated 1.10. Please use `ajax` for this functionality now.
10505 "fnServerParams": null,
10509 * Load the table state. With this function you can define from where, and how, the
10510 * state of a table is loaded. By default DataTables will load from `localStorage`
10511 * but you might wish to use a server-side database or cookies.
10514 * @param {object} settings DataTables settings object
10515 * @return {object} The DataTables state object to be loaded
10518 * @name DataTable.defaults.stateLoadCallback
10521 * $(document).ready( function() {
10522 * $('#example').dataTable( {
10523 * "stateSave": true,
10524 * "stateLoadCallback": function (settings) {
10527 * // Send an Ajax request to the server to get the data. Note that
10528 * // this is a synchronous request.
10530 * "url": "/state_load",
10532 * "dataType": "json",
10533 * "success": function (json) {
10543 "fnStateLoadCallback": function ( settings
) {
10546 (settings
.iStateDuration
=== -1 ? sessionStorage
: localStorage
).getItem(
10547 'DataTables_'+settings
.sInstance
+'_'+location
.pathname
10555 * Callback which allows modification of the saved state prior to loading that state.
10556 * This callback is called when the table is loading state from the stored data, but
10557 * prior to the settings object being modified by the saved state. Note that for
10558 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10561 * @param {object} settings DataTables settings object
10562 * @param {object} data The state object that is to be loaded
10565 * @name DataTable.defaults.stateLoadParams
10568 * // Remove a saved filter, so filtering is never loaded
10569 * $(document).ready( function() {
10570 * $('#example').dataTable( {
10571 * "stateSave": true,
10572 * "stateLoadParams": function (settings, data) {
10573 * data.oSearch.sSearch = "";
10579 * // Disallow state loading by returning false
10580 * $(document).ready( function() {
10581 * $('#example').dataTable( {
10582 * "stateSave": true,
10583 * "stateLoadParams": function (settings, data) {
10589 "fnStateLoadParams": null,
10593 * Callback that is called when the state has been loaded from the state saving method
10594 * and the DataTables settings object has been modified as a result of the loaded state.
10596 * @param {object} settings DataTables settings object
10597 * @param {object} data The state object that was loaded
10600 * @name DataTable.defaults.stateLoaded
10603 * // Show an alert with the filtering value that was saved
10604 * $(document).ready( function() {
10605 * $('#example').dataTable( {
10606 * "stateSave": true,
10607 * "stateLoaded": function (settings, data) {
10608 * alert( 'Saved filter was: '+data.oSearch.sSearch );
10613 "fnStateLoaded": null,
10617 * Save the table state. This function allows you to define where and how the state
10618 * information for the table is stored By default DataTables will use `localStorage`
10619 * but you might wish to use a server-side database or cookies.
10622 * @param {object} settings DataTables settings object
10623 * @param {object} data The state object to be saved
10626 * @name DataTable.defaults.stateSaveCallback
10629 * $(document).ready( function() {
10630 * $('#example').dataTable( {
10631 * "stateSave": true,
10632 * "stateSaveCallback": function (settings, data) {
10633 * // Send an Ajax request to the server with the state object
10635 * "url": "/state_save",
10637 * "dataType": "json",
10639 * "success": function () {}
10645 "fnStateSaveCallback": function ( settings
, data
) {
10647 (settings
.iStateDuration
=== -1 ? sessionStorage
: localStorage
).setItem(
10648 'DataTables_'+settings
.sInstance
+'_'+location
.pathname
,
10649 JSON
.stringify( data
)
10656 * Callback which allows modification of the state to be saved. Called when the table
10657 * has changed state a new state save is required. This method allows modification of
10658 * the state saving object prior to actually doing the save, including addition or
10659 * other state properties or modification. Note that for plug-in authors, you should
10660 * use the `stateSaveParams` event to save parameters for a plug-in.
10662 * @param {object} settings DataTables settings object
10663 * @param {object} data The state object to be saved
10666 * @name DataTable.defaults.stateSaveParams
10669 * // Remove a saved filter, so filtering is never saved
10670 * $(document).ready( function() {
10671 * $('#example').dataTable( {
10672 * "stateSave": true,
10673 * "stateSaveParams": function (settings, data) {
10674 * data.oSearch.sSearch = "";
10679 "fnStateSaveParams": null,
10683 * Duration for which the saved state information is considered valid. After this period
10684 * has elapsed the state will be returned to the default.
10685 * Value is given in seconds.
10687 * @default 7200 <i>(2 hours)</i>
10690 * @name DataTable.defaults.stateDuration
10693 * $(document).ready( function() {
10694 * $('#example').dataTable( {
10695 * "stateDuration": 60*60*24; // 1 day
10699 "iStateDuration": 7200,
10703 * When enabled DataTables will not make a request to the server for the first
10704 * page draw - rather it will use the data already on the page (no sorting etc
10705 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10706 * is used to indicate that deferred loading is required, but it is also used
10707 * to tell DataTables how many records there are in the full table (allowing
10708 * the information element and pagination to be displayed correctly). In the case
10709 * where a filtering is applied to the table on initial load, this can be
10710 * indicated by giving the parameter as an array, where the first element is
10711 * the number of records available after filtering and the second element is the
10712 * number of records without filtering (allowing the table information element
10713 * to be shown correctly).
10714 * @type int | array
10718 * @name DataTable.defaults.deferLoading
10721 * // 57 records available in the table, no filtering applied
10722 * $(document).ready( function() {
10723 * $('#example').dataTable( {
10724 * "serverSide": true,
10725 * "ajax": "scripts/server_processing.php",
10726 * "deferLoading": 57
10731 * // 57 records after filtering, 100 without filtering (an initial filter applied)
10732 * $(document).ready( function() {
10733 * $('#example').dataTable( {
10734 * "serverSide": true,
10735 * "ajax": "scripts/server_processing.php",
10736 * "deferLoading": [ 57, 100 ],
10738 * "search": "my_filter"
10743 "iDeferLoading": null,
10747 * Number of rows to display on a single page when using pagination. If
10748 * feature enabled (`lengthChange`) then the end user will be able to override
10749 * this to a custom setting using a pop-up menu.
10754 * @name DataTable.defaults.pageLength
10757 * $(document).ready( function() {
10758 * $('#example').dataTable( {
10763 "iDisplayLength": 10,
10767 * Define the starting point for data display when using DataTables with
10768 * pagination. Note that this parameter is the number of records, rather than
10769 * the page number, so if you have 10 records per page and want to start on
10770 * the third page, it should be "20".
10775 * @name DataTable.defaults.displayStart
10778 * $(document).ready( function() {
10779 * $('#example').dataTable( {
10780 * "displayStart": 20
10784 "iDisplayStart": 0,
10788 * By default DataTables allows keyboard navigation of the table (sorting, paging,
10789 * and filtering) by adding a `tabindex` attribute to the required elements. This
10790 * allows you to tab through the controls and press the enter key to activate them.
10791 * The tabindex is default 0, meaning that the tab follows the flow of the document.
10792 * You can overrule this using this parameter if you wish. Use a value of -1 to
10793 * disable built-in keyboard navigation.
10798 * @name DataTable.defaults.tabIndex
10801 * $(document).ready( function() {
10802 * $('#example').dataTable( {
10811 * Classes that DataTables assigns to the various components and features
10812 * that it adds to the HTML table. This allows classes to be configured
10813 * during initialisation in addition to through the static
10814 * {@link DataTable.ext.oStdClasses} object).
10816 * @name DataTable.defaults.classes
10822 * All strings that DataTables uses in the user interface that it creates
10823 * are defined in this object, allowing you to modified them individually or
10824 * completely replace them all as required.
10826 * @name DataTable.defaults.language
10830 * Strings that are used for WAI-ARIA labels and controls only (these are not
10831 * actually visible on the page, but will be read by screenreaders, and thus
10832 * must be internationalised as well).
10834 * @name DataTable.defaults.language.aria
10838 * ARIA label that is added to the table headers when the column may be
10839 * sorted ascending by activing the column (click or return when focused).
10840 * Note that the column header is prefixed to this string.
10842 * @default : activate to sort column ascending
10845 * @name DataTable.defaults.language.aria.sortAscending
10848 * $(document).ready( function() {
10849 * $('#example').dataTable( {
10852 * "sortAscending": " - click/return to sort ascending"
10858 "sSortAscending": ": activate to sort column ascending",
10861 * ARIA label that is added to the table headers when the column may be
10862 * sorted descending by activing the column (click or return when focused).
10863 * Note that the column header is prefixed to this string.
10865 * @default : activate to sort column ascending
10868 * @name DataTable.defaults.language.aria.sortDescending
10871 * $(document).ready( function() {
10872 * $('#example').dataTable( {
10875 * "sortDescending": " - click/return to sort descending"
10881 "sSortDescending": ": activate to sort column descending"
10885 * Pagination string used by DataTables for the built-in pagination
10888 * @name DataTable.defaults.language.paginate
10892 * Text to use when using the 'full_numbers' type of pagination for the
10893 * button to take the user to the first page.
10898 * @name DataTable.defaults.language.paginate.first
10901 * $(document).ready( function() {
10902 * $('#example').dataTable( {
10905 * "first": "First page"
10915 * Text to use when using the 'full_numbers' type of pagination for the
10916 * button to take the user to the last page.
10921 * @name DataTable.defaults.language.paginate.last
10924 * $(document).ready( function() {
10925 * $('#example').dataTable( {
10928 * "last": "Last page"
10938 * Text to use for the 'next' pagination button (to take the user to the
10944 * @name DataTable.defaults.language.paginate.next
10947 * $(document).ready( function() {
10948 * $('#example').dataTable( {
10951 * "next": "Next page"
10961 * Text to use for the 'previous' pagination button (to take the user to
10962 * the previous page).
10964 * @default Previous
10967 * @name DataTable.defaults.language.paginate.previous
10970 * $(document).ready( function() {
10971 * $('#example').dataTable( {
10974 * "previous": "Previous page"
10980 "sPrevious": "Previous"
10984 * This string is shown in preference to `zeroRecords` when the table is
10985 * empty of data (regardless of filtering). Note that this is an optional
10986 * parameter - if it is not given, the value of `zeroRecords` will be used
10987 * instead (either the default or given value).
10989 * @default No data available in table
10992 * @name DataTable.defaults.language.emptyTable
10995 * $(document).ready( function() {
10996 * $('#example').dataTable( {
10998 * "emptyTable": "No data available in table"
11003 "sEmptyTable": "No data available in table",
11007 * This string gives information to the end user about the information
11008 * that is current on display on the page. The following tokens can be
11009 * used in the string and will be dynamically replaced as the table
11010 * display updates. This tokens can be placed anywhere in the string, or
11011 * removed as needed by the language requires:
11013 * * `\_START\_` - Display index of the first record on the current page
11014 * * `\_END\_` - Display index of the last record on the current page
11015 * * `\_TOTAL\_` - Number of records in the table after filtering
11016 * * `\_MAX\_` - Number of records in the table without filtering
11017 * * `\_PAGE\_` - Current page number
11018 * * `\_PAGES\_` - Total number of pages of data in the table
11021 * @default Showing _START_ to _END_ of _TOTAL_ entries
11024 * @name DataTable.defaults.language.info
11027 * $(document).ready( function() {
11028 * $('#example').dataTable( {
11030 * "info": "Showing page _PAGE_ of _PAGES_"
11035 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11039 * Display information string for when the table is empty. Typically the
11040 * format of this string should match `info`.
11042 * @default Showing 0 to 0 of 0 entries
11045 * @name DataTable.defaults.language.infoEmpty
11048 * $(document).ready( function() {
11049 * $('#example').dataTable( {
11051 * "infoEmpty": "No entries to show"
11056 "sInfoEmpty": "Showing 0 to 0 of 0 entries",
11060 * When a user filters the information in a table, this string is appended
11061 * to the information (`info`) to give an idea of how strong the filtering
11062 * is. The variable _MAX_ is dynamically updated.
11064 * @default (filtered from _MAX_ total entries)
11067 * @name DataTable.defaults.language.infoFiltered
11070 * $(document).ready( function() {
11071 * $('#example').dataTable( {
11073 * "infoFiltered": " - filtering from _MAX_ records"
11078 "sInfoFiltered": "(filtered from _MAX_ total entries)",
11082 * If can be useful to append extra information to the info string at times,
11083 * and this variable does exactly that. This information will be appended to
11084 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11085 * being used) at all times.
11087 * @default <i>Empty string</i>
11090 * @name DataTable.defaults.language.infoPostFix
11093 * $(document).ready( function() {
11094 * $('#example').dataTable( {
11096 * "infoPostFix": "All records shown are derived from real information."
11101 "sInfoPostFix": "",
11105 * This decimal place operator is a little different from the other
11106 * language options since DataTables doesn't output floating point
11107 * numbers, so it won't ever use this for display of a number. Rather,
11108 * what this parameter does is modify the sort methods of the table so
11109 * that numbers which are in a format which has a character other than
11110 * a period (`.`) as a decimal place will be sorted numerically.
11112 * Note that numbers with different decimal places cannot be shown in
11113 * the same table and still be sortable, the table must be consistent.
11114 * However, multiple different tables on the page can use different
11115 * decimal place characters.
11120 * @name DataTable.defaults.language.decimal
11123 * $(document).ready( function() {
11124 * $('#example').dataTable( {
11136 * DataTables has a build in number formatter (`formatNumber`) which is
11137 * used to format large numbers that are used in the table information.
11138 * By default a comma is used, but this can be trivially changed to any
11139 * character you wish with this parameter.
11144 * @name DataTable.defaults.language.thousands
11147 * $(document).ready( function() {
11148 * $('#example').dataTable( {
11159 * Detail the action that will be taken when the drop down menu for the
11160 * pagination length option is changed. The '_MENU_' variable is replaced
11161 * with a default select list of 10, 25, 50 and 100, and can be replaced
11162 * with a custom select box if required.
11164 * @default Show _MENU_ entries
11167 * @name DataTable.defaults.language.lengthMenu
11170 * // Language change only
11171 * $(document).ready( function() {
11172 * $('#example').dataTable( {
11174 * "lengthMenu": "Display _MENU_ records"
11180 * // Language and options change
11181 * $(document).ready( function() {
11182 * $('#example').dataTable( {
11184 * "lengthMenu": 'Display <select>'+
11185 * '<option value="10">10</option>'+
11186 * '<option value="20">20</option>'+
11187 * '<option value="30">30</option>'+
11188 * '<option value="40">40</option>'+
11189 * '<option value="50">50</option>'+
11190 * '<option value="-1">All</option>'+
11191 * '</select> records'
11196 "sLengthMenu": "Show _MENU_ entries",
11200 * When using Ajax sourced data and during the first draw when DataTables is
11201 * gathering the data, this message is shown in an empty row in the table to
11202 * indicate to the end user the the data is being loaded. Note that this
11203 * parameter is not used when loading data by server-side processing, just
11204 * Ajax sourced data with client-side processing.
11206 * @default Loading...
11209 * @name DataTable.defaults.language.loadingRecords
11212 * $(document).ready( function() {
11213 * $('#example').dataTable( {
11215 * "loadingRecords": "Please wait - loading..."
11220 "sLoadingRecords": "Loading...",
11224 * Text which is displayed when the table is processing a user action
11225 * (usually a sort command or similar).
11227 * @default Processing...
11230 * @name DataTable.defaults.language.processing
11233 * $(document).ready( function() {
11234 * $('#example').dataTable( {
11236 * "processing": "DataTables is currently busy"
11241 "sProcessing": "Processing...",
11245 * Details the actions that will be taken when the user types into the
11246 * filtering input text box. The variable "_INPUT_", if used in the string,
11247 * is replaced with the HTML text box for the filtering input allowing
11248 * control over where it appears in the string. If "_INPUT_" is not given
11249 * then the input box is appended to the string automatically.
11254 * @name DataTable.defaults.language.search
11257 * // Input text box will be appended at the end automatically
11258 * $(document).ready( function() {
11259 * $('#example').dataTable( {
11261 * "search": "Filter records:"
11267 * // Specify where the filter should appear
11268 * $(document).ready( function() {
11269 * $('#example').dataTable( {
11271 * "search": "Apply filter _INPUT_ to table"
11276 "sSearch": "Search:",
11280 * Assign a `placeholder` attribute to the search `input` element
11285 * @name DataTable.defaults.language.searchPlaceholder
11287 "sSearchPlaceholder": "",
11291 * All of the language information can be stored in a file on the
11292 * server-side, which DataTables will look up if this parameter is passed.
11293 * It must store the URL of the language file, which is in a JSON format,
11294 * and the object has the same properties as the oLanguage object in the
11295 * initialiser object (i.e. the above parameters). Please refer to one of
11296 * the example language files to see how this works in action.
11298 * @default <i>Empty string - i.e. disabled</i>
11301 * @name DataTable.defaults.language.url
11304 * $(document).ready( function() {
11305 * $('#example').dataTable( {
11307 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11316 * Text shown inside the table records when the is no information to be
11317 * displayed after filtering. `emptyTable` is shown when there is simply no
11318 * information in the table at all (regardless of filtering).
11320 * @default No matching records found
11323 * @name DataTable.defaults.language.zeroRecords
11326 * $(document).ready( function() {
11327 * $('#example').dataTable( {
11329 * "zeroRecords": "No records to display"
11334 "sZeroRecords": "No matching records found"
11339 * This parameter allows you to have define the global filtering state at
11340 * initialisation time. As an object the `search` parameter must be
11341 * defined, but all other parameters are optional. When `regex` is true,
11342 * the search string will be treated as a regular expression, when false
11343 * (default) it will be treated as a straight string. When `smart`
11344 * DataTables will use it's smart filtering methods (to word match at
11345 * any point in the data), when false this will not be done.
11347 * @extends DataTable.models.oSearch
11350 * @name DataTable.defaults.search
11353 * $(document).ready( function() {
11354 * $('#example').dataTable( {
11355 * "search": {"search": "Initial search"}
11359 "oSearch": $.extend( {}, DataTable
.models
.oSearch
),
11363 * __Deprecated__ The functionality provided by this parameter has now been
11364 * superseded by that provided through `ajax`, which should be used instead.
11366 * By default DataTables will look for the property `data` (or `aaData` for
11367 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11368 * source or for server-side processing - this parameter allows that
11369 * property to be changed. You can use Javascript dotted object notation to
11370 * get a data source for multiple levels of nesting.
11375 * @dtopt Server-side
11376 * @name DataTable.defaults.ajaxDataProp
11378 * @deprecated 1.10. Please use `ajax` for this functionality now.
11380 "sAjaxDataProp": "data",
11384 * __Deprecated__ The functionality provided by this parameter has now been
11385 * superseded by that provided through `ajax`, which should be used instead.
11387 * You can instruct DataTables to load data from an external
11388 * source using this parameter (use aData if you want to pass data in you
11389 * already have). Simply provide a url a JSON object can be obtained from.
11394 * @dtopt Server-side
11395 * @name DataTable.defaults.ajaxSource
11397 * @deprecated 1.10. Please use `ajax` for this functionality now.
11399 "sAjaxSource": null,
11403 * This initialisation variable allows you to specify exactly where in the
11404 * DOM you want DataTables to inject the various controls it adds to the page
11405 * (for example you might want the pagination controls at the top of the
11406 * table). DIV elements (with or without a custom class) can also be added to
11407 * aid styling. The follow syntax is used:
11409 * <li>The following options are allowed:
11411 * <li>'l' - Length changing</li>
11412 * <li>'f' - Filtering input</li>
11413 * <li>'t' - The table!</li>
11414 * <li>'i' - Information</li>
11415 * <li>'p' - Pagination</li>
11416 * <li>'r' - pRocessing</li>
11419 * <li>The following constants are allowed:
11421 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11422 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11425 * <li>The following syntax is expected:
11427 * <li>'<' and '>' - div elements</li>
11428 * <li>'<"class" and '>' - div with a class</li>
11429 * <li>'<"#id" and '>' - div with an ID</li>
11434 * <li>'<"wrapper"flipt>'</li>
11435 * <li>'<lf<t>ip>'</li>
11440 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11441 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11444 * @name DataTable.defaults.dom
11447 * $(document).ready( function() {
11448 * $('#example').dataTable( {
11449 * "dom": '<"top"i>rt<"bottom"flp><"clear">'
11457 * Search delay option. This will throttle full table searches that use the
11458 * DataTables provided search input element (it does not effect calls to
11459 * `dt-api search()`, providing a delay before the search is made.
11464 * @name DataTable.defaults.searchDelay
11467 * $(document).ready( function() {
11468 * $('#example').dataTable( {
11469 * "searchDelay": 200
11473 "searchDelay": null,
11477 * DataTables features four different built-in options for the buttons to
11478 * display for pagination control:
11480 * * `simple` - 'Previous' and 'Next' buttons only
11481 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11482 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11483 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11486 * Further methods can be added using {@link DataTable.ext.oPagination}.
11488 * @default simple_numbers
11491 * @name DataTable.defaults.pagingType
11494 * $(document).ready( function() {
11495 * $('#example').dataTable( {
11496 * "pagingType": "full_numbers"
11500 "sPaginationType": "simple_numbers",
11504 * Enable horizontal scrolling. When a table is too wide to fit into a
11505 * certain layout, or you have a large number of columns in the table, you
11506 * can enable x-scrolling to show the table in a viewport, which can be
11507 * scrolled. This property can be `true` which will allow the table to
11508 * scroll horizontally when needed, or any CSS unit, or a number (in which
11509 * case it will be treated as a pixel measurement). Setting as simply `true`
11511 * @type boolean|string
11512 * @default <i>blank string - i.e. disabled</i>
11515 * @name DataTable.defaults.scrollX
11518 * $(document).ready( function() {
11519 * $('#example').dataTable( {
11521 * "scrollCollapse": true
11529 * This property can be used to force a DataTable to use more width than it
11530 * might otherwise do when x-scrolling is enabled. For example if you have a
11531 * table which requires to be well spaced, this parameter is useful for
11532 * "over-sizing" the table, and thus forcing scrolling. This property can by
11533 * any CSS unit, or a number (in which case it will be treated as a pixel
11536 * @default <i>blank string - i.e. disabled</i>
11539 * @name DataTable.defaults.scrollXInner
11542 * $(document).ready( function() {
11543 * $('#example').dataTable( {
11544 * "scrollX": "100%",
11545 * "scrollXInner": "110%"
11549 "sScrollXInner": "",
11553 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11554 * to the given height, and enable scrolling for any data which overflows the
11555 * current viewport. This can be used as an alternative to paging to display
11556 * a lot of data in a small area (although paging and scrolling can both be
11557 * enabled at the same time). This property can be any CSS unit, or a number
11558 * (in which case it will be treated as a pixel measurement).
11560 * @default <i>blank string - i.e. disabled</i>
11563 * @name DataTable.defaults.scrollY
11566 * $(document).ready( function() {
11567 * $('#example').dataTable( {
11568 * "scrollY": "200px",
11569 * "paginate": false
11577 * __Deprecated__ The functionality provided by this parameter has now been
11578 * superseded by that provided through `ajax`, which should be used instead.
11580 * Set the HTTP method that is used to make the Ajax call for server-side
11581 * processing or Ajax sourced data.
11586 * @dtopt Server-side
11587 * @name DataTable.defaults.serverMethod
11589 * @deprecated 1.10. Please use `ajax` for this functionality now.
11591 "sServerMethod": "GET",
11595 * DataTables makes use of renderers when displaying HTML elements for
11596 * a table. These renderers can be added or modified by plug-ins to
11597 * generate suitable mark-up for a site. For example the Bootstrap
11598 * integration plug-in for DataTables uses a paging button renderer to
11599 * display pagination buttons in the mark-up required by Bootstrap.
11601 * For further information about the renderers available see
11602 * DataTable.ext.renderer
11603 * @type string|object
11606 * @name DataTable.defaults.renderer
11612 _fnHungarianMap( DataTable
.defaults
);
11617 * Developer note - See note in model.defaults.js about the use of Hungarian
11618 * notation and camel case.
11622 * Column options that can be given to DataTables at initialisation time.
11625 DataTable
.defaults
.column
= {
11627 * Define which column(s) an order will occur on for this column. This
11628 * allows a column's ordering to take multiple columns into account when
11629 * doing a sort or use the data from a different column. For example first
11630 * name / last name columns make sense to do a multi-column sort over the
11633 * @default null <i>Takes the value of the column index automatically</i>
11635 * @name DataTable.defaults.column.orderData
11639 * // Using `columnDefs`
11640 * $(document).ready( function() {
11641 * $('#example').dataTable( {
11643 * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11644 * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11645 * { "orderData": 2, "targets": [ 2 ] }
11651 * // Using `columns`
11652 * $(document).ready( function() {
11653 * $('#example').dataTable( {
11655 * { "orderData": [ 0, 1 ] },
11656 * { "orderData": [ 1, 0 ] },
11657 * { "orderData": 2 },
11669 * You can control the default ordering direction, and even alter the
11670 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11671 * using this parameter.
11673 * @default [ 'asc', 'desc' ]
11675 * @name DataTable.defaults.column.orderSequence
11679 * // Using `columnDefs`
11680 * $(document).ready( function() {
11681 * $('#example').dataTable( {
11683 * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11684 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11685 * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11691 * // Using `columns`
11692 * $(document).ready( function() {
11693 * $('#example').dataTable( {
11696 * { "orderSequence": [ "asc" ] },
11697 * { "orderSequence": [ "desc", "asc", "asc" ] },
11698 * { "orderSequence": [ "desc" ] },
11704 "asSorting": [ 'asc', 'desc' ],
11708 * Enable or disable filtering on the data in this column.
11712 * @name DataTable.defaults.column.searchable
11716 * // Using `columnDefs`
11717 * $(document).ready( function() {
11718 * $('#example').dataTable( {
11720 * { "searchable": false, "targets": [ 0 ] }
11725 * // Using `columns`
11726 * $(document).ready( function() {
11727 * $('#example').dataTable( {
11729 * { "searchable": false },
11737 "bSearchable": true,
11741 * Enable or disable ordering on this column.
11745 * @name DataTable.defaults.column.orderable
11749 * // Using `columnDefs`
11750 * $(document).ready( function() {
11751 * $('#example').dataTable( {
11753 * { "orderable": false, "targets": [ 0 ] }
11758 * // Using `columns`
11759 * $(document).ready( function() {
11760 * $('#example').dataTable( {
11762 * { "orderable": false },
11774 * Enable or disable the display of this column.
11778 * @name DataTable.defaults.column.visible
11782 * // Using `columnDefs`
11783 * $(document).ready( function() {
11784 * $('#example').dataTable( {
11786 * { "visible": false, "targets": [ 0 ] }
11791 * // Using `columns`
11792 * $(document).ready( function() {
11793 * $('#example').dataTable( {
11795 * { "visible": false },
11807 * Developer definable function that is called whenever a cell is created (Ajax source,
11808 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11809 * allowing you to modify the DOM element (add background colour for example) when the
11810 * element is available.
11812 * @param {element} td The TD node that has been created
11813 * @param {*} cellData The Data for the cell
11814 * @param {array|object} rowData The data for the whole row
11815 * @param {int} row The row index for the aoData data store
11816 * @param {int} col The column index for aoColumns
11818 * @name DataTable.defaults.column.createdCell
11822 * $(document).ready( function() {
11823 * $('#example').dataTable( {
11824 * "columnDefs": [ {
11826 * "createdCell": function (td, cellData, rowData, row, col) {
11827 * if ( cellData == "1.7" ) {
11828 * $(td).css('color', 'blue')
11835 "fnCreatedCell": null,
11839 * This parameter has been replaced by `data` in DataTables to ensure naming
11840 * consistency. `dataProp` can still be used, as there is backwards
11841 * compatibility in DataTables for this option, but it is strongly
11842 * recommended that you use `data` in preference to `dataProp`.
11843 * @name DataTable.defaults.column.dataProp
11848 * This property can be used to read data from any data source property,
11849 * including deeply nested objects / properties. `data` can be given in a
11850 * number of different ways which effect its behaviour:
11852 * * `integer` - treated as an array index for the data source. This is the
11853 * default that DataTables uses (incrementally increased for each column).
11854 * * `string` - read an object property from the data source. There are
11855 * three 'special' options that can be used in the string to alter how
11856 * DataTables reads the data from the source object:
11857 * * `.` - Dotted Javascript notation. Just as you use a `.` in
11858 * Javascript to read from nested objects, so to can the options
11859 * specified in `data`. For example: `browser.version` or
11860 * `browser.name`. If your object parameter name contains a period, use
11861 * `\\` to escape it - i.e. `first\\.name`.
11862 * * `[]` - Array notation. DataTables can automatically combine data
11863 * from and array source, joining the data with the characters provided
11864 * between the two brackets. For example: `name[, ]` would provide a
11865 * comma-space separated list from the source array. If no characters
11866 * are provided between the brackets, the original array source is
11868 * * `()` - Function notation. Adding `()` to the end of a parameter will
11869 * execute a function of the name given. For example: `browser()` for a
11870 * simple function on the data source, `browser.version()` for a
11871 * function in a nested property or even `browser().version` to get an
11872 * object property if the function called returns an object. Note that
11873 * function notation is recommended for use in `render` rather than
11874 * `data` as it is much simpler to use as a renderer.
11875 * * `null` - use the original data source for the row rather than plucking
11876 * data directly from it. This action has effects on two other
11877 * initialisation options:
11878 * * `defaultContent` - When null is given as the `data` option and
11879 * `defaultContent` is specified for the column, the value defined by
11880 * `defaultContent` will be used for the cell.
11881 * * `render` - When null is used for the `data` option and the `render`
11882 * option is specified for the column, the whole data source for the
11883 * row is used for the renderer.
11884 * * `function` - the function given will be executed whenever DataTables
11885 * needs to set or get the data for a cell in the column. The function
11886 * takes three parameters:
11888 * * `{array|object}` The data source for the row
11889 * * `{string}` The type call data requested - this will be 'set' when
11890 * setting data or 'filter', 'display', 'type', 'sort' or undefined
11891 * when gathering data. Note that when `undefined` is given for the
11892 * type DataTables expects to get the raw data for the object back<
11893 * * `{*}` Data to set when the second parameter is 'set'.
11895 * * The return value from the function is not required when 'set' is
11896 * the type of call, but otherwise the return is what will be used
11897 * for the data requested.
11899 * Note that `data` is a getter and setter option. If you just require
11900 * formatting of data for output, you will likely want to use `render` which
11901 * is simply a getter and thus simpler to use.
11903 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
11904 * name change reflects the flexibility of this property and is consistent
11905 * with the naming of mRender. If 'mDataProp' is given, then it will still
11906 * be used by DataTables, as it automatically maps the old name to the new
11909 * @type string|int|function|null
11910 * @default null <i>Use automatically calculated column index</i>
11912 * @name DataTable.defaults.column.data
11916 * // Read table data from objects
11917 * // JSON structure for each row:
11919 * // "engine": {value},
11920 * // "browser": {value},
11921 * // "platform": {value},
11922 * // "version": {value},
11923 * // "grade": {value}
11925 * $(document).ready( function() {
11926 * $('#example').dataTable( {
11927 * "ajaxSource": "sources/objects.txt",
11929 * { "data": "engine" },
11930 * { "data": "browser" },
11931 * { "data": "platform" },
11932 * { "data": "version" },
11933 * { "data": "grade" }
11939 * // Read information from deeply nested objects
11940 * // JSON structure for each row:
11942 * // "engine": {value},
11943 * // "browser": {value},
11945 * // "inner": {value}
11948 * // {value}, {value}
11951 * $(document).ready( function() {
11952 * $('#example').dataTable( {
11953 * "ajaxSource": "sources/deep.txt",
11955 * { "data": "engine" },
11956 * { "data": "browser" },
11957 * { "data": "platform.inner" },
11958 * { "data": "platform.details.0" },
11959 * { "data": "platform.details.1" }
11965 * // Using `data` as a function to provide different information for
11966 * // sorting, filtering and display. In this case, currency (price)
11967 * $(document).ready( function() {
11968 * $('#example').dataTable( {
11969 * "columnDefs": [ {
11970 * "targets": [ 0 ],
11971 * "data": function ( source, type, val ) {
11972 * if (type === 'set') {
11973 * source.price = val;
11974 * // Store the computed dislay and filter values for efficiency
11975 * source.price_display = val=="" ? "" : "$"+numberFormat(val);
11976 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
11979 * else if (type === 'display') {
11980 * return source.price_display;
11982 * else if (type === 'filter') {
11983 * return source.price_filter;
11985 * // 'sort', 'type' and undefined all just use the integer
11986 * return source.price;
11993 * // Using default content
11994 * $(document).ready( function() {
11995 * $('#example').dataTable( {
11996 * "columnDefs": [ {
11997 * "targets": [ 0 ],
11999 * "defaultContent": "Click to edit"
12005 * // Using array notation - outputting a list from an array
12006 * $(document).ready( function() {
12007 * $('#example').dataTable( {
12008 * "columnDefs": [ {
12009 * "targets": [ 0 ],
12010 * "data": "name[, ]"
12020 * This property is the rendering partner to `data` and it is suggested that
12021 * when you want to manipulate data for display (including filtering,
12022 * sorting etc) without altering the underlying data for the table, use this
12023 * property. `render` can be considered to be the the read only companion to
12024 * `data` which is read / write (then as such more complex). Like `data`
12025 * this option can be given in a number of different ways to effect its
12028 * * `integer` - treated as an array index for the data source. This is the
12029 * default that DataTables uses (incrementally increased for each column).
12030 * * `string` - read an object property from the data source. There are
12031 * three 'special' options that can be used in the string to alter how
12032 * DataTables reads the data from the source object:
12033 * * `.` - Dotted Javascript notation. Just as you use a `.` in
12034 * Javascript to read from nested objects, so to can the options
12035 * specified in `data`. For example: `browser.version` or
12036 * `browser.name`. If your object parameter name contains a period, use
12037 * `\\` to escape it - i.e. `first\\.name`.
12038 * * `[]` - Array notation. DataTables can automatically combine data
12039 * from and array source, joining the data with the characters provided
12040 * between the two brackets. For example: `name[, ]` would provide a
12041 * comma-space separated list from the source array. If no characters
12042 * are provided between the brackets, the original array source is
12044 * * `()` - Function notation. Adding `()` to the end of a parameter will
12045 * execute a function of the name given. For example: `browser()` for a
12046 * simple function on the data source, `browser.version()` for a
12047 * function in a nested property or even `browser().version` to get an
12048 * object property if the function called returns an object.
12049 * * `object` - use different data for the different data types requested by
12050 * DataTables ('filter', 'display', 'type' or 'sort'). The property names
12051 * of the object is the data type the property refers to and the value can
12052 * defined using an integer, string or function using the same rules as
12053 * `render` normally does. Note that an `_` option _must_ be specified.
12054 * This is the default value to use if you haven't specified a value for
12055 * the data type requested by DataTables.
12056 * * `function` - the function given will be executed whenever DataTables
12057 * needs to set or get the data for a cell in the column. The function
12058 * takes three parameters:
12060 * * {array|object} The data source for the row (based on `data`)
12061 * * {string} The type call data requested - this will be 'filter',
12062 * 'display', 'type' or 'sort'.
12063 * * {array|object} The full data source for the row (not based on
12066 * * The return value from the function is what will be used for the
12069 * @type string|int|function|object|null
12070 * @default null Use the data source value.
12072 * @name DataTable.defaults.column.render
12076 * // Create a comma separated list from an array of objects
12077 * $(document).ready( function() {
12078 * $('#example').dataTable( {
12079 * "ajaxSource": "sources/deep.txt",
12081 * { "data": "engine" },
12082 * { "data": "browser" },
12084 * "data": "platform",
12085 * "render": "[, ].name"
12092 * // Execute a function to obtain data
12093 * $(document).ready( function() {
12094 * $('#example').dataTable( {
12095 * "columnDefs": [ {
12096 * "targets": [ 0 ],
12097 * "data": null, // Use the full data source object for the renderer's source
12098 * "render": "browserName()"
12104 * // As an object, extracting different data for the different types
12105 * // This would be used with a data source such as:
12106 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12107 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12108 * // (which has both forms) is used for filtering for if a user inputs either format, while
12109 * // the formatted phone number is the one that is shown in the table.
12110 * $(document).ready( function() {
12111 * $('#example').dataTable( {
12112 * "columnDefs": [ {
12113 * "targets": [ 0 ],
12114 * "data": null, // Use the full data source object for the renderer's source
12117 * "filter": "phone_filter",
12118 * "display": "phone_display"
12125 * // Use as a function to create a link from the data source
12126 * $(document).ready( function() {
12127 * $('#example').dataTable( {
12128 * "columnDefs": [ {
12129 * "targets": [ 0 ],
12130 * "data": "download_link",
12131 * "render": function ( data, type, full ) {
12132 * return '<a href="'+data+'">Download</a>';
12142 * Change the cell type created for the column - either TD cells or TH cells. This
12143 * can be useful as TH cells have semantic meaning in the table body, allowing them
12144 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12148 * @name DataTable.defaults.column.cellType
12152 * // Make the first column use TH cells
12153 * $(document).ready( function() {
12154 * $('#example').dataTable( {
12155 * "columnDefs": [ {
12156 * "targets": [ 0 ],
12166 * Class to give to each cell in this column.
12168 * @default <i>Empty string</i>
12170 * @name DataTable.defaults.column.class
12174 * // Using `columnDefs`
12175 * $(document).ready( function() {
12176 * $('#example').dataTable( {
12178 * { "class": "my_class", "targets": [ 0 ] }
12184 * // Using `columns`
12185 * $(document).ready( function() {
12186 * $('#example').dataTable( {
12188 * { "class": "my_class" },
12200 * When DataTables calculates the column widths to assign to each column,
12201 * it finds the longest string in each column and then constructs a
12202 * temporary table and reads the widths from that. The problem with this
12203 * is that "mmm" is much wider then "iiii", but the latter is a longer
12204 * string - thus the calculation can go wrong (doing it properly and putting
12205 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12206 * a "work around" we provide this option. It will append its value to the
12207 * text that is found to be the longest string for the column - i.e. padding.
12208 * Generally you shouldn't need this!
12210 * @default <i>Empty string<i>
12212 * @name DataTable.defaults.column.contentPadding
12216 * // Using `columns`
12217 * $(document).ready( function() {
12218 * $('#example').dataTable( {
12224 * "contentPadding": "mmm"
12230 "sContentPadding": "",
12234 * Allows a default value to be given for a column's data, and will be used
12235 * whenever a null data source is encountered (this can be because `data`
12236 * is set to null, or because the data source itself is null).
12240 * @name DataTable.defaults.column.defaultContent
12244 * // Using `columnDefs`
12245 * $(document).ready( function() {
12246 * $('#example').dataTable( {
12250 * "defaultContent": "Edit",
12251 * "targets": [ -1 ]
12258 * // Using `columns`
12259 * $(document).ready( function() {
12260 * $('#example').dataTable( {
12267 * "defaultContent": "Edit"
12273 "sDefaultContent": null,
12277 * This parameter is only used in DataTables' server-side processing. It can
12278 * be exceptionally useful to know what columns are being displayed on the
12279 * client side, and to map these to database fields. When defined, the names
12280 * also allow DataTables to reorder information from the server if it comes
12281 * back in an unexpected order (i.e. if you switch your columns around on the
12282 * client-side, your server-side code does not also need updating).
12284 * @default <i>Empty string</i>
12286 * @name DataTable.defaults.column.name
12290 * // Using `columnDefs`
12291 * $(document).ready( function() {
12292 * $('#example').dataTable( {
12294 * { "name": "engine", "targets": [ 0 ] },
12295 * { "name": "browser", "targets": [ 1 ] },
12296 * { "name": "platform", "targets": [ 2 ] },
12297 * { "name": "version", "targets": [ 3 ] },
12298 * { "name": "grade", "targets": [ 4 ] }
12304 * // Using `columns`
12305 * $(document).ready( function() {
12306 * $('#example').dataTable( {
12308 * { "name": "engine" },
12309 * { "name": "browser" },
12310 * { "name": "platform" },
12311 * { "name": "version" },
12312 * { "name": "grade" }
12321 * Defines a data source type for the ordering which can be used to read
12322 * real-time information from the table (updating the internally cached
12323 * version) prior to ordering. This allows ordering to occur on user
12324 * editable elements such as form inputs.
12328 * @name DataTable.defaults.column.orderDataType
12332 * // Using `columnDefs`
12333 * $(document).ready( function() {
12334 * $('#example').dataTable( {
12336 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12337 * { "type": "numeric", "targets": [ 3 ] },
12338 * { "orderDataType": "dom-select", "targets": [ 4 ] },
12339 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12345 * // Using `columns`
12346 * $(document).ready( function() {
12347 * $('#example').dataTable( {
12351 * { "orderDataType": "dom-text" },
12352 * { "orderDataType": "dom-text", "type": "numeric" },
12353 * { "orderDataType": "dom-select" },
12354 * { "orderDataType": "dom-checkbox" }
12359 "sSortDataType": "std",
12363 * The title of this column.
12365 * @default null <i>Derived from the 'TH' value for this column in the
12366 * original HTML table.</i>
12368 * @name DataTable.defaults.column.title
12372 * // Using `columnDefs`
12373 * $(document).ready( function() {
12374 * $('#example').dataTable( {
12376 * { "title": "My column title", "targets": [ 0 ] }
12382 * // Using `columns`
12383 * $(document).ready( function() {
12384 * $('#example').dataTable( {
12386 * { "title": "My column title" },
12399 * The type allows you to specify how the data for this column will be
12400 * ordered. Four types (string, numeric, date and html (which will strip
12401 * HTML tags before ordering)) are currently available. Note that only date
12402 * formats understood by Javascript's Date() object will be accepted as type
12403 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12404 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12405 * through plug-ins.
12407 * @default null <i>Auto-detected from raw data</i>
12409 * @name DataTable.defaults.column.type
12413 * // Using `columnDefs`
12414 * $(document).ready( function() {
12415 * $('#example').dataTable( {
12417 * { "type": "html", "targets": [ 0 ] }
12423 * // Using `columns`
12424 * $(document).ready( function() {
12425 * $('#example').dataTable( {
12427 * { "type": "html" },
12440 * Defining the width of the column, this parameter may take any CSS value
12441 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12442 * been given a specific width through this interface ensuring that the table
12443 * remains readable.
12445 * @default null <i>Automatic</i>
12447 * @name DataTable.defaults.column.width
12451 * // Using `columnDefs`
12452 * $(document).ready( function() {
12453 * $('#example').dataTable( {
12455 * { "width": "20%", "targets": [ 0 ] }
12461 * // Using `columns`
12462 * $(document).ready( function() {
12463 * $('#example').dataTable( {
12465 * { "width": "20%" },
12477 _fnHungarianMap( DataTable
.defaults
.column
);
12482 * DataTables settings object - this holds all the information needed for a
12483 * given table, including configuration, data and current application of the
12484 * table options. DataTables does not have a single instance for each DataTable
12485 * with the settings attached to that instance, but rather instances of the
12486 * DataTable "class" are created on-the-fly as needed (typically by a
12487 * $().dataTable() call) and the settings object is then applied to that
12490 * Note that this object is related to {@link DataTable.defaults} but this
12491 * one is the internal data store for DataTables's cache of columns. It should
12492 * NOT be manipulated outside of DataTables. Any configuration should be done
12493 * through the initialisation options.
12495 * @todo Really should attach the settings object to individual instances so we
12496 * don't need to create new instances on each $().dataTable() call (if the
12497 * table already exists). It would also save passing oSettings around and
12498 * into every single function. However, this is a very significant
12499 * architecture change for DataTables and will almost certainly break
12500 * backwards compatibility with older installations. This is something that
12501 * will be done in 2.0.
12503 DataTable
.models
.oSettings
= {
12505 * Primary features of DataTables and their enablement state.
12511 * Flag to say if DataTables should automatically try to calculate the
12512 * optimum table and columns widths (true) or not (false).
12513 * Note that this parameter will be set by the initialisation routine. To
12514 * set a default use {@link DataTable.defaults}.
12517 "bAutoWidth": null,
12520 * Delay the creation of TR and TD elements until they are actually
12521 * needed by a driven page draw. This can give a significant speed
12522 * increase for Ajax source and Javascript source data, but makes no
12523 * difference at all fro DOM and server-side processing tables.
12524 * Note that this parameter will be set by the initialisation routine. To
12525 * set a default use {@link DataTable.defaults}.
12528 "bDeferRender": null,
12531 * Enable filtering on the table or not. Note that if this is disabled
12532 * then there is no filtering at all on the table, including fnFilter.
12533 * To just remove the filtering input use sDom and remove the 'f' option.
12534 * Note that this parameter will be set by the initialisation routine. To
12535 * set a default use {@link DataTable.defaults}.
12541 * Table information element (the 'Showing x of y records' div) enable
12543 * Note that this parameter will be set by the initialisation routine. To
12544 * set a default use {@link DataTable.defaults}.
12550 * Present a user control allowing the end user to change the page size
12551 * when pagination is enabled.
12552 * Note that this parameter will be set by the initialisation routine. To
12553 * set a default use {@link DataTable.defaults}.
12556 "bLengthChange": null,
12559 * Pagination enabled or not. Note that if this is disabled then length
12560 * changing must also be disabled.
12561 * Note that this parameter will be set by the initialisation routine. To
12562 * set a default use {@link DataTable.defaults}.
12568 * Processing indicator enable flag whenever DataTables is enacting a
12569 * user request - typically an Ajax request for server-side processing.
12570 * Note that this parameter will be set by the initialisation routine. To
12571 * set a default use {@link DataTable.defaults}.
12574 "bProcessing": null,
12577 * Server-side processing enabled flag - when enabled DataTables will
12578 * get all data from the server for every draw - there is no filtering,
12579 * sorting or paging done on the client-side.
12580 * Note that this parameter will be set by the initialisation routine. To
12581 * set a default use {@link DataTable.defaults}.
12584 "bServerSide": null,
12587 * Sorting enablement flag.
12588 * Note that this parameter will be set by the initialisation routine. To
12589 * set a default use {@link DataTable.defaults}.
12595 * Multi-column sorting
12596 * Note that this parameter will be set by the initialisation routine. To
12597 * set a default use {@link DataTable.defaults}.
12600 "bSortMulti": null,
12603 * Apply a class to the columns which are being sorted to provide a
12604 * visual highlight or not. This can slow things down when enabled since
12605 * there is a lot of DOM interaction.
12606 * Note that this parameter will be set by the initialisation routine. To
12607 * set a default use {@link DataTable.defaults}.
12610 "bSortClasses": null,
12613 * State saving enablement flag.
12614 * Note that this parameter will be set by the initialisation routine. To
12615 * set a default use {@link DataTable.defaults}.
12623 * Scrolling settings for a table.
12628 * When the table is shorter in height than sScrollY, collapse the
12629 * table container down to the height of the table (when true).
12630 * Note that this parameter will be set by the initialisation routine. To
12631 * set a default use {@link DataTable.defaults}.
12637 * Width of the scrollbar for the web-browser's platform. Calculated
12638 * during table initialisation.
12645 * Viewport width for horizontal scrolling. Horizontal scrolling is
12646 * disabled if an empty string.
12647 * Note that this parameter will be set by the initialisation routine. To
12648 * set a default use {@link DataTable.defaults}.
12654 * Width to expand the table to when using x-scrolling. Typically you
12655 * should not need to use this.
12656 * Note that this parameter will be set by the initialisation routine. To
12657 * set a default use {@link DataTable.defaults}.
12664 * Viewport height for vertical scrolling. Vertical scrolling is disabled
12665 * if an empty string.
12666 * Note that this parameter will be set by the initialisation routine. To
12667 * set a default use {@link DataTable.defaults}.
12674 * Language information for the table.
12676 * @extends DataTable.defaults.oLanguage
12680 * Information callback function. See
12681 * {@link DataTable.defaults.fnInfoCallback}
12685 "fnInfoCallback": null
12689 * Browser support parameters
12694 * Indicate if the browser incorrectly calculates width:100% inside a
12695 * scrolling element (IE6/7)
12699 "bScrollOversize": false,
12702 * Determine if the vertical scrollbar is on the right or left of the
12703 * scrolling container - needed for rtl language layout, although not
12704 * all browsers move the scrollbar (Safari).
12708 "bScrollbarLeft": false
12716 * Array referencing the nodes which are used for the features. The
12717 * parameters of this object match what is allowed by sDom - i.e.
12719 * <li>'l' - Length changing</li>
12720 * <li>'f' - Filtering input</li>
12721 * <li>'t' - The table!</li>
12722 * <li>'i' - Information</li>
12723 * <li>'p' - Pagination</li>
12724 * <li>'r' - pRocessing</li>
12732 * Store data information - see {@link DataTable.models.oRow} for detailed
12740 * Array of indexes which are in the current display (after filtering etc)
12747 * Array of indexes for display - no filtering
12751 "aiDisplayMaster": [],
12754 * Store information about each column that is in use
12761 * Store information about the table's header
12768 * Store information about the table's footer
12775 * Store the applied global search information in case we want to force a
12776 * research or compare the old search to a new one.
12777 * Note that this parameter will be set by the initialisation routine. To
12778 * set a default use {@link DataTable.defaults}.
12780 * @extends DataTable.models.oSearch
12782 "oPreviousSearch": {},
12785 * Store the applied search for each column - see
12786 * {@link DataTable.models.oSearch} for the format that is used for the
12787 * filtering information for each column.
12791 "aoPreSearchCols": [],
12794 * Sorting that is applied to the table. Note that the inner arrays are
12795 * used in the following manner:
12797 * <li>Index 0 - column number</li>
12798 * <li>Index 1 - current sorting direction</li>
12800 * Note that this parameter will be set by the initialisation routine. To
12801 * set a default use {@link DataTable.defaults}.
12803 * @todo These inner arrays should really be objects
12808 * Sorting that is always applied to the table (i.e. prefixed in front of
12810 * Note that this parameter will be set by the initialisation routine. To
12811 * set a default use {@link DataTable.defaults}.
12815 "aaSortingFixed": [],
12818 * Classes to use for the striping of a table.
12819 * Note that this parameter will be set by the initialisation routine. To
12820 * set a default use {@link DataTable.defaults}.
12824 "asStripeClasses": null,
12827 * If restoring a table - we should restore its striping classes as well
12831 "asDestroyStripes": [],
12834 * If restoring a table - we should restore its width
12838 "sDestroyWidth": 0,
12841 * Callback functions array for every time a row is inserted (i.e. on a draw).
12845 "aoRowCallback": [],
12848 * Callback functions for the header on each draw.
12852 "aoHeaderCallback": [],
12855 * Callback function for the footer on each draw.
12859 "aoFooterCallback": [],
12862 * Array of callback functions for draw callback functions
12866 "aoDrawCallback": [],
12869 * Array of callback functions for row created function
12873 "aoRowCreatedCallback": [],
12876 * Callback functions for just before the table is redrawn. A return of
12877 * false will be used to cancel the draw.
12881 "aoPreDrawCallback": [],
12884 * Callback functions for when the table has been initialised.
12888 "aoInitComplete": [],
12892 * Callbacks for modifying the settings to be stored for state saving, prior to
12897 "aoStateSaveParams": [],
12900 * Callbacks for modifying the settings that have been stored for state saving
12901 * prior to using the stored values to restore the state.
12905 "aoStateLoadParams": [],
12908 * Callbacks for operating on the settings object once the saved state has been
12913 "aoStateLoaded": [],
12916 * Cache the table ID for quick access
12918 * @default <i>Empty string</i>
12923 * The TABLE node for the main table
12930 * Permanent ref to the thead element
12937 * Permanent ref to the tfoot element - if it exists
12944 * Permanent ref to the tbody element
12951 * Cache the wrapper node (contains all DataTables controlled elements)
12955 "nTableWrapper": null,
12958 * Indicate if when using server-side processing the loading of data
12959 * should be deferred until the second draw.
12960 * Note that this parameter will be set by the initialisation routine. To
12961 * set a default use {@link DataTable.defaults}.
12965 "bDeferLoading": false,
12968 * Indicate if all required information has been read in
12972 "bInitialised": false,
12975 * Information about open rows. Each object in the array has the parameters
12976 * 'nTr' and 'nParent'
12983 * Dictate the positioning of DataTables' control elements - see
12984 * {@link DataTable.model.oInit.sDom}.
12985 * Note that this parameter will be set by the initialisation routine. To
12986 * set a default use {@link DataTable.defaults}.
12993 * Search delay (in mS)
12997 "searchDelay": null,
13000 * Which type of pagination should be used.
13001 * Note that this parameter will be set by the initialisation routine. To
13002 * set a default use {@link DataTable.defaults}.
13004 * @default two_button
13006 "sPaginationType": "two_button",
13009 * The state duration (for `stateSave`) in seconds.
13010 * Note that this parameter will be set by the initialisation routine. To
13011 * set a default use {@link DataTable.defaults}.
13015 "iStateDuration": 0,
13018 * Array of callback functions for state saving. Each array element is an
13019 * object with the following parameters:
13021 * <li>function:fn - function to call. Takes two parameters, oSettings
13022 * and the JSON string to save that has been thus far created. Returns
13023 * a JSON string to be inserted into a json object
13024 * (i.e. '"param": [ 0, 1, 2]')</li>
13025 * <li>string:sName - name of callback</li>
13033 * Array of callback functions for state loading. Each array element is an
13034 * object with the following parameters:
13036 * <li>function:fn - function to call. Takes two parameters, oSettings
13037 * and the object stored. May return false to cancel state loading</li>
13038 * <li>string:sName - name of callback</li>
13046 * State that was saved. Useful for back reference
13050 "oSavedState": null,
13053 * State that was loaded. Useful for back reference
13057 "oLoadedState": null,
13060 * Source url for AJAX data for the table.
13061 * Note that this parameter will be set by the initialisation routine. To
13062 * set a default use {@link DataTable.defaults}.
13066 "sAjaxSource": null,
13069 * Property from a given object from which to read the table data from. This
13070 * can be an empty string (when not server-side processing), in which case
13071 * it is assumed an an array is given directly.
13072 * Note that this parameter will be set by the initialisation routine. To
13073 * set a default use {@link DataTable.defaults}.
13076 "sAjaxDataProp": null,
13079 * Note if draw should be blocked while getting data
13083 "bAjaxDataGet": true,
13086 * The last jQuery XHR object that was used for server-side data gathering.
13087 * This can be used for working with the XHR information in one of the
13095 * JSON returned from the server in the last Ajax request
13097 * @default undefined
13102 * Data submitted as part of the last Ajax request
13104 * @default undefined
13106 "oAjaxData": undefined,
13109 * Function to get the server-side data.
13110 * Note that this parameter will be set by the initialisation routine. To
13111 * set a default use {@link DataTable.defaults}.
13114 "fnServerData": null,
13117 * Functions which are called prior to sending an Ajax request so extra
13118 * parameters can easily be sent to the server
13122 "aoServerParams": [],
13125 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13127 * Note that this parameter will be set by the initialisation routine. To
13128 * set a default use {@link DataTable.defaults}.
13131 "sServerMethod": null,
13134 * Format numbers for display.
13135 * Note that this parameter will be set by the initialisation routine. To
13136 * set a default use {@link DataTable.defaults}.
13139 "fnFormatNumber": null,
13142 * List of options that can be used for the user selectable length menu.
13143 * Note that this parameter will be set by the initialisation routine. To
13144 * set a default use {@link DataTable.defaults}.
13148 "aLengthMenu": null,
13151 * Counter for the draws that the table does. Also used as a tracker for
13152 * server-side processing
13159 * Indicate if a redraw is being done - useful for Ajax
13166 * Draw index (iDraw) of the last error when parsing the returned data
13173 * Paging display length
13177 "_iDisplayLength": 10,
13180 * Paging start point - aiDisplay index
13184 "_iDisplayStart": 0,
13187 * Server-side processing - number of records in the result set
13188 * (i.e. before filtering), Use fnRecordsTotal rather than
13189 * this property to get the value of the number of records, regardless of
13190 * the server-side processing setting.
13195 "_iRecordsTotal": 0,
13198 * Server-side processing - number of records in the current display set
13199 * (i.e. after filtering). Use fnRecordsDisplay rather than
13200 * this property to get the value of the number of records, regardless of
13201 * the server-side processing setting.
13206 "_iRecordsDisplay": 0,
13209 * Flag to indicate if jQuery UI marking and classes should be used.
13210 * Note that this parameter will be set by the initialisation routine. To
13211 * set a default use {@link DataTable.defaults}.
13217 * The classes to use for the table
13224 * Flag attached to the settings object so you can check in the draw
13225 * callback if filtering has been done in the draw. Deprecated in favour of
13231 "bFiltered": false,
13234 * Flag attached to the settings object so you can check in the draw
13235 * callback if sorting has been done in the draw. Deprecated in favour of
13244 * Indicate that if multiple rows are in the header and there is more than
13245 * one unique cell per column, if the top one (true) or bottom one (false)
13246 * should be used for sorting / title by DataTables.
13247 * Note that this parameter will be set by the initialisation routine. To
13248 * set a default use {@link DataTable.defaults}.
13251 "bSortCellsTop": null,
13254 * Initialisation object that is used for the table
13261 * Destroy callback functions - for plug-ins to attach themselves to the
13262 * destroy so they can clean up markup and events.
13266 "aoDestroyCallback": [],
13270 * Get the number of records in the current record set, before filtering
13273 "fnRecordsTotal": function ()
13275 return _fnDataSource( this ) == 'ssp' ?
13276 this._iRecordsTotal
* 1 :
13277 this.aiDisplayMaster
.length
;
13281 * Get the number of records in the current record set, after filtering
13284 "fnRecordsDisplay": function ()
13286 return _fnDataSource( this ) == 'ssp' ?
13287 this._iRecordsDisplay
* 1 :
13288 this.aiDisplay
.length
;
13292 * Get the display end point - aiDisplay index
13295 "fnDisplayEnd": function ()
13298 len
= this._iDisplayLength
,
13299 start
= this._iDisplayStart
,
13300 calc
= start
+ len
,
13301 records
= this.aiDisplay
.length
,
13302 features
= this.oFeatures
,
13303 paginate
= features
.bPaginate
;
13305 if ( features
.bServerSide
) {
13306 return paginate
=== false || len
=== -1 ?
13308 Math
.min( start
+len
, this._iRecordsDisplay
);
13311 return ! paginate
|| calc
>records
|| len
===-1 ?
13318 * The DataTables object for this table
13325 * Unique identifier for each instance of the DataTables object. If there
13326 * is an ID on the table node, then it takes that value, otherwise an
13327 * incrementing internal counter is used.
13334 * tabindex attribute value that is added to DataTables control elements, allowing
13335 * keyboard navigation of the table and its controls.
13340 * DIV container for the footer scrolling table if scrolling
13342 "nScrollHead": null,
13345 * DIV container for the footer scrolling table if scrolling
13347 "nScrollFoot": null,
13350 * Last applied sort
13357 * Stored plug-in instances
13365 * Extension object for DataTables that is used to provide all extension
13368 * Note that the `DataTable.ext` object is available through
13369 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13370 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13372 * @extends DataTable.models.ext
13377 * DataTables extensions
13379 * This namespace acts as a collection area for plug-ins that can be used to
13380 * extend DataTables capabilities. Indeed many of the build in methods
13381 * use this method to provide their own capabilities (sorting methods for
13384 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13389 DataTable
.ext
= _ext
= {
13391 * Element class names
13402 * How should DataTables report an error. Can take the value 'alert' or
13412 * Feature plug-ins.
13414 * This is an array of objects which describe the feature plug-ins that are
13415 * available to DataTables. These feature plug-ins are then available for
13416 * use through the `dom` initialisation option.
13418 * Each feature plug-in is described by an object which must have the
13419 * following properties:
13421 * * `fnInit` - function that is used to initialise the plug-in,
13422 * * `cFeature` - a character so the feature can be enabled by the `dom`
13423 * instillation option. This is case sensitive.
13425 * The `fnInit` function has the following input parameters:
13427 * 1. `{object}` DataTables settings object: see
13428 * {@link DataTable.models.oSettings}
13430 * And the following return is expected:
13432 * * {node|null} The element which contains your feature. Note that the
13433 * return may also be void if your plug-in does not require to inject any
13434 * DOM elements into DataTables control (`dom`) - for example this might
13435 * be useful when developing a plug-in which allows table control via
13441 * $.fn.dataTable.ext.features.push( {
13442 * "fnInit": function( oSettings ) {
13443 * return new TableTools( { "oDTSettings": oSettings } );
13454 * This method of searching is complimentary to the default type based
13455 * searching, and a lot more comprehensive as it allows you complete control
13456 * over the searching logic. Each element in this array is a function
13457 * (parameters described below) that is called for every row in the table,
13458 * and your logic decides if it should be included in the searching data set
13461 * Searching functions have the following input parameters:
13463 * 1. `{object}` DataTables settings object: see
13464 * {@link DataTable.models.oSettings}
13465 * 2. `{array|object}` Data for the row to be processed (same as the
13466 * original format that was passed in as the data source, or an array
13467 * from a DOM data source
13468 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13469 * can be useful to retrieve the `TR` element if you need DOM interaction.
13471 * And the following return is expected:
13473 * * {boolean} Include the row in the searched result set (true) or not
13476 * Note that as with the main search ability in DataTables, technically this
13477 * is "filtering", since it is subtractive. However, for consistency in
13478 * naming we call it searching here.
13484 * // The following example shows custom search being applied to the
13485 * // fourth column (i.e. the data[3] index) based on two input values
13486 * // from the end-user, matching the data in a certain range.
13487 * $.fn.dataTable.ext.search.push(
13488 * function( settings, data, dataIndex ) {
13489 * var min = document.getElementById('min').value * 1;
13490 * var max = document.getElementById('max').value * 1;
13491 * var version = data[3] == "-" ? 0 : data[3]*1;
13493 * if ( min == "" && max == "" ) {
13496 * else if ( min == "" && version < max ) {
13499 * else if ( min < version && "" == max ) {
13502 * else if ( min < version && version < max ) {
13513 * Internal functions, exposed for used in plug-ins.
13515 * Please note that you should not need to use the internal methods for
13516 * anything other than a plug-in (and even then, try to avoid if possible).
13517 * The internal function may change between releases.
13526 * Legacy configuration options. Enable and disable legacy options that
13527 * are available in DataTables.
13533 * Enable / disable DataTables 1.9 compatible server-side processing
13544 * Pagination plug-in methods.
13546 * Each entry in this object is a function and defines which buttons should
13547 * be shown by the pagination rendering method that is used for the table:
13548 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13549 * buttons are displayed in the document, while the functions here tell it
13550 * what buttons to display. This is done by returning an array of button
13551 * descriptions (what each button will do).
13553 * Pagination types (the four built in options and any additional plug-in
13554 * options defined here) can be used through the `paginationType`
13555 * initialisation parameter.
13557 * The functions defined take two parameters:
13559 * 1. `{int} page` The current page index
13560 * 2. `{int} pages` The number of pages in the table
13562 * Each function is expected to return an array where each element of the
13563 * array can be one of:
13565 * * `first` - Jump to first page when activated
13566 * * `last` - Jump to last page when activated
13567 * * `previous` - Show previous page when activated
13568 * * `next` - Show next page when activated
13569 * * `{int}` - Show page of the index given
13570 * * `{array}` - A nested array containing the above elements to add a
13571 * containing 'DIV' element (might be useful for styling).
13573 * Note that DataTables v1.9- used this object slightly differently whereby
13574 * an object with two functions would be defined for each plug-in. That
13575 * ability is still supported by DataTables 1.10+ to provide backwards
13576 * compatibility, but this option of use is now decremented and no longer
13577 * documented in DataTables 1.10+.
13583 * // Show previous, next and current page buttons only
13584 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13585 * return [ 'previous', page, 'next' ];
13598 * Ordering plug-ins - custom data source
13600 * The extension options for ordering of data available here is complimentary
13601 * to the default type based ordering that DataTables typically uses. It
13602 * allows much greater control over the the data that is being used to
13603 * order a column, but is necessarily therefore more complex.
13605 * This type of ordering is useful if you want to do ordering based on data
13606 * live from the DOM (for example the contents of an 'input' element) rather
13607 * than just the static string that DataTables knows of.
13609 * The way these plug-ins work is that you create an array of the values you
13610 * wish to be ordering for the column in question and then return that
13611 * array. The data in the array much be in the index order of the rows in
13612 * the table (not the currently ordering order!). Which order data gathering
13613 * function is run here depends on the `dt-init columns.orderDataType`
13614 * parameter that is used for the column (if any).
13616 * The functions defined take two parameters:
13618 * 1. `{object}` DataTables settings object: see
13619 * {@link DataTable.models.oSettings}
13620 * 2. `{int}` Target column index
13622 * Each function is expected to return an array:
13624 * * `{array}` Data for the column to be ordering upon
13629 * // Ordering using `input` node values
13630 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
13632 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13633 * return $('input', td).val();
13641 * Type based plug-ins.
13643 * Each column in DataTables has a type assigned to it, either by automatic
13644 * detection or by direct assignment using the `type` option for the column.
13645 * The type of a column will effect how it is ordering and search (plug-ins
13646 * can also make use of the column type if required).
13652 * Type detection functions.
13654 * The functions defined in this object are used to automatically detect
13655 * a column's type, making initialisation of DataTables super easy, even
13656 * when complex data is in the table.
13658 * The functions defined take two parameters:
13660 * 1. `{*}` Data from the column cell to be analysed
13661 * 2. `{settings}` DataTables settings object. This can be used to
13662 * perform context specific type detection - for example detection
13663 * based on language settings such as using a comma for a decimal
13664 * place. Generally speaking the options from the settings will not
13667 * Each function is expected to return:
13669 * * `{string|null}` Data type detected, or null if unknown (and thus
13670 * pass it on to the other type detection functions.
13675 * // Currency type detection plug-in:
13676 * $.fn.dataTable.ext.type.detect.push(
13677 * function ( data, settings ) {
13678 * // Check the numeric part
13679 * if ( ! $.isNumeric( data.substring(1) ) ) {
13683 * // Check prefixed by currency
13684 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) {
13685 * return 'currency';
13695 * Type based search formatting.
13697 * The type based searching functions can be used to pre-format the
13698 * data to be search on. For example, it can be used to strip HTML
13699 * tags or to de-format telephone numbers for numeric only searching.
13701 * Note that is a search is not defined for a column of a given type,
13702 * no search formatting will be performed.
13704 * Pre-processing of searching data plug-ins - When you assign the sType
13705 * for a column (or have it automatically detected for you by DataTables
13706 * or a type detection plug-in), you will typically be using this for
13707 * custom sorting, but it can also be used to provide custom searching
13708 * by allowing you to pre-processing the data and returning the data in
13709 * the format that should be searched upon. This is done by adding
13710 * functions this object with a parameter name which matches the sType
13711 * for that target column. This is the corollary of <i>afnSortData</i>
13712 * for searching data.
13714 * The functions defined take a single parameter:
13716 * 1. `{*}` Data from the column cell to be prepared for searching
13718 * Each function is expected to return:
13720 * * `{string|null}` Formatted string that will be used for the searching.
13726 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
13727 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
13734 * Type based ordering.
13736 * The column type tells DataTables what ordering to apply to the table
13737 * when a column is sorted upon. The order for each type that is defined,
13738 * is defined by the functions available in this object.
13740 * Each ordering option can be described by three properties added to
13743 * * `{type}-pre` - Pre-formatting function
13744 * * `{type}-asc` - Ascending order function
13745 * * `{type}-desc` - Descending order function
13747 * All three can be used together, only `{type}-pre` or only
13748 * `{type}-asc` and `{type}-desc` together. It is generally recommended
13749 * that only `{type}-pre` is used, as this provides the optimal
13750 * implementation in terms of speed, although the others are provided
13751 * for compatibility with existing Javascript sort functions.
13753 * `{type}-pre`: Functions defined take a single parameter:
13755 * 1. `{*}` Data from the column cell to be prepared for ordering
13759 * * `{*}` Data to be sorted upon
13761 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
13762 * functions, taking two parameters:
13764 * 1. `{*}` Data to compare to the second parameter
13765 * 2. `{*}` Data to compare to the first parameter
13769 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
13770 * than the second parameter, ===0 if the two parameters are equal and
13771 * >0 if the first parameter should be sorted height than the second
13778 * // Numeric ordering of formatted numbers with a pre-formatter
13779 * $.extend( $.fn.dataTable.ext.type.order, {
13780 * "string-pre": function(x) {
13781 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
13782 * return parseFloat( a );
13787 * // Case-sensitive string ordering, with no pre-formatting method
13788 * $.extend( $.fn.dataTable.ext.order, {
13789 * "string-case-asc": function(x,y) {
13790 * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13792 * "string-case-desc": function(x,y) {
13793 * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13801 * Unique DataTables instance counter
13811 // The following properties are retained for backwards compatiblity only.
13812 // The should not be used in new projects and will be removed in a future
13817 * Version check function.
13819 * @depreciated Since 1.10
13821 fnVersionCheck
: DataTable
.fnVersionCheck
,
13825 * Index for what 'this' index API functions should use
13827 * @deprecated Since v1.10
13833 * jQuery UI class container
13835 * @deprecated Since v1.10
13843 * @deprecated Since v1.10
13845 sVersion
: DataTable
.version
13850 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
13853 afnFiltering
: _ext
.search
,
13854 aTypes
: _ext
.type
.detect
,
13855 ofnSearch
: _ext
.type
.search
,
13856 oSort
: _ext
.type
.order
,
13857 afnSortData
: _ext
.order
,
13858 aoFeatures
: _ext
.feature
,
13859 oApi
: _ext
.internal,
13860 oStdClasses
: _ext
.classes
,
13861 oPagination
: _ext
.pager
13865 $.extend( DataTable
.ext
.classes
, {
13866 "sTable": "dataTable",
13867 "sNoFooter": "no-footer",
13869 /* Paging buttons */
13870 "sPageButton": "paginate_button",
13871 "sPageButtonActive": "current",
13872 "sPageButtonDisabled": "disabled",
13874 /* Striping classes */
13875 "sStripeOdd": "odd",
13876 "sStripeEven": "even",
13879 "sRowEmpty": "dataTables_empty",
13882 "sWrapper": "dataTables_wrapper",
13883 "sFilter": "dataTables_filter",
13884 "sInfo": "dataTables_info",
13885 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
13886 "sLength": "dataTables_length",
13887 "sProcessing": "dataTables_processing",
13890 "sSortAsc": "sorting_asc",
13891 "sSortDesc": "sorting_desc",
13892 "sSortable": "sorting", /* Sortable in both directions */
13893 "sSortableAsc": "sorting_asc_disabled",
13894 "sSortableDesc": "sorting_desc_disabled",
13895 "sSortableNone": "sorting_disabled",
13896 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
13899 "sFilterInput": "",
13902 "sLengthSelect": "",
13905 "sScrollWrapper": "dataTables_scroll",
13906 "sScrollHead": "dataTables_scrollHead",
13907 "sScrollHeadInner": "dataTables_scrollHeadInner",
13908 "sScrollBody": "dataTables_scrollBody",
13909 "sScrollFoot": "dataTables_scrollFoot",
13910 "sScrollFootInner": "dataTables_scrollFootInner",
13918 "sSortJUIDesc": "",
13920 "sSortJUIAscAllowed": "",
13921 "sSortJUIDescAllowed": "",
13922 "sSortJUIWrapper": "",
13931 // Reused strings for better compression. Closure compiler appears to have a
13932 // weird edge case where it is trying to expand strings rather than use the
13933 // variable version. This results in about 200 bytes being added, for very
13934 // little preference benefit since it this run on script load only.
13938 var _stateDefault
= _empty
+ 'ui-state-default';
13939 var _sortIcon
= _empty
+ 'css_right ui-icon ui-icon-';
13940 var _headerFooter
= _empty
+ 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
13942 $.extend( DataTable
.ext
.oJUIClasses
, DataTable
.ext
.classes
, {
13943 /* Full numbers paging buttons */
13944 "sPageButton": "fg-button ui-button "+_stateDefault
,
13945 "sPageButtonActive": "ui-state-disabled",
13946 "sPageButtonDisabled": "ui-state-disabled",
13949 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
13950 "ui-buttonset-multi paging_", /* Note that the type is postfixed */
13953 "sSortAsc": _stateDefault
+" sorting_asc",
13954 "sSortDesc": _stateDefault
+" sorting_desc",
13955 "sSortable": _stateDefault
+" sorting",
13956 "sSortableAsc": _stateDefault
+" sorting_asc_disabled",
13957 "sSortableDesc": _stateDefault
+" sorting_desc_disabled",
13958 "sSortableNone": _stateDefault
+" sorting_disabled",
13959 "sSortJUIAsc": _sortIcon
+"triangle-1-n",
13960 "sSortJUIDesc": _sortIcon
+"triangle-1-s",
13961 "sSortJUI": _sortIcon
+"carat-2-n-s",
13962 "sSortJUIAscAllowed": _sortIcon
+"carat-1-n",
13963 "sSortJUIDescAllowed": _sortIcon
+"carat-1-s",
13964 "sSortJUIWrapper": "DataTables_sort_wrapper",
13965 "sSortIcon": "DataTables_sort_icon",
13968 "sScrollHead": "dataTables_scrollHead "+_stateDefault
,
13969 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault
,
13972 "sHeaderTH": _stateDefault
,
13973 "sFooterTH": _stateDefault
,
13974 "sJUIHeader": _headerFooter
+" ui-corner-tl ui-corner-tr",
13975 "sJUIFooter": _headerFooter
+" ui-corner-bl ui-corner-br"
13982 var extPagination
= DataTable
.ext
.pager
;
13984 function _numbers ( page
, pages
) {
13987 buttons
= extPagination
.numbers_length
,
13988 half
= Math
.floor( buttons
/ 2 ),
13991 if ( pages
<= buttons
) {
13992 numbers
= _range( 0, pages
);
13994 else if ( page
<= half
) {
13995 numbers
= _range( 0, buttons
-2 );
13996 numbers
.push( 'ellipsis' );
13997 numbers
.push( pages
-1 );
13999 else if ( page
>= pages
- 1 - half
) {
14000 numbers
= _range( pages
-(buttons
-2), pages
);
14001 numbers
.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14002 numbers
.splice( 0, 0, 0 );
14005 numbers
= _range( page
-1, page
+2 );
14006 numbers
.push( 'ellipsis' );
14007 numbers
.push( pages
-1 );
14008 numbers
.splice( 0, 0, 'ellipsis' );
14009 numbers
.splice( 0, 0, 0 );
14012 numbers
.DT_el
= 'span';
14017 $.extend( extPagination
, {
14018 simple: function ( page
, pages
) {
14019 return [ 'previous', 'next' ];
14022 full: function ( page
, pages
) {
14023 return [ 'first', 'previous', 'next', 'last' ];
14026 simple_numbers: function ( page
, pages
) {
14027 return [ 'previous', _numbers(page
, pages
), 'next' ];
14030 full_numbers: function ( page
, pages
) {
14031 return [ 'first', 'previous', _numbers(page
, pages
), 'next', 'last' ];
14034 // For testing and plug-ins to use
14035 _numbers
: _numbers
,
14040 $.extend( true, DataTable
.ext
.renderer
, {
14042 _: function ( settings
, host
, idx
, buttons
, page
, pages
) {
14043 var classes
= settings
.oClasses
;
14044 var lang
= settings
.oLanguage
.oPaginate
;
14045 var btnDisplay
, btnClass
, counter
=0;
14047 var attach = function( container
, buttons
) {
14048 var i
, ien
, node
, button
;
14049 var clickHandler = function ( e
) {
14050 _fnPageChange( settings
, e
.data
.action
, true );
14053 for ( i
=0, ien
=buttons
.length
; i
<ien
; i
++ ) {
14054 button
= buttons
[i
];
14056 if ( $.isArray( button
) ) {
14057 var inner
= $( '<'+(button
.DT_el
|| 'div')+'/>' )
14058 .appendTo( container
);
14059 attach( inner
, button
);
14065 switch ( button
) {
14067 container
.append('<span>…</span>');
14071 btnDisplay
= lang
.sFirst
;
14072 btnClass
= button
+ (page
> 0 ?
14073 '' : ' '+classes
.sPageButtonDisabled
);
14077 btnDisplay
= lang
.sPrevious
;
14078 btnClass
= button
+ (page
> 0 ?
14079 '' : ' '+classes
.sPageButtonDisabled
);
14083 btnDisplay
= lang
.sNext
;
14084 btnClass
= button
+ (page
< pages
-1 ?
14085 '' : ' '+classes
.sPageButtonDisabled
);
14089 btnDisplay
= lang
.sLast
;
14090 btnClass
= button
+ (page
< pages
-1 ?
14091 '' : ' '+classes
.sPageButtonDisabled
);
14095 btnDisplay
= button
+ 1;
14096 btnClass
= page
=== button
?
14097 classes
.sPageButtonActive
: '';
14101 if ( btnDisplay
) {
14103 'class': classes
.sPageButton
+' '+btnClass
,
14104 'aria-controls': settings
.sTableId
,
14105 'data-dt-idx': counter
,
14106 'tabindex': settings
.iTabIndex
,
14107 'id': idx
=== 0 && typeof button
=== 'string' ?
14108 settings
.sTableId
+'_'+ button
:
14111 .html( btnDisplay
)
14112 .appendTo( container
);
14115 node
, {action
: button
}, clickHandler
14124 // IE9 throws an 'unknown error' if document.activeElement is used
14125 // inside an iframe or frame. Try / catch the error. Not good for
14126 // accessibility, but neither are frames.
14128 // Because this approach is destroying and recreating the paging
14129 // elements, focus is lost on the select button which is bad for
14130 // accessibility. So we want to restore focus once the draw has
14132 var activeEl
= $(document
.activeElement
).data('dt-idx');
14134 attach( $(host
).empty(), buttons
);
14136 if ( activeEl
!== null ) {
14137 $(host
).find( '[data-dt-idx='+activeEl
+']' ).focus();
14147 var __numericReplace = function ( d
, decimalPlace
, re1
, re2
) {
14148 if ( d
!== 0 && (!d
|| d
=== '-') ) {
14152 // If a decimal place other than `.` is used, it needs to be given to the
14153 // function so we can detect it and replace with a `.` which is the only
14154 // decimal place Javascript recognises - it is not locale aware.
14155 if ( decimalPlace
) {
14156 d
= _numToDecimal( d
, decimalPlace
);
14161 d
= d
.replace( re1
, '' );
14165 d
= d
.replace( re2
, '' );
14173 // Add the numeric 'deformatting' functions for sorting. This is done in a
14174 // function to provide an easy ability for the language options to add
14175 // additional methods if a non-period decimal place is used.
14176 function _addNumericSort ( decimalPlace
) {
14180 "num": function ( d
) {
14181 return __numericReplace( d
, decimalPlace
);
14184 // Formatted numbers
14185 "num-fmt": function ( d
) {
14186 return __numericReplace( d
, decimalPlace
, _re_formatted_numeric
);
14190 "html-num": function ( d
) {
14191 return __numericReplace( d
, decimalPlace
, _re_html
);
14194 // HTML numeric, formatted
14195 "html-num-fmt": function ( d
) {
14196 return __numericReplace( d
, decimalPlace
, _re_html
, _re_formatted_numeric
);
14199 function ( key
, fn
) {
14200 _ext
.type
.order
[ key
+decimalPlace
+'-pre' ] = fn
;
14206 // Default sort methods
14207 $.extend( _ext
.type
.order
, {
14209 "date-pre": function ( d
) {
14210 return Date
.parse( d
) || 0;
14214 "html-pre": function ( a
) {
14218 a
.replace( /<.*?>/g, "" ).toLowerCase() :
14223 "string-pre": function ( a
) {
14224 // This is a little complex, but faster than always calling toString,
14225 // http://jsperf.com/tostring-v-check
14228 typeof a
=== 'string' ?
14235 // string-asc and -desc are retained only for compatibility with the old
14237 "string-asc": function ( x
, y
) {
14238 return ((x
< y
) ? -1 : ((x
> y
) ? 1 : 0));
14241 "string-desc": function ( x
, y
) {
14242 return ((x
< y
) ? 1 : ((x
> y
) ? -1 : 0));
14247 // Numeric sorting types - order doesn't matter here
14248 _addNumericSort( '' );
14251 // Built in type detection. See model.ext.aTypes for information about
14252 // what is required from this methods.
14253 $.extend( DataTable
.ext
.type
.detect
, [
14254 // Plain numbers - first since V8 detects some plain numbers as dates
14255 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14256 function ( d
, settings
)
14258 var decimal = settings
.oLanguage
.sDecimal
;
14259 return _isNumber( d
, decimal ) ? 'num'+decimal : null;
14262 // Dates (only those recognised by the browser's Date.parse)
14263 function ( d
, settings
)
14265 // V8 will remove any unknown characters at the start and end of the
14266 // expression, leading to false matches such as `$245.12` or `10%` being
14267 // a valid date. See forum thread 18941 for detail.
14268 if ( d
&& !(d
instanceof Date
) && ( ! _re_date_start
.test(d
) || ! _re_date_end
.test(d
) ) ) {
14271 var parsed
= Date
.parse(d
);
14272 return (parsed
!== null && !isNaN(parsed
)) || _empty(d
) ? 'date' : null;
14275 // Formatted numbers
14276 function ( d
, settings
)
14278 var decimal = settings
.oLanguage
.sDecimal
;
14279 return _isNumber( d
, decimal, true ) ? 'num-fmt'+decimal : null;
14283 function ( d
, settings
)
14285 var decimal = settings
.oLanguage
.sDecimal
;
14286 return _htmlNumeric( d
, decimal ) ? 'html-num'+decimal : null;
14289 // HTML numeric, formatted
14290 function ( d
, settings
)
14292 var decimal = settings
.oLanguage
.sDecimal
;
14293 return _htmlNumeric( d
, decimal, true ) ? 'html-num-fmt'+decimal : null;
14296 // HTML (this is strict checking - there must be html)
14297 function ( d
, settings
)
14299 return _empty( d
) || (typeof d
=== 'string' && d
.indexOf('<') !== -1) ?
14306 // Filter formatting functions. See model.ext.ofnSearch for information about
14307 // what is required from these methods.
14310 $.extend( DataTable
.ext
.type
.search
, {
14311 html: function ( data
) {
14312 return _empty(data
) ?
14314 typeof data
=== 'string' ?
14316 .replace( _re_new_lines
, " " )
14317 .replace( _re_html
, "" ) :
14321 string: function ( data
) {
14322 return _empty(data
) ?
14324 typeof data
=== 'string' ?
14325 data
.replace( _re_new_lines
, " " ) :
14332 $.extend( true, DataTable
.ext
.renderer
, {
14334 _: function ( settings
, cell
, column
, classes
) {
14335 // No additional mark-up required
14336 // Attach a sort listener to update on sort - note that using the
14337 // `DT` namespace will allow the event to be removed automatically
14338 // on destroy, while the `dt` namespaced event is the one we are
14340 $(settings
.nTable
).on( 'order.dt.DT', function ( e
, ctx
, sorting
, columns
) {
14341 if ( settings
!== ctx
) { // need to check this this is the host
14342 return; // table, not a nested one
14345 var colIdx
= column
.idx
;
14349 column
.sSortingClass
+' '+
14350 classes
.sSortAsc
+' '+
14353 .addClass( columns
[ colIdx
] == 'asc' ?
14354 classes
.sSortAsc
: columns
[ colIdx
] == 'desc' ?
14355 classes
.sSortDesc
:
14356 column
.sSortingClass
14361 jqueryui: function ( settings
, cell
, column
, classes
) {
14363 .addClass( classes
.sSortJUIWrapper
)
14364 .append( cell
.contents() )
14365 .append( $('<span/>')
14366 .addClass( classes
.sSortIcon
+' '+column
.sSortingClassJUI
)
14370 // Attach a sort listener to update on sort
14371 $(settings
.nTable
).on( 'order.dt.DT', function ( e
, ctx
, sorting
, columns
) {
14372 if ( settings
!== ctx
) {
14376 var colIdx
= column
.idx
;
14379 .removeClass( classes
.sSortAsc
+" "+classes
.sSortDesc
)
14380 .addClass( columns
[ colIdx
] == 'asc' ?
14381 classes
.sSortAsc
: columns
[ colIdx
] == 'desc' ?
14382 classes
.sSortDesc
:
14383 column
.sSortingClass
14387 .find( 'span.'+classes
.sSortIcon
)
14389 classes
.sSortJUIAsc
+" "+
14390 classes
.sSortJUIDesc
+" "+
14391 classes
.sSortJUI
+" "+
14392 classes
.sSortJUIAscAllowed
+" "+
14393 classes
.sSortJUIDescAllowed
14395 .addClass( columns
[ colIdx
] == 'asc' ?
14396 classes
.sSortJUIAsc
: columns
[ colIdx
] == 'desc' ?
14397 classes
.sSortJUIDesc
:
14398 column
.sSortingClassJUI
14406 * Public helper functions. These aren't used internally by DataTables, or
14407 * called by any of the options passed into DataTables, but they can be used
14408 * externally by developers working with DataTables. They are helper functions
14409 * to make working with DataTables a little bit easier.
14413 * Helpers for `columns.render`.
14415 * The options defined here can be used with the `columns.render` initialisation
14416 * option to provide a display renderer. The following functions are defined:
14418 * * `number` - Will format numeric data (defined by `columns.data`) for
14419 * display, retaining the original unformatted data for sorting and filtering.
14420 * It takes 4 parameters:
14421 * * `string` - Thousands grouping separator
14422 * * `string` - Decimal point indicator
14423 * * `integer` - Number of decimal points to show
14424 * * `string` (optional) - Prefix.
14427 * // Column definition using the number renderer
14430 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14435 DataTable
.render
= {
14436 number: function ( thousands
, decimal, precision
, prefix
) {
14438 display: function ( d
) {
14439 var negative
= d
< 0 ? '-' : '';
14440 d
= Math
.abs( parseFloat( d
) );
14442 var intPart
= parseInt( d
, 10 );
14443 var floatPart
= precision
?
14444 decimal+(d
- intPart
).toFixed( precision
).substring( 2 ):
14447 return negative
+ (prefix
||'') +
14448 intPart
.toString().replace(
14449 /\B(?=(\d{3})+(?!\d))/g, thousands
14459 * This is really a good bit rubbish this method of exposing the internal methods
14460 * publicly... - To be fixed in 2.0 using methods on the prototype
14465 * Create a wrapper function for exporting an internal functions to an external API.
14466 * @param {string} fn API function name
14467 * @returns {function} wrapped function
14468 * @memberof DataTable#internal
14470 function _fnExternApiFunc (fn
)
14472 return function() {
14473 var args
= [_fnSettingsFromNode( this[DataTable
.ext
.iApiIndex
] )].concat(
14474 Array
.prototype.slice
.call(arguments
)
14476 return DataTable
.ext
.internal[fn
].apply( this, args
);
14482 * Reference to internal functions for use by plug-in developers. Note that
14483 * these methods are references to internal functions and are considered to be
14484 * private. If you use these methods, be aware that they are liable to change
14485 * between versions.
14488 $.extend( DataTable
.ext
.internal, {
14489 _fnExternApiFunc
: _fnExternApiFunc
,
14490 _fnBuildAjax
: _fnBuildAjax
,
14491 _fnAjaxUpdate
: _fnAjaxUpdate
,
14492 _fnAjaxParameters
: _fnAjaxParameters
,
14493 _fnAjaxUpdateDraw
: _fnAjaxUpdateDraw
,
14494 _fnAjaxDataSrc
: _fnAjaxDataSrc
,
14495 _fnAddColumn
: _fnAddColumn
,
14496 _fnColumnOptions
: _fnColumnOptions
,
14497 _fnAdjustColumnSizing
: _fnAdjustColumnSizing
,
14498 _fnVisibleToColumnIndex
: _fnVisibleToColumnIndex
,
14499 _fnColumnIndexToVisible
: _fnColumnIndexToVisible
,
14500 _fnVisbleColumns
: _fnVisbleColumns
,
14501 _fnGetColumns
: _fnGetColumns
,
14502 _fnColumnTypes
: _fnColumnTypes
,
14503 _fnApplyColumnDefs
: _fnApplyColumnDefs
,
14504 _fnHungarianMap
: _fnHungarianMap
,
14505 _fnCamelToHungarian
: _fnCamelToHungarian
,
14506 _fnLanguageCompat
: _fnLanguageCompat
,
14507 _fnBrowserDetect
: _fnBrowserDetect
,
14508 _fnAddData
: _fnAddData
,
14509 _fnAddTr
: _fnAddTr
,
14510 _fnNodeToDataIndex
: _fnNodeToDataIndex
,
14511 _fnNodeToColumnIndex
: _fnNodeToColumnIndex
,
14512 _fnGetCellData
: _fnGetCellData
,
14513 _fnSetCellData
: _fnSetCellData
,
14514 _fnSplitObjNotation
: _fnSplitObjNotation
,
14515 _fnGetObjectDataFn
: _fnGetObjectDataFn
,
14516 _fnSetObjectDataFn
: _fnSetObjectDataFn
,
14517 _fnGetDataMaster
: _fnGetDataMaster
,
14518 _fnClearTable
: _fnClearTable
,
14519 _fnDeleteIndex
: _fnDeleteIndex
,
14520 _fnInvalidateRow
: _fnInvalidateRow
,
14521 _fnGetRowElements
: _fnGetRowElements
,
14522 _fnCreateTr
: _fnCreateTr
,
14523 _fnBuildHead
: _fnBuildHead
,
14524 _fnDrawHead
: _fnDrawHead
,
14526 _fnReDraw
: _fnReDraw
,
14527 _fnAddOptionsHtml
: _fnAddOptionsHtml
,
14528 _fnDetectHeader
: _fnDetectHeader
,
14529 _fnGetUniqueThs
: _fnGetUniqueThs
,
14530 _fnFeatureHtmlFilter
: _fnFeatureHtmlFilter
,
14531 _fnFilterComplete
: _fnFilterComplete
,
14532 _fnFilterCustom
: _fnFilterCustom
,
14533 _fnFilterColumn
: _fnFilterColumn
,
14534 _fnFilter
: _fnFilter
,
14535 _fnFilterCreateSearch
: _fnFilterCreateSearch
,
14536 _fnEscapeRegex
: _fnEscapeRegex
,
14537 _fnFilterData
: _fnFilterData
,
14538 _fnFeatureHtmlInfo
: _fnFeatureHtmlInfo
,
14539 _fnUpdateInfo
: _fnUpdateInfo
,
14540 _fnInfoMacros
: _fnInfoMacros
,
14541 _fnInitialise
: _fnInitialise
,
14542 _fnInitComplete
: _fnInitComplete
,
14543 _fnLengthChange
: _fnLengthChange
,
14544 _fnFeatureHtmlLength
: _fnFeatureHtmlLength
,
14545 _fnFeatureHtmlPaginate
: _fnFeatureHtmlPaginate
,
14546 _fnPageChange
: _fnPageChange
,
14547 _fnFeatureHtmlProcessing
: _fnFeatureHtmlProcessing
,
14548 _fnProcessingDisplay
: _fnProcessingDisplay
,
14549 _fnFeatureHtmlTable
: _fnFeatureHtmlTable
,
14550 _fnScrollDraw
: _fnScrollDraw
,
14551 _fnApplyToChildren
: _fnApplyToChildren
,
14552 _fnCalculateColumnWidths
: _fnCalculateColumnWidths
,
14553 _fnThrottle
: _fnThrottle
,
14554 _fnConvertToWidth
: _fnConvertToWidth
,
14555 _fnScrollingWidthAdjust
: _fnScrollingWidthAdjust
,
14556 _fnGetWidestNode
: _fnGetWidestNode
,
14557 _fnGetMaxLenString
: _fnGetMaxLenString
,
14558 _fnStringToCss
: _fnStringToCss
,
14559 _fnScrollBarWidth
: _fnScrollBarWidth
,
14560 _fnSortFlatten
: _fnSortFlatten
,
14562 _fnSortAria
: _fnSortAria
,
14563 _fnSortListener
: _fnSortListener
,
14564 _fnSortAttachListener
: _fnSortAttachListener
,
14565 _fnSortingClasses
: _fnSortingClasses
,
14566 _fnSortData
: _fnSortData
,
14567 _fnSaveState
: _fnSaveState
,
14568 _fnLoadState
: _fnLoadState
,
14569 _fnSettingsFromNode
: _fnSettingsFromNode
,
14572 _fnBindAction
: _fnBindAction
,
14573 _fnCallbackReg
: _fnCallbackReg
,
14574 _fnCallbackFire
: _fnCallbackFire
,
14575 _fnLengthOverflow
: _fnLengthOverflow
,
14576 _fnRenderer
: _fnRenderer
,
14577 _fnDataSource
: _fnDataSource
,
14578 _fnRowAttributes
: _fnRowAttributes
,
14579 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14580 // in 1.10, so this dead-end function is
14581 // added to prevent errors
14586 $.fn
.dataTable
= DataTable
;
14589 $.fn
.dataTableSettings
= DataTable
.settings
;
14590 $.fn
.dataTableExt
= DataTable
.ext
;
14592 // With a capital `D` we return a DataTables API instance rather than a
14594 $.fn
.DataTable = function ( opts
) {
14595 return $(this).dataTable( opts
).api();
14598 // All properties that are available to $.fn.dataTable should also be
14599 // available on $.fn.DataTable
14600 $.each( DataTable
, function ( prop
, val
) {
14601 $.fn
.DataTable
[ prop
] = val
;
14605 // Information about events fired by DataTables - for documentation.
14607 * Draw event, fired whenever the table is redrawn on the page, at the same
14608 * point as fnDrawCallback. This may be useful for binding events or
14609 * performing calculations when the table is altered at all.
14610 * @name DataTable#draw.dt
14612 * @param {event} e jQuery event object
14613 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14617 * Search event, fired when the searching applied to the table (using the
14618 * built-in global search, or column filters) is altered.
14619 * @name DataTable#search.dt
14621 * @param {event} e jQuery event object
14622 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14626 * Page change event, fired when the paging of the table is altered.
14627 * @name DataTable#page.dt
14629 * @param {event} e jQuery event object
14630 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14634 * Order event, fired when the ordering applied to the table is altered.
14635 * @name DataTable#order.dt
14637 * @param {event} e jQuery event object
14638 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14642 * DataTables initialisation complete event, fired when the table is fully
14643 * drawn, including Ajax data loaded, if Ajax data is required.
14644 * @name DataTable#init.dt
14646 * @param {event} e jQuery event object
14647 * @param {object} oSettings DataTables settings object
14648 * @param {object} json The JSON object request from the server - only
14649 * present if client-side Ajax sourced data is used</li></ol>
14653 * State save event, fired when the table has changed state a new state save
14654 * is required. This event allows modification of the state saving object
14655 * prior to actually doing the save, including addition or other state
14656 * properties (for plug-ins) or modification of a DataTables core property.
14657 * @name DataTable#stateSaveParams.dt
14659 * @param {event} e jQuery event object
14660 * @param {object} oSettings DataTables settings object
14661 * @param {object} json The state information to be saved
14665 * State load event, fired when the table is loading state from the stored
14666 * data, but prior to the settings object being modified by the saved state
14667 * - allowing modification of the saved state is required or loading of
14668 * state for a plug-in.
14669 * @name DataTable#stateLoadParams.dt
14671 * @param {event} e jQuery event object
14672 * @param {object} oSettings DataTables settings object
14673 * @param {object} json The saved state information
14677 * State loaded event, fired when state has been loaded from stored data and
14678 * the settings object has been modified by the loaded data.
14679 * @name DataTable#stateLoaded.dt
14681 * @param {event} e jQuery event object
14682 * @param {object} oSettings DataTables settings object
14683 * @param {object} json The saved state information
14687 * Processing event, fired when DataTables is doing some kind of processing
14688 * (be it, order, searcg or anything else). It can be used to indicate to
14689 * the end user that there is something happening, or that something has
14691 * @name DataTable#processing.dt
14693 * @param {event} e jQuery event object
14694 * @param {object} oSettings DataTables settings object
14695 * @param {boolean} bShow Flag for if DataTables is doing processing or not
14699 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
14700 * request to made to the server for new data. This event is called before
14701 * DataTables processed the returned data, so it can also be used to pre-
14702 * process the data returned from the server, if needed.
14704 * Note that this trigger is called in `fnServerData`, if you override
14705 * `fnServerData` and which to use this event, you need to trigger it in you
14706 * success function.
14707 * @name DataTable#xhr.dt
14709 * @param {event} e jQuery event object
14710 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14711 * @param {object} json JSON returned from the server
14714 * // Use a custom property returned from the server in another DOM element
14715 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14716 * $('#status').html( json.status );
14720 * // Pre-process the data returned from the server
14721 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14722 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
14723 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
14725 * // Note no return - manipulate the data directly in the JSON object.
14730 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
14731 * or passing the bDestroy:true parameter in the initialisation object. This
14732 * can be used to remove bound events, added DOM nodes, etc.
14733 * @name DataTable#destroy.dt
14735 * @param {event} e jQuery event object
14736 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14740 * Page length change event, fired when number of records to show on each
14741 * page (the length) is changed.
14742 * @name DataTable#length.dt
14744 * @param {event} e jQuery event object
14745 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14746 * @param {integer} len New length
14750 * Column sizing has changed.
14751 * @name DataTable#column-sizing.dt
14753 * @param {event} e jQuery event object
14754 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14758 * Column visibility has changed.
14759 * @name DataTable#column-visibility.dt
14761 * @param {event} e jQuery event object
14762 * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14763 * @param {int} column Column index
14764 * @param {bool} vis `false` if column now hidden, or `true` if visible
14767 return $.fn
.dataTable
;
14770 }(window
, document
));