1d array of data - add a single row with the data provided
*
2d array of arrays - add multiple rows in a single call
*
object - data object when using mdata
*
array of objects - multiple data objects when using mdata
*
* @param {bool} [redraw=true] redraw the table or not
* @returns {array} an array of integers, representing the list of indexes in
* aodata ({@link datatable.models.osettings}) that have been added to
* the table.
* @dtopt api
* @deprecated since v1.10
*
* @example
* // global var for counter
* var gicount = 2;
*
* $(document).ready(function() {
* $('#example').datatable();
* } );
*
* function fnclickaddrow() {
* $('#example').datatable().fnadddata( [
* gicount+".1",
* gicount+".2",
* gicount+".3",
* gicount+".4" ]
* );
*
* gicount++;
* }
*/
this.fnadddata = function( data, redraw )
{
var api = this.api( true );
/* check if we want to add multiple rows or not */
var rows = $.isarray(data) && ( $.isarray(data[0]) || $.isplainobject(data[0]) ) ?
api.rows.add( data ) :
api.row.add( data );
if ( redraw === undefined || redraw ) {
api.draw();
}
return rows.flatten().toarray();
};
/**
* this function will make datatables recalculate the column sizes, based on the data
* contained in the table and the sizes applied to the columns (in the dom, css or
* through the swidth parameter). this can be useful when the width of the table's
* parent element changes (for example a window resize).
* @param {boolean} [bredraw=true] redraw the table or not, you will typically want to
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable( {
* "sscrolly": "200px",
* "bpaginate": false
* } );
*
* $(window).on('resize', function () {
* otable.fnadjustcolumnsizing();
* } );
* } );
*/
this.fnadjustcolumnsizing = function ( bredraw )
{
var api = this.api( true ).columns.adjust();
var settings = api.settings()[0];
var scroll = settings.oscroll;
if ( bredraw === undefined || bredraw ) {
api.draw( false );
}
else if ( scroll.sx !== "" || scroll.sy !== "" ) {
/* if not redrawing, but scrolling, we want to apply the new column sizes anyway */
_fnscrolldraw( settings );
}
};
/**
* quickly and simply clear a table
* @param {bool} [bredraw=true] redraw the table or not
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // immediately 'nuke' the current rows (perhaps waiting for an ajax callback...)
* otable.fncleartable();
* } );
*/
this.fncleartable = function( bredraw )
{
var api = this.api( true ).clear();
if ( bredraw === undefined || bredraw ) {
api.draw();
}
};
/**
* the exact opposite of 'opening' a row, this function will close any rows which
* are currently 'open'.
* @param {node} ntr the table row to 'close'
* @returns {int} 0 on success, or 1 if failed (can't find the row)
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable;
*
* // 'open' an information row when a row is clicked on
* $('#example tbody tr').click( function () {
* if ( otable.fnisopen(this) ) {
* otable.fnclose( this );
* } else {
* otable.fnopen( this, "temporary row opened", "info_row" );
* }
* } );
*
* otable = $('#example').datatable();
* } );
*/
this.fnclose = function( ntr )
{
this.api( true ).row( ntr ).child.hide();
};
/**
* remove a row for the table
* @param {mixed} target the index of the row from aodata to be deleted, or
* the tr element you want to delete
* @param {function|null} [callback] callback function
* @param {bool} [redraw=true] redraw the table or not
* @returns {array} the row that was deleted
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // immediately remove the first row
* otable.fndeleterow( 0 );
* } );
*/
this.fndeleterow = function( target, callback, redraw )
{
var api = this.api( true );
var rows = api.rows( target );
var settings = rows.settings()[0];
var data = settings.aodata[ rows[0][0] ];
rows.remove();
if ( callback ) {
callback.call( this, settings, data );
}
if ( redraw === undefined || redraw ) {
api.draw();
}
return data;
};
/**
* restore the table to it's original state in the dom by removing all of datatables
* enhancements, alterations to the dom structure of the table and event listeners.
* @param {boolean} [remove=false] completely remove the table from the dom
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* // this example is fairly pointless in reality, but shows how fndestroy can be used
* var otable = $('#example').datatable();
* otable.fndestroy();
* } );
*/
this.fndestroy = function ( remove )
{
this.api( true ).destroy( remove );
};
/**
* redraw the table
* @param {bool} [complete=true] re-filter and resort (if enabled) the table before the draw.
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // re-draw the table - you wouldn't want to do it here, but it's an example :-)
* otable.fndraw();
* } );
*/
this.fndraw = function( complete )
{
// note that this isn't an exact match to the old call to _fndraw - it takes
// into account the new data, but can hold position.
this.api( true ).draw( complete );
};
/**
* filter the input based on data
* @param {string} sinput string to filter the table on
* @param {int|null} [icolumn] column to limit filtering to
* @param {bool} [bregex=false] treat as regular expression or not
* @param {bool} [bsmart=true] perform smart filtering or not
* @param {bool} [bshowglobal=true] show the input global filter in it's input box(es)
* @param {bool} [bcaseinsensitive=true] do case-insensitive matching (true) or not (false)
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // sometime later - filter...
* otable.fnfilter( 'test string' );
* } );
*/
this.fnfilter = function( sinput, icolumn, bregex, bsmart, bshowglobal, bcaseinsensitive )
{
var api = this.api( true );
if ( icolumn === null || icolumn === undefined ) {
api.search( sinput, bregex, bsmart, bcaseinsensitive );
}
else {
api.column( icolumn ).search( sinput, bregex, bsmart, bcaseinsensitive );
}
api.draw();
};
/**
* get the data for the whole table, an individual row or an individual cell based on the
* provided parameters.
* @param {int|node} [src] a tr row node, td/th cell node or an integer. if given as
* a tr node then the data source for the whole row will be returned. if given as a
* td/th cell node then icol will be automatically calculated and the data for the
* cell returned. if given as an integer, then this is treated as the aodata internal
* data index for the row (see fngetposition) and the data for that row used.
* @param {int} [col] optional column index that you want the data of.
* @returns {array|object|string} if mrow is undefined, then the data for all rows is
* returned. if mrow is defined, just data for that row, and is icol is
* defined, only data for the designated cell is returned.
* @dtopt api
* @deprecated since v1.10
*
* @example
* // row data
* $(document).ready(function() {
* otable = $('#example').datatable();
*
* otable.$('tr').click( function () {
* var data = otable.fngetdata( this );
* // ... do something with the array / object of data for the row
* } );
* } );
*
* @example
* // individual cell data
* $(document).ready(function() {
* otable = $('#example').datatable();
*
* otable.$('td').click( function () {
* var sdata = otable.fngetdata( this );
* alert( 'the cell clicked on had the value of '+sdata );
* } );
* } );
*/
this.fngetdata = function( src, col )
{
var api = this.api( true );
if ( src !== undefined ) {
var type = src.nodename ? src.nodename.tolowercase() : '';
return col !== undefined || type == 'td' || type == 'th' ?
api.cell( src, col ).data() :
api.row( src ).data() || null;
}
return api.data().toarray();
};
/**
* get an array of the tr nodes that are used in the table's body. note that you will
* typically want to use the '$' api method in preference to this as it is more
* flexible.
* @param {int} [irow] optional row index for the tr element you want
* @returns {array|node} if irow is undefined, returns an array of all tr elements
* in the table's body, or irow is defined, just the tr element requested.
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // get the nodes from the table
* var nnodes = otable.fngetnodes( );
* } );
*/
this.fngetnodes = function( irow )
{
var api = this.api( true );
return irow !== undefined ?
api.row( irow ).node() :
api.rows().nodes().flatten().toarray();
};
/**
* get the array indexes of a particular cell from it's dom element
* and column index including hidden columns
* @param {node} node this can either be a tr, td or th in the table's body
* @returns {int} if nnode is given as a tr, then a single index is returned, or
* if given as a cell, an array of [row index, column index (visible),
* column index (all)] is given.
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* $('#example tbody td').click( function () {
* // get the position of the current data from the node
* var apos = otable.fngetposition( this );
*
* // get the data array for this row
* var adata = otable.fngetdata( apos[0] );
*
* // update the data array and return the value
* adata[ apos[1] ] = 'clicked';
* this.innerhtml = 'clicked';
* } );
*
* // init datatables
* otable = $('#example').datatable();
* } );
*/
this.fngetposition = function( node )
{
var api = this.api( true );
var nodename = node.nodename.touppercase();
if ( nodename == 'tr' ) {
return api.row( node ).index();
}
else if ( nodename == 'td' || nodename == 'th' ) {
var cell = api.cell( node ).index();
return [
cell.row,
cell.columnvisible,
cell.column
];
}
return null;
};
/**
* check to see if a row is 'open' or not.
* @param {node} ntr the table row to check
* @returns {boolean} true if the row is currently open, false otherwise
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable;
*
* // 'open' an information row when a row is clicked on
* $('#example tbody tr').click( function () {
* if ( otable.fnisopen(this) ) {
* otable.fnclose( this );
* } else {
* otable.fnopen( this, "temporary row opened", "info_row" );
* }
* } );
*
* otable = $('#example').datatable();
* } );
*/
this.fnisopen = function( ntr )
{
return this.api( true ).row( ntr ).child.isshown();
};
/**
* this function will place a new row directly after a row which is currently
* on display on the page, with the html contents that is passed into the
* function. this can be used, for example, to ask for confirmation that a
* particular record should be deleted.
* @param {node} ntr the table row to 'open'
* @param {string|node|jquery} mhtml the html to put into the row
* @param {string} sclass class to give the new td cell
* @returns {node} the row opened. note that if the table row passed in as the
* first parameter, is not found in the table, this method will silently
* return.
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable;
*
* // 'open' an information row when a row is clicked on
* $('#example tbody tr').click( function () {
* if ( otable.fnisopen(this) ) {
* otable.fnclose( this );
* } else {
* otable.fnopen( this, "temporary row opened", "info_row" );
* }
* } );
*
* otable = $('#example').datatable();
* } );
*/
this.fnopen = function( ntr, mhtml, sclass )
{
return this.api( true )
.row( ntr )
.child( mhtml, sclass )
.show()
.child()[0];
};
/**
* change the pagination - provides the internal logic for pagination in a simple api
* function. with this function you can have a datatables table go to the next,
* previous, first or last pages.
* @param {string|int} maction paging action to take: "first", "previous", "next" or "last"
* or page number to jump to (integer), note that page 0 is the first page.
* @param {bool} [bredraw=true] redraw the table or not
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
* otable.fnpagechange( 'next' );
* } );
*/
this.fnpagechange = function ( maction, bredraw )
{
var api = this.api( true ).page( maction );
if ( bredraw === undefined || bredraw ) {
api.draw(false);
}
};
/**
* show a particular column
* @param {int} icol the column whose display should be changed
* @param {bool} bshow show (true) or hide (false) the column
* @param {bool} [bredraw=true] redraw the table or not
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // hide the second column after initialisation
* otable.fnsetcolumnvis( 1, false );
* } );
*/
this.fnsetcolumnvis = function ( icol, bshow, bredraw )
{
var api = this.api( true ).column( icol ).visible( bshow );
if ( bredraw === undefined || bredraw ) {
api.columns.adjust().draw();
}
};
/**
* get the settings for a particular table for external manipulation
* @returns {object} datatables settings object. see
* {@link datatable.models.osettings}
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
* var osettings = otable.fnsettings();
*
* // show an example parameter from the settings
* alert( osettings._idisplaystart );
* } );
*/
this.fnsettings = function()
{
return _fnsettingsfromnode( this[_ext.iapiindex] );
};
/**
* sort the table by a particular column
* @param {int} icol the data index to sort on. note that this will not match the
* 'display index' if you have hidden data entries
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // sort immediately with columns 0 and 1
* otable.fnsort( [ [0,'asc'], [1,'asc'] ] );
* } );
*/
this.fnsort = function( aasort )
{
this.api( true ).order( aasort ).draw();
};
/**
* attach a sort listener to an element for a given column
* @param {node} nnode the element to attach the sort listener to
* @param {int} icolumn the column that a click on this node will sort on
* @param {function} [fncallback] callback function when sort is run
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
*
* // sort on column 1, when 'sorter' is clicked on
* otable.fnsortlistener( document.getelementbyid('sorter'), 1 );
* } );
*/
this.fnsortlistener = function( nnode, icolumn, fncallback )
{
this.api( true ).order.listener( nnode, icolumn, fncallback );
};
/**
* update a table cell or row - this method will accept either a single value to
* update the cell with, an array of values with one element for each column or
* an object in the same format as the original data source. the function is
* self-referencing in order to make the multi column updates easier.
* @param {object|array|string} mdata data to update the cell/row with
* @param {node|int} mrow tr element you want to update or the aodata index
* @param {int} [icolumn] the column to update, give as null or undefined to
* update a whole row.
* @param {bool} [bredraw=true] redraw the table or not
* @param {bool} [baction=true] perform pre-draw actions or not
* @returns {int} 0 on success, 1 on error
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
* otable.fnupdate( 'example update', 0, 0 ); // single cell
* otable.fnupdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // row
* } );
*/
this.fnupdate = function( mdata, mrow, icolumn, bredraw, baction )
{
var api = this.api( true );
if ( icolumn === undefined || icolumn === null ) {
api.row( mrow ).data( mdata );
}
else {
api.cell( mrow, icolumn ).data( mdata );
}
if ( baction === undefined || baction ) {
api.columns.adjust();
}
if ( bredraw === undefined || bredraw ) {
api.draw();
}
return 0;
};
/**
* provide a common method for plug-ins to check the version of datatables being used, in order
* to ensure compatibility.
* @param {string} sversion version string to check for, in the format "x.y.z". note that the
* formats "x" and "x.y" are also acceptable.
* @returns {boolean} true if this version of datatables is greater or equal to the required
* version, or false if this version of datatales is not suitable
* @method
* @dtopt api
* @deprecated since v1.10
*
* @example
* $(document).ready(function() {
* var otable = $('#example').datatable();
* alert( otable.fnversioncheck( '1.9.0' ) );
* } );
*/
this.fnversioncheck = _ext.fnversioncheck;
var _that = this;
var emptyinit = options === undefined;
var len = this.length;
if ( emptyinit ) {
options = {};
}
this.oapi = this.internal = _ext.internal;
// extend with old style plug-in api methods
for ( var fn in datatable.ext.internal ) {
if ( fn ) {
this[fn] = _fnexternapifunc(fn);
}
}
this.each(function() {
// for each initialisation we want to give it a clean initialisation
// object that can be bashed around
var o = {};
var oinit = len > 1 ? // optimisation for single table case
_fnextend( o, options, true ) :
options;
/*global oinit,_that,emptyinit*/
var i=0, ilen, j, jlen, k, klen;
var sid = this.getattribute( 'id' );
var binithandedoff = false;
var defaults = datatable.defaults;
var $this = $(this);
/* sanity check */
if ( this.nodename.tolowercase() != 'table' )
{
_fnlog( null, 0, 'non-table node initialisation ('+this.nodename+')', 2 );
return;
}
/* backwards compatibility for the defaults */
_fncompatopts( defaults );
_fncompatcols( defaults.column );
/* convert the camel-case defaults to hungarian */
_fncameltohungarian( defaults, defaults, true );
_fncameltohungarian( defaults.column, defaults.column, true );
/* setting up the initialisation object */
_fncameltohungarian( defaults, $.extend( oinit, $this.data() ), true );
/* check to see if we are re-initialising a table */
var allsettings = datatable.settings;
for ( i=0, ilen=allsettings.length ; i').appendto($this);
}
osettings.nthead = thead[0];
var tbody = $this.children('tbody');
if ( tbody.length === 0 ) {
tbody = $('').appendto($this);
}
osettings.ntbody = tbody[0];
var tfoot = $this.children('tfoot');
if ( tfoot.length === 0 && captions.length > 0 && (osettings.oscroll.sx !== "" || osettings.oscroll.sy !== "") ) {
// if we are a scrolling table, and no footer has been given, then we need to create
// a tfoot element for the caption element to be appended to
tfoot = $('').appendto($this);
}
if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
$this.addclass( oclasses.snofooter );
}
else if ( tfoot.length > 0 ) {
osettings.ntfoot = tfoot[0];
_fndetectheader( osettings.aofooter, osettings.ntfoot );
}
/* check if there is data passing into the constructor */
if ( oinit.aadata ) {
for ( i=0 ; i/g;
// this is not strict iso8601 - date.parse() is quite lax, although
// implementations differ between browsers.
var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([t ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
// escape regular expression special characters
var _re_escape_regex = new regexp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
// http://en.wikipedia.org/wiki/foreign_exchange_market
// - \u20bd - russian ruble.
// - \u20a9 - south korean won
// - \u20ba - turkish lira
// - \u20b9 - indian rupee
// - r - brazil (r$) and south africa
// - fr - swiss franc
// - kr - swedish krona, norwegian krone and danish krone
// - \u2009 is thin space and \u202f is narrow no-break space, both used in many
// - ƀ - bitcoin
// - ξ - ethereum
// standards as thousands separators.
var _re_formatted_numeric = /[',$£€¥%\u2009\u202f\u20bd\u20a9\u20barfkƀξ]/gi;
var _empty = function ( d ) {
return !d || d === true || d === '-' ? true : false;
};
var _intval = function ( s ) {
var integer = parseint( s, 10 );
return !isnan(integer) && isfinite(s) ? integer : null;
};
// convert from a formatted number with characters other than `.` as the
// decimal place, to a javascript number
var _numtodecimal = function ( num, decimalpoint ) {
// cache created regular expressions for speed as this function is called often
if ( ! _re_dic[ decimalpoint ] ) {
_re_dic[ decimalpoint ] = new regexp( _fnescaperegex( decimalpoint ), 'g' );
}
return typeof num === 'string' && decimalpoint !== '.' ?
num.replace( /\./g, '' ).replace( _re_dic[ decimalpoint ], '.' ) :
num;
};
var _isnumber = function ( d, decimalpoint, formatted ) {
var strtype = typeof d === 'string';
// if empty return immediately so there must be a number if it is a
// formatted string (this stops the string "k", or "kr", etc being detected
// as a formatted number for currency
if ( _empty( d ) ) {
return true;
}
if ( decimalpoint && strtype ) {
d = _numtodecimal( d, decimalpoint );
}
if ( formatted && strtype ) {
d = d.replace( _re_formatted_numeric, '' );
}
return !isnan( parsefloat(d) ) && isfinite( d );
};
// a string without html in it can be considered to be html still
var _ishtml = function ( d ) {
return _empty( d ) || typeof d === 'string';
};
var _htmlnumeric = function ( d, decimalpoint, formatted ) {
if ( _empty( d ) ) {
return true;
}
var html = _ishtml( d );
return ! html ?
null :
_isnumber( _striphtml( d ), decimalpoint, formatted ) ?
true :
null;
};
var _pluck = function ( a, prop, prop2 ) {
var out = [];
var i=0, ien=a.length;
// could have the test in the loop for slightly smaller code, but speed
// is essential here
if ( prop2 !== undefined ) {
for ( ; i')
.css( {
position: 'fixed',
top: 0,
left: $(window).scrollleft()*-1, // allow for scrolling
height: 1,
width: 1,
overflow: 'hidden'
} )
.append(
$('')
.css( {
position: 'absolute',
top: 1,
left: 1,
width: 100,
overflow: 'scroll'
} )
.append(
$('')
.css( {
width: '100%',
height: 10
} )
)
)
.appendto( 'body' );
var outer = n.children();
var inner = outer.children();
// numbers below, in order, are:
// inner.offsetwidth, inner.clientwidth, outer.offsetwidth, outer.clientwidth
//
// ie6 xp: 100 100 100 83
// ie7 vista: 100 100 100 83
// ie 8+ windows: 83 83 100 83
// evergreen windows: 83 83 100 83
// evergreen mac with scrollbars: 85 85 100 85
// evergreen mac without scrollbars: 100 100 100 100
// get scrollbar width
browser.barwidth = outer[0].offsetwidth - outer[0].clientwidth;
// ie6/7 will oversize a width 100% element inside a scrolling element, to
// include the width of the scrollbar, while other browsers ensure the inner
// element is contained without forcing scrolling
browser.bscrolloversize = inner[0].offsetwidth === 100 && outer[0].clientwidth !== 100;
// in rtl text layout, some browsers (most, but not all) will place the
// scrollbar on the left, rather than the right.
browser.bscrollbarleft = math.round( inner.offset().left ) !== 1;
// ie8- don't provide height and width for getboundingclientrect
browser.bbounding = n[0].getboundingclientrect().width ? true : false;
n.remove();
}
$.extend( settings.obrowser, datatable.__browser );
settings.oscroll.ibarwidth = datatable.__browser.barwidth;
}
/**
* array.prototype reduce[right] method, used for browsers which don't support
* js 1.6. done this way to reduce code size, since we iterate either way
* @param {object} settings datatables settings object
* @memberof datatable#oapi
*/
function _fnreduce ( that, fn, init, start, end, inc )
{
var
i = start,
value,
isset = false;
if ( init !== undefined ) {
value = init;
isset = true;
}
while ( i !== end ) {
if ( ! that.hasownproperty(i) ) {
continue;
}
value = isset ?
fn( value, that[i], i, that ) :
that[i];
isset = true;
i += inc;
}
return value;
}
/**
* add a column to the list used for the table with default values
* @param {object} osettings datatables settings object
* @param {node} nth the th element for this column
* @memberof datatable#oapi
*/
function _fnaddcolumn( osettings, nth )
{
// add column to aocolumns array
var odefaults = datatable.defaults.column;
var icol = osettings.aocolumns.length;
var ocol = $.extend( {}, datatable.models.ocolumn, odefaults, {
"nth": nth ? nth : document.createelement('th'),
"stitle": odefaults.stitle ? odefaults.stitle : nth ? nth.innerhtml : '',
"adatasort": odefaults.adatasort ? odefaults.adatasort : [icol],
"mdata": odefaults.mdata ? odefaults.mdata : icol,
idx: icol
} );
osettings.aocolumns.push( ocol );
// add search object for column specific search. note that the `searchcols[ icol ]`
// passed into extend can be undefined. this allows the user to give a default
// with only some of the parameters defined, and also not give a default
var searchcols = osettings.aopresearchcols;
searchcols[ icol ] = $.extend( {}, datatable.models.osearch, searchcols[ icol ] );
// use the default column options function to initialise classes etc
_fncolumnoptions( osettings, icol, $(nth).data() );
}
/**
* apply options for a column
* @param {object} osettings datatables settings object
* @param {int} icol column index to consider
* @param {object} ooptions object with stype, bvisible and bsearchable etc
* @memberof datatable#oapi
*/
function _fncolumnoptions( osettings, icol, ooptions )
{
var ocol = osettings.aocolumns[ icol ];
var oclasses = osettings.oclasses;
var th = $(ocol.nth);
// try to get width information from the dom. we can't get it from css
// as we'd need to parse the css stylesheet. `width` option can override
if ( ! ocol.swidthorig ) {
// width attribute
ocol.swidthorig = th.attr('width') || null;
// style attribute
var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
if ( t ) {
ocol.swidthorig = t[1];
}
}
/* user specified column options */
if ( ooptions !== undefined && ooptions !== null )
{
// backwards compatibility
_fncompatcols( ooptions );
// map camel case parameters to their hungarian counterparts
_fncameltohungarian( datatable.defaults.column, ooptions, true );
/* backwards compatibility for mdataprop */
if ( ooptions.mdataprop !== undefined && !ooptions.mdata )
{
ooptions.mdata = ooptions.mdataprop;
}
if ( ooptions.stype )
{
ocol._smanualtype = ooptions.stype;
}
// `class` is a reserved word in javascript, so we need to provide
// the ability to use a valid name for the camel case input
if ( ooptions.classname && ! ooptions.sclass )
{
ooptions.sclass = ooptions.classname;
}
if ( ooptions.sclass ) {
th.addclass( ooptions.sclass );
}
$.extend( ocol, ooptions );
_fnmap( ocol, ooptions, "swidth", "swidthorig" );
/* idatasort to be applied (backwards compatibility), but adatasort will take
* priority if defined
*/
if ( ooptions.idatasort !== undefined )
{
ocol.adatasort = [ ooptions.idatasort ];
}
_fnmap( ocol, ooptions, "adatasort" );
}
/* cache the data get and set functions for speed */
var mdatasrc = ocol.mdata;
var mdata = _fngetobjectdatafn( mdatasrc );
var mrender = ocol.mrender ? _fngetobjectdatafn( ocol.mrender ) : null;
var attrtest = function( src ) {
return typeof src === 'string' && src.indexof('@') !== -1;
};
ocol._battrsrc = $.isplainobject( mdatasrc ) && (
attrtest(mdatasrc.sort) || attrtest(mdatasrc.type) || attrtest(mdatasrc.filter)
);
ocol._setter = null;
ocol.fngetdata = function (rowdata, type, meta) {
var innerdata = mdata( rowdata, type, undefined, meta );
return mrender && type ?
mrender( innerdata, type, rowdata, meta ) :
innerdata;
};
ocol.fnsetdata = function ( rowdata, val, meta ) {
return _fnsetobjectdatafn( mdatasrc )( rowdata, val, meta );
};
// indicate if datatables should read dom data as an object or array
// used in _fngetrowelements
if ( typeof mdatasrc !== 'number' ) {
osettings._rowreadobject = true;
}
/* feature sorting overrides column specific when off */
if ( !osettings.ofeatures.bsort )
{
ocol.bsortable = false;
th.addclass( oclasses.ssortablenone ); // have to add class here as order event isn't called
}
/* check that the class assignment is correct for sorting */
var basc = $.inarray('asc', ocol.assorting) !== -1;
var bdesc = $.inarray('desc', ocol.assorting) !== -1;
if ( !ocol.bsortable || (!basc && !bdesc) )
{
ocol.ssortingclass = oclasses.ssortablenone;
ocol.ssortingclassjui = "";
}
else if ( basc && !bdesc )
{
ocol.ssortingclass = oclasses.ssortableasc;
ocol.ssortingclassjui = oclasses.ssortjuiascallowed;
}
else if ( !basc && bdesc )
{
ocol.ssortingclass = oclasses.ssortabledesc;
ocol.ssortingclassjui = oclasses.ssortjuidescallowed;
}
else
{
ocol.ssortingclass = oclasses.ssortable;
ocol.ssortingclassjui = oclasses.ssortjui;
}
}
/**
* adjust the table column widths for new data. note: you would probably want to
* do a redraw after calling this function!
* @param {object} settings datatables settings object
* @memberof datatable#oapi
*/
function _fnadjustcolumnsizing ( settings )
{
/* not interested in doing column width calculation if auto-width is disabled */
if ( settings.ofeatures.bautowidth !== false )
{
var columns = settings.aocolumns;
_fncalculatecolumnwidths( settings );
for ( var i=0 , ilen=columns.length ; i=0 ; i-- )
{
def = aocoldefs[i];
/* each definition can target multiple columns, as it is an array */
var atargets = def.targets !== undefined ?
def.targets :
def.atargets;
if ( ! $.isarray( atargets ) )
{
atargets = [ atargets ];
}
for ( j=0, jlen=atargets.length ; j= 0 )
{
/* add columns that we don't yet know about */
while( columns.length <= atargets[j] )
{
_fnaddcolumn( osettings );
}
/* integer, basic index */
fn( atargets[j], def );
}
else if ( typeof atargets[j] === 'number' && atargets[j] < 0 )
{
/* negative integer, right to left column counting */
fn( columns.length+atargets[j], def );
}
else if ( typeof atargets[j] === 'string' )
{
/* class name matching on th element */
for ( k=0, klen=columns.length ; k=0 if successful (index of new aodata entry), -1 if failed
* @memberof datatable#oapi
*/
function _fnadddata ( osettings, adatain, ntr, antds )
{
/* create the object for storing information about this new row */
var irow = osettings.aodata.length;
var odata = $.extend( true, {}, datatable.models.orow, {
src: ntr ? 'dom' : 'data',
idx: irow
} );
odata._adata = adatain;
osettings.aodata.push( odata );
/* create the cells */
var ntd, sthistype;
var columns = osettings.aocolumns;
// invalidate the column types as the new data needs to be revalidated
for ( var i=0, ilen=columns.length ; i itarget )
{
a[i]--;
}
}
if ( itargetindex != -1 && splice === undefined )
{
a.splice( itargetindex, 1 );
}
}
/**
* mark cached data as invalid such that a re-read of the data will occur when
* the cached data is next requested. also update from the data source object.
*
* @param {object} settings datatables settings object
* @param {int} rowidx row index to invalidate
* @param {string} [src] source to invalidate from: undefined, 'auto', 'dom'
* or 'data'
* @param {int} [colidx] column index to invalidate. if undefined the whole
* row will be invalidated
* @memberof datatable#oapi
*
* @todo for the modularisation of v1.11 this will need to become a callback, so
* the sort and filter methods can subscribe to it. that will required
* initialisation options for sorting, which is why it is not already baked in
*/
function _fninvalidate( settings, rowidx, src, colidx )
{
var row = settings.aodata[ rowidx ];
var i, ien;
var cellwrite = function ( cell, col ) {
// this is very frustrating, but in ie if you just write directly
// to innerhtml, and elements that are overwritten are gc'ed,
// even if there is a reference to them elsewhere
while ( cell.childnodes.length ) {
cell.removechild( cell.firstchild );
}
cell.innerhtml = _fngetcelldata( settings, rowidx, col, 'display' );
};
// are we reading last data from dom or the data object?
if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
// read the data from the dom
row._adata = _fngetrowelements(
settings, row, colidx, colidx === undefined ? undefined : row._adata
)
.data;
}
else {
// reading from data object, update the dom
var cells = row.ancells;
if ( cells ) {
if ( colidx !== undefined ) {
cellwrite( cells[colidx], colidx );
}
else {
for ( i=0, ien=cells.length ; i').appendto( thead );
}
for ( i=0, ien=columns.length ; itr').attr('role', 'row');
/* deal with the footer - add classes if required */
$(thead).find('>tr>th, >tr>td').addclass( classes.sheaderth );
$(tfoot).find('>tr>th, >tr>td').addclass( classes.sfooterth );
// cache the footer cells. note that we only take the cells from the first
// row in the footer. if there is more than one row the user wants to
// interact with, they need to use the table().foot() method. note also this
// allows cells to be used for multiple columns using colspan
if ( tfoot !== null ) {
var cells = osettings.aofooter[0];
for ( i=0, ien=cells.length ; i=0 ; j-- )
{
if ( !osettings.aocolumns[j].bvisible && !bincludehidden )
{
aolocal[i].splice( j, 1 );
}
}
/* prep the applied array - it needs an element for each row */
aapplied.push( [] );
}
for ( i=0, ilen=aolocal.length ; i= osettings.fnrecordsdisplay() ?
0 :
iinitdisplaystart;
osettings.iinitdisplaystart = -1;
}
var idisplaystart = osettings._idisplaystart;
var idisplayend = osettings.fndisplayend();
/* server-side processing draw intercept */
if ( osettings.bdeferloading )
{
osettings.bdeferloading = false;
osettings.idraw++;
_fnprocessingdisplay( osettings, false );
}
else if ( !bserverside )
{
osettings.idraw++;
}
else if ( !osettings.bdestroying && !_fnajaxupdate( osettings ) )
{
return;
}
if ( aidisplay.length !== 0 )
{
var istart = bserverside ? 0 : idisplaystart;
var iend = bserverside ? osettings.aodata.length : idisplayend;
for ( var j=istart ; j', { 'class': istripes ? asstripeclasses[0] : '' } )
.append( $('
', {
'valign': 'top',
'colspan': _fnvisblecolumns( osettings ),
'class': osettings.oclasses.srowempty
} ).html( szero ) )[0];
}
/* header and footer callbacks */
_fncallbackfire( osettings, 'aoheadercallback', 'header', [ $(osettings.nthead).children('tr')[0],
_fngetdatamaster( osettings ), idisplaystart, idisplayend, aidisplay ] );
_fncallbackfire( osettings, 'aofootercallback', 'footer', [ $(osettings.ntfoot).children('tr')[0],
_fngetdatamaster( osettings ), idisplaystart, idisplayend, aidisplay ] );
var body = $(osettings.ntbody);
body.children().detach();
body.append( $(anrows) );
/* call all required callback functions for the end of a draw */
_fncallbackfire( osettings, 'aodrawcallback', 'draw', [osettings] );
/* draw is complete, sorting and filtering must be as well */
osettings.bsorted = false;
osettings.bfiltered = false;
osettings.bdrawing = false;
}
/**
* redraw the table - taking account of the various features which are enabled
* @param {object} osettings datatables settings object
* @param {boolean} [holdposition] keep the current paging position. by default
* the paging is reset to the first page
* @memberof datatable#oapi
*/
function _fnredraw( settings, holdposition )
{
var
features = settings.ofeatures,
sort = features.bsort,
filter = features.bfilter;
if ( sort ) {
_fnsort( settings );
}
if ( filter ) {
_fnfiltercomplete( settings, settings.oprevioussearch );
}
else {
// no filtering, so we want to just use the display master
settings.aidisplay = settings.aidisplaymaster.slice();
}
if ( holdposition !== true ) {
settings._idisplaystart = 0;
}
// let any modules know about the draw hold position state (used by
// scrolling internally)
settings._drawhold = holdposition;
_fndraw( settings );
settings._drawhold = false;
}
/**
* add the options to the page html for the table
* @param {object} osettings datatables settings object
* @memberof datatable#oapi
*/
function _fnaddoptionshtml ( osettings )
{
var classes = osettings.oclasses;
var table = $(osettings.ntable);
var holding = $('').insertbefore( table ); // holding element for speed
var features = osettings.ofeatures;
// all datatables are wrapped in a div
var insert = $('', {
id: osettings.stableid+'_wrapper',
'class': classes.swrapper + (osettings.ntfoot ? '' : ' '+classes.snofooter)
} );
osettings.nholding = holding[0];
osettings.ntablewrapper = insert[0];
osettings.ntablereinsertbefore = osettings.ntable.nextsibling;
/* loop over the user set positioning and place the elements as needed */
var adom = osettings.sdom.split('');
var featurenode, coption, nnewnode, cnext, sattr, j;
for ( var i=0 ; i')[0];
/* check to see if we should append an id and/or a class name to the container */
cnext = adom[i+1];
if ( cnext == "'" || cnext == '"' )
{
sattr = "";
j = 2;
while ( adom[i+j] != cnext )
{
sattr += adom[i+j];
j++;
}
/* replace jquery ui constants @todo depreciated */
if ( sattr == "h" )
{
sattr = classes.sjuiheader;
}
else if ( sattr == "f" )
{
sattr = classes.sjuifooter;
}
/* the attribute can be in the format of "#id.class", "#id" or "class" this logic
* breaks the string into parts and applies them as needed
*/
if ( sattr.indexof('.') != -1 )
{
var asplit = sattr.split('.');
nnewnode.id = asplit[0].substr(1, asplit[0].length-1);
nnewnode.classname = asplit[1];
}
else if ( sattr.charat(0) == "#" )
{
nnewnode.id = sattr.substr(1, sattr.length-1);
}
else
{
nnewnode.classname = sattr;
}
i += j; /* move along the position array */
}
insert.append( nnewnode );
insert = $(nnewnode);
}
else if ( coption == '>' )
{
/* end container div */
insert = insert.parent();
}
// @todo move options into their own plugins?
else if ( coption == 'l' && features.bpaginate && features.blengthchange )
{
/* length */
featurenode = _fnfeaturehtmllength( osettings );
}
else if ( coption == 'f' && features.bfilter )
{
/* filter */
featurenode = _fnfeaturehtmlfilter( osettings );
}
else if ( coption == 'r' && features.bprocessing )
{
/* processing */
featurenode = _fnfeaturehtmlprocessing( osettings );
}
else if ( coption == 't' )
{
/* table */
featurenode = _fnfeaturehtmltable( osettings );
}
else if ( coption == 'i' && features.binfo )
{
/* info */
featurenode = _fnfeaturehtmlinfo( osettings );
}
else if ( coption == 'p' && features.bpaginate )
{
/* pagination */
featurenode = _fnfeaturehtmlpaginate( osettings );
}
else if ( datatable.ext.feature.length !== 0 )
{
/* plug-in features */
var aofeatures = datatable.ext.feature;
for ( var k=0, klen=aofeatures.length ; k';
var str = language.ssearch;
str = str.match(/_input_/) ?
str.replace('_input_', input) :
str+input;
var filter = $('', {
'id': ! features.f ? tableid+'_filter' : null,
'class': classes.sfilter
} )
.append( $('' ).append( str ) );
var searchfn = function() {
/* update all other filter input elements for the new display */
var n = features.f;
var val = !this.value ? "" : this.value; // mental ie8 fix :-(
/* now do the filter */
if ( val != previoussearch.ssearch ) {
_fnfiltercomplete( settings, {
"ssearch": val,
"bregex": previoussearch.bregex,
"bsmart": previoussearch.bsmart ,
"bcaseinsensitive": previoussearch.bcaseinsensitive
} );
// need to redraw, without resorting
settings._idisplaystart = 0;
_fndraw( settings );
}
};
var searchdelay = settings.searchdelay !== null ?
settings.searchdelay :
_fndatasource( settings ) === 'ssp' ?
400 :
0;
var jqfilter = $('input', filter)
.val( previoussearch.ssearch )
.attr( 'placeholder', language.ssearchplaceholder )
.on(
'keyup.dt search.dt input.dt paste.dt cut.dt',
searchdelay ?
_fnthrottle( searchfn, searchdelay ) :
searchfn
)
.on( 'mouseup', function(e) {
// edge fix! edge 17 does not trigger anything other than mouse events when clicking
// on the clear icon (edge bug 17584515). this is safe in other browsers as `searchfn`
// checks the value to see if it has changed. in other browsers it won't have.
settimeout( function () {
searchfn.call(jqfilter[0]);
}, 10);
} )
.on( 'keypress.dt', function(e) {
/* prevent form submission */
if ( e.keycode == 13 ) {
return false;
}
} )
.attr('aria-controls', tableid);
// update the input elements whenever the table is filtered
$(settings.ntable).on( 'search.dt.dt', function ( ev, s ) {
if ( settings === s ) {
// ie9 throws an 'unknown error' if document.activeelement is used
// inside an iframe or frame...
try {
if ( jqfilter[0] !== document.activeelement ) {
jqfilter.val( previoussearch.ssearch );
}
}
catch ( e ) {}
}
} );
return filter[0];
}
/**
* filter the table using both the global filter and column based filtering
* @param {object} osettings datatables settings object
* @param {object} osearch search information
* @param {int} [iforce] force a research of the master array (1) or not (undefined or 0)
* @memberof datatable#oapi
*/
function _fnfiltercomplete ( osettings, oinput, iforce )
{
var oprevsearch = osettings.oprevioussearch;
var aoprevsearch = osettings.aopresearchcols;
var fnsavefilter = function ( ofilter ) {
/* save the filtering values */
oprevsearch.ssearch = ofilter.ssearch;
oprevsearch.bregex = ofilter.bregex;
oprevsearch.bsmart = ofilter.bsmart;
oprevsearch.bcaseinsensitive = ofilter.bcaseinsensitive;
};
var fnregex = function ( o ) {
// backwards compatibility with the bescaperegex option
return o.bescaperegex !== undefined ? !o.bescaperegex : o.bregex;
};
// resolve any column types that are unknown due to addition or invalidation
// @todo as per sort - can this be moved into an event handler?
_fncolumntypes( osettings );
/* in server-side processing all filtering is done by the server, so no point hanging around here */
if ( _fndatasource( osettings ) != 'ssp' )
{
/* global filter */
_fnfilter( osettings, oinput.ssearch, iforce, fnregex(oinput), oinput.bsmart, oinput.bcaseinsensitive );
fnsavefilter( oinput );
/* now do the individual column filter */
for ( var i=0 ; i input.length ||
input.indexof(prevsearch) !== 0 ||
settings.bsorted // on resort, the display master needs to be
// re-filtered since indexes will have changed
) {
settings.aidisplay = displaymaster.slice();
}
// search the display array
display = settings.aidisplay;
for ( i=0 ; i')[0];
var __filter_div_textcontent = __filter_div.textcontent !== undefined;
// update the filtering data for each row if needed (by invalidation or first run)
function _fnfilterdata ( settings )
{
var columns = settings.aocolumns;
var column;
var i, j, ien, jen, filterdata, celldata, row;
var fomatters = datatable.ext.type.search;
var wasinvalidated = false;
for ( i=0, ien=settings.aodata.length ; i', {
'class': settings.oclasses.sinfo,
'id': ! nodes ? tid+'_info' : null
} );
if ( ! nodes ) {
// update display on each draw
settings.aodrawcallback.push( {
"fn": _fnupdateinfo,
"sname": "information"
} );
n
.attr( 'role', 'status' )
.attr( 'aria-live', 'polite' );
// table is described by our info div
$(settings.ntable).attr( 'aria-describedby', tid+'_info' );
}
return n[0];
}
/**
* update the information elements in the display
* @param {object} settings datatables settings object
* @memberof datatable#oapi
*/
function _fnupdateinfo ( settings )
{
/* show information about the table */
var nodes = settings.aanfeatures.i;
if ( nodes.length === 0 ) {
return;
}
var
lang = settings.olanguage,
start = settings._idisplaystart+1,
end = settings.fndisplayend(),
max = settings.fnrecordstotal(),
total = settings.fnrecordsdisplay(),
out = total ?
lang.sinfo :
lang.sinfoempty;
if ( total !== max ) {
/* record set after filtering */
out += ' ' + lang.sinfofiltered;
}
// convert the macros
out += lang.sinfopostfix;
out = _fninfomacros( settings, out );
var callback = lang.fninfocallback;
if ( callback !== null ) {
out = callback.call( settings.oinstance,
settings, start, end, max, total, out
);
}
$(nodes).html( out );
}
function _fninfomacros ( settings, str )
{
// when infinite scrolling, we are always starting at 1. _idisplaystart is used only
// internally
var
formatter = settings.fnformatnumber,
start = settings._idisplaystart+1,
len = settings._idisplaylength,
vis = settings.fnrecordsdisplay(),
all = len === -1;
return str.
replace(/_start_/g, formatter.call( settings, start ) ).
replace(/_end_/g, formatter.call( settings, settings.fndisplayend() ) ).
replace(/_max_/g, formatter.call( settings, settings.fnrecordstotal() ) ).
replace(/_total_/g, formatter.call( settings, vis ) ).
replace(/_page_/g, formatter.call( settings, all ? 1 : math.ceil( start / len ) ) ).
replace(/_pages_/g, formatter.call( settings, all ? 1 : math.ceil( vis / len ) ) );
}
/**
* draw the table for the first time, adding all required features
* @param {object} settings datatables settings object
* @memberof datatable#oapi
*/
function _fninitialise ( settings )
{
var i, ilen, iajaxstart=settings.iinitdisplaystart;
var columns = settings.aocolumns, column;
var features = settings.ofeatures;
var deferloading = settings.bdeferloading; // value modified by the draw
/* ensure that the table data is fully initialised */
if ( ! settings.binitialised ) {
settimeout( function(){ _fninitialise( settings ); }, 200 );
return;
}
/* show the display html options */
_fnaddoptionshtml( settings );
/* build and draw the header / footer for the table */
_fnbuildhead( settings );
_fndrawhead( settings, settings.aoheader );
_fndrawhead( settings, settings.aofooter );
/* okay to show that something is going on now */
_fnprocessingdisplay( settings, true );
/* calculate sizes for columns */
if ( features.bautowidth ) {
_fncalculatecolumnwidths( settings );
}
for ( i=0, ilen=columns.length ; i', {
'name': tableid+'_length',
'aria-controls': tableid,
'class': classes.slengthselect
} );
for ( var i=0, ien=lengths.length ; i').addclass( classes.slength );
if ( ! settings.aanfeatures.l ) {
div[0].id = tableid+'_length';
}
div.children().append(
settings.olanguage.slengthmenu.replace( '_menu_', select[0].outerhtml )
);
// can't use `select` variable as user might provide their own and the
// reference is broken by the use of outerhtml
$('select', div)
.val( settings._idisplaylength )
.on( 'change.dt', function(e) {
_fnlengthchange( settings, $(this).val() );
_fndraw( settings );
} );
// update node value whenever anything changes the table's length
$(settings.ntable).on( 'length.dt.dt', function (e, s, len) {
if ( settings === s ) {
$('select', div).val( len );
}
} );
return div[0];
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* note that most of the paging logic is done in
* datatable.ext.pager
*/
/**
* generate the node required for default pagination
* @param {object} osettings datatables settings object
* @returns {node} pagination feature node
* @memberof datatable#oapi
*/
function _fnfeaturehtmlpaginate ( settings )
{
var
type = settings.spaginationtype,
plugin = datatable.ext.pager[ type ],
modern = typeof plugin === 'function',
redraw = function( settings ) {
_fndraw( settings );
},
node = $('').addclass( settings.oclasses.spaging + type )[0],
features = settings.aanfeatures;
if ( ! modern ) {
plugin.fninit( settings, node, redraw );
}
/* add a draw callback for the pagination on first instance, to update the paging display */
if ( ! features.p )
{
node.id = settings.stableid+'_paginate';
settings.aodrawcallback.push( {
"fn": function( settings ) {
if ( modern ) {
var
start = settings._idisplaystart,
len = settings._idisplaylength,
visrecords = settings.fnrecordsdisplay(),
all = len === -1,
page = all ? 0 : math.ceil( start / len ),
pages = all ? 1 : math.ceil( visrecords / len ),
buttons = plugin(page, pages),
i, ien;
for ( i=0, ien=features.p.length ; i records )
{
start = 0;
}
}
else if ( action == "first" )
{
start = 0;
}
else if ( action == "previous" )
{
start = len >= 0 ?
start - len :
0;
if ( start < 0 )
{
start = 0;
}
}
else if ( action == "next" )
{
if ( start + len < records )
{
start += len;
}
}
else if ( action == "last" )
{
start = math.floor( (records-1) / len) * len;
}
else
{
_fnlog( settings, 0, "unknown paging action: "+action, 5 );
}
var changed = settings._idisplaystart !== start;
settings._idisplaystart = start;
if ( changed ) {
_fncallbackfire( settings, null, 'page', [settings] );
if ( redraw ) {
_fndraw( settings );
}
}
return changed;
}
/**
* generate the node required for the processing node
* @param {object} settings datatables settings object
* @returns {node} processing element
* @memberof datatable#oapi
*/
function _fnfeaturehtmlprocessing ( settings )
{
return $('', {
'id': ! settings.aanfeatures.r ? settings.stableid+'_processing' : null,
'class': settings.oclasses.sprocessing
} )
.html( settings.olanguage.sprocessing )
.insertbefore( settings.ntable )[0];
}
/**
* display or hide the processing indicator
* @param {object} settings datatables settings object
* @param {bool} show show the processing indicator (true) or not (false)
* @memberof datatable#oapi
*/
function _fnprocessingdisplay ( settings, show )
{
if ( settings.ofeatures.bprocessing ) {
$(settings.aanfeatures.r).css( 'display', show ? 'block' : 'none' );
}
_fncallbackfire( settings, null, 'processing', [settings, show] );
}
/**
* add any control elements for the table - specifically scrolling
* @param {object} settings datatables settings object
* @returns {node} node to add to the dom
* @memberof datatable#oapi
*/
function _fnfeaturehtmltable ( settings )
{
var table = $(settings.ntable);
// add the aria grid role to the table
table.attr( 'role', 'grid' );
// scrolling from here on in
var scroll = settings.oscroll;
if ( scroll.sx === '' && scroll.sy === '' ) {
return settings.ntable;
}
var scrollx = scroll.sx;
var scrolly = scroll.sy;
var classes = settings.oclasses;
var caption = table.children('caption');
var captionside = caption.length ? caption[0]._captionside : null;
var headerclone = $( table[0].clonenode(false) );
var footerclone = $( table[0].clonenode(false) );
var footer = table.children('tfoot');
var _div = '';
var size = function ( s ) {
return !s ? null : _fnstringtocss( s );
};
if ( ! footer.length ) {
footer = null;
}
/*
* the html structure that we want to generate in this function is:
* div - scroller
* div - scroll head
* div - scroll head inner
* table - scroll head table
* thead - thead
* div - scroll body
* table - table (master table)
* thead - thead clone for sizing
* tbody - tbody
* div - scroll foot
* div - scroll foot inner
* table - scroll foot table
* tfoot - tfoot
*/
var scroller = $( _div, { 'class': classes.sscrollwrapper } )
.append(
$(_div, { 'class': classes.sscrollhead } )
.css( {
overflow: 'hidden',
position: 'relative',
border: 0,
width: scrollx ? size(scrollx) : '100%'
} )
.append(
$(_div, { 'class': classes.sscrollheadinner } )
.css( {
'box-sizing': 'content-box',
width: scroll.sxinner || '100%'
} )
.append(
headerclone
.removeattr('id')
.css( 'margin-left', 0 )
.append( captionside === 'top' ? caption : null )
.append(
table.children('thead')
)
)
)
)
.append(
$(_div, { 'class': classes.sscrollbody } )
.css( {
position: 'relative',
overflow: 'auto',
width: size( scrollx )
} )
.append( table )
);
if ( footer ) {
scroller.append(
$(_div, { 'class': classes.sscrollfoot } )
.css( {
overflow: 'hidden',
border: 0,
width: scrollx ? size(scrollx) : '100%'
} )
.append(
$(_div, { 'class': classes.sscrollfootinner } )
.append(
footerclone
.removeattr('id')
.css( 'margin-left', 0 )
.append( captionside === 'bottom' ? caption : null )
.append(
table.children('tfoot')
)
)
)
);
}
var children = scroller.children();
var scrollhead = children[0];
var scrollbody = children[1];
var scrollfoot = footer ? children[2] : null;
// when the body is scrolled, then we also want to scroll the headers
if ( scrollx ) {
$(scrollbody).on( 'scroll.dt', function (e) {
var scrollleft = this.scrollleft;
scrollhead.scrollleft = scrollleft;
if ( footer ) {
scrollfoot.scrollleft = scrollleft;
}
} );
}
$(scrollbody).css('max-height', scrolly);
if (! scroll.bcollapse) {
$(scrollbody).css('height', scrolly);
}
settings.nscrollhead = scrollhead;
settings.nscrollbody = scrollbody;
settings.nscrollfoot = scrollfoot;
// on redraw - align columns
settings.aodrawcallback.push( {
"fn": _fnscrolldraw,
"sname": "scrolling"
} );
return scroller[0];
}
/**
* update the header, footer and body tables for resizing - i.e. column
* alignment.
*
* welcome to the most horrible function datatables. the process that this
* function follows is basically:
* 1. re-create the table inside the scrolling div
* 2. take live measurements from the dom
* 3. apply the measurements to align the columns
* 4. clean up
*
* @param {object} settings datatables settings object
* @memberof datatable#oapi
*/
function _fnscrolldraw ( settings )
{
// given that this is such a monster function, a lot of variables are use
// to try and keep the minimised size as small as possible
var
scroll = settings.oscroll,
scrollx = scroll.sx,
scrollxinner = scroll.sxinner,
scrolly = scroll.sy,
barwidth = scroll.ibarwidth,
divheader = $(settings.nscrollhead),
divheaderstyle = divheader[0].style,
divheaderinner = divheader.children('div'),
divheaderinnerstyle = divheaderinner[0].style,
divheadertable = divheaderinner.children('table'),
divbodyel = settings.nscrollbody,
divbody = $(divbodyel),
divbodystyle = divbodyel.style,
divfooter = $(settings.nscrollfoot),
divfooterinner = divfooter.children('div'),
divfootertable = divfooterinner.children('table'),
header = $(settings.nthead),
table = $(settings.ntable),
tableel = table[0],
tablestyle = tableel.style,
footer = settings.ntfoot ? $(settings.ntfoot) : null,
browser = settings.obrowser,
ie67 = browser.bscrolloversize,
dtheadercells = _pluck( settings.aocolumns, 'nth' ),
headertrgels, footertrgels,
headersrcels, footersrcels,
headercopy, footercopy,
headerwidths=[], footerwidths=[],
headercontent=[], footercontent=[],
idx, correction, sanitywidth,
zeroout = function(nsizer) {
var style = nsizer.style;
style.paddingtop = "0";
style.paddingbottom = "0";
style.bordertopwidth = "0";
style.borderbottomwidth = "0";
style.height = 0;
};
// if the scrollbar visibility has changed from the last draw, we need to
// adjust the column sizes as the table width will have changed to account
// for the scrollbar
var scrollbarvis = divbodyel.scrollheight > divbodyel.clientheight;
if ( settings.scrollbarvis !== scrollbarvis && settings.scrollbarvis !== undefined ) {
settings.scrollbarvis = scrollbarvis;
_fnadjustcolumnsizing( settings );
return; // adjust column sizing will call this function again
}
else {
settings.scrollbarvis = scrollbarvis;
}
/*
* 1. re-create the table inside the scrolling div
*/
// remove the old minimised thead and tfoot elements in the inner table
table.children('thead, tfoot').remove();
if ( footer ) {
footercopy = footer.clone().prependto( table );
footertrgels = footer.find('tr'); // the original tfoot is in its own table and must be sized
footersrcels = footercopy.find('tr');
}
// clone the current header and footer elements and then place it into the inner table
headercopy = header.clone().prependto( table );
headertrgels = header.find('tr'); // original header is in its own table
headersrcels = headercopy.find('tr');
headercopy.find('th, td').removeattr('tabindex');
/*
* 2. take live measurements from the dom - do not alter the dom itself!
*/
// remove old sizing and apply the calculated column widths
// get the unique column headers in the newly created (cloned) header. we want to apply the
// calculated sizes to this header
if ( ! scrollx )
{
divbodystyle.width = '100%';
divheader[0].style.width = '100%';
}
$.each( _fngetuniqueths( settings, headercopy ), function ( i, el ) {
idx = _fnvisibletocolumnindex( settings, i );
el.style.width = settings.aocolumns[idx].swidth;
} );
if ( footer ) {
_fnapplytochildren( function(n) {
n.style.width = "";
}, footersrcels );
}
// size the table as a whole
sanitywidth = table.outerwidth();
if ( scrollx === "" ) {
// no x scrolling
tablestyle.width = "100%";
// ie7 will make the width of the table when 100% include the scrollbar
// - which is shouldn't. when there is a scrollbar we need to take this
// into account.
if ( ie67 && (table.find('tbody').height() > divbodyel.offsetheight ||
divbody.css('overflow-y') == "scroll")
) {
tablestyle.width = _fnstringtocss( table.outerwidth() - barwidth);
}
// recalculate the sanity width
sanitywidth = table.outerwidth();
}
else if ( scrollxinner !== "" ) {
// legacy x scroll inner has been given - use it
tablestyle.width = _fnstringtocss(scrollxinner);
// recalculate the sanity width
sanitywidth = table.outerwidth();
}
// hidden header should have zero height, so remove padding and borders. then
// set the width based on the real headers
// apply all styles in one pass
_fnapplytochildren( zeroout, headersrcels );
// read all widths in next pass
_fnapplytochildren( function(nsizer) {
headercontent.push( nsizer.innerhtml );
headerwidths.push( _fnstringtocss( $(nsizer).css('width') ) );
}, headersrcels );
// apply all widths in final pass
_fnapplytochildren( function(ntosize, i) {
// only apply widths to the datatables detected header cells - this
// prevents complex headers from having contradictory sizes applied
if ( $.inarray( ntosize, dtheadercells ) !== -1 ) {
ntosize.style.width = headerwidths[i];
}
}, headertrgels );
$(headersrcels).height(0);
/* same again with the footer if we have one */
if ( footer )
{
_fnapplytochildren( zeroout, footersrcels );
_fnapplytochildren( function(nsizer) {
footercontent.push( nsizer.innerhtml );
footerwidths.push( _fnstringtocss( $(nsizer).css('width') ) );
}, footersrcels );
_fnapplytochildren( function(ntosize, i) {
ntosize.style.width = footerwidths[i];
}, footertrgels );
$(footersrcels).height(0);
}
/*
* 3. apply the measurements
*/
// "hide" the header and footer that we used for the sizing. we need to keep
// the content of the cell so that the width applied to the header and body
// both match, but we want to hide it completely. we want to also fix their
// width to what they currently are
_fnapplytochildren( function(nsizer, i) {
nsizer.innerhtml = '
';
nsizer.childnodes[0].style.height = "0";
nsizer.childnodes[0].style.overflow = "hidden";
nsizer.style.width = footerwidths[i];
}, footersrcels );
}
// sanity check that the table is of a sensible width. if not then we are going to get
// misalignment - try to prevent this by not allowing the table to shrink below its min width
if ( table.outerwidth() < sanitywidth )
{
// the min width depends upon if we have a vertical scrollbar visible or not */
correction = ((divbodyel.scrollheight > divbodyel.offsetheight ||
divbody.css('overflow-y') == "scroll")) ?
sanitywidth+barwidth :
sanitywidth;
// ie6/7 are a law unto themselves...
if ( ie67 && (divbodyel.scrollheight >
divbodyel.offsetheight || divbody.css('overflow-y') == "scroll")
) {
tablestyle.width = _fnstringtocss( correction-barwidth );
}
// and give the user a warning that we've stopped the table getting too small
if ( scrollx === "" || scrollxinner !== "" ) {
_fnlog( settings, 1, 'possible column misalignment', 6 );
}
}
else
{
correction = '100%';
}
// apply to the container elements
divbodystyle.width = _fnstringtocss( correction );
divheaderstyle.width = _fnstringtocss( correction );
if ( footer ) {
settings.nscrollfoot.style.width = _fnstringtocss( correction );
}
/*
* 4. clean up
*/
if ( ! scrolly ) {
/* ie7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
* the scrollbar height from the visible display, rather than adding it on. we need to
* set the height in order to sort this. don't want to do it in any other browsers.
*/
if ( ie67 ) {
divbodystyle.height = _fnstringtocss( tableel.offsetheight+barwidth );
}
}
/* finally set the width's of the header and footer tables */
var iouterwidth = table.outerwidth();
divheadertable[0].style.width = _fnstringtocss( iouterwidth );
divheaderinnerstyle.width = _fnstringtocss( iouterwidth );
// figure out if there are scrollbar present - if so then we need a the header and footer to
// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
var bscrolling = table.height() > divbodyel.clientheight || divbody.css('overflow-y') == "scroll";
var padding = 'padding' + (browser.bscrollbarleft ? 'left' : 'right' );
divheaderinnerstyle[ padding ] = bscrolling ? barwidth+"px" : "0px";
if ( footer ) {
divfootertable[0].style.width = _fnstringtocss( iouterwidth );
divfooterinner[0].style.width = _fnstringtocss( iouterwidth );
divfooterinner[0].style[padding] = bscrolling ? barwidth+"px" : "0px";
}
// correct dom ordering for colgroup - comes before the thead
table.children('colgroup').insertbefore( table.children('thead') );
/* adjust the position of the header in case we loose the y-scrollbar */
divbody.trigger('scroll');
// if sorting or filtering has occurred, jump the scrolling back to the top
// only if we aren't holding the position
if ( (settings.bsorted || settings.bfiltered) && ! settings._drawhold ) {
divbodyel.scrolltop = 0;
}
}
/**
* apply a given function to the display child nodes of an element array (typically
* td children of tr rows
* @param {function} fn method to apply to the objects
* @param array {nodes} an1 list of elements to look through for display children
* @param array {nodes} an2 another list (identical structure to the first) - optional
* @memberof datatable#oapi
*/
function _fnapplytochildren( fn, an1, an2 )
{
var index=0, i=0, ilen=an1.length;
var nnode1, nnode2;
while ( i < ilen ) {
nnode1 = an1[i].firstchild;
nnode2 = an2 ? an2[i].firstchild : null;
while ( nnode1 ) {
if ( nnode1.nodetype === 1 ) {
if ( an2 ) {
fn( nnode1, nnode2, index );
}
else {
fn( nnode1, index );
}
index++;
}
nnode1 = nnode1.nextsibling;
nnode2 = an2 ? nnode2.nextsibling : null;
}
i++;
}
}
var __re_html_remove = /<.*?>/g;
/**
* calculate the width of columns for the table
* @param {object} osettings datatables settings object
* @memberof datatable#oapi
*/
function _fncalculatecolumnwidths ( osettings )
{
var
table = osettings.ntable,
columns = osettings.aocolumns,
scroll = osettings.oscroll,
scrolly = scroll.sy,
scrollx = scroll.sx,
scrollxinner = scroll.sxinner,
columncount = columns.length,
visiblecolumns = _fngetcolumns( osettings, 'bvisible' ),
headercells = $('th', osettings.nthead),
tablewidthattr = table.getattribute('width'), // from dom element
tablecontainer = table.parentnode,
userinputs = false,
i, column, columnidx, width, outerwidth,
browser = osettings.obrowser,
ie67 = browser.bscrolloversize;
var stylewidth = table.style.width;
if ( stylewidth && stylewidth.indexof('%') !== -1 ) {
tablewidthattr = stylewidth;
}
/* convert any user input sizes into pixel sizes */
for ( i=0 ; i').appendto( tmptable.find('tbody') );
// clone the table header and footer - we can't use the header / footer
// from the cloned table, since if scrolling is active, the table's
// real header and footer are contained in different table tags
tmptable.find('thead, tfoot').remove();
tmptable
.append( $(osettings.nthead).clone() )
.append( $(osettings.ntfoot).clone() );
// remove any assigned widths from the footer (from scrolling)
tmptable.find('tfoot th, tfoot td').css('width', '');
// apply custom sizing to the cloned header
headercells = _fngetuniqueths( osettings, tmptable.find('thead')[0] );
for ( i=0 ; i').css( {
width: column.swidthorig,
margin: 0,
padding: 0,
border: 0,
height: 1
} ) );
}
}
// find the widest cell for each column and put it into the table
if ( osettings.aodata.length ) {
for ( i=0 ; i').css( scrollx || scrolly ?
{
position: 'absolute',
top: 0,
left: 0,
height: 1,
right: 0,
overflow: 'hidden'
} :
{}
)
.append( tmptable )
.appendto( tablecontainer );
// when scrolling (x or y) we want to set the width of the table as
// appropriate. however, when not scrolling leave the table width as it
// is. this results in slightly different, but i think correct behaviour
if ( scrollx && scrollxinner ) {
tmptable.width( scrollxinner );
}
else if ( scrollx ) {
tmptable.css( 'width', 'auto' );
tmptable.removeattr('width');
// if there is no width attribute or style, then allow the table to
// collapse
if ( tmptable.width() < tablecontainer.clientwidth && tablewidthattr ) {
tmptable.width( tablecontainer.clientwidth );
}
}
else if ( scrolly ) {
tmptable.width( tablecontainer.clientwidth );
}
else if ( tablewidthattr ) {
tmptable.width( tablewidthattr );
}
// get the width of each column in the constructed table - we need to
// know the inner width (so it can be assigned to the other table's
// cells) and the outer width so we can calculate the full width of the
// table. this is safe since datatables requires a unique cell for each
// column, but if ever a header can span multiple columns, this will
// need to be modified.
var total = 0;
for ( i=0 ; i')
.css( 'width', _fnstringtocss( width ) )
.appendto( parent || document.body );
var val = n[0].offsetwidth;
n.remove();
return val;
}
/**
* get the widest node
* @param {object} settings datatables settings object
* @param {int} colidx column of interest
* @returns {node} widest table node
* @memberof datatable#oapi
*/
function _fngetwidestnode( settings, colidx )
{
var idx = _fngetmaxlenstring( settings, colidx );
if ( idx < 0 ) {
return null;
}
var data = settings.aodata[ idx ];
return ! data.ntr ? // might not have been created when deferred rendering
$('
').html( _fngetcelldata( settings, idx, colidx, 'display' ) )[0] :
data.ancells[ colidx ];
}
/**
* get the maximum strlen for each data column
* @param {object} settings datatables settings object
* @param {int} colidx column of interest
* @returns {string} max string length for each column
* @memberof datatable#oapi
*/
function _fngetmaxlenstring( settings, colidx )
{
var s, max=-1, maxidx = -1;
for ( var i=0, ien=settings.aodata.length ; i max ) {
max = s.length;
maxidx = i;
}
}
return maxidx;
}
/**
* append a css unit (only if required) to a string
* @param {string} value to css-ify
* @returns {string} value with css unit
* @memberof datatable#oapi
*/
function _fnstringtocss( s )
{
if ( s === null ) {
return '0px';
}
if ( typeof s == 'number' ) {
return s < 0 ?
'0px' :
s+'px';
}
// check it has a unit character already
return s.match(/\d$/) ?
s+'px' :
s;
}
function _fnsortflatten ( settings )
{
var
i, ilen, k, klen,
asort = [],
aiorig = [],
aocolumns = settings.aocolumns,
adatasort, icol, stype, srccol,
fixed = settings.aasortingfixed,
fixedobj = $.isplainobject( fixed ),
nestedsort = [],
add = function ( a ) {
if ( a.length && ! $.isarray( a[0] ) ) {
// 1d array
nestedsort.push( a );
}
else {
// 2d array
$.merge( nestedsort, a );
}
};
// build the sort array, with pre-fix and post-fix options if they have been
// specified
if ( $.isarray( fixed ) ) {
add( fixed );
}
if ( fixedobj && fixed.pre ) {
add( fixed.pre );
}
add( settings.aasorting );
if (fixedobj && fixed.post ) {
add( fixed.post );
}
for ( i=0 ; iy ? 1 : 0;
if ( test !== 0 ) {
return sort.dir === 'asc' ? test : -test;
}
}
x = aiorig[a];
y = aiorig[b];
return xy ? 1 : 0;
} );
}
else {
// depreciated - remove in 1.11 (providing a plug-in option)
// not all sort types have formatting methods, so we have to call their sorting
// methods.
displaymaster.sort( function ( a, b ) {
var
x, y, k, l, test, sort, fn,
len=asort.length,
dataa = aodata[a]._asortdata,
datab = aodata[b]._asortdata;
for ( k=0 ; ky ? 1 : 0;
} );
}
}
/* tell the draw function that we have sorted the data */
osettings.bsorted = true;
}
function _fnsortaria ( settings )
{
var label;
var nextsort;
var columns = settings.aocolumns;
var asort = _fnsortflatten( settings );
var oaria = settings.olanguage.oaria;
// aria attributes - need to loop all columns, to update all (removing old
// attributes as needed)
for ( var i=0, ilen=columns.length ; i/g, "" );
var th = col.nth;
// ie7 is throwing an error when setting these properties with jquery's
// attr() and removeattr() methods...
th.removeattribute('aria-sort');
/* in aria only the first sorting column can be marked as sorting - no multi-sort option */
if ( col.bsortable ) {
if ( asort.length > 0 && asort[0].col == i ) {
th.setattribute('aria-sort', asort[0].dir=="asc" ? "ascending" : "descending" );
nextsort = assorting[ asort[0].index+1 ] || assorting[0];
}
else {
nextsort = assorting[0];
}
label = stitle + ( nextsort === "asc" ?
oaria.ssortascending :
oaria.ssortdescending
);
}
else {
label = stitle;
}
th.setattribute('aria-label', label);
}
}
/**
* function to run on user sort request
* @param {object} settings datatables settings object
* @param {node} attachto node to attach the handler to
* @param {int} colidx column sorting index
* @param {boolean} [append=false] append the requested sort to the existing
* sort if true (i.e. multi-column sort)
* @param {function} [callback] callback function
* @memberof datatable#oapi
*/
function _fnsortlistener ( settings, colidx, append, callback )
{
var col = settings.aocolumns[ colidx ];
var sorting = settings.aasorting;
var assorting = col.assorting;
var nextsortidx;
var next = function ( a, overflow ) {
var idx = a._idx;
if ( idx === undefined ) {
idx = $.inarray( a[1], assorting );
}
return idx+1 < assorting.length ?
idx+1 :
overflow ?
null :
0;
};
// convert to 2d array if needed
if ( typeof sorting[0] === 'number' ) {
sorting = settings.aasorting = [ sorting ];
}
// if appending the sort then we are multi-column sorting
if ( append && settings.ofeatures.bsortmulti ) {
// are we already doing some kind of sort on this column?
var sortidx = $.inarray( colidx, _pluck(sorting, '0') );
if ( sortidx !== -1 ) {
// yes, modify the sort
nextsortidx = next( sorting[sortidx], true );
if ( nextsortidx === null && sorting.length === 1 ) {
nextsortidx = 0; // can't remove sorting completely
}
if ( nextsortidx === null ) {
sorting.splice( sortidx, 1 );
}
else {
sorting[sortidx][1] = assorting[ nextsortidx ];
sorting[sortidx]._idx = nextsortidx;
}
}
else {
// no sort on this column yet
sorting.push( [ colidx, assorting[0], 0 ] );
sorting[sorting.length-1]._idx = 0;
}
}
else if ( sorting.length && sorting[0][0] == colidx ) {
// single column - already sorting on this column, modify the sort
nextsortidx = next( sorting[0] );
sorting.length = 1;
sorting[0][1] = assorting[ nextsortidx ];
sorting[0]._idx = nextsortidx;
}
else {
// single column - sort only on this column
sorting.length = 0;
sorting.push( [ colidx, assorting[0] ] );
sorting[0]._idx = 0;
}
// run the sort by calling a full redraw
_fnredraw( settings );
// callback used for async user interaction
if ( typeof callback == 'function' ) {
callback( settings );
}
}
/**
* attach a sort handler (click) to a node
* @param {object} settings datatables settings object
* @param {node} attachto node to attach the handler to
* @param {int} colidx column sorting index
* @param {function} [callback] callback function
* @memberof datatable#oapi
*/
function _fnsortattachlistener ( settings, attachto, colidx, callback )
{
var col = settings.aocolumns[ colidx ];
_fnbindaction( attachto, {}, function (e) {
/* if the column is not sortable - don't to anything */
if ( col.bsortable === false ) {
return;
}
// if processing is enabled use a timeout to allow the processing
// display to be shown - otherwise to it synchronously
if ( settings.ofeatures.bprocessing ) {
_fnprocessingdisplay( settings, true );
settimeout( function() {
_fnsortlistener( settings, colidx, e.shiftkey, callback );
// in server-side processing, the draw callback will remove the
// processing display
if ( _fndatasource( settings ) !== 'ssp' ) {
_fnprocessingdisplay( settings, false );
}
}, 0 );
}
else {
_fnsortlistener( settings, colidx, e.shiftkey, callback );
}
} );
}
/**
* set the sorting classes on table's body, note: it is safe to call this function
* when bsort and bsortclasses are false
* @param {object} osettings datatables settings object
* @memberof datatable#oapi
*/
function _fnsortingclasses( settings )
{
var oldsort = settings.alastsort;
var sortclass = settings.oclasses.ssortcolumn;
var sort = _fnsortflatten( settings );
var features = settings.ofeatures;
var i, ien, colidx;
if ( features.bsort && features.bsortclasses ) {
// remove old sorting classes
for ( i=0, ien=oldsort.length ; i 0 && s.time < +new date() - (duration*1000) ) {
callback();
return;
}
// number of columns have changed - all bets are off, no restore of settings
if ( s.columns && columns.length !== s.columns.length ) {
callback();
return;
}
// store the saved state so it might be accessed at any time
settings.oloadedstate = $.extend( true, {}, s );
// restore key features - todo - for 1.11 this needs to be done by
// subscribed events
if ( s.start !== undefined ) {
settings._idisplaystart = s.start;
settings.iinitdisplaystart = s.start;
}
if ( s.length !== undefined ) {
settings._idisplaylength = s.length;
}
// order
if ( s.order !== undefined ) {
settings.aasorting = [];
$.each( s.order, function ( i, col ) {
settings.aasorting.push( col[0] >= columns.length ?
[ 0, col[1] ] :
col
);
} );
}
// search
if ( s.search !== undefined ) {
$.extend( settings.oprevioussearch, _fnsearchtohung( s.search ) );
}
// columns
//
if ( s.columns ) {
for ( i=0, ien=s.columns.length ; i= end )
{
start = end - len;
}
// keep the start record on the current page
start -= (start % len);
if ( len === -1 || start < 0 )
{
start = 0;
}
settings._idisplaystart = start;
}
function _fnrenderer( settings, type )
{
var renderer = settings.renderer;
var host = datatable.ext.renderer[type];
if ( $.isplainobject( renderer ) && renderer[type] ) {
// specific renderer for this type. if available use it, otherwise use
// the default.
return host[renderer[type]] || host._;
}
else if ( typeof renderer === 'string' ) {
// common renderer - if there is one available for this type use it,
// otherwise use the default
return host[renderer] || host._;
}
// use the default
return host._;
}
/**
* detect the data source being used for the table. used to simplify the code
* a little (ajax) and to make it compress a little smaller.
*
* @param {object} settings datatables settings object
* @returns {string} data source
* @memberof datatable#oapi
*/
function _fndatasource ( settings )
{
if ( settings.ofeatures.bserverside ) {
return 'ssp';
}
else if ( settings.ajax || settings.sajaxsource ) {
return 'ajax';
}
return 'dom';
}
/**
* computed structure of the datatables api, defined by the options passed to
* `datatable.api.register()` when building the api.
*
* the structure is built in order to speed creation and extension of the api
* objects since the extensions are effectively pre-parsed.
*
* the array is an array of objects with the following structure, where this
* base array represents the api prototype base:
*
* [
* {
* name: 'data' -- string - property name
* val: function () {}, -- function - api method (or undefined if just an object
* methodext: [ ... ], -- array - array of api object definitions to extend the method result
* propext: [ ... ] -- array - array of api object definitions to extend the property
* },
* {
* name: 'row'
* val: {},
* methodext: [ ... ],
* propext: [
* {
* name: 'data'
* val: function () {},
* methodext: [ ... ],
* propext: [ ... ]
* },
* ...
* ]
* }
* ]
*
* @type {array}
* @ignore
*/
var __apistruct = [];
/**
* `array.prototype` reference.
*
* @type object
* @ignore
*/
var __arrayproto = array.prototype;
/**
* abstraction for `context` parameter of the `api` constructor to allow it to
* take several different forms for ease of use.
*
* each of the input parameter types will be converted to a datatables settings
* object where possible.
*
* @param {string|node|jquery|object} mixed datatable identifier. can be one
* of:
*
* * `string` - jquery selector. any datatables' matching the given selector
* with be found and used.
* * `node` - `table` node which has already been formed into a datatable.
* * `jquery` - a jquery object of `table` nodes.
* * `object` - datatables settings object
* * `datatables.api` - api instance
* @return {array|null} matching datatables settings objects. `null` or
* `undefined` is returned if no matching datatable is found.
* @ignore
*/
var _tosettings = function ( mixed )
{
var idx, jq;
var settings = datatable.settings;
var tables = $.map( settings, function (el, i) {
return el.ntable;
} );
if ( ! mixed ) {
return [];
}
else if ( mixed.ntable && mixed.oapi ) {
// datatables settings object
return [ mixed ];
}
else if ( mixed.nodename && mixed.nodename.tolowercase() === 'table' ) {
// table node
idx = $.inarray( mixed, tables );
return idx !== -1 ? [ settings[idx] ] : null;
}
else if ( mixed && typeof mixed.settings === 'function' ) {
return mixed.settings().toarray();
}
else if ( typeof mixed === 'string' ) {
// jquery selector
jq = $(mixed);
}
else if ( mixed instanceof $ ) {
// jquery object (also datatables instance)
jq = mixed;
}
if ( jq ) {
return jq.map( function(i) {
idx = $.inarray( this, tables );
return idx !== -1 ? settings[idx] : null;
} ).toarray();
}
};
/**
* datatables api class - used to control and interface with one or more
* datatables enhanced tables.
*
* the api class is heavily based on jquery, presenting a chainable interface
* that you can use to interact with tables. each instance of the api class has
* a "context" - i.e. the tables that it will operate on. this could be a single
* table, all tables on a page or a sub-set thereof.
*
* additionally the api is designed to allow you to easily work with the data in
* the tables, retrieving and manipulating it as required. this is done by
* presenting the api class as an array like interface. the contents of the
* array depend upon the actions requested by each method (for example
* `rows().nodes()` will return an array of nodes, while `rows().data()` will
* return an array of objects or arrays depending upon your table's
* configuration). the api object has a number of array like methods (`push`,
* `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
* `unique` etc) to assist your working with the data held in a table.
*
* most methods (those which return an api instance) are chainable, which means
* the return from a method call also has all of the methods available that the
* top level object had. for example, these two calls are equivalent:
*
* // not chained
* api.row.add( {...} );
* api.draw();
*
* // chained
* api.row.add( {...} ).draw();
*
* @class datatable.api
* @param {array|object|string|jquery} context datatable identifier. this is
* used to define which datatables enhanced tables this api will operate on.
* can be one of:
*
* * `string` - jquery selector. any datatables' matching the given selector
* with be found and used.
* * `node` - `table` node which has already been formed into a datatable.
* * `jquery` - a jquery object of `table` nodes.
* * `object` - datatables settings object
* @param {array} [data] data to initialise the api instance with.
*
* @example
* // direct initialisation during datatables construction
* var api = $('#example').datatable();
*
* @example
* // initialisation using a datatables jquery object
* var api = $('#example').datatable().api();
*
* @example
* // initialisation as a constructor
* var api = new $.fn.datatable.api( 'table.datatable' );
*/
_api = function ( context, data )
{
if ( ! (this instanceof _api) ) {
return new _api( context, data );
}
var settings = [];
var ctxsettings = function ( o ) {
var a = _tosettings( o );
if ( a ) {
settings.push.apply( settings, a );
}
};
if ( $.isarray( context ) ) {
for ( var i=0, ien=context.length ; i idx ?
new _api( ctx[idx], this[idx] ) :
null;
},
filter: function ( fn )
{
var a = [];
if ( __arrayproto.filter ) {
a = __arrayproto.filter.call( this, fn, this );
}
else {
// compatibility for browsers without emca-252-5 (js 1.6)
for ( var i=0, ien=this.length ; i 0 ) {
return ctx[0].json;
}
// else return undefined;
} );
/**
* get the data submitted in the last ajax request
*/
_api_register( 'ajax.params()', function () {
var ctx = this.context;
if ( ctx.length > 0 ) {
return ctx[0].oajaxdata;
}
// else return undefined;
} );
/**
* reload tables from the ajax data source. note that this function will
* automatically re-draw the table when the remote data has been loaded.
*
* @param {boolean} [reset=true] reset (default) or hold the current paging
* position. a full re-sort and re-filter is performed when this method is
* called, which is why the pagination reset is the default action.
* @returns {datatables.api} this
*/
_api_register( 'ajax.reload()', function ( callback, resetpaging ) {
return this.iterator( 'table', function (settings) {
__reload( settings, resetpaging===false, callback );
} );
} );
/**
* get the current ajax url. note that this returns the url from the first
* table in the current context.
*
* @return {string} current ajax source url
*//**
* set the ajax url. note that this will set the url for all tables in the
* current context.
*
* @param {string} url url to set.
* @returns {datatables.api} this
*/
_api_register( 'ajax.url()', function ( url ) {
var ctx = this.context;
if ( url === undefined ) {
// get
if ( ctx.length === 0 ) {
return undefined;
}
ctx = ctx[0];
return ctx.ajax ?
$.isplainobject( ctx.ajax ) ?
ctx.ajax.url :
ctx.ajax :
ctx.sajaxsource;
}
// set
return this.iterator( 'table', function ( settings ) {
if ( $.isplainobject( settings.ajax ) ) {
settings.ajax.url = url;
}
else {
settings.ajax = url;
}
// no need to consider sajaxsource here since datatables gives priority
// to `ajax` over `sajaxsource`. so setting `ajax` here, renders any
// value of `sajaxsource` redundant.
} );
} );
/**
* load data from the newly set ajax url. note that this method is only
* available when `ajax.url()` is used to set a url. additionally, this method
* has the same effect as calling `ajax.reload()` but is provided for
* convenience when setting a new url. like `ajax.reload()` it will
* automatically redraw the table once the remote data has been loaded.
*
* @returns {datatables.api} this
*/
_api_register( 'ajax.url().load()', function ( callback, resetpaging ) {
// same as a reload, but makes sense to present it for easy access after a
// url change
return this.iterator( 'table', function ( ctx ) {
__reload( ctx, resetpaging===false, callback );
} );
} );
var _selector_run = function ( type, selector, selectfn, settings, opts )
{
var
out = [], res,
a, i, ien, j, jen,
selectortype = typeof selector;
// can't just check for isarray here, as an api or jquery instance might be
// given with their array like look
if ( ! selector || selectortype === 'string' || selectortype === 'function' || selector.length === undefined ) {
selector = [ selector ];
}
for ( i=0, ien=selector.length ; i 0 ) {
// assign the first element to the first item in the instance
// and truncate the instance and context
inst[0] = inst[i];
inst[0].length = 1;
inst.length = 1;
inst.context = [ inst.context[i] ];
return inst;
}
}
// not found - return an empty instance
inst.length = 0;
return inst;
};
var _selector_row_indexes = function ( settings, opts )
{
var
i, ien, tmp, a=[],
displayfiltered = settings.aidisplay,
displaymaster = settings.aidisplaymaster;
var
search = opts.search, // none, applied, removed
order = opts.order, // applied, current, index (original - compatibility with 1.9)
page = opts.page; // all, current
if ( _fndatasource( settings ) == 'ssp' ) {
// in server-side processing mode, most options are irrelevant since
// rows not shown don't exist and the index order is the applied order
// removed is a special case - for consistency just return an empty
// array
return search === 'removed' ?
[] :
_range( 0, displaymaster.length );
}
else if ( page == 'current' ) {
// current page implies that order=current and fitler=applied, since it is
// fairly senseless otherwise, regardless of what order and search actually
// are
for ( i=settings._idisplaystart, ien=settings.fndisplayend() ; i= 0 && search == 'applied') )
{
a.push( i );
}
}
}
}
return a;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* rows
*
* {} - no selector - use all available rows
* {integer} - row aodata index
* {node} - tr node
* {string} - jquery selector to apply to the tr elements
* {array} - jquery array of nodes, or simply an array of tr nodes
*
*/
var __row_selector = function ( settings, selector, opts )
{
var rows;
var run = function ( sel ) {
var selint = _intval( sel );
var i, ien;
var aodata = settings.aodata;
// short cut - selector is a number and no options provided (default is
// all records, so no need to check if the index is in there, since it
// must be - dev error if the index doesn't exist).
if ( selint !== null && ! opts ) {
return [ selint ];
}
if ( ! rows ) {
rows = _selector_row_indexes( settings, opts );
}
if ( selint !== null && $.inarray( selint, rows ) !== -1 ) {
// selector - integer
return [ selint ];
}
else if ( sel === null || sel === undefined || sel === '' ) {
// selector - none
return rows;
}
// selector - function
if ( typeof sel === 'function' ) {
return $.map( rows, function (idx) {
var row = aodata[ idx ];
return sel( idx, row._adata, row.ntr ) ? idx : null;
} );
}
// selector - node
if ( sel.nodename ) {
var rowidx = sel._dt_rowindex; // property added by dt for fast lookup
var cellidx = sel._dt_cellindex;
if ( rowidx !== undefined ) {
// make sure that the row is actually still present in the table
return aodata[ rowidx ] && aodata[ rowidx ].ntr === sel ?
[ rowidx ] :
[];
}
else if ( cellidx ) {
return aodata[ cellidx.row ] && aodata[ cellidx.row ].ntr === sel.parentnode ?
[ cellidx.row ] :
[];
}
else {
var host = $(sel).closest('*[data-dt-row]');
return host.length ?
[ host.data('dt-row') ] :
[];
}
}
// id selector. want to always be able to select rows by id, regardless
// of if the tr element has been created or not, so can't rely upon
// jquery here - hence a custom implementation. this does not match
// sizzle's fast selector or html4 - in html5 the id can be anything,
// but to select it using a css selector engine (like sizzle or
// queryselect) it would need to need to be escaped for some characters.
// datatables simplifies this for row selectors since you can select
// only a row. a # indicates an id any anything that follows is the id -
// unescaped.
if ( typeof sel === 'string' && sel.charat(0) === '#' ) {
// get row index from id
var rowobj = settings.aids[ sel.replace( /^#/, '' ) ];
if ( rowobj !== undefined ) {
return [ rowobj.idx ];
}
// need to fall through to jquery in case there is dom id that
// matches
}
// get nodes in the order from the `rows` array with null values removed
var nodes = _removeempty(
_pluck_order( settings.aodata, rows, 'ntr' )
);
// selector - jquery selector string, array of nodes or jquery object/
// as jquery's .filter() allows jquery objects to be passed in filter,
// it also allows arrays, so this will cope with all three options
return $(nodes)
.filter( sel )
.map( function () {
return this._dt_rowindex;
} )
.toarray();
};
return _selector_run( 'row', selector, run, settings, opts );
};
_api_register( 'rows()', function ( selector, opts ) {
// argument shifting
if ( selector === undefined ) {
selector = '';
}
else if ( $.isplainobject( selector ) ) {
opts = selector;
selector = '';
}
opts = _selector_opts( opts );
var inst = this.iterator( 'table', function ( settings ) {
return __row_selector( settings, selector, opts );
}, 1 );
// want argument shifting here and in __row_selector?
inst.selector.rows = selector;
inst.selector.opts = opts;
return inst;
} );
_api_register( 'rows().nodes()', function () {
return this.iterator( 'row', function ( settings, row ) {
return settings.aodata[ row ].ntr || undefined;
}, 1 );
} );
_api_register( 'rows().data()', function () {
return this.iterator( true, 'rows', function ( settings, rows ) {
return _pluck_order( settings.aodata, rows, '_adata' );
}, 1 );
} );
_api_registerplural( 'rows().cache()', 'row().cache()', function ( type ) {
return this.iterator( 'row', function ( settings, row ) {
var r = settings.aodata[ row ];
return type === 'search' ? r._afilterdata : r._asortdata;
}, 1 );
} );
_api_registerplural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
return this.iterator( 'row', function ( settings, row ) {
_fninvalidate( settings, row, src );
} );
} );
_api_registerplural( 'rows().indexes()', 'row().index()', function () {
return this.iterator( 'row', function ( settings, row ) {
return row;
}, 1 );
} );
_api_registerplural( 'rows().ids()', 'row().id()', function ( hash ) {
var a = [];
var context = this.context;
// `iterator` will drop undefined values, but in this case we want them
for ( var i=0, ien=context.length ; i 0 ) {
settings._irecordsdisplay--;
}
// check for an 'overflow' they case for displaying the table
_fnlengthoverflow( settings );
// remove the row's id reference if there is one
var id = settings.rowidfn( rowdata._adata );
if ( id !== undefined ) {
delete settings.aids[ id ];
}
} );
this.iterator( 'table', function ( settings ) {
for ( var i=0, ien=settings.aodata.length ; i
').addclass( k );
$('td', created)
.addclass( k )
.html( r )
[0].colspan = _fnvisblecolumns( ctx );
rows.push( created[0] );
}
};
addrow( data, klass );
if ( row._details ) {
row._details.detach();
}
row._details = $(rows);
// if the children were already shown, that state should be retained
if ( row._detailsshow ) {
row._details.insertafter( row.ntr );
}
};
var __details_remove = function ( api, idx )
{
var ctx = api.context;
if ( ctx.length ) {
var row = ctx[0].aodata[ idx !== undefined ? idx : api[0] ];
if ( row && row._details ) {
row._details.remove();
row._detailsshow = undefined;
row._details = undefined;
}
}
};
var __details_display = function ( api, show ) {
var ctx = api.context;
if ( ctx.length && api.length ) {
var row = ctx[0].aodata[ api[0] ];
if ( row._details ) {
row._detailsshow = show;
if ( show ) {
row._details.insertafter( row.ntr );
}
else {
row._details.detach();
}
__details_events( ctx[0] );
}
}
};
var __details_events = function ( settings )
{
var api = new _api( settings );
var namespace = '.dt.dt_details';
var drawevent = 'draw'+namespace;
var colvisevent = 'column-visibility'+namespace;
var destroyevent = 'destroy'+namespace;
var data = settings.aodata;
api.off( drawevent +' '+ colvisevent +' '+ destroyevent );
if ( _pluck( data, '_details' ).length > 0 ) {
// on each draw, insert the required elements into the document
api.on( drawevent, function ( e, ctx ) {
if ( settings !== ctx ) {
return;
}
api.rows( {page:'current'} ).eq(0).each( function (idx) {
// internal data grab
var row = data[ idx ];
if ( row._detailsshow ) {
row._details.insertafter( row.ntr );
}
} );
} );
// column visibility change - update the colspan
api.on( colvisevent, function ( e, ctx, idx, vis ) {
if ( settings !== ctx ) {
return;
}
// update the colspan for the details rows (note, only if it already has
// a colspan)
var row, visible = _fnvisblecolumns( ctx );
for ( var i=0, ien=data.length ; i=0 count from left, <0 count from right)
* "{integer}:visidx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
* "{integer}:visible" - alias for {integer}:visidx (>=0 count from left, <0 count from right)
* "{string}:name" - column name
* "{string}" - jquery selector on column header nodes
*
*/
// can be an array of these items, comma separated list, or an array of comma
// separated lists
var __re_column_selector = /^([^:]+):(name|visidx|visible)$/;
// r1 and r2 are redundant - but it means that the parameters match for the
// iterator callback in columns().data()
var __columndata = function ( settings, column, r1, r2, rows ) {
var a = [];
for ( var row=0, ien=rows.length ; row= 0 ?
selint : // count from left
columns.length + selint // count from right (+ because its a negative value)
];
}
// selector = function
if ( typeof s === 'function' ) {
var rows = _selector_row_indexes( settings, opts );
return $.map( columns, function (col, idx) {
return s(
idx,
__columndata( settings, idx, 0, 0, rows ),
nodes[ idx ]
) ? idx : null;
} );
}
// jquery or string selector
var match = typeof s === 'string' ?
s.match( __re_column_selector ) :
'';
if ( match ) {
switch( match[2] ) {
case 'visidx':
case 'visible':
var idx = parseint( match[1], 10 );
// visible index given, convert to column index
if ( idx < 0 ) {
// counting from the right
var viscolumns = $.map( columns, function (col,i) {
return col.bvisible ? i : null;
} );
return [ viscolumns[ viscolumns.length + idx ] ];
}
// counting from the left
return [ _fnvisibletocolumnindex( settings, idx ) ];
case 'name':
// match by name. `names` is column index complete and in order
return $.map( names, function (name, i) {
return name === match[1] ? i : null;
} );
default:
return [];
}
}
// cell in the table body
if ( s.nodename && s._dt_cellindex ) {
return [ s._dt_cellindex.column ];
}
// jquery selector on the th elements for the columns
var jqresult = $( nodes )
.filter( s )
.map( function () {
return $.inarray( this, nodes ); // `nodes` is column index complete and in order
} )
.toarray();
if ( jqresult.length || ! s.nodename ) {
return jqresult;
}
// otherwise a node which might have a `dt-column` data attribute, or be
// a child or such an element
var host = $(s).closest('*[data-dt-column]');
return host.length ?
[ host.data('dt-column') ] :
[];
};
return _selector_run( 'column', selector, run, settings, opts );
};
var __setcolumnvis = function ( settings, column, vis ) {
var
cols = settings.aocolumns,
col = cols[ column ],
data = settings.aodata,
row, cells, i, ien, tr;
// get
if ( vis === undefined ) {
return col.bvisible;
}
// set
// no change
if ( col.bvisible === vis ) {
return;
}
if ( vis ) {
// insert column
// need to decide if we should use appendchild or insertbefore
var insertbefore = $.inarray( true, _pluck(cols, 'bvisible'), column+1 );
for ( i=0, ien=data.length ; i ithat;
}
return true;
};
/**
* check if a `
` node is a datatable table already or not.
*
* @param {node|jquery|string} table table node, jquery object or jquery
* selector for the table to test. note that if more than more than one
* table is passed on, only the first will be checked
* @returns {boolean} true the table given is a datatable, or false otherwise
* @static
* @dtopt api-static
*
* @example
* if ( ! $.fn.datatable.isdatatable( '#example' ) ) {
* $('#example').datatable();
* }
*/
datatable.isdatatable = datatable.fnisdatatable = function ( table )
{
var t = $(table).get(0);
var is = false;
if ( table instanceof datatable.api ) {
return true;
}
$.each( datatable.settings, function (i, o) {
var head = o.nscrollhead ? $('table', o.nscrollhead)[0] : null;
var foot = o.nscrollfoot ? $('table', o.nscrollfoot)[0] : null;
if ( o.ntable === t || head === t || foot === t ) {
is = true;
}
} );
return is;
};
/**
* get all datatable tables that have been initialised - optionally you can
* select to get only currently visible tables.
*
* @param {boolean} [visible=false] flag to indicate if you want all (default)
* or visible tables only.
* @returns {array} array of `table` nodes (not datatable instances) which are
* datatables
* @static
* @dtopt api-static
*
* @example
* $.each( $.fn.datatable.tables(true), function () {
* $(table).datatable().columns.adjust();
* } );
*/
datatable.tables = datatable.fntables = function ( visible )
{
var api = false;
if ( $.isplainobject( visible ) ) {
api = visible.api;
visible = visible.visible;
}
var a = $.map( datatable.settings, function (o) {
if ( !visible || (visible && $(o.ntable).is(':visible')) ) {
return o.ntable;
}
} );
return api ?
new _api( a ) :
a;
};
/**
* convert from camel case parameters to hungarian notation. this is made public
* for the extensions to provide the same ability as datatables core to accept
* either the 1.9 style hungarian notation, or the 1.10+ style camelcase
* parameters.
*
* @param {object} src the model object which holds all parameters that can be
* mapped.
* @param {object} user the object to convert from camel case to hungarian.
* @param {boolean} force when set to `true`, properties which already have a
* hungarian value in the `user` object will be overwritten. otherwise they
* won't be.
*/
datatable.cameltohungarian = _fncameltohungarian;
/**
*
*/
_api_register( '$()', function ( selector, opts ) {
var
rows = this.rows( opts ).nodes(), // get all rows
jqrows = $(rows);
return $( [].concat(
jqrows.filter( selector ).toarray(),
jqrows.find( selector ).toarray()
) );
} );
// jquery functions to operate on the tables
$.each( [ 'on', 'one', 'off' ], function (i, key) {
_api_register( key+'()', function ( /* event, handler */ ) {
var args = array.prototype.slice.call(arguments);
// add the `dt` namespace automatically if it isn't already present
args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
return ! e.match(/\.dt\b/) ?
e+'.dt' :
e;
} ).join( ' ' );
var inst = $( this.tables().nodes() );
inst[key].apply( inst, args );
return this;
} );
} );
_api_register( 'clear()', function () {
return this.iterator( 'table', function ( settings ) {
_fncleartable( settings );
} );
} );
_api_register( 'settings()', function () {
return new _api( this.context, this.context );
} );
_api_register( 'init()', function () {
var ctx = this.context;
return ctx.length ? ctx[0].oinit : null;
} );
_api_register( 'data()', function () {
return this.iterator( 'table', function ( settings ) {
return _pluck( settings.aodata, '_adata' );
} ).flatten();
} );
_api_register( 'destroy()', function ( remove ) {
remove = remove || false;
return this.iterator( 'table', function ( settings ) {
var orig = settings.ntablewrapper.parentnode;
var classes = settings.oclasses;
var table = settings.ntable;
var tbody = settings.ntbody;
var thead = settings.nthead;
var tfoot = settings.ntfoot;
var jqtable = $(table);
var jqtbody = $(tbody);
var jqwrapper = $(settings.ntablewrapper);
var rows = $.map( settings.aodata, function (r) { return r.ntr; } );
var i, ien;
// flag to note that the table is currently being destroyed - no action
// should be taken
settings.bdestroying = true;
// fire off the destroy callbacks for plug-ins etc
_fncallbackfire( settings, "aodestroycallback", "destroy", [settings] );
// if not being removed from the document, make all columns visible
if ( ! remove ) {
new _api( settings ).columns().visible( true );
}
// blitz all `dt` namespaced events (these are internal events, the
// lowercase, `dt` events are user subscribed and they are responsible
// for removing them
jqwrapper.off('.dt').find(':not(tbody *)').off('.dt');
$(window).off('.dt-'+settings.sinstance);
// when scrolling we had to break the table up - restore it
if ( table != thead.parentnode ) {
jqtable.children('thead').detach();
jqtable.append( thead );
}
if ( tfoot && table != tfoot.parentnode ) {
jqtable.children('tfoot').detach();
jqtable.append( tfoot );
}
settings.aasorting = [];
settings.aasortingfixed = [];
_fnsortingclasses( settings );
$( rows ).removeclass( settings.asstripeclasses.join(' ') );
$('th, td', thead).removeclass( classes.ssortable+' '+
classes.ssortableasc+' '+classes.ssortabledesc+' '+classes.ssortablenone
);
// add the tr elements back into the table in their original order
jqtbody.children().detach();
jqtbody.append( rows );
// remove the datatables generated nodes, events and classes
var removedmethod = remove ? 'remove' : 'detach';
jqtable[ removedmethod ]();
jqwrapper[ removedmethod ]();
// if we need to reattach the table to the document
if ( ! remove && orig ) {
// insertbefore acts like appendchild if !arg[1]
orig.insertbefore( table, settings.ntablereinsertbefore );
// restore the width of the original table - was read from the style property,
// so we can restore directly to that
jqtable
.css( 'width', settings.sdestroywidth )
.removeclass( classes.stable );
// if the were originally stripe classes - then we add them back here.
// note this is not fool proof (for example if not all rows had stripe
// classes - but it's a good effort without getting carried away
ien = settings.asdestroystripes.length;
if ( ien ) {
jqtbody.children().each( function (i) {
$(this).addclass( settings.asdestroystripes[i % ien] );
} );
}
}
/* remove the settings object from the settings array */
var idx = $.inarray( settings, datatable.settings );
if ( idx !== -1 ) {
datatable.settings.splice( idx, 1 );
}
} );
} );
// add the `every()` method for rows, columns and cells in a compact form
$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
_api_register( type+'s().every()', function ( fn ) {
var opts = this.selector.opts;
var api = this;
return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
// rows and columns:
// arg1 - index
// arg2 - table counter
// arg3 - loop counter
// arg4 - undefined
// cells:
// arg1 - row index
// arg2 - column index
// arg3 - table counter
// arg4 - loop counter
fn.call(
api[ type ](
arg1,
type==='cell' ? arg2 : opts,
type==='cell' ? opts : undefined
),
arg1, arg2, arg3, arg4
);
} );
} );
} );
// i18n method for extensions to be able to use the language object from the
// datatable
_api_register( 'i18n()', function ( token, def, plural ) {
var ctx = this.context[0];
var resolved = _fngetobjectdatafn( token )( ctx.olanguage );
if ( resolved === undefined ) {
resolved = def;
}
if ( plural !== undefined && $.isplainobject( resolved ) ) {
resolved = resolved[ plural ] !== undefined ?
resolved[ plural ] :
resolved._;
}
return resolved.replace( '%d', plural ); // nb: plural might be undefined,
} );
/**
* version string for plug-ins to check compatibility. allowed format is
* `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
* only for non-release builds. see http://semver.org/ for more information.
* @member
* @type string
* @default version number
*/
datatable.version = "1.10.21";
/**
* private data store, containing all of the settings objects that are
* created for the tables on a given page.
*
* note that the `datatable.settings` object is aliased to
* `jquery.fn.datatableext` through which it may be accessed and
* manipulated, or `jquery.fn.datatable.settings`.
* @member
* @type array
* @default []
* @private
*/
datatable.settings = [];
/**
* object models container, for the various models that datatables has
* available to it. these models define the objects that are used to hold
* the active state and configuration of the table.
* @namespace
*/
datatable.models = {};
/**
* template object for the way in which datatables holds information about
* search information for the global filter and individual column filters.
* @namespace
*/
datatable.models.osearch = {
/**
* flag to indicate if the filtering should be case insensitive or not
* @type boolean
* @default true
*/
"bcaseinsensitive": true,
/**
* applied search term
* @type string
* @default empty string
*/
"ssearch": "",
/**
* flag to indicate if the search term should be interpreted as a
* regular expression (true) or not (false) and therefore and special
* regex characters escaped.
* @type boolean
* @default false
*/
"bregex": false,
/**
* flag to indicate if datatables is to use its smart filtering or not.
* @type boolean
* @default true
*/
"bsmart": true
};
/**
* template object for the way in which datatables holds information about
* each individual row. this is the object format used for the settings
* aodata array.
* @namespace
*/
datatable.models.orow = {
/**
* tr element for the row
* @type node
* @default null
*/
"ntr": null,
/**
* array of td elements for each row. this is null until the row has been
* created.
* @type array nodes
* @default []
*/
"ancells": null,
/**
* data object from the original data source for the row. this is either
* an array if using the traditional form of datatables, or an object if
* using mdata options. the exact type will depend on the passed in
* data from the data source, or will be an array if using dom a data
* source.
* @type array|object
* @default []
*/
"_adata": [],
/**
* sorting data cache - this array is ostensibly the same length as the
* number of columns (although each index is generated only as it is
* needed), and holds the data that is used for sorting each column in the
* row. we do this cache generation at the start of the sort in order that
* the formatting of the sort data need be done only once for each cell
* per sort. this array should not be read from or written to by anything
* other than the master sorting methods.
* @type array
* @default null
* @private
*/
"_asortdata": null,
/**
* per cell filtering data cache. as per the sort data cache, used to
* increase the performance of the filtering in datatables
* @type array
* @default null
* @private
*/
"_afilterdata": null,
/**
* filtering data cache. this is the same as the cell filtering cache, but
* in this case a string rather than an array. this is easily computed with
* a join on `_afilterdata`, but is provided as a cache so the join isn't
* needed on every search (memory traded for performance)
* @type array
* @default null
* @private
*/
"_sfilterrow": null,
/**
* cache of the class name that datatables has applied to the row, so we
* can quickly look at this variable rather than needing to do a dom check
* on classname for the ntr property.
* @type string
* @default empty string
* @private
*/
"_srowstripe": "",
/**
* denote if the original data source was from the dom, or the data source
* object. this is used for invalidating data, so datatables can
* automatically read data from the original source, unless uninstructed
* otherwise.
* @type string
* @default null
* @private
*/
"src": null,
/**
* index in the aodata array. this saves an indexof lookup when we have the
* object, but want to know the index
* @type integer
* @default -1
* @private
*/
"idx": -1
};
/**
* template object for the column information object in datatables. this object
* is held in the settings aocolumns array and contains all the information that
* datatables needs about each individual column.
*
* note that this object is related to {@link datatable.defaults.column}
* but this one is the internal data store for datatables's cache of columns.
* it should not be manipulated outside of datatables. any configuration should
* be done through the initialisation options.
* @namespace
*/
datatable.models.ocolumn = {
/**
* column index. this could be worked out on-the-fly with $.inarray, but it
* is faster to just hold it as a variable
* @type integer
* @default null
*/
"idx": null,
/**
* a list of the columns that sorting should occur on when this column
* is sorted. that this property is an array allows multi-column sorting
* to be defined for a column (for example first name / last name columns
* would benefit from this). the values are integers pointing to the
* columns to be sorted on (typically it will be a single integer pointing
* at itself, but that doesn't need to be the case).
* @type array
*/
"adatasort": null,
/**
* define the sorting directions that are applied to the column, in sequence
* as the column is repeatedly sorted upon - i.e. the first value is used
* as the sorting direction when the column if first sorted (clicked on).
* sort it again (click again) and it will move on to the next index.
* repeat until loop.
* @type array
*/
"assorting": null,
/**
* flag to indicate if the column is searchable, and thus should be included
* in the filtering or not.
* @type boolean
*/
"bsearchable": null,
/**
* flag to indicate if the column is sortable or not.
* @type boolean
*/
"bsortable": null,
/**
* flag to indicate if the column is currently visible in the table or not
* @type boolean
*/
"bvisible": null,
/**
* store for manual type assignment using the `column.type` option. this
* is held in store so we can manipulate the column's `stype` property.
* @type string
* @default null
* @private
*/
"_smanualtype": null,
/**
* flag to indicate if html5 data attributes should be used as the data
* source for filtering or sorting. true is either are.
* @type boolean
* @default false
* @private
*/
"_battrsrc": false,
/**
* developer definable function that is called whenever a cell is created (ajax source,
* etc) or processed for input (dom source). this can be used as a compliment to mrender
* allowing you to modify the dom element (add background colour for example) when the
* element is available.
* @type function
* @param {element} ntd the td node that has been created
* @param {*} sdata the data for the cell
* @param {array|object} odata the data for the whole row
* @param {int} irow the row index for the aodata data store
* @default null
*/
"fncreatedcell": null,
/**
* function to get data from a cell in a column. you should never
* access data directly through _adata internally in datatables - always use
* the method attached to this property. it allows mdata to function as
* required. this function is automatically assigned by the column
* initialisation method
* @type function
* @param {array|object} odata the data array/object for the array
* (i.e. aodata[]._adata)
* @param {string} sspecific the specific data type you want to get -
* 'display', 'type' 'filter' 'sort'
* @returns {*} the data for the cell from the given row's data
* @default null
*/
"fngetdata": null,
/**
* function to set data for a cell in the column. you should never
* set the data directly to _adata internally in datatables - always use
* this method. it allows mdata to function as required. this function
* is automatically assigned by the column initialisation method
* @type function
* @param {array|object} odata the data array/object for the array
* (i.e. aodata[]._adata)
* @param {*} svalue value to set
* @default null
*/
"fnsetdata": null,
/**
* property to read the value for the cells in the column from the data
* source array / object. if null, then the default content is used, if a
* function is given then the return from the function is used.
* @type function|int|string|null
* @default null
*/
"mdata": null,
/**
* partner property to mdata which is used (only when defined) to get
* the data - i.e. it is basically the same as mdata, but without the
* 'set' option, and also the data fed to it is the result from mdata.
* this is the rendering method to match the data method of mdata.
* @type function|int|string|null
* @default null
*/
"mrender": null,
/**
* unique header th/td element for this column - this is what the sorting
* listener is attached to (if sorting is enabled.)
* @type node
* @default null
*/
"nth": null,
/**
* unique footer th/td element for this column (if there is one). not used
* in datatables as such, but can be used for plug-ins to reference the
* footer for each column.
* @type node
* @default null
*/
"ntf": null,
/**
* the class to apply to all td elements in the table's tbody for the column
* @type string
* @default null
*/
"sclass": null,
/**
* when datatables calculates the column widths to assign to each column,
* it finds the longest string in each column and then constructs a
* temporary table and reads the widths from that. the problem with this
* is that "mmm" is much wider then "iiii", but the latter is a longer
* string - thus the calculation can go wrong (doing it properly and putting
* it into an dom object and measuring that is horribly(!) slow). thus as
* a "work around" we provide this option. it will append its value to the
* text that is found to be the longest string for the column - i.e. padding.
* @type string
*/
"scontentpadding": null,
/**
* allows a default value to be given for a column's data, and will be used
* whenever a null data source is encountered (this can be because mdata
* is set to null, or because the data source itself is null).
* @type string
* @default null
*/
"sdefaultcontent": null,
/**
* name for the column, allowing reference to the column by name as well as
* by index (needs a lookup to work by name).
* @type string
*/
"sname": null,
/**
* custom sorting data type - defines which of the available plug-ins in
* afnsortdata the custom sorting will use - if any is defined.
* @type string
* @default std
*/
"ssortdatatype": 'std',
/**
* class to be applied to the header element when sorting on this column
* @type string
* @default null
*/
"ssortingclass": null,
/**
* class to be applied to the header element when sorting on this column -
* when jquery ui theming is used.
* @type string
* @default null
*/
"ssortingclassjui": null,
/**
* title of the column - what is seen in the th element (nth).
* @type string
*/
"stitle": null,
/**
* column sorting and filtering type
* @type string
* @default null
*/
"stype": null,
/**
* width of the column
* @type string
* @default null
*/
"swidth": null,
/**
* width of the column when it was first "encountered"
* @type string
* @default null
*/
"swidthorig": null
};
/*
* developer note: the properties of the object below are given in hungarian
* notation, that was used as the interface for datatables prior to v1.10, however
* from v1.10 onwards the primary interface is camel case. in order to avoid
* breaking backwards compatibility utterly with this change, the hungarian
* version is still, internally the primary interface, but is is not documented
* - hence the @name tags in each doc comment. this allows a javascript function
* to create a map from hungarian notation to camel case (going the other direction
* would require each property to be listed, which would at around 3k to the size
* of datatables, while this method is about a 0.5k hit.
*
* ultimately this does pave the way for hungarian notation to be dropped
* completely, but that is a massive amount of work and will break current
* installs (therefore is on-hold until v2).
*/
/**
* initialisation options that can be given to datatables at initialisation
* time.
* @namespace
*/
datatable.defaults = {
/**
* an array of data to use for the table, passed in at initialisation which
* will be used in preference to any data which is already in the dom. this is
* particularly useful for constructing tables purely in javascript, for
* example with a custom ajax call.
* @type array
* @default null
*
* @dtopt option
* @name datatable.defaults.data
*
* @example
* // using a 2d array data source
* $(document).ready( function () {
* $('#example').datatable( {
* "data": [
* ['trident', 'internet explorer 4.0', 'win 95+', 4, 'x'],
* ['trident', 'internet explorer 5.0', 'win 95+', 5, 'c'],
* ],
* "columns": [
* { "title": "engine" },
* { "title": "browser" },
* { "title": "platform" },
* { "title": "version" },
* { "title": "grade" }
* ]
* } );
* } );
*
* @example
* // using an array of objects as a data source (`data`)
* $(document).ready( function () {
* $('#example').datatable( {
* "data": [
* {
* "engine": "trident",
* "browser": "internet explorer 4.0",
* "platform": "win 95+",
* "version": 4,
* "grade": "x"
* },
* {
* "engine": "trident",
* "browser": "internet explorer 5.0",
* "platform": "win 95+",
* "version": 5,
* "grade": "c"
* }
* ],
* "columns": [
* { "title": "engine", "data": "engine" },
* { "title": "browser", "data": "browser" },
* { "title": "platform", "data": "platform" },
* { "title": "version", "data": "version" },
* { "title": "grade", "data": "grade" }
* ]
* } );
* } );
*/
"aadata": null,
/**
* if ordering is enabled, then datatables will perform a first pass sort on
* initialisation. you can define which column(s) the sort is performed
* upon, and the sorting direction, with this variable. the `sorting` array
* should contain an array for each column to be sorted initially containing
* the column's index and a direction string ('asc' or 'desc').
* @type array
* @default [[0,'asc']]
*
* @dtopt option
* @name datatable.defaults.order
*
* @example
* // sort by 3rd column first, and then 4th column
* $(document).ready( function() {
* $('#example').datatable( {
* "order": [[2,'asc'], [3,'desc']]
* } );
* } );
*
* // no initial sorting
* $(document).ready( function() {
* $('#example').datatable( {
* "order": []
* } );
* } );
*/
"aasorting": [[0,'asc']],
/**
* this parameter is basically identical to the `sorting` parameter, but
* cannot be overridden by user interaction with the table. what this means
* is that you could have a column (visible or hidden) which the sorting
* will always be forced on first - any sorting after that (from the user)
* will then be performed as required. this can be useful for grouping rows
* together.
* @type array
* @default null
*
* @dtopt option
* @name datatable.defaults.orderfixed
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "orderfixed": [[0,'asc']]
* } );
* } )
*/
"aasortingfixed": [],
/**
* datatables can be instructed to load data to display in the table from a
* ajax source. this option defines how that ajax call is made and where to.
*
* the `ajax` property has three different modes of operation, depending on
* how it is defined. these are:
*
* * `string` - set the url from where the data should be loaded from.
* * `object` - define properties for `jquery.ajax`.
* * `function` - custom data get function
*
* `string`
* --------
*
* as a string, the `ajax` property simply defines the url from which
* datatables will load data.
*
* `object`
* --------
*
* as an object, the parameters in the object are passed to
* [jquery.ajax](http://api.jquery.com/jquery.ajax/) allowing fine control
* of the ajax request. datatables has a number of default parameters which
* you can override using this option. please refer to the jquery
* documentation for a full description of the options available, although
* the following parameters provide additional options in datatables or
* require special consideration:
*
* * `data` - as with jquery, `data` can be provided as an object, but it
* can also be used as a function to manipulate the data datatables sends
* to the server. the function takes a single parameter, an object of
* parameters with the values that datatables has readied for sending. an
* object may be returned which will be merged into the datatables
* defaults, or you can add the items to the object that was passed in and
* not return anything from the function. this supersedes `fnserverparams`
* from datatables 1.9-.
*
* * `datasrc` - by default datatables will look for the property `data` (or
* `aadata` for compatibility with datatables 1.9-) when obtaining data
* from an ajax source or for server-side processing - this parameter
* allows that property to be changed. you can use javascript dotted
* object notation to get a data source for multiple levels of nesting, or
* it my be used as a function. as a function it takes a single parameter,
* the json returned from the server, which can be manipulated as
* required, with the returned value being that used by datatables as the
* data source for the table. this supersedes `sajaxdataprop` from
* datatables 1.9-.
*
* * `success` - should not be overridden it is used internally in
* datatables. to manipulate / transform the data returned by the server
* use `ajax.datasrc`, or use `ajax` as a function (see below).
*
* `function`
* ----------
*
* as a function, making the ajax call is left up to yourself allowing
* complete control of the ajax request. indeed, if desired, a method other
* than ajax could be used to obtain the required data, such as web storage
* or an air database.
*
* the function is given four parameters and no return is required. the
* parameters are:
*
* 1. _object_ - data to send to the server
* 2. _function_ - callback function that must be executed when the required
* data has been obtained. that data should be passed into the callback
* as the only parameter
* 3. _object_ - datatables settings object for the table
*
* note that this supersedes `fnserverdata` from datatables 1.9-.
*
* @type string|object|function
* @default null
*
* @dtopt option
* @name datatable.defaults.ajax
* @since 1.10.0
*
* @example
* // get json data from a file via ajax.
* // note datatables expects data in the form `{ data: [ ...data... ] }` by default).
* $('#example').datatable( {
* "ajax": "data.json"
* } );
*
* @example
* // get json data from a file via ajax, using `datasrc` to change
* // `data` to `tabledata` (i.e. `{ tabledata: [ ...data... ] }`)
* $('#example').datatable( {
* "ajax": {
* "url": "data.json",
* "datasrc": "tabledata"
* }
* } );
*
* @example
* // get json data from a file via ajax, using `datasrc` to read data
* // from a plain array rather than an array in an object
* $('#example').datatable( {
* "ajax": {
* "url": "data.json",
* "datasrc": ""
* }
* } );
*
* @example
* // manipulate the data returned from the server - add a link to data
* // (note this can, should, be done using `render` for the column - this
* // is just a simple example of how the data can be manipulated).
* $('#example').datatable( {
* "ajax": {
* "url": "data.json",
* "datasrc": function ( json ) {
* for ( var i=0, ien=json.length ; i
*
a string - class name will be matched on the th for the column
*
0 or a positive integer - column index counting from the left
*
a negative integer - column index counting from the right
*
the string "_all" - all columns (i.e. assign a default)
*
* @member
*
* @name datatable.defaults.columndefs
*/
"aocolumndefs": null,
/**
* basically the same as `search`, this parameter defines the individual column
* filtering state at initialisation time. the array must be of the same size
* as the number of columns, and each element be an object with the parameters
* `search` and `escaperegex` (the latter is optional). 'null' is also
* accepted and the default will be used.
* @type array
* @default []
*
* @dtopt option
* @name datatable.defaults.searchcols
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "searchcols": [
* null,
* { "search": "my filter" },
* null,
* { "search": "^[0-9]", "escaperegex": false }
* ]
* } );
* } )
*/
"aosearchcols": [],
/**
* an array of css classes that should be applied to displayed rows. this
* array may be of any length, and datatables will apply each class
* sequentially, looping when required.
* @type array
* @default null will take the values determined by the `oclasses.stripe*`
* options
*
* @dtopt option
* @name datatable.defaults.stripeclasses
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "stripeclasses": [ 'strip1', 'strip2', 'strip3' ]
* } );
* } )
*/
"asstripeclasses": null,
/**
* enable or disable automatic column width calculation. this can be disabled
* as an optimisation (it takes some time to calculate the widths) if the
* tables widths are passed in using `columns`.
* @type boolean
* @default true
*
* @dtopt features
* @name datatable.defaults.autowidth
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "autowidth": false
* } );
* } );
*/
"bautowidth": true,
/**
* deferred rendering can provide datatables with a huge speed boost when you
* are using an ajax or js data source for the table. this option, when set to
* true, will cause datatables to defer the creation of the table elements for
* each row until they are needed for a draw - saving a significant amount of
* time.
* @type boolean
* @default false
*
* @dtopt features
* @name datatable.defaults.deferrender
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "ajax": "sources/arrays.txt",
* "deferrender": true
* } );
* } );
*/
"bdeferrender": false,
/**
* replace a datatable which matches the given selector and replace it with
* one which has the properties of the new initialisation object passed. if no
* table matches the selector, then the new datatable will be constructed as
* per normal.
* @type boolean
* @default false
*
* @dtopt options
* @name datatable.defaults.destroy
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "srolly": "200px",
* "paginate": false
* } );
*
* // some time later....
* $('#example').datatable( {
* "filter": false,
* "destroy": true
* } );
* } );
*/
"bdestroy": false,
/**
* enable or disable filtering of data. filtering in datatables is "smart" in
* that it allows the end user to input multiple words (space separated) and
* will match a row containing those words, even if not in the order that was
* specified (this allow matching across multiple columns). note that if you
* wish to use filtering in datatables this must remain 'true' - to remove the
* default filtering input box and retain filtering abilities, please use
* {@link datatable.defaults.dom}.
* @type boolean
* @default true
*
* @dtopt features
* @name datatable.defaults.searching
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "searching": false
* } );
* } );
*/
"bfilter": true,
/**
* enable or disable the table information display. this shows information
* about the data that is currently visible on the page, including information
* about filtered data if that action is being performed.
* @type boolean
* @default true
*
* @dtopt features
* @name datatable.defaults.info
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "info": false
* } );
* } );
*/
"binfo": true,
/**
* allows the end user to select the size of a formatted page from a select
* menu (sizes are 10, 25, 50 and 100). requires pagination (`paginate`).
* @type boolean
* @default true
*
* @dtopt features
* @name datatable.defaults.lengthchange
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "lengthchange": false
* } );
* } );
*/
"blengthchange": true,
/**
* enable or disable pagination.
* @type boolean
* @default true
*
* @dtopt features
* @name datatable.defaults.paging
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "paging": false
* } );
* } );
*/
"bpaginate": true,
/**
* enable or disable the display of a 'processing' indicator when the table is
* being processed (e.g. a sort). this is particularly useful for tables with
* large amounts of data where it can take a noticeable amount of time to sort
* the entries.
* @type boolean
* @default false
*
* @dtopt features
* @name datatable.defaults.processing
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "processing": true
* } );
* } );
*/
"bprocessing": false,
/**
* retrieve the datatables object for the given selector. note that if the
* table has already been initialised, this parameter will cause datatables
* to simply return the object that has already been set up - it will not take
* account of any changes you might have made to the initialisation object
* passed to datatables (setting this parameter to true is an acknowledgement
* that you understand this). `destroy` can be used to reinitialise a table if
* you need.
* @type boolean
* @default false
*
* @dtopt options
* @name datatable.defaults.retrieve
*
* @example
* $(document).ready( function() {
* inittable();
* tableactions();
* } );
*
* function inittable ()
* {
* return $('#example').datatable( {
* "scrolly": "200px",
* "paginate": false,
* "retrieve": true
* } );
* }
*
* function tableactions ()
* {
* var table = inittable();
* // perform api operations with otable
* }
*/
"bretrieve": false,
/**
* when vertical (y) scrolling is enabled, datatables will force the height of
* the table's viewport to the given height at all times (useful for layout).
* however, this can look odd when filtering data down to a small data set,
* and the footer is left "floating" further down. this parameter (when
* enabled) will cause datatables to collapse the table's viewport down when
* the result set will fit within the given y height.
* @type boolean
* @default false
*
* @dtopt options
* @name datatable.defaults.scrollcollapse
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "scrolly": "200",
* "scrollcollapse": true
* } );
* } );
*/
"bscrollcollapse": false,
/**
* configure datatables to use server-side processing. note that the
* `ajax` parameter must also be given in order to give datatables a
* source to obtain the required data for each draw.
* @type boolean
* @default false
*
* @dtopt features
* @dtopt server-side
* @name datatable.defaults.serverside
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "serverside": true,
* "ajax": "xhr.php"
* } );
* } );
*/
"bserverside": false,
/**
* enable or disable sorting of columns. sorting of individual columns can be
* disabled by the `sortable` option for each column.
* @type boolean
* @default true
*
* @dtopt features
* @name datatable.defaults.ordering
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "ordering": false
* } );
* } );
*/
"bsort": true,
/**
* enable or display datatables' ability to sort multiple columns at the
* same time (activated by shift-click by the user).
* @type boolean
* @default true
*
* @dtopt options
* @name datatable.defaults.ordermulti
*
* @example
* // disable multiple column sorting ability
* $(document).ready( function () {
* $('#example').datatable( {
* "ordermulti": false
* } );
* } );
*/
"bsortmulti": true,
/**
* allows control over whether datatables should use the top (true) unique
* cell that is found for a single column, or the bottom (false - default).
* this is useful when using complex headers.
* @type boolean
* @default false
*
* @dtopt options
* @name datatable.defaults.ordercellstop
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "ordercellstop": true
* } );
* } );
*/
"bsortcellstop": false,
/**
* enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
* `sorting\_3` to the columns which are currently being sorted on. this is
* presented as a feature switch as it can increase processing time (while
* classes are removed and added) so for large data sets you might want to
* turn this off.
* @type boolean
* @default true
*
* @dtopt features
* @name datatable.defaults.orderclasses
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "orderclasses": false
* } );
* } );
*/
"bsortclasses": true,
/**
* enable or disable state saving. when enabled html5 `localstorage` will be
* used to save table display information such as pagination information,
* display length, filtering and sorting. as such when the end user reloads
* the page the display display will match what thy had previously set up.
*
* due to the use of `localstorage` the default state saving is not supported
* in ie6 or 7. if state saving is required in those browsers, use
* `statesavecallback` to provide a storage solution such as cookies.
* @type boolean
* @default false
*
* @dtopt features
* @name datatable.defaults.statesave
*
* @example
* $(document).ready( function () {
* $('#example').datatable( {
* "statesave": true
* } );
* } );
*/
"bstatesave": false,
/**
* this function is called when a tr element is created (and all td child
* elements have been inserted), or registered if using a dom source, allowing
* manipulation of the tr element (adding classes etc).
* @type function
* @param {node} row "tr" element for the current row
* @param {array} data raw data array for this row
* @param {int} dataindex the index of this row in the internal aodata array
*
* @dtopt callbacks
* @name datatable.defaults.createdrow
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "createdrow": function( row, data, dataindex ) {
* // bold the grade for all 'a' grade browsers
* if ( data[4] == "a" )
* {
* $('td:eq(4)', row).html( 'a' );
* }
* }
* } );
* } );
*/
"fncreatedrow": null,
/**
* this function is called on every 'draw' event, and allows you to
* dynamically modify any aspect you want about the created dom.
* @type function
* @param {object} settings datatables settings object
*
* @dtopt callbacks
* @name datatable.defaults.drawcallback
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "drawcallback": function( settings ) {
* alert( 'datatables has redrawn the table' );
* }
* } );
* } );
*/
"fndrawcallback": null,
/**
* identical to fnheadercallback() but for the table footer this function
* allows you to modify the table footer on every 'draw' event.
* @type function
* @param {node} foot "tr" element for the footer
* @param {array} data full table data (as derived from the original html)
* @param {int} start index for the current display starting point in the
* display array
* @param {int} end index for the current display ending point in the
* display array
* @param {array int} display index array to translate the visual position
* to the full data array
*
* @dtopt callbacks
* @name datatable.defaults.footercallback
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "footercallback": function( tfoot, data, start, end, display ) {
* tfoot.getelementsbytagname('th')[0].innerhtml = "starting index is "+start;
* }
* } );
* } )
*/
"fnfootercallback": null,
/**
* when rendering large numbers in the information element for the table
* (i.e. "showing 1 to 10 of 57 entries") datatables will render large numbers
* to have a comma separator for the 'thousands' units (e.g. 1 million is
* rendered as "1,000,000") to help readability for the end user. this
* function will override the default method datatables uses.
* @type function
* @member
* @param {int} toformat number to be formatted
* @returns {string} formatted string for datatables to show the number
*
* @dtopt callbacks
* @name datatable.defaults.formatnumber
*
* @example
* // format a number using a single quote for the separator (note that
* // this can also be done with the language.thousands option)
* $(document).ready( function() {
* $('#example').datatable( {
* "formatnumber": function ( toformat ) {
* return toformat.tostring().replace(
* /\b(?=(\d{3})+(?!\d))/g, "'"
* );
* };
* } );
* } );
*/
"fnformatnumber": function ( toformat ) {
return toformat.tostring().replace(
/\b(?=(\d{3})+(?!\d))/g,
this.olanguage.sthousands
);
},
/**
* this function is called on every 'draw' event, and allows you to
* dynamically modify the header row. this can be used to calculate and
* display useful information about the table.
* @type function
* @param {node} head "tr" element for the header
* @param {array} data full table data (as derived from the original html)
* @param {int} start index for the current display starting point in the
* display array
* @param {int} end index for the current display ending point in the
* display array
* @param {array int} display index array to translate the visual position
* to the full data array
*
* @dtopt callbacks
* @name datatable.defaults.headercallback
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "fheadercallback": function( head, data, start, end, display ) {
* head.getelementsbytagname('th')[0].innerhtml = "displaying "+(end-start)+" records";
* }
* } );
* } )
*/
"fnheadercallback": null,
/**
* the information element can be used to convey information about the current
* state of the table. although the internationalisation options presented by
* datatables are quite capable of dealing with most customisations, there may
* be times where you wish to customise the string further. this callback
* allows you to do exactly that.
* @type function
* @param {object} osettings datatables settings object
* @param {int} start starting position in data for the draw
* @param {int} end end position in data for the draw
* @param {int} max total number of rows in the table (regardless of
* filtering)
* @param {int} total total number of rows in the data set, after filtering
* @param {string} pre the string that datatables has formatted using it's
* own rules
* @returns {string} the string to be displayed in the information element.
*
* @dtopt callbacks
* @name datatable.defaults.infocallback
*
* @example
* $('#example').datatable( {
* "infocallback": function( settings, start, end, max, total, pre ) {
* return start +" to "+ end;
* }
* } );
*/
"fninfocallback": null,
/**
* called when the table has been initialised. normally datatables will
* initialise sequentially and there will be no need for this function,
* however, this does not hold true when using external language information
* since that is obtained using an async xhr call.
* @type function
* @param {object} settings datatables settings object
* @param {object} json the json object request from the server - only
* present if client-side ajax sourced data is used
*
* @dtopt callbacks
* @name datatable.defaults.initcomplete
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "initcomplete": function(settings, json) {
* alert( 'datatables has finished its initialisation.' );
* }
* } );
* } )
*/
"fninitcomplete": null,
/**
* called at the very start of each table draw and can be used to cancel the
* draw by returning false, any other return (including undefined) results in
* the full draw occurring).
* @type function
* @param {object} settings datatables settings object
* @returns {boolean} false will cancel the draw, anything else (including no
* return) will allow it to complete.
*
* @dtopt callbacks
* @name datatable.defaults.predrawcallback
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "predrawcallback": function( settings ) {
* if ( $('#test').val() == 1 ) {
* return false;
* }
* }
* } );
* } );
*/
"fnpredrawcallback": null,
/**
* this function allows you to 'post process' each row after it have been
* generated for each table draw, but before it is rendered on screen. this
* function might be used for setting the row class name etc.
* @type function
* @param {node} row "tr" element for the current row
* @param {array} data raw data array for this row
* @param {int} displayindex the display index for the current table draw
* @param {int} displayindexfull the index of the data in the full list of
* rows (after filtering)
*
* @dtopt callbacks
* @name datatable.defaults.rowcallback
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "rowcallback": function( row, data, displayindex, displayindexfull ) {
* // bold the grade for all 'a' grade browsers
* if ( data[4] == "a" ) {
* $('td:eq(4)', row).html( 'a' );
* }
* }
* } );
* } );
*/
"fnrowcallback": null,
/**
* __deprecated__ the functionality provided by this parameter has now been
* superseded by that provided through `ajax`, which should be used instead.
*
* this parameter allows you to override the default function which obtains
* the data from the server so something more suitable for your application.
* for example you could use post data, or pull information from a gears or
* air database.
* @type function
* @member
* @param {string} source http source to obtain the data from (`ajax`)
* @param {array} data a key/value pair object containing the data to send
* to the server
* @param {function} callback to be called on completion of the data get
* process that will draw the data on the page.
* @param {object} settings datatables settings object
*
* @dtopt callbacks
* @dtopt server-side
* @name datatable.defaults.serverdata
*
* @deprecated 1.10. please use `ajax` for this functionality now.
*/
"fnserverdata": null,
/**
* __deprecated__ the functionality provided by this parameter has now been
* superseded by that provided through `ajax`, which should be used instead.
*
* it is often useful to send extra data to the server when making an ajax
* request - for example custom filtering information, and this callback
* function makes it trivial to send extra information to the server. the
* passed in parameter is the data set that has been constructed by
* datatables, and you can add to this or modify it as you require.
* @type function
* @param {array} data data array (array of objects which are name/value
* pairs) that has been constructed by datatables and will be sent to the
* server. in the case of ajax sourced data with server-side processing
* this will be an empty array, for server-side processing there will be a
* significant number of parameters!
* @returns {undefined} ensure that you modify the data array passed in,
* as this is passed by reference.
*
* @dtopt callbacks
* @dtopt server-side
* @name datatable.defaults.serverparams
*
* @deprecated 1.10. please use `ajax` for this functionality now.
*/
"fnserverparams": null,
/**
* load the table state. with this function you can define from where, and how, the
* state of a table is loaded. by default datatables will load from `localstorage`
* but you might wish to use a server-side database or cookies.
* @type function
* @member
* @param {object} settings datatables settings object
* @param {object} callback callback that can be executed when done. it
* should be passed the loaded state object.
* @return {object} the datatables state object to be loaded
*
* @dtopt callbacks
* @name datatable.defaults.stateloadcallback
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "statesave": true,
* "stateloadcallback": function (settings, callback) {
* $.ajax( {
* "url": "/state_load",
* "datatype": "json",
* "success": function (json) {
* callback( json );
* }
* } );
* }
* } );
* } );
*/
"fnstateloadcallback": function ( settings ) {
try {
return json.parse(
(settings.istateduration === -1 ? sessionstorage : localstorage).getitem(
'datatables_'+settings.sinstance+'_'+location.pathname
)
);
} catch (e) {
return {};
}
},
/**
* callback which allows modification of the saved state prior to loading that state.
* this callback is called when the table is loading state from the stored data, but
* prior to the settings object being modified by the saved state. note that for
* plug-in authors, you should use the `stateloadparams` event to load parameters for
* a plug-in.
* @type function
* @param {object} settings datatables settings object
* @param {object} data the state object that is to be loaded
*
* @dtopt callbacks
* @name datatable.defaults.stateloadparams
*
* @example
* // remove a saved filter, so filtering is never loaded
* $(document).ready( function() {
* $('#example').datatable( {
* "statesave": true,
* "stateloadparams": function (settings, data) {
* data.osearch.ssearch = "";
* }
* } );
* } );
*
* @example
* // disallow state loading by returning false
* $(document).ready( function() {
* $('#example').datatable( {
* "statesave": true,
* "stateloadparams": function (settings, data) {
* return false;
* }
* } );
* } );
*/
"fnstateloadparams": null,
/**
* callback that is called when the state has been loaded from the state saving method
* and the datatables settings object has been modified as a result of the loaded state.
* @type function
* @param {object} settings datatables settings object
* @param {object} data the state object that was loaded
*
* @dtopt callbacks
* @name datatable.defaults.stateloaded
*
* @example
* // show an alert with the filtering value that was saved
* $(document).ready( function() {
* $('#example').datatable( {
* "statesave": true,
* "stateloaded": function (settings, data) {
* alert( 'saved filter was: '+data.osearch.ssearch );
* }
* } );
* } );
*/
"fnstateloaded": null,
/**
* save the table state. this function allows you to define where and how the state
* information for the table is stored by default datatables will use `localstorage`
* but you might wish to use a server-side database or cookies.
* @type function
* @member
* @param {object} settings datatables settings object
* @param {object} data the state object to be saved
*
* @dtopt callbacks
* @name datatable.defaults.statesavecallback
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "statesave": true,
* "statesavecallback": function (settings, data) {
* // send an ajax request to the server with the state object
* $.ajax( {
* "url": "/state_save",
* "data": data,
* "datatype": "json",
* "method": "post"
* "success": function () {}
* } );
* }
* } );
* } );
*/
"fnstatesavecallback": function ( settings, data ) {
try {
(settings.istateduration === -1 ? sessionstorage : localstorage).setitem(
'datatables_'+settings.sinstance+'_'+location.pathname,
json.stringify( data )
);
} catch (e) {}
},
/**
* callback which allows modification of the state to be saved. called when the table
* has changed state a new state save is required. this method allows modification of
* the state saving object prior to actually doing the save, including addition or
* other state properties or modification. note that for plug-in authors, you should
* use the `statesaveparams` event to save parameters for a plug-in.
* @type function
* @param {object} settings datatables settings object
* @param {object} data the state object to be saved
*
* @dtopt callbacks
* @name datatable.defaults.statesaveparams
*
* @example
* // remove a saved filter, so filtering is never saved
* $(document).ready( function() {
* $('#example').datatable( {
* "statesave": true,
* "statesaveparams": function (settings, data) {
* data.osearch.ssearch = "";
* }
* } );
* } );
*/
"fnstatesaveparams": null,
/**
* duration for which the saved state information is considered valid. after this period
* has elapsed the state will be returned to the default.
* value is given in seconds.
* @type int
* @default 7200 (2 hours)
*
* @dtopt options
* @name datatable.defaults.stateduration
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "stateduration": 60*60*24; // 1 day
* } );
* } )
*/
"istateduration": 7200,
/**
* when enabled datatables will not make a request to the server for the first
* page draw - rather it will use the data already on the page (no sorting etc
* will be applied to it), thus saving on an xhr at load time. `deferloading`
* is used to indicate that deferred loading is required, but it is also used
* to tell datatables how many records there are in the full table (allowing
* the information element and pagination to be displayed correctly). in the case
* where a filtering is applied to the table on initial load, this can be
* indicated by giving the parameter as an array, where the first element is
* the number of records available after filtering and the second element is the
* number of records without filtering (allowing the table information element
* to be shown correctly).
* @type int | array
* @default null
*
* @dtopt options
* @name datatable.defaults.deferloading
*
* @example
* // 57 records available in the table, no filtering applied
* $(document).ready( function() {
* $('#example').datatable( {
* "serverside": true,
* "ajax": "scripts/server_processing.php",
* "deferloading": 57
* } );
* } );
*
* @example
* // 57 records after filtering, 100 without filtering (an initial filter applied)
* $(document).ready( function() {
* $('#example').datatable( {
* "serverside": true,
* "ajax": "scripts/server_processing.php",
* "deferloading": [ 57, 100 ],
* "search": {
* "search": "my_filter"
* }
* } );
* } );
*/
"ideferloading": null,
/**
* number of rows to display on a single page when using pagination. if
* feature enabled (`lengthchange`) then the end user will be able to override
* this to a custom setting using a pop-up menu.
* @type int
* @default 10
*
* @dtopt options
* @name datatable.defaults.pagelength
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "pagelength": 50
* } );
* } )
*/
"idisplaylength": 10,
/**
* define the starting point for data display when using datatables with
* pagination. note that this parameter is the number of records, rather than
* the page number, so if you have 10 records per page and want to start on
* the third page, it should be "20".
* @type int
* @default 0
*
* @dtopt options
* @name datatable.defaults.displaystart
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "displaystart": 20
* } );
* } )
*/
"idisplaystart": 0,
/**
* by default datatables allows keyboard navigation of the table (sorting, paging,
* and filtering) by adding a `tabindex` attribute to the required elements. this
* allows you to tab through the controls and press the enter key to activate them.
* the tabindex is default 0, meaning that the tab follows the flow of the document.
* you can overrule this using this parameter if you wish. use a value of -1 to
* disable built-in keyboard navigation.
* @type int
* @default 0
*
* @dtopt options
* @name datatable.defaults.tabindex
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "tabindex": 1
* } );
* } );
*/
"itabindex": 0,
/**
* classes that datatables assigns to the various components and features
* that it adds to the html table. this allows classes to be configured
* during initialisation in addition to through the static
* {@link datatable.ext.ostdclasses} object).
* @namespace
* @name datatable.defaults.classes
*/
"oclasses": {},
/**
* all strings that datatables uses in the user interface that it creates
* are defined in this object, allowing you to modified them individually or
* completely replace them all as required.
* @namespace
* @name datatable.defaults.language
*/
"olanguage": {
/**
* strings that are used for wai-aria labels and controls only (these are not
* actually visible on the page, but will be read by screenreaders, and thus
* must be internationalised as well).
* @namespace
* @name datatable.defaults.language.aria
*/
"oaria": {
/**
* aria label that is added to the table headers when the column may be
* sorted ascending by activing the column (click or return when focused).
* note that the column header is prefixed to this string.
* @type string
* @default : activate to sort column ascending
*
* @dtopt language
* @name datatable.defaults.language.aria.sortascending
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "aria": {
* "sortascending": " - click/return to sort ascending"
* }
* }
* } );
* } );
*/
"ssortascending": ": activate to sort column ascending",
/**
* aria label that is added to the table headers when the column may be
* sorted descending by activing the column (click or return when focused).
* note that the column header is prefixed to this string.
* @type string
* @default : activate to sort column ascending
*
* @dtopt language
* @name datatable.defaults.language.aria.sortdescending
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "aria": {
* "sortdescending": " - click/return to sort descending"
* }
* }
* } );
* } );
*/
"ssortdescending": ": activate to sort column descending"
},
/**
* pagination string used by datatables for the built-in pagination
* control types.
* @namespace
* @name datatable.defaults.language.paginate
*/
"opaginate": {
/**
* text to use when using the 'full_numbers' type of pagination for the
* button to take the user to the first page.
* @type string
* @default first
*
* @dtopt language
* @name datatable.defaults.language.paginate.first
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "paginate": {
* "first": "first page"
* }
* }
* } );
* } );
*/
"sfirst": "first",
/**
* text to use when using the 'full_numbers' type of pagination for the
* button to take the user to the last page.
* @type string
* @default last
*
* @dtopt language
* @name datatable.defaults.language.paginate.last
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "paginate": {
* "last": "last page"
* }
* }
* } );
* } );
*/
"slast": "last",
/**
* text to use for the 'next' pagination button (to take the user to the
* next page).
* @type string
* @default next
*
* @dtopt language
* @name datatable.defaults.language.paginate.next
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "paginate": {
* "next": "next page"
* }
* }
* } );
* } );
*/
"snext": "next",
/**
* text to use for the 'previous' pagination button (to take the user to
* the previous page).
* @type string
* @default previous
*
* @dtopt language
* @name datatable.defaults.language.paginate.previous
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "paginate": {
* "previous": "previous page"
* }
* }
* } );
* } );
*/
"sprevious": "previous"
},
/**
* this string is shown in preference to `zerorecords` when the table is
* empty of data (regardless of filtering). note that this is an optional
* parameter - if it is not given, the value of `zerorecords` will be used
* instead (either the default or given value).
* @type string
* @default no data available in table
*
* @dtopt language
* @name datatable.defaults.language.emptytable
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "emptytable": "no data available in table"
* }
* } );
* } );
*/
"semptytable": "no data available in table",
/**
* this string gives information to the end user about the information
* that is current on display on the page. the following tokens can be
* used in the string and will be dynamically replaced as the table
* display updates. this tokens can be placed anywhere in the string, or
* removed as needed by the language requires:
*
* * `\_start\_` - display index of the first record on the current page
* * `\_end\_` - display index of the last record on the current page
* * `\_total\_` - number of records in the table after filtering
* * `\_max\_` - number of records in the table without filtering
* * `\_page\_` - current page number
* * `\_pages\_` - total number of pages of data in the table
*
* @type string
* @default showing _start_ to _end_ of _total_ entries
*
* @dtopt language
* @name datatable.defaults.language.info
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "info": "showing page _page_ of _pages_"
* }
* } );
* } );
*/
"sinfo": "showing _start_ to _end_ of _total_ entries",
/**
* display information string for when the table is empty. typically the
* format of this string should match `info`.
* @type string
* @default showing 0 to 0 of 0 entries
*
* @dtopt language
* @name datatable.defaults.language.infoempty
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "infoempty": "no entries to show"
* }
* } );
* } );
*/
"sinfoempty": "showing 0 to 0 of 0 entries",
/**
* when a user filters the information in a table, this string is appended
* to the information (`info`) to give an idea of how strong the filtering
* is. the variable _max_ is dynamically updated.
* @type string
* @default (filtered from _max_ total entries)
*
* @dtopt language
* @name datatable.defaults.language.infofiltered
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "infofiltered": " - filtering from _max_ records"
* }
* } );
* } );
*/
"sinfofiltered": "(filtered from _max_ total entries)",
/**
* if can be useful to append extra information to the info string at times,
* and this variable does exactly that. this information will be appended to
* the `info` (`infoempty` and `infofiltered` in whatever combination they are
* being used) at all times.
* @type string
* @default empty string
*
* @dtopt language
* @name datatable.defaults.language.infopostfix
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "infopostfix": "all records shown are derived from real information."
* }
* } );
* } );
*/
"sinfopostfix": "",
/**
* this decimal place operator is a little different from the other
* language options since datatables doesn't output floating point
* numbers, so it won't ever use this for display of a number. rather,
* what this parameter does is modify the sort methods of the table so
* that numbers which are in a format which has a character other than
* a period (`.`) as a decimal place will be sorted numerically.
*
* note that numbers with different decimal places cannot be shown in
* the same table and still be sortable, the table must be consistent.
* however, multiple different tables on the page can use different
* decimal place characters.
* @type string
* @default
*
* @dtopt language
* @name datatable.defaults.language.decimal
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "decimal": ","
* "thousands": "."
* }
* } );
* } );
*/
"sdecimal": "",
/**
* datatables has a build in number formatter (`formatnumber`) which is
* used to format large numbers that are used in the table information.
* by default a comma is used, but this can be trivially changed to any
* character you wish with this parameter.
* @type string
* @default ,
*
* @dtopt language
* @name datatable.defaults.language.thousands
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "thousands": "'"
* }
* } );
* } );
*/
"sthousands": ",",
/**
* detail the action that will be taken when the drop down menu for the
* pagination length option is changed. the '_menu_' variable is replaced
* with a default select list of 10, 25, 50 and 100, and can be replaced
* with a custom select box if required.
* @type string
* @default show _menu_ entries
*
* @dtopt language
* @name datatable.defaults.language.lengthmenu
*
* @example
* // language change only
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "lengthmenu": "display _menu_ records"
* }
* } );
* } );
*
* @example
* // language and options change
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "lengthmenu": 'display records'
* }
* } );
* } );
*/
"slengthmenu": "show _menu_ entries",
/**
* when using ajax sourced data and during the first draw when datatables is
* gathering the data, this message is shown in an empty row in the table to
* indicate to the end user the the data is being loaded. note that this
* parameter is not used when loading data by server-side processing, just
* ajax sourced data with client-side processing.
* @type string
* @default loading...
*
* @dtopt language
* @name datatable.defaults.language.loadingrecords
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "loadingrecords": "please wait - loading..."
* }
* } );
* } );
*/
"sloadingrecords": "loading...",
/**
* text which is displayed when the table is processing a user action
* (usually a sort command or similar).
* @type string
* @default processing...
*
* @dtopt language
* @name datatable.defaults.language.processing
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "processing": "datatables is currently busy"
* }
* } );
* } );
*/
"sprocessing": "processing...",
/**
* details the actions that will be taken when the user types into the
* filtering input text box. the variable "_input_", if used in the string,
* is replaced with the html text box for the filtering input allowing
* control over where it appears in the string. if "_input_" is not given
* then the input box is appended to the string automatically.
* @type string
* @default search:
*
* @dtopt language
* @name datatable.defaults.language.search
*
* @example
* // input text box will be appended at the end automatically
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "search": "filter records:"
* }
* } );
* } );
*
* @example
* // specify where the filter should appear
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "search": "apply filter _input_ to table"
* }
* } );
* } );
*/
"ssearch": "search:",
/**
* assign a `placeholder` attribute to the search `input` element
* @type string
* @default
*
* @dtopt language
* @name datatable.defaults.language.searchplaceholder
*/
"ssearchplaceholder": "",
/**
* all of the language information can be stored in a file on the
* server-side, which datatables will look up if this parameter is passed.
* it must store the url of the language file, which is in a json format,
* and the object has the same properties as the olanguage object in the
* initialiser object (i.e. the above parameters). please refer to one of
* the example language files to see how this works in action.
* @type string
* @default empty string - i.e. disabled
*
* @dtopt language
* @name datatable.defaults.language.url
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "url": "http://www.sprymedia.co.uk/datatables/lang.txt"
* }
* } );
* } );
*/
"surl": "",
/**
* text shown inside the table records when the is no information to be
* displayed after filtering. `emptytable` is shown when there is simply no
* information in the table at all (regardless of filtering).
* @type string
* @default no matching records found
*
* @dtopt language
* @name datatable.defaults.language.zerorecords
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "language": {
* "zerorecords": "no records to display"
* }
* } );
* } );
*/
"szerorecords": "no matching records found"
},
/**
* this parameter allows you to have define the global filtering state at
* initialisation time. as an object the `search` parameter must be
* defined, but all other parameters are optional. when `regex` is true,
* the search string will be treated as a regular expression, when false
* (default) it will be treated as a straight string. when `smart`
* datatables will use it's smart filtering methods (to word match at
* any point in the data), when false this will not be done.
* @namespace
* @extends datatable.models.osearch
*
* @dtopt options
* @name datatable.defaults.search
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "search": {"search": "initial search"}
* } );
* } )
*/
"osearch": $.extend( {}, datatable.models.osearch ),
/**
* __deprecated__ the functionality provided by this parameter has now been
* superseded by that provided through `ajax`, which should be used instead.
*
* by default datatables will look for the property `data` (or `aadata` for
* compatibility with datatables 1.9-) when obtaining data from an ajax
* source or for server-side processing - this parameter allows that
* property to be changed. you can use javascript dotted object notation to
* get a data source for multiple levels of nesting.
* @type string
* @default data
*
* @dtopt options
* @dtopt server-side
* @name datatable.defaults.ajaxdataprop
*
* @deprecated 1.10. please use `ajax` for this functionality now.
*/
"sajaxdataprop": "data",
/**
* __deprecated__ the functionality provided by this parameter has now been
* superseded by that provided through `ajax`, which should be used instead.
*
* you can instruct datatables to load data from an external
* source using this parameter (use adata if you want to pass data in you
* already have). simply provide a url a json object can be obtained from.
* @type string
* @default null
*
* @dtopt options
* @dtopt server-side
* @name datatable.defaults.ajaxsource
*
* @deprecated 1.10. please use `ajax` for this functionality now.
*/
"sajaxsource": null,
/**
* this initialisation variable allows you to specify exactly where in the
* dom you want datatables to inject the various controls it adds to the page
* (for example you might want the pagination controls at the top of the
* table). div elements (with or without a custom class) can also be added to
* aid styling. the follow syntax is used:
*
* @type string
* @default lfrtip (when `jqueryui` is false)or
* <"h"lfr>t<"f"ip> (when `jqueryui` is true)
*
* @dtopt options
* @name datatable.defaults.dom
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "dom": '<"top"i>rt<"bottom"flp><"clear">'
* } );
* } );
*/
"sdom": "lfrtip",
/**
* search delay option. this will throttle full table searches that use the
* datatables provided search input element (it does not effect calls to
* `dt-api search()`, providing a delay before the search is made.
* @type integer
* @default 0
*
* @dtopt options
* @name datatable.defaults.searchdelay
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "searchdelay": 200
* } );
* } )
*/
"searchdelay": null,
/**
* datatables features six different built-in options for the buttons to
* display for pagination control:
*
* * `numbers` - page number buttons only
* * `simple` - 'previous' and 'next' buttons only
* * 'simple_numbers` - 'previous' and 'next' buttons, plus page numbers
* * `full` - 'first', 'previous', 'next' and 'last' buttons
* * `full_numbers` - 'first', 'previous', 'next' and 'last' buttons, plus page numbers
* * `first_last_numbers` - 'first' and 'last' buttons, plus page numbers
*
* further methods can be added using {@link datatable.ext.opagination}.
* @type string
* @default simple_numbers
*
* @dtopt options
* @name datatable.defaults.pagingtype
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "pagingtype": "full_numbers"
* } );
* } )
*/
"spaginationtype": "simple_numbers",
/**
* enable horizontal scrolling. when a table is too wide to fit into a
* certain layout, or you have a large number of columns in the table, you
* can enable x-scrolling to show the table in a viewport, which can be
* scrolled. this property can be `true` which will allow the table to
* scroll horizontally when needed, or any css unit, or a number (in which
* case it will be treated as a pixel measurement). setting as simply `true`
* is recommended.
* @type boolean|string
* @default blank string - i.e. disabled
*
* @dtopt features
* @name datatable.defaults.scrollx
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "scrollx": true,
* "scrollcollapse": true
* } );
* } );
*/
"sscrollx": "",
/**
* this property can be used to force a datatable to use more width than it
* might otherwise do when x-scrolling is enabled. for example if you have a
* table which requires to be well spaced, this parameter is useful for
* "over-sizing" the table, and thus forcing scrolling. this property can by
* any css unit, or a number (in which case it will be treated as a pixel
* measurement).
* @type string
* @default blank string - i.e. disabled
*
* @dtopt options
* @name datatable.defaults.scrollxinner
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "scrollx": "100%",
* "scrollxinner": "110%"
* } );
* } );
*/
"sscrollxinner": "",
/**
* enable vertical scrolling. vertical scrolling will constrain the datatable
* to the given height, and enable scrolling for any data which overflows the
* current viewport. this can be used as an alternative to paging to display
* a lot of data in a small area (although paging and scrolling can both be
* enabled at the same time). this property can be any css unit, or a number
* (in which case it will be treated as a pixel measurement).
* @type string
* @default blank string - i.e. disabled
*
* @dtopt features
* @name datatable.defaults.scrolly
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "scrolly": "200px",
* "paginate": false
* } );
* } );
*/
"sscrolly": "",
/**
* __deprecated__ the functionality provided by this parameter has now been
* superseded by that provided through `ajax`, which should be used instead.
*
* set the http method that is used to make the ajax call for server-side
* processing or ajax sourced data.
* @type string
* @default get
*
* @dtopt options
* @dtopt server-side
* @name datatable.defaults.servermethod
*
* @deprecated 1.10. please use `ajax` for this functionality now.
*/
"sservermethod": "get",
/**
* datatables makes use of renderers when displaying html elements for
* a table. these renderers can be added or modified by plug-ins to
* generate suitable mark-up for a site. for example the bootstrap
* integration plug-in for datatables uses a paging button renderer to
* display pagination buttons in the mark-up required by bootstrap.
*
* for further information about the renderers available see
* datatable.ext.renderer
* @type string|object
* @default null
*
* @name datatable.defaults.renderer
*
*/
"renderer": null,
/**
* set the data property name that datatables should use to get a row's id
* to set as the `id` property in the node.
* @type string
* @default dt_rowid
*
* @name datatable.defaults.rowid
*/
"rowid": "dt_rowid"
};
_fnhungarianmap( datatable.defaults );
/*
* developer note - see note in model.defaults.js about the use of hungarian
* notation and camel case.
*/
/**
* column options that can be given to datatables at initialisation time.
* @namespace
*/
datatable.defaults.column = {
/**
* define which column(s) an order will occur on for this column. this
* allows a column's ordering to take multiple columns into account when
* doing a sort or use the data from a different column. for example first
* name / last name columns make sense to do a multi-column sort over the
* two columns.
* @type array|int
* @default null takes the value of the column index automatically
*
* @name datatable.defaults.column.orderdata
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "orderdata": [ 0, 1 ], "targets": [ 0 ] },
* { "orderdata": [ 1, 0 ], "targets": [ 1 ] },
* { "orderdata": 2, "targets": [ 2 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "orderdata": [ 0, 1 ] },
* { "orderdata": [ 1, 0 ] },
* { "orderdata": 2 },
* null,
* null
* ]
* } );
* } );
*/
"adatasort": null,
"idatasort": -1,
/**
* you can control the default ordering direction, and even alter the
* behaviour of the sort handler (i.e. only allow ascending ordering etc)
* using this parameter.
* @type array
* @default [ 'asc', 'desc' ]
*
* @name datatable.defaults.column.ordersequence
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "ordersequence": [ "asc" ], "targets": [ 1 ] },
* { "ordersequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
* { "ordersequence": [ "desc" ], "targets": [ 3 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* null,
* { "ordersequence": [ "asc" ] },
* { "ordersequence": [ "desc", "asc", "asc" ] },
* { "ordersequence": [ "desc" ] },
* null
* ]
* } );
* } );
*/
"assorting": [ 'asc', 'desc' ],
/**
* enable or disable filtering on the data in this column.
* @type boolean
* @default true
*
* @name datatable.defaults.column.searchable
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "searchable": false, "targets": [ 0 ] }
* ] } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "searchable": false },
* null,
* null,
* null,
* null
* ] } );
* } );
*/
"bsearchable": true,
/**
* enable or disable ordering on this column.
* @type boolean
* @default true
*
* @name datatable.defaults.column.orderable
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "orderable": false, "targets": [ 0 ] }
* ] } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "orderable": false },
* null,
* null,
* null,
* null
* ] } );
* } );
*/
"bsortable": true,
/**
* enable or disable the display of this column.
* @type boolean
* @default true
*
* @name datatable.defaults.column.visible
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "visible": false, "targets": [ 0 ] }
* ] } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "visible": false },
* null,
* null,
* null,
* null
* ] } );
* } );
*/
"bvisible": true,
/**
* developer definable function that is called whenever a cell is created (ajax source,
* etc) or processed for input (dom source). this can be used as a compliment to mrender
* allowing you to modify the dom element (add background colour for example) when the
* element is available.
* @type function
* @param {element} td the td node that has been created
* @param {*} celldata the data for the cell
* @param {array|object} rowdata the data for the whole row
* @param {int} row the row index for the aodata data store
* @param {int} col the column index for aocolumns
*
* @name datatable.defaults.column.createdcell
* @dtopt columns
*
* @example
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [3],
* "createdcell": function (td, celldata, rowdata, row, col) {
* if ( celldata == "1.7" ) {
* $(td).css('color', 'blue')
* }
* }
* } ]
* });
* } );
*/
"fncreatedcell": null,
/**
* this parameter has been replaced by `data` in datatables to ensure naming
* consistency. `dataprop` can still be used, as there is backwards
* compatibility in datatables for this option, but it is strongly
* recommended that you use `data` in preference to `dataprop`.
* @name datatable.defaults.column.dataprop
*/
/**
* this property can be used to read data from any data source property,
* including deeply nested objects / properties. `data` can be given in a
* number of different ways which effect its behaviour:
*
* * `integer` - treated as an array index for the data source. this is the
* default that datatables uses (incrementally increased for each column).
* * `string` - read an object property from the data source. there are
* three 'special' options that can be used in the string to alter how
* datatables reads the data from the source object:
* * `.` - dotted javascript notation. just as you use a `.` in
* javascript to read from nested objects, so to can the options
* specified in `data`. for example: `browser.version` or
* `browser.name`. if your object parameter name contains a period, use
* `\\` to escape it - i.e. `first\\.name`.
* * `[]` - array notation. datatables can automatically combine data
* from and array source, joining the data with the characters provided
* between the two brackets. for example: `name[, ]` would provide a
* comma-space separated list from the source array. if no characters
* are provided between the brackets, the original array source is
* returned.
* * `()` - function notation. adding `()` to the end of a parameter will
* execute a function of the name given. for example: `browser()` for a
* simple function on the data source, `browser.version()` for a
* function in a nested property or even `browser().version` to get an
* object property if the function called returns an object. note that
* function notation is recommended for use in `render` rather than
* `data` as it is much simpler to use as a renderer.
* * `null` - use the original data source for the row rather than plucking
* data directly from it. this action has effects on two other
* initialisation options:
* * `defaultcontent` - when null is given as the `data` option and
* `defaultcontent` is specified for the column, the value defined by
* `defaultcontent` will be used for the cell.
* * `render` - when null is used for the `data` option and the `render`
* option is specified for the column, the whole data source for the
* row is used for the renderer.
* * `function` - the function given will be executed whenever datatables
* needs to set or get the data for a cell in the column. the function
* takes three parameters:
* * parameters:
* * `{array|object}` the data source for the row
* * `{string}` the type call data requested - this will be 'set' when
* setting data or 'filter', 'display', 'type', 'sort' or undefined
* when gathering data. note that when `undefined` is given for the
* type datatables expects to get the raw data for the object back<
* * `{*}` data to set when the second parameter is 'set'.
* * return:
* * the return value from the function is not required when 'set' is
* the type of call, but otherwise the return is what will be used
* for the data requested.
*
* note that `data` is a getter and setter option. if you just require
* formatting of data for output, you will likely want to use `render` which
* is simply a getter and thus simpler to use.
*
* note that prior to datatables 1.9.2 `data` was called `mdataprop`. the
* name change reflects the flexibility of this property and is consistent
* with the naming of mrender. if 'mdataprop' is given, then it will still
* be used by datatables, as it automatically maps the old name to the new
* if required.
*
* @type string|int|function|null
* @default null use automatically calculated column index
*
* @name datatable.defaults.column.data
* @dtopt columns
*
* @example
* // read table data from objects
* // json structure for each row:
* // {
* // "engine": {value},
* // "browser": {value},
* // "platform": {value},
* // "version": {value},
* // "grade": {value}
* // }
* $(document).ready( function() {
* $('#example').datatable( {
* "ajaxsource": "sources/objects.txt",
* "columns": [
* { "data": "engine" },
* { "data": "browser" },
* { "data": "platform" },
* { "data": "version" },
* { "data": "grade" }
* ]
* } );
* } );
*
* @example
* // read information from deeply nested objects
* // json structure for each row:
* // {
* // "engine": {value},
* // "browser": {value},
* // "platform": {
* // "inner": {value}
* // },
* // "details": [
* // {value}, {value}
* // ]
* // }
* $(document).ready( function() {
* $('#example').datatable( {
* "ajaxsource": "sources/deep.txt",
* "columns": [
* { "data": "engine" },
* { "data": "browser" },
* { "data": "platform.inner" },
* { "data": "details.0" },
* { "data": "details.1" }
* ]
* } );
* } );
*
* @example
* // using `data` as a function to provide different information for
* // sorting, filtering and display. in this case, currency (price)
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [ 0 ],
* "data": function ( source, type, val ) {
* if (type === 'set') {
* source.price = val;
* // store the computed dislay and filter values for efficiency
* source.price_display = val=="" ? "" : "$"+numberformat(val);
* source.price_filter = val=="" ? "" : "$"+numberformat(val)+" "+val;
* return;
* }
* else if (type === 'display') {
* return source.price_display;
* }
* else if (type === 'filter') {
* return source.price_filter;
* }
* // 'sort', 'type' and undefined all just use the integer
* return source.price;
* }
* } ]
* } );
* } );
*
* @example
* // using default content
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [ 0 ],
* "data": null,
* "defaultcontent": "click to edit"
* } ]
* } );
* } );
*
* @example
* // using array notation - outputting a list from an array
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [ 0 ],
* "data": "name[, ]"
* } ]
* } );
* } );
*
*/
"mdata": null,
/**
* this property is the rendering partner to `data` and it is suggested that
* when you want to manipulate data for display (including filtering,
* sorting etc) without altering the underlying data for the table, use this
* property. `render` can be considered to be the the read only companion to
* `data` which is read / write (then as such more complex). like `data`
* this option can be given in a number of different ways to effect its
* behaviour:
*
* * `integer` - treated as an array index for the data source. this is the
* default that datatables uses (incrementally increased for each column).
* * `string` - read an object property from the data source. there are
* three 'special' options that can be used in the string to alter how
* datatables reads the data from the source object:
* * `.` - dotted javascript notation. just as you use a `.` in
* javascript to read from nested objects, so to can the options
* specified in `data`. for example: `browser.version` or
* `browser.name`. if your object parameter name contains a period, use
* `\\` to escape it - i.e. `first\\.name`.
* * `[]` - array notation. datatables can automatically combine data
* from and array source, joining the data with the characters provided
* between the two brackets. for example: `name[, ]` would provide a
* comma-space separated list from the source array. if no characters
* are provided between the brackets, the original array source is
* returned.
* * `()` - function notation. adding `()` to the end of a parameter will
* execute a function of the name given. for example: `browser()` for a
* simple function on the data source, `browser.version()` for a
* function in a nested property or even `browser().version` to get an
* object property if the function called returns an object.
* * `object` - use different data for the different data types requested by
* datatables ('filter', 'display', 'type' or 'sort'). the property names
* of the object is the data type the property refers to and the value can
* defined using an integer, string or function using the same rules as
* `render` normally does. note that an `_` option _must_ be specified.
* this is the default value to use if you haven't specified a value for
* the data type requested by datatables.
* * `function` - the function given will be executed whenever datatables
* needs to set or get the data for a cell in the column. the function
* takes three parameters:
* * parameters:
* * {array|object} the data source for the row (based on `data`)
* * {string} the type call data requested - this will be 'filter',
* 'display', 'type' or 'sort'.
* * {array|object} the full data source for the row (not based on
* `data`)
* * return:
* * the return value from the function is what will be used for the
* data requested.
*
* @type string|int|function|object|null
* @default null use the data source value.
*
* @name datatable.defaults.column.render
* @dtopt columns
*
* @example
* // create a comma separated list from an array of objects
* $(document).ready( function() {
* $('#example').datatable( {
* "ajaxsource": "sources/deep.txt",
* "columns": [
* { "data": "engine" },
* { "data": "browser" },
* {
* "data": "platform",
* "render": "[, ].name"
* }
* ]
* } );
* } );
*
* @example
* // execute a function to obtain data
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [ 0 ],
* "data": null, // use the full data source object for the renderer's source
* "render": "browsername()"
* } ]
* } );
* } );
*
* @example
* // as an object, extracting different data for the different types
* // this would be used with a data source such as:
* // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
* // here the `phone` integer is used for sorting and type detection, while `phone_filter`
* // (which has both forms) is used for filtering for if a user inputs either format, while
* // the formatted phone number is the one that is shown in the table.
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [ 0 ],
* "data": null, // use the full data source object for the renderer's source
* "render": {
* "_": "phone",
* "filter": "phone_filter",
* "display": "phone_display"
* }
* } ]
* } );
* } );
*
* @example
* // use as a function to create a link from the data source
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [ 0 ],
* "data": "download_link",
* "render": function ( data, type, full ) {
* return 'download';
* }
* } ]
* } );
* } );
*/
"mrender": null,
/**
* change the cell type created for the column - either td cells or th cells. this
* can be useful as th cells have semantic meaning in the table body, allowing them
* to act as a header for a row (you may wish to add scope='row' to the th elements).
* @type string
* @default td
*
* @name datatable.defaults.column.celltype
* @dtopt columns
*
* @example
* // make the first column use th cells
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [ {
* "targets": [ 0 ],
* "celltype": "th"
* } ]
* } );
* } );
*/
"scelltype": "td",
/**
* class to give to each cell in this column.
* @type string
* @default empty string
*
* @name datatable.defaults.column.class
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "class": "my_class", "targets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "class": "my_class" },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"sclass": "",
/**
* when datatables calculates the column widths to assign to each column,
* it finds the longest string in each column and then constructs a
* temporary table and reads the widths from that. the problem with this
* is that "mmm" is much wider then "iiii", but the latter is a longer
* string - thus the calculation can go wrong (doing it properly and putting
* it into an dom object and measuring that is horribly(!) slow). thus as
* a "work around" we provide this option. it will append its value to the
* text that is found to be the longest string for the column - i.e. padding.
* generally you shouldn't need this!
* @type string
* @default empty string
*
* @name datatable.defaults.column.contentpadding
* @dtopt columns
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* null,
* null,
* null,
* {
* "contentpadding": "mmm"
* }
* ]
* } );
* } );
*/
"scontentpadding": "",
/**
* allows a default value to be given for a column's data, and will be used
* whenever a null data source is encountered (this can be because `data`
* is set to null, or because the data source itself is null).
* @type string
* @default null
*
* @name datatable.defaults.column.defaultcontent
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* {
* "data": null,
* "defaultcontent": "edit",
* "targets": [ -1 ]
* }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* null,
* null,
* null,
* {
* "data": null,
* "defaultcontent": "edit"
* }
* ]
* } );
* } );
*/
"sdefaultcontent": null,
/**
* this parameter is only used in datatables' server-side processing. it can
* be exceptionally useful to know what columns are being displayed on the
* client side, and to map these to database fields. when defined, the names
* also allow datatables to reorder information from the server if it comes
* back in an unexpected order (i.e. if you switch your columns around on the
* client-side, your server-side code does not also need updating).
* @type string
* @default empty string
*
* @name datatable.defaults.column.name
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "name": "engine", "targets": [ 0 ] },
* { "name": "browser", "targets": [ 1 ] },
* { "name": "platform", "targets": [ 2 ] },
* { "name": "version", "targets": [ 3 ] },
* { "name": "grade", "targets": [ 4 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "name": "engine" },
* { "name": "browser" },
* { "name": "platform" },
* { "name": "version" },
* { "name": "grade" }
* ]
* } );
* } );
*/
"sname": "",
/**
* defines a data source type for the ordering which can be used to read
* real-time information from the table (updating the internally cached
* version) prior to ordering. this allows ordering to occur on user
* editable elements such as form inputs.
* @type string
* @default std
*
* @name datatable.defaults.column.orderdatatype
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "orderdatatype": "dom-text", "targets": [ 2, 3 ] },
* { "type": "numeric", "targets": [ 3 ] },
* { "orderdatatype": "dom-select", "targets": [ 4 ] },
* { "orderdatatype": "dom-checkbox", "targets": [ 5 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* null,
* null,
* { "orderdatatype": "dom-text" },
* { "orderdatatype": "dom-text", "type": "numeric" },
* { "orderdatatype": "dom-select" },
* { "orderdatatype": "dom-checkbox" }
* ]
* } );
* } );
*/
"ssortdatatype": "std",
/**
* the title of this column.
* @type string
* @default null derived from the 'th' value for this column in the
* original html table.
*
* @name datatable.defaults.column.title
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "title": "my column title", "targets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "title": "my column title" },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"stitle": null,
/**
* the type allows you to specify how the data for this column will be
* ordered. four types (string, numeric, date and html (which will strip
* html tags before ordering)) are currently available. note that only date
* formats understood by javascript's date() object will be accepted as type
* date. for example: "mar 26, 2008 5:03 pm". may take the values: 'string',
* 'numeric', 'date' or 'html' (by default). further types can be adding
* through plug-ins.
* @type string
* @default null auto-detected from raw data
*
* @name datatable.defaults.column.type
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "type": "html", "targets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "type": "html" },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"stype": null,
/**
* defining the width of the column, this parameter may take any css value
* (3em, 20px etc). datatables applies 'smart' widths to columns which have not
* been given a specific width through this interface ensuring that the table
* remains readable.
* @type string
* @default null automatic
*
* @name datatable.defaults.column.width
* @dtopt columns
*
* @example
* // using `columndefs`
* $(document).ready( function() {
* $('#example').datatable( {
* "columndefs": [
* { "width": "20%", "targets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // using `columns`
* $(document).ready( function() {
* $('#example').datatable( {
* "columns": [
* { "width": "20%" },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"swidth": null
};
_fnhungarianmap( datatable.defaults.column );
/**
* datatables settings object - this holds all the information needed for a
* given table, including configuration, data and current application of the
* table options. datatables does not have a single instance for each datatable
* with the settings attached to that instance, but rather instances of the
* datatable "class" are created on-the-fly as needed (typically by a
* $().datatable() call) and the settings object is then applied to that
* instance.
*
* note that this object is related to {@link datatable.defaults} but this
* one is the internal data store for datatables's cache of columns. it should
* not be manipulated outside of datatables. any configuration should be done
* through the initialisation options.
* @namespace
* @todo really should attach the settings object to individual instances so we
* don't need to create new instances on each $().datatable() call (if the
* table already exists). it would also save passing osettings around and
* into every single function. however, this is a very significant
* architecture change for datatables and will almost certainly break
* backwards compatibility with older installations. this is something that
* will be done in 2.0.
*/
datatable.models.osettings = {
/**
* primary features of datatables and their enablement state.
* @namespace
*/
"ofeatures": {
/**
* flag to say if datatables should automatically try to calculate the
* optimum table and columns widths (true) or not (false).
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bautowidth": null,
/**
* delay the creation of tr and td elements until they are actually
* needed by a driven page draw. this can give a significant speed
* increase for ajax source and javascript source data, but makes no
* difference at all fro dom and server-side processing tables.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bdeferrender": null,
/**
* enable filtering on the table or not. note that if this is disabled
* then there is no filtering at all on the table, including fnfilter.
* to just remove the filtering input use sdom and remove the 'f' option.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bfilter": null,
/**
* table information element (the 'showing x of y records' div) enable
* flag.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"binfo": null,
/**
* present a user control allowing the end user to change the page size
* when pagination is enabled.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"blengthchange": null,
/**
* pagination enabled or not. note that if this is disabled then length
* changing must also be disabled.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bpaginate": null,
/**
* processing indicator enable flag whenever datatables is enacting a
* user request - typically an ajax request for server-side processing.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bprocessing": null,
/**
* server-side processing enabled flag - when enabled datatables will
* get all data from the server for every draw - there is no filtering,
* sorting or paging done on the client-side.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bserverside": null,
/**
* sorting enablement flag.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bsort": null,
/**
* multi-column sorting
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bsortmulti": null,
/**
* apply a class to the columns which are being sorted to provide a
* visual highlight or not. this can slow things down when enabled since
* there is a lot of dom interaction.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bsortclasses": null,
/**
* state saving enablement flag.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bstatesave": null
},
/**
* scrolling settings for a table.
* @namespace
*/
"oscroll": {
/**
* when the table is shorter in height than sscrolly, collapse the
* table container down to the height of the table (when true).
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
*/
"bcollapse": null,
/**
* width of the scrollbar for the web-browser's platform. calculated
* during table initialisation.
* @type int
* @default 0
*/
"ibarwidth": 0,
/**
* viewport width for horizontal scrolling. horizontal scrolling is
* disabled if an empty string.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type string
*/
"sx": null,
/**
* width to expand the table to when using x-scrolling. typically you
* should not need to use this.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type string
* @deprecated
*/
"sxinner": null,
/**
* viewport height for vertical scrolling. vertical scrolling is disabled
* if an empty string.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type string
*/
"sy": null
},
/**
* language information for the table.
* @namespace
* @extends datatable.defaults.olanguage
*/
"olanguage": {
/**
* information callback function. see
* {@link datatable.defaults.fninfocallback}
* @type function
* @default null
*/
"fninfocallback": null
},
/**
* browser support parameters
* @namespace
*/
"obrowser": {
/**
* indicate if the browser incorrectly calculates width:100% inside a
* scrolling element (ie6/7)
* @type boolean
* @default false
*/
"bscrolloversize": false,
/**
* determine if the vertical scrollbar is on the right or left of the
* scrolling container - needed for rtl language layout, although not
* all browsers move the scrollbar (safari).
* @type boolean
* @default false
*/
"bscrollbarleft": false,
/**
* flag for if `getboundingclientrect` is fully supported or not
* @type boolean
* @default false
*/
"bbounding": false,
/**
* browser scrollbar width
* @type integer
* @default 0
*/
"barwidth": 0
},
"ajax": null,
/**
* array referencing the nodes which are used for the features. the
* parameters of this object match what is allowed by sdom - i.e.
*
*
'l' - length changing
*
'f' - filtering input
*
't' - the table!
*
'i' - information
*
'p' - pagination
*
'r' - processing
*
* @type array
* @default []
*/
"aanfeatures": [],
/**
* store data information - see {@link datatable.models.orow} for detailed
* information.
* @type array
* @default []
*/
"aodata": [],
/**
* array of indexes which are in the current display (after filtering etc)
* @type array
* @default []
*/
"aidisplay": [],
/**
* array of indexes for display - no filtering
* @type array
* @default []
*/
"aidisplaymaster": [],
/**
* map of row ids to data indexes
* @type object
* @default {}
*/
"aids": {},
/**
* store information about each column that is in use
* @type array
* @default []
*/
"aocolumns": [],
/**
* store information about the table's header
* @type array
* @default []
*/
"aoheader": [],
/**
* store information about the table's footer
* @type array
* @default []
*/
"aofooter": [],
/**
* store the applied global search information in case we want to force a
* research or compare the old search to a new one.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @namespace
* @extends datatable.models.osearch
*/
"oprevioussearch": {},
/**
* store the applied search for each column - see
* {@link datatable.models.osearch} for the format that is used for the
* filtering information for each column.
* @type array
* @default []
*/
"aopresearchcols": [],
/**
* sorting that is applied to the table. note that the inner arrays are
* used in the following manner:
*
*
index 0 - column number
*
index 1 - current sorting direction
*
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type array
* @todo these inner arrays should really be objects
*/
"aasorting": null,
/**
* sorting that is always applied to the table (i.e. prefixed in front of
* aasorting).
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type array
* @default []
*/
"aasortingfixed": [],
/**
* classes to use for the striping of a table.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type array
* @default []
*/
"asstripeclasses": null,
/**
* if restoring a table - we should restore its striping classes as well
* @type array
* @default []
*/
"asdestroystripes": [],
/**
* if restoring a table - we should restore its width
* @type int
* @default 0
*/
"sdestroywidth": 0,
/**
* callback functions array for every time a row is inserted (i.e. on a draw).
* @type array
* @default []
*/
"aorowcallback": [],
/**
* callback functions for the header on each draw.
* @type array
* @default []
*/
"aoheadercallback": [],
/**
* callback function for the footer on each draw.
* @type array
* @default []
*/
"aofootercallback": [],
/**
* array of callback functions for draw callback functions
* @type array
* @default []
*/
"aodrawcallback": [],
/**
* array of callback functions for row created function
* @type array
* @default []
*/
"aorowcreatedcallback": [],
/**
* callback functions for just before the table is redrawn. a return of
* false will be used to cancel the draw.
* @type array
* @default []
*/
"aopredrawcallback": [],
/**
* callback functions for when the table has been initialised.
* @type array
* @default []
*/
"aoinitcomplete": [],
/**
* callbacks for modifying the settings to be stored for state saving, prior to
* saving state.
* @type array
* @default []
*/
"aostatesaveparams": [],
/**
* callbacks for modifying the settings that have been stored for state saving
* prior to using the stored values to restore the state.
* @type array
* @default []
*/
"aostateloadparams": [],
/**
* callbacks for operating on the settings object once the saved state has been
* loaded
* @type array
* @default []
*/
"aostateloaded": [],
/**
* cache the table id for quick access
* @type string
* @default empty string
*/
"stableid": "",
/**
* the table node for the main table
* @type node
* @default null
*/
"ntable": null,
/**
* permanent ref to the thead element
* @type node
* @default null
*/
"nthead": null,
/**
* permanent ref to the tfoot element - if it exists
* @type node
* @default null
*/
"ntfoot": null,
/**
* permanent ref to the tbody element
* @type node
* @default null
*/
"ntbody": null,
/**
* cache the wrapper node (contains all datatables controlled elements)
* @type node
* @default null
*/
"ntablewrapper": null,
/**
* indicate if when using server-side processing the loading of data
* should be deferred until the second draw.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type boolean
* @default false
*/
"bdeferloading": false,
/**
* indicate if all required information has been read in
* @type boolean
* @default false
*/
"binitialised": false,
/**
* information about open rows. each object in the array has the parameters
* 'ntr' and 'nparent'
* @type array
* @default []
*/
"aoopenrows": [],
/**
* dictate the positioning of datatables' control elements - see
* {@link datatable.model.oinit.sdom}.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type string
* @default null
*/
"sdom": null,
/**
* search delay (in ms)
* @type integer
* @default null
*/
"searchdelay": null,
/**
* which type of pagination should be used.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type string
* @default two_button
*/
"spaginationtype": "two_button",
/**
* the state duration (for `statesave`) in seconds.
* note that this parameter will be set by the initialisation routine. to
* set a default use {@link datatable.defaults}.
* @type int
* @default 0
*/
"istateduration": 0,
/**
* array of callback functions for state saving. each array element is an
* object with the following parameters:
*
*
function:fn - function to call. takes two parameters, osettings
* and the json string to save that has been thus far created. returns
* a json string to be inserted into a json object
* (i.e. '"param": [ 0, 1, 2]')
*
string:sname - name of callback
*
* @type array
* @default []
*/
"aostatesave": [],
/**
* array of callback functions for state loading. each array element is an
* object with the following parameters:
*
*
function:fn - function to call. takes two parameters, osettings
* and the object stored. may return false to cancel state loading