求助 关于Optimize Start Menu Cache Files任务计划任务

[4/8] remove the dev/ files (since we run require.js optimize we don't need that copy of original JS source), and fix some broken usages of old path to brooklyn files
brooklyn-commits mailing list archives
Message view
rich...@apache.org
[4/8] remove the dev/ files (since we run require.js optimize we don't need that copy of original JS source), and fix some broken usages of old path to brooklyn files
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b601f3ab/usage/jsgui/src/main/dev/js/libs/jquery.dataTables.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/dev/js/libs/jquery.dataTables.js b/usage/jsgui/src/main/dev/js/libs/jquery.dataTables.js
deleted file mode 100644
index 1d8a220..0000000
--- a/usage/jsgui/src/main/dev/js/libs/jquery.dataTables.js
+++ /dev/null
@@ -1,1 @@
- * @summary
DataTables
- * @description Paginate, search and sort HTML tables
- * @version
jquery.dataTables.js
- * @author
Allan Jardine (www.sprymedia.co.uk)
- * @contact
www.sprymedia.co.uk/contact
- * @copyright Copyright
Allan Jardine, all rights reserved.
- * This source file is free software, under either the GPL v2 license or a
- * BSD style license, available at:
http://datatables.net/license_gpl2
http://datatables.net/license_bsd
- * This source file is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
- * For details please refer to: http://www.datatables.net
-/*jslint evil: true, undef: true, browser: true */
-/*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_
fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/
-(/** @lends &global& */function( window, document, undefined ) {
-(function( factory ) {
- "use strict";
- // Define as an AMD module if possible
- if ( typeof define === 'function' && define.amd )
define( ['jquery'], factory );
- /* Define using browser globals otherwise
* Prevent multiple instantiations if the script is loaded twice
- else if ( jQuery && !jQuery.fn.dataTable )
factory( jQuery );
-(/** @lends &global& */function( $ ) {
- "use strict";
* DataTables is a plug-in for the jQuery Javascript library. It is a
* highly flexible tool, based upon the foundations of progressive
* enhancement, which will add advanced interaction controls to any
* HTML table. For a full list of features please refer to
* &a href="http://datatables.net"&DataTables.net&/a&.
* Note that the &i&DataTable&/i& object is not a global variable but is
* aliased to &i&jQuery.fn.DataTable&/i& and &i&jQuery.fn.dataTable&/i& through which
* it may be
@param {object} [oInit={}] Configuration object for DataTables. Options
are defined by {@link DataTable.defaults}
@requires jQuery 1.3+
// Basic initialisation
$(document).ready( function {
$('#example').dataTable();
// Initialisation with configuration options - in this case, disable
// pagination and sorting.
$(document).ready( function {
$('#example').dataTable( {
"bPaginate": false,
"bSort": false
- var DataTable = function( oInit )
* 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 )
var oDefaults = DataTable.defaults.
var iCol = oSettings.aoColumns.
var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
"sSortingClass": oSettings.oClasses.sSortable,
"sSortingClassJUI": oSettings.oClasses.sSortJUI,
"nTh": nTh ? nTh : document.createElement('th'),
oDefaults.sTitle
? oDefaults.sTitle
: nTh ? nTh.innerHTML : '',
"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
"mData": oDefaults.mData ? oDefaults.oDefaults : iCol
oSettings.aoColumns.push( oCol );
/* Add a column specific filter */
if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )
oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch );
var oPre = oSettings.aoPreSearchCols[ iCol ];
/* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
if ( oPre.bRegex === undefined )
oPre.bRegex =
if ( oPre.bSmart === undefined )
oPre.bSmart =
if ( oPre.bCaseInsensitive === undefined )
oPre.bCaseInsensitive =
/* Use the column options function to initialise classes etc */
_fnColumnOptions( oSettings, iCol, null );
* 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 ];
/* User specified column options */
if ( oOptions !== undefined && oOptions !== null )
/* Backwards compatibility for mDataProp */
if ( oOptions.mDataProp && !oOptions.mData )
oOptions.mData = oOptions.mDataP
if ( oOptions.sType !== undefined )
oCol.sType = oOptions.sT
oCol._bAutoType =
$.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 mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) :
var mData = _fnGetObjectDataFn( oCol.mData );
oCol.fnGetData = function (oData, sSpecific) {
var innerData = mData( oData, sSpecific );
if ( oCol.mRender && (sSpecific && sSpecific !== '') )
return mRender( innerData, sSpecific, oData );
return innerD
oCol.fnSetData = _fnSetObjectDataFn( oCol.mData );
/* Feature sorting overrides column specific when off */
if ( !oSettings.oFeatures.bSort )
oCol.bSortable =
/* Check that the class assignment is correct for sorting */
if ( !oCol.bSortable ||
($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
oCol.sSortingClass = oSettings.oClasses.sSortableN
oCol.sSortingClassJUI = "";
else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 )
oCol.sSortingClass = oSettings.oClasses.sS
oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
oCol.sSortingClass = oSettings.oClasses.sSortableA
oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscA
else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
oCol.sSortingClass = oSettings.oClasses.sSortableD
oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescA
* Adjust the table column widths for new data. Note: you would probably want to
* do a redraw after calling this function!
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnAdjustColumnSizing ( oSettings )
/* Not interested in doing column width calculation if auto-width is disabled */
if ( oSettings.oFeatures.bAutoWidth === false )
_fnCalculateColumnWidths( oSettings );
for ( var i=0 , iLen=oSettings.aoColumns. i&iL i++ )
oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sW
* Covert the index of a visible column to the index in the data array (take account
* of hidden columns)
@param {object} oSettings dataTables settings object
@param {int} iMatch Visible column index to lookup
@returns {int} i the data index
@memberof DataTable#oApi
function _fnVisibleToColumnIndex( oSettings, iMatch )
var aiVis = _fnGetColumns( oSettings, 'bVisible' );
return typeof aiVis[iMatch] === 'number' ?
aiVis[iMatch] :
* Covert the index of an index in the data array and convert it to the visible
column index (take account of hidden columns)
@param {int} iMatch Column index to lookup
@param {object} oSettings dataTables settings object
@returns {int} i the data index
@memberof DataTable#oApi
function _fnColumnIndexToVisible( oSettings, iMatch )
var aiVis = _fnGetColumns( oSettings, 'bVisible' );
var iPos = $.inArray( iMatch, aiVis );
return iPos !== -1 ? iPos :
* Get the number of visible columns
@param {object} oSettings dataTables settings object
@returns {int} i the number of visible columns
@memberof DataTable#oApi
function _fnVisbleColumns( oSettings )
return _fnGetColumns( oSettings, 'bVisible' ).
* Get an array of column indexes that match a given property
@param {object} oSettings dataTables settings object
@param {string} sParam Parameter in aoColumns to look for - typically
bVisible or bSearchable
@returns {array} Array of indexes with matched properties
@memberof DataTable#oApi
function _fnGetColumns( oSettings, sParam )
var a = [];
$.map( oSettings.aoColumns, function(val, i) {
if ( val[sParam] ) {
a.push( i );
* Get the sort type based on an input string
@param {string} sData data we wish to know the type of
@returns {string} type (defaults to 'string' if no type can be detected)
@memberof DataTable#oApi
function _fnDetectType( sData )
var aTypes = DataTable.ext.aT
var iLen = aTypes.
for ( var i=0 ; i&iL i++ )
var sType = aTypes[i]( sData );
if ( sType !== null )
return 'string';
* Figure out how to reorder a display list
@param {object} oSettings dataTables settings object
@returns array {int} aiReturn index list for reordering
@memberof DataTable#oApi
function _fnReOrderIndex ( oSettings, sColumns )
var aColumns = sColumns.split(',');
var aiReturn = [];
for ( var i=0, iLen=oSettings.aoColumns. i&iL i++ )
for ( var j=0 ; j&iL j++ )
if ( oSettings.aoColumns[i].sName == aColumns[j] )
aiReturn.push( j );
return aiR
* Get the column ordering that DataTables expects
@param {object} oSettings dataTables settings object
@returns {string} comma separated list of names
@memberof DataTable#oApi
function _fnColumnOrdering ( oSettings )
var sNames = '';
for ( var i=0, iLen=oSettings.aoColumns. i&iL i++ )
sNames += oSettings.aoColumns[i].sName+',';
if ( sNames.length == iLen )
return "";
return sNames.slice(0, -1);
* Take the column definitions and static columns arrays and calculate how
* they relate to column indexes. The callback function will then apply the
* definition found for a column to a suitable configuration object.
@param {object} oSettings dataTables settings object
@param {array} aoColDefs The aoColumnDefs array that is to be applied
@param {array} aoCols The aoColumns array that defines columns individually
@param {function} fn Callback function - takes two parameters, the calculated
column index and the definition for that column.
@memberof DataTable#oApi
function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
var i, iLen, j, jLen, k, kL
// Column definitions with aTargets
if ( aoColDefs )
/* Loop over the definitions array - loop in reverse so first instance has priority */
for ( i=aoColDefs.length-1 ; i&=0 ; i-- )
/* Each definition can target multiple columns, as it is an array */
var aTargets = aoColDefs[i].aT
if ( !$.isArray( aTargets ) )
_fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
for ( j=0, jLen=aTargets. j&jL j++ )
if ( typeof aTargets[j] === 'number' && aTargets[j] &= 0 )
/* Add columns that we don't yet know about */
while( oSettings.aoColumns.length &= aTargets[j] )
_fnAddColumn( oSettings );
/* Integer, basic index */
fn( aTargets[j], aoColDefs[i] );
else if ( typeof aTargets[j] === 'number' && aTargets[j] & 0 )
/* Negative integer, right to left column counting */
fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] );
else if ( typeof aTargets[j] === 'string' )
/* Class name matching on TH element */
for ( k=0, kLen=oSettings.aoColumns. k&kL k++ )
if ( aTargets[j] == "_all" ||
$(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) )
fn( k, aoColDefs[i] );
// Statically defined columns array
if ( aoCols )
for ( i=0, iLen=aoCols. i&iL i++ )
fn( i, aoCols[i] );
* Add a data array to the table, creating DOM node etc. This is the parallel to
* _fnGatherData, but for adding rows from a Javascript source, rather than a
* DOM source.
@param {object} oSettings dataTables settings object
@param {array} aData data array to be added
@returns {int} &=0 if successful (index of new aoData entry), -1 if failed
@memberof DataTable#oApi
function _fnAddData ( oSettings, aDataSupplied )
/* Take an independent copy of the data source so we can bash it about as we wish */
var aDataIn = ($.isArray(aDataSupplied)) ?
aDataSupplied.slice() :
$.extend( true, {}, aDataSupplied );
/* Create the object for storing information about this new row */
var iRow = oSettings.aoData.
var oData = $.extend( true, {}, DataTable.models.oRow );
oData._aData = aDataIn;
oSettings.aoData.push( oData );
/* Create the cells */
var nTd, sThisT
for ( var i=0, iLen=oSettings.aoColumns. i&iL i++ )
oCol = oSettings.aoColumns[i];
/* Use rendered data for filtering / sorting */
if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null )
_fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) );
_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
/* See if we should auto-detect the column type */
if ( oCol._bAutoType && oCol.sType != 'string' )
/* Attempt to auto detect the type - same as _fnGatherData() */
var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' );
if ( sVarType !== null && sVarType !== '' )
sThisType = _fnDetectType( sVarType );
if ( oCol.sType === null )
oCol.sType = sThisT
else if ( oCol.sType != sThisType && oCol.sType != "html" )
/* String is always the 'fallback' option */
oCol.sType = 'string';
/* Add to the display array */
oSettings.aiDisplayMaster.push( iRow );
/* Create the DOM information */
if ( !oSettings.oFeatures.bDeferRender )
_fnCreateTr( oSettings, iRow );
* Read in the data from the target table from the DOM
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnGatherData( oSettings )
var iLoop, i, iLen, j, jLen, jInner,
nTds, nTrs, nTd, nTr, aLocalData, iThisIndex,
iRow, iRows, iColumn, iColumns, sNodeName,
* Process by row first
* Add the data object for the whole table - storing the tr node. Note - no point in getting
* DOM based data if we are going to go and replace it with Ajax source data.
if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null )
nTr = oSettings.nTBody.firstC
while ( nTr )
if ( nTr.nodeName.toUpperCase() == "TR" )
iThisIndex = oSettings.aoData.
nTr._DT_RowIndex = iThisI
oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, {
"nTr": nTr
oSettings.aiDisplayMaster.push( iThisIndex );
nTd = nTr.firstC
jInner = 0;
while ( nTd )
sNodeName = nTd.nodeName.toUpperCase();
if ( sNodeName == "TD" || sNodeName == "TH" )
_fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML) );
nTd = nTd.nextS
nTr = nTr.nextS
/* Gather in the TD elements of the Table - note that this is basically the same as
* fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
nTrs = _fnGetTrNodes( oSettings );
nTds = [];
for ( i=0, iLen=nTrs. i&iL i++ )
nTd = nTrs[i].firstC
while ( nTd )
sNodeName = nTd.nodeName.toUpperCase();
if ( sNodeName == "TD" || sNodeName == "TH" )
nTds.push( nTd );
nTd = nTd.nextS
/* Now process by column */
for ( iColumn=0, iColumns=oSettings.aoColumns. iColumn&iC iColumn++ )
oCol = oSettings.aoColumns[iColumn];
/* Get the title of the column - unless there is a user set one */
if ( oCol.sTitle === null )
oCol.sTitle = oCol.nTh.innerHTML;
bAutoType = oCol._bAutoType,
bRender = typeof oCol.fnRender === 'function',
bClass = oCol.sClass !== null,
bVisible = oCol.bVisible,
nCell, sThisType, sRendered, sValT
/* A single loop to rule them all (and be more efficient) */
if ( bAutoType || bRender || bClass || !bVisible )
for ( iRow=0, iRows=oSettings.aoData. iRow&iR iRow++ )
oData = oSettings.aoData[iRow];
nCell = nTds[ (iRow*iColumns) + iColumn ];
/* Type detection */
if ( bAutoType && oCol.sType != 'string' )
sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' );
if ( sValType !== '' )
sThisType = _fnDetectType( sValType );
if ( oCol.sType === null )
oCol.sType = sThisT
else if ( oCol.sType != sThisType &&
oCol.sType != "html" )
/* String is always the 'fallback' option */
oCol.sType = 'string';
if ( oCol.mRender )
// mRender has been defined, so we need to get the value and set it
nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
else if ( oCol.mData !== iColumn )
// If mData is not the same as the column number, then we need to
// get the dev set value. If it is the column, no point in wasting
// time setting the value that is already there!
nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
/* Rendering */
if ( bRender )
sRendered = _fnRender( oSettings, iRow, iColumn );
nCell.innerHTML = sR
if ( oCol.bUseRendered )
/* Use the rendered data for filtering / sorting */
_fnSetCellData( oSettings, iRow, iColumn, sRendered );
/* Classes */
if ( bClass )
nCell.className += ' '+oCol.sC
/* Column visibility */
if ( !bVisible )
oData._anHidden[iColumn] = nC
nCell.parentNode.removeChild( nCell );
oData._anHidden[iColumn] =
if ( oCol.fnCreatedCell )
oCol.fnCreatedCell.call( oSettings.oInstance,
nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn
/* Row created callbacks */
if ( oSettings.aoRowCreatedCallback.length !== 0 )
for ( i=0, iLen=oSettings.aoData. i&iL i++ )
oData = oSettings.aoData[i];
_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] );
* Take a TR element and convert it to an index in aoData
@param {object} oSettings dataTables settings object
@param {node} n the TR element to find
@returns {int} index if the node is found, null if not
@memberof DataTable#oApi
function _fnNodeToDataIndex( oSettings, n )
return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex :
* Take a TD element and convert it into a column data index (not the visible index)
@param {object} oSettings dataTables settings object
@param {int} iRow The row number the TD/TH can be found in
@param {node} n The TD/TH element to find
@returns {int} index if the node is found, -1 if not
@memberof DataTable#oApi
function _fnNodeToColumnIndex( oSettings, iRow, n )
var anCells = _fnGetTdNodes( oSettings, iRow );
for ( var i=0, iLen=oSettings.aoColumns. i&iL i++ )
if ( anCells[i] === n )
return -1;
* Get an array of data for a given row from the internal data cache
@param {object} oSettings dataTables settings object
@param {int} iRow aoData row id
@param {string} sSpecific data get type ('type' 'filter' 'sort')
@param {array} aiColumns Array of column indexes to get data from
@returns {array} Data array
@memberof DataTable#oApi
function _fnGetRowData( oSettings, iRow, sSpecific, aiColumns )
var out = [];
for ( var i=0, iLen=aiColumns. i&iL i++ )
out.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) );
* Get the data for a given cell from the internal cache, taking into account data mapping
@param {object} oSettings dataTables settings object
@param {int} iRow aoData row id
@param {int} iCol Column index
@param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
@returns {*} Cell data
@memberof DataTable#oApi
function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
var oCol = oSettings.aoColumns[iCol];
var oData = oSettings.aoData[iRow]._aD
if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined )
if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
_fnLog( oSettings, 0, "Requested unknown parameter "+
(typeof oCol.mData=='function' ? '{mData function}' : "'"+oCol.mData+"'")+
" from the data source for row "+iRow );
oSettings.iDrawError = oSettings.iD
return oCol.sDefaultC
/* When the data source is null, we can use default column data */
if ( sData === null && oCol.sDefaultContent !== null )
sData = oCol.sDefaultC
else if ( typeof sData === 'function' )
/* If the data source is a function, then we run it and use the return */
return sData();
if ( sSpecific == 'display' && sData === null )
return '';
* Set the value for a specific cell, into the internal data cache
@param {object} oSettings dataTables settings object
@param {int} iRow aoData row id
@param {int} iCol Column index
@param {*} val Value to set
@memberof DataTable#oApi
function _fnSetCellData( oSettings, iRow, iCol, val )
var oCol = oSettings.aoColumns[iCol];
var oData = oSettings.aoData[iRow]._aD
oCol.fnSetData( oData, val );
// Private variable that is used to match array syntax in the data property object
var __reArray = /\[.*?\]$/;
* Return a function that can be used to get data from a source object, taking
* into account the ability to use nested objects as a source
@param {string|int|function} mSource The data source for the object
@returns {function} Data get function
@memberof DataTable#oApi
function _fnGetObjectDataFn( mSource )
if ( mSource === null )
/* Give an empty string for rendering / sorting etc */
return function (data, type) {
else if ( typeof mSource === 'function' )
return function (data, type, extra) {
return mSource( data, type, extra );
else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )
/* If there is a . in the source string then the data source is in a
* nested object so we loop over the data for each level to get the next
* level down. On each loop we test for undefined, and if found immediately
* return. This allows entire objects to be missing and sDefaultContent to
* be used if defined, rather than throwing an error
var fetchData = function (data, type, src) {
var a = src.split('.');
var arrayNotation, out, innerS
if ( src !== "" )
for ( var i=0, iLen=a. i&iL i++ )
// Check if we are dealing with an array notation request
arrayNotation = a[i].match(__reArray);
if ( arrayNotation ) {
a[i] = a[i].replace(__reArray, '');
// Condition allows simply [] to be passed in
if ( a[i] !== "" ) {
data = data[ a[i] ];
// Get the remainder of the nested object to get
a.splice( 0, i+1 );
innerSrc = a.join('.');
// Traverse each entry in the array getting the properties requested
for ( var j=0, jLen=data. j&jL j++ ) {
out.push( fetchData( data[j], type, innerSrc ) );
// If a string is given in between the array notation indicators, that
// is used to join the strings together, otherwise an array is returned
var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
data = (join==="") ? out : out.join(join);
// The inner call to fetchData has already traversed through the remainder
// of the source requested, so we exit from the loop
if ( data === null || data[ a[i] ] === undefined )
data = data[ a[i] ];
return function (data, type) {
return fetchData( data, type, mSource );
/* Array or flat object mapping */
return function (data, type) {
return data[mSource];
* Return a function that can be used to set data from a source object, taking
* into account the ability to use nested objects as a source
@param {string|int|function} mSource The data source for the object
@returns {function} Data set function
@memberof DataTable#oApi
function _fnSetObjectDataFn( mSource )
if ( mSource === null )
/* Nothing to do when the data source is null */
return function (data, val) {};
else if ( typeof mSource === 'function' )
return function (data, val) {
mSource( data, 'set', val );
else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )
/* Like the get, we need to get data from a nested object */
var setData = function (data, val, src) {
var a = src.split('.'),
var arrayNotation, o, innerS
for ( var i=0, iLen=a.length-1 ; i&iL i++ )
// Check if we are dealing with an array notation request
arrayNotation = a[i].match(__reArray);
if ( arrayNotation )
a[i] = a[i].replace(__reArray, '');
data[ a[i] ] = [];
// Get the remainder of the nested object to set so we can recurse
b = a.slice();
b.splice( 0, i+1 );
innerSrc = b.join('.');
// Traverse each entry in the array setting the properties requested
for ( var j=0, jLen=val. j&jL j++ )
setData( o, val[j], innerSrc );
data[ a[i] ].push( o );
// The inner call to setData has already traversed through the remainder
// of the source and has set the data, thus we can exit here
// If the nested object doesn't currently exist - since we are
// trying to set the value - create it
if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
data[ a[i] ] = {};
data = data[ a[i] ];
// If array notation is used, we just want to strip it and use the property name
// and assign the value. If it isn't used, then we get the result we want anyway
data[ a[a.length-1].replace(__reArray, '') ] =
return function (data, val) {
return setData( data, val, mSource );
/* Array or flat object mapping */
return function (data, val) {
data[mSource] =
* Return an array with the full table data
@param {object} oSettings dataTables settings object
@returns array {array} aData Master data array
@memberof DataTable#oApi
function _fnGetDataMaster ( oSettings )
var aData = [];
var iLen = oSettings.aoData.
for ( var i=0 ; i&iL i++ )
aData.push( oSettings.aoData[i]._aData );
* Nuke the table
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnClearTable( oSettings )
oSettings.aoData.splice( 0, oSettings.aoData.length );
oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length );
oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length );
_fnCalculateEnd( oSettings );
* Take an array of integers (index array) and remove a target integer (value - not
* the key!)
@param {array} a Index array to target
@param {int} iTarget value to find
@memberof DataTable#oApi
function _fnDeleteIndex( a, iTarget )
var iTargetIndex = -1;
for ( var i=0, iLen=a. i&iL i++ )
if ( a[i] == iTarget )
iTargetIndex =
else if ( a[i] & iTarget )
if ( iTargetIndex != -1 )
a.splice( iTargetIndex, 1 );
* Call the developer defined fnRender function for a given cell (row/column) with
* the required parameters and return the result.
@param {object} oSettings dataTables settings object
@param {int} iRow aoData index for the row
@param {int} iCol aoColumns index for the column
@returns {*} Return of the developer's fnRender function
@memberof DataTable#oApi
function _fnRender( oSettings, iRow, iCol )
var oCol = oSettings.aoColumns[iCol];
return oCol.fnRender( {
"iDataRow":
"iDataColumn": iCol,
"oSettings":
oSettings,
oSettings.aoData[iRow]._aData,
"mDataProp":
oCol.mData
}, _fnGetCellData(oSettings, iRow, iCol, 'display') );
* Create a new TR element (and it's TD children) for a row
@param {object} oSettings dataTables settings object
@param {int} iRow Row to consider
@memberof DataTable#oApi
function _fnCreateTr ( oSettings, iRow )
var oData = oSettings.aoData[iRow];
if ( oData.nTr === null )
oData.nTr = document.createElement('tr');
/* Use a private property on the node to allow reserve mapping from the node
* to the aoData array for fast look up
oData.nTr._DT_RowIndex = iR
/* Special parameters can be given by the data source to be used on the row */
if ( oData._aData.DT_RowId )
oData.nTr.id = oData._aData.DT_RowId;
if ( oData._aData.DT_RowClass )
oData.nTr.className = oData._aData.DT_RowC
/* Process each column */
for ( var i=0, iLen=oSettings.aoColumns. i&iL i++ )
var oCol = oSettings.aoColumns[i];
nTd = document.createElement( oCol.sCellType );
/* Render if needed - if bUseRendered is true then we already have the rendered
* value in the data source - so can just use that
nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ?
_fnRender( oSettings, iRow, i ) :
_fnGetCellData( oSettings, iRow, i, 'display' );
/* Add user defined class */
if ( oCol.sClass !== null )
nTd.className = oCol.sC
if ( oCol.bVisible )
oData.nTr.appendChild( nTd );
oData._anHidden[i] =
oData._anHidden[i] = nTd;
if ( oCol.fnCreatedCell )
oCol.fnCreatedCell.call( oSettings.oInstance,
nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i
_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] );
* Create the HTML header for the table
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnBuildHead( oSettings )
var i, nTh, iLen, j, jL
var iThs = $('th, td', oSettings.nTHead).
var iCorrector = 0;
/* If there is a header in place - then use it - otherwise it's going to get nuked... */
if ( iThs !== 0 )
/* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
for ( i=0, iLen=oSettings.aoColumns. i&iL i++ )
nTh = oSettings.aoColumns[i].nTh;
nTh.setAttribute('role', 'columnheader');
if ( oSettings.aoColumns[i].bSortable )
nTh.setAttribute('tabindex', oSettings.iTabIndex);
nTh.setAttribute('aria-controls', oSettings.sTableId);
if ( oSettings.aoColumns[i].sClass !== null )
$(nTh).addClass( oSettings.aoColumns[i].sClass );
/* Set the title of the column if it is user defined (not what was auto detected) */
if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )
nTh.innerHTML = oSettings.aoColumns[i].sT
/* We don't have a header in the DOM - so we are going to have to create one */
var nTr = document.createElement( "tr" );
for ( i=0, iLen=oSettings.aoColumns. i&iL i++ )
nTh = oSettings.aoColumns[i].nTh;
nTh.innerHTML = oSettings.aoColumns[i].sT
nTh.setAttribute('tabindex', '0');
if ( oSettings.aoColumns[i].sClass !== null )
$(nTh).addClass( oSettings.aoColumns[i].sClass );
nTr.appendChild( nTh );
$(oSettings.nTHead).html( '' )[0].appendChild( nTr );
_fnDetectHeader( oSettings.aoHeader, oSettings.nTHead );
/* ARIA role for the rows */
$(oSettings.nTHead).children('tr').attr('role', 'row');
/* Add the extra markup needed by jQuery UI's themes */
if ( oSettings.bJUI )
for ( i=0, iLen=oSettings.aoColumns. i&iL i++ )
nTh = oSettings.aoColumns[i].nTh;
var nDiv = document.createElement('div');
nDiv.className = oSettings.oClasses.sSortJUIW
$(nTh).contents().appendTo(nDiv);
var nSpan = document.createElement('span');
nSpan.className = oSettings.oClasses.sSortI
nDiv.appendChild( nSpan );
nTh.appendChild( nDiv );
if ( oSettings.oFeatures.bSort )
for ( i=0 ; i&oSettings.aoColumns. i++ )
if ( oSettings.aoColumns[i].bSortable !== false )
_fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
$(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone );
/* Deal with the footer - add classes if required */
if ( oSettings.oClasses.sFooterTH !== "" )
$(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH );
/* Cache the footer elements */
if ( oSettings.nTFoot !== null )
var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter );
for ( i=0, iLen=oSettings.aoColumns. i&iL i++ )
if ( anCells[i] )
oSettings.aoColumns[i].nTf = anCells[i];
if ( oSettings.aoColumns[i].sClass )
$(anCells[i]).addClass( oSettings.aoColumns[i].sClass );
* Draw the header (or footer) element based on the column visibility states. The
* methodology here is to use the layout array from _fnDetectHeader, modified for
* the instantaneous column visibility, to construct the new layout. The grid is
* traversed over cell at a time in a rows x columns grid fashion, although each
* cell insert can cover multiple elements in the grid - which is tracks using the
* aApplied array. Cell inserts in the grid will only occur where there isn't
* already a cell in that position.
@param {object} oSettings dataTables settings object
@param array {objects} aoSource Layout array from _fnDetectHeader
@param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
@memberof DataTable#oApi
function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
var i, iLen, j, jLen, k, kLen, n, nLocalTr;
var aoLocal = [];
var aApplied = [];
var iColumns = oSettings.aoColumns.
var iRowspan, iC
bIncludeHidden === undefined )
bIncludeHidden =
/* Make a copy of the master layout array, but without the visible columns in it */
for ( i=0, iLen=aoSource. i&iL i++ )
aoLocal[i] = aoSource[i].slice();
aoLocal[i].nTr = aoSource[i].nTr;
/* Remove any columns which are currently hidden */
for ( j=iColumns-1 ; j&=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. i&iL i++ )
nLocalTr = aoLocal[i].nTr;
/* All cells are going to be replaced, so empty out the row */
if ( nLocalTr )
while( (n = nLocalTr.firstChild) )
nLocalTr.removeChild( n );
for ( j=0, jLen=aoLocal[i]. j&jL j++ )
iRowspan = 1;
iColspan = 1;
/* Check to see if there is already a cell (row/colspan) covering our target
* insert point. If there is, then there is nothing to do.
if ( aApplied[i][j] === undefined )
nLocalTr.appendChild( aoLocal[i][j].cell );
aApplied[i][j] = 1;
/* Expand the cell to cover as many rows as needed */
while ( aoLocal[i+iRowspan] !== undefined &&
aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
aApplied[i+iRowspan][j] = 1;
iRowspan++;
/* Expand the cell to cover as many columns as needed */
while ( aoLocal[i][j+iColspan] !== undefined &&
aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
/* Must update the applied array over the rows for the columns */
for ( k=0 ; k&iR k++ )
aApplied[i+k][j+iColspan] = 1;
iColspan++;
/* Do the actual expansion in the DOM */
aoLocal[i][j].cell.rowSpan = iR
aoLocal[i][j].cell.colSpan = iC
* Insert the required TR nodes into the table for display
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnDraw( oSettings )
/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
if ( $.inArray( false, aPreDraw ) !== -1 )
_fnProcessingDisplay( oSettings, false );
var i, iLen,
var anRows = [];
var iRowCount = 0;
var iStripes = oSettings.asStripeClasses.
var iOpenRows = oSettings.aoOpenRows.
oSettings.bDrawing =
/* Check and see if we have an initial draw position from state saving */
if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 )
if ( oSettings.oFeatures.bServerSide )
oSettings._iDisplayStart = oSettings.iInitDisplayS
oSettings._iDisplayStart = (oSettings.iInitDisplayStart &= oSettings.fnRecordsDisplay()) ?
0 : oSettings.iInitDisplayS
oSettings.iInitDisplayStart = -1;
_fnCalculateEnd( oSettings );
/* Server-side processing draw intercept */
if ( oSettings.bDeferLoading )
oSettings.bDeferLoading =
oSettings.iDraw++;
else if ( !oSettings.oFeatures.bServerSide )
oSettings.iDraw++;
else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
if ( oSettings.aiDisplay.length !== 0 )
var iStart = oSettings._iDisplayS
var iEnd = oSettings._iDisplayE
if ( oSettings.oFeatures.bServerSide )
iStart = 0;
iEnd = oSettings.aoData.
for ( var j=iS j&iE j++ )
var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];
if ( aoData.nTr === null )
_fnCreateTr( oSettings, oSettings.aiDisplay[j] );
var nRow = aoData.nTr;
/* Remove the old striping classes and then add the new one */
if ( iStripes !== 0 )
var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ];
if ( aoData._sRowStripe != sStripe )
$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
aoData._sRowStripe = sS
/* Row callback functions - might want to manipulate the row */
_fnCallbackFire( oSettings, 'aoRowCallback', null,
[nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] );
anRows.push( nRow );
iRowCount++;
/* If there is an open row - and it is attached to this parent - attach it on redraw */
if ( iOpenRows !== 0 )
for ( var k=0 ; k&iOpenR k++ )
if ( nRow == oSettings.aoOpenRows[k].nParent )
anRows.push( oSettings.aoOpenRows[k].nTr );
/* Table is empty - create a row with an empty message in it */
anRows[ 0 ] = document.createElement( 'tr' );
if ( oSettings.asStripeClasses[0] )
anRows[ 0 ].className = oSettings.asStripeClasses[0];
var oLang = oSettings.oL
var sZero = oLang.sZeroR
if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
sZero = oLang.sLoadingR
else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
sZero = oLang.sEmptyT
var nTd = document.createElement( 'td' );
nTd.setAttribute( 'valign', "top" );
nTd.colSpan = _fnVisbleColumns( oSettings );
nTd.className = oSettings.oClasses.sRowE
nTd.innerHTML = _fnInfoMacros( oSettings, sZero );
anRows[ iRowCount ].appendChild( nTd );
/* Header and footer callbacks */
_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
* Need to remove any old row from the display - note we can't just empty the tbody using
* $().html('') since this will unbind the jQuery event handlers (even although the node
* still exists!) - equally we can't use innerHTML, since IE throws an exception.
nAddFrag = document.createDocumentFragment(),
nRemoveFrag = document.createDocumentFragment(),
nBodyPar, nT
if ( oSettings.nTBody )
nBodyPar = oSettings.nTBody.parentN
nRemoveFrag.appendChild( oSettings.nTBody );
/* When doing infinite scrolling, only remove child rows when sorting, filtering or start
* up. When not infinite scroll, always do it.
if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||
oSettings.bSorted || oSettings.bFiltered )
while( (n = oSettings.nTBody.firstChild) )
oSettings.nTBody.removeChild( n );
/* Put the draw table into the dom */
for ( i=0, iLen=anRows. i&iL i++ )
nAddFrag.appendChild( anRows[i] );
oSettings.nTBody.appendChild( nAddFrag );
if ( nBodyPar !== null )
nBodyPar.appendChild( oSettings.nTBody );
/* 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 =
oSettings.bFiltered =
oSettings.bDrawing =
if ( oSettings.oFeatures.bServerSide )
_fnProcessingDisplay( oSettings, false );
if ( !oSettings._bInitComplete )
_fnInitComplete( oSettings );
* Redraw the table - taking account of the various features which are enabled
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnReDraw( oSettings )
if ( oSettings.oFeatures.bSort )
/* Sorting will refilter and draw for us */
_fnSort( oSettings, oSettings.oPreviousSearch );
else if ( oSettings.oFeatures.bFilter )
/* Filtering will redraw for us */
_fnFilterComplete( oSettings, oSettings.oPreviousSearch );
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
* Add the options to the page HTML for the table
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnAddOptionsHtml ( oSettings )
* Create a temporary, empty, div which we can later on replace with what we have generated
* we do it this way to rendering the 'options' html offline - speed :-)
var nHolding = $('&div&&/div&')[0];
oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
* All DataTables are wrapped in a div
oSettings.nTableWrapper = $('&div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"&&/div&')[0];
oSettings.nTableReinsertBefore = oSettings.nTable.nextS
/* Track where we want to insert the option */
var nInsertNode = oSettings.nTableW
/* Loop over the user set positioning and place the elements as needed */
var aDom = oSettings.sDom.split('');
var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr,
for ( var i=0 ; i&aDom. i++ )
iPushFeature = 0;
cOption = aDom[i];
if ( cOption == '&' )
/* New container div */
nNewNode = $('&div&&/div&')[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 = "";
while ( aDom[i+j] != cNext )
sAttr += aDom[i+j];
/* Replace jQuery UI constants */
if ( sAttr == "H" )
sAttr = oSettings.oClasses.sJUIH
else if ( sAttr == "F" )
sAttr = oSettings.oClasses.sJUIF
/* 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);
nNewNode.className = sA
i += /* Move along the position array */
nInsertNode.appendChild( nNewNode );
nInsertNode = nNewN
else if ( cOption == '&' )
/* End container div */
nInsertNode = nInsertNode.parentN
else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
/* Length */
nTmp = _fnFeatureHtmlLength( oSettings );
iPushFeature = 1;
else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
/* Filter */
nTmp = _fnFeatureHtmlFilter( oSettings );
iPushFeature = 1;
else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
/* pRocessing */
nTmp = _fnFeatureHtmlProcessing( oSettings );
iPushFeature = 1;
else if ( cOption == 't' )
/* Table */
nTmp = _fnFeatureHtmlTable( oSettings );
iPushFeature = 1;
else if ( cOption ==
'i' && oSettings.oFeatures.bInfo )
/* Info */
nTmp = _fnFeatureHtmlInfo( oSettings );
iPushFeature = 1;
else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
/* Pagination */
nTmp = _fnFeatureHtmlPaginate( oSettings );
iPushFeature = 1;
else if ( DataTable.ext.aoFeatures.length !== 0 )
/* Plug-in features */
var aoFeatures = DataTable.ext.aoF
for ( var k=0, kLen=aoFeatures. k&kL k++ )
if ( cOption == aoFeatures[k].cFeature )
nTmp = aoFeatures[k].fnInit( oSettings );
if ( nTmp )
iPushFeature = 1;
/* Add to the 2D features array */
if ( iPushFeature == 1 && nTmp !== null )
if ( typeof oSettings.aanFeatures[cOption] !== 'object' )
oSettings.aanFeatures[cOption] = [];
oSettings.aanFeatures[cOption].push( nTmp );
nInsertNode.appendChild( nTmp );
/* Built our DOM structure - replace the holding div with what we want */
nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );
* Use the DOM source to create up an array of header cells. The idea here is to
* create a layout grid (array) of rows x columns, which contains a reference
* to the cell that that point in the grid (regardless of col/rowspan), such that
* any column / row could be removed and the new grid constructed
@param array {object} aLayout Array to store the calculated layout in
@param {node} nThead The header/footer element for the table
@memberof DataTable#oApi
function _fnDetectHeader ( aLayout, nThead )
var nTrs = $(nThead).children('tr');
var nTr, nC
var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iR
var fnShiftCol = function ( a, i, j ) {
var k = a[i];
while ( k[j] ) {
aLayout.splice( 0, aLayout.length );
/* We know how many rows there are in the layout - so prep it */
for ( i=0, iLen=nTrs. i&iL i++ )
aLayout.push( [] );
/* Calculate a layout array */
for ( i=0, iLen=nTrs. i&iL i++ )
nTr = nTrs[i];
iColumn = 0;
/* For every cell in the row... */
nCell = nTr.firstC
while ( nCell ) {
if ( nCell.nodeName.toUpperCase() == "TD" ||
nCell.nodeName.toUpperCase() == "TH" )
/* Get the col and rowspan attributes from the DOM and sanitise them */
iColspan = nCell.getAttribute('colspan') * 1;
iRowspan = nCell.getAttribute('rowspan') * 1;
iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iC
iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iR
/* There might be colspan cells already in this row, so shift our target
* accordingly
iColShifted = fnShiftCol( aLayout, i, iColumn );
/* Cache calculation for unique columns */
bUnique = iColspan === 1 ? true :
/* If there is col / rowspan, copy the information into the layout grid */
for ( l=0 ; l&iC l++ )
for ( k=0 ; k&iR k++ )
aLayout[i+k][iColShifted+l] = {
"cell": nCell,
"unique": bUnique
aLayout[i+k].nTr = nTr;
nCell = nCell.nextS
* Get an array of unique th elements, one for each column
@param {object} oSettings dataTables settings object
@param {node} nHeader automatically detect the layout from this node - optional
@param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
@returns array {node} aReturn list of unique th's
@memberof DataTable#oApi
function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
var aReturn = [];
if ( !aLayout )
aLayout = oSettings.aoH
if ( nHeader )
aLayout = [];
_fnDetectHeader( aLayout, nHeader );
for ( var i=0, iLen=aLayout. i&iL i++ )
for ( var j=0, jLen=aLayout[i]. j&jL j++ )
if ( aLayout[i][j].unique &&
(!aReturn[j] || !oSettings.bSortCellsTop) )
aReturn[j] = aLayout[i][j].
* Update the table using an Ajax call
@param {object} oSettings dataTables settings object
@returns {boolean} Block the table drawing or not
@memberof DataTable#oApi
function _fnAjaxUpdate( oSettings )
if ( oSettings.bAjaxDataGet )
oSettings.iDraw++;
_fnProcessingDisplay( oSettings, true );
var iColumns = oSettings.aoColumns.
var aoData = _fnAjaxParameters( oSettings );
_fnServerParams( oSettings, aoData );
oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData,
function(json) {
_fnAjaxUpdateDraw( oSettings, json );
}, oSettings );
* Build up the parameters in an object needed for a server-side processing request
@param {object} oSettings dataTables settings object
@returns {bool} block the table drawing or not
@memberof DataTable#oApi
function _fnAjaxParameters( oSettings )
var iColumns = oSettings.aoColumns.
var aoData = [], mDataProp, aaSort, aDataS
aoData.push( { "name": "sEcho",
"value": oSettings.iDraw } );
aoData.push( { "name": "iColumns",
"value": iColumns } );
aoData.push( { "name": "sColumns",
"value": _fnColumnOrdering(oSettings) } );
aoData.push( { "name": "iDisplayStart",
"value": oSettings._iDisplayStart } );
aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ?
oSettings._iDisplayLength : -1 } );
for ( i=0 ; i&iC i++ )
mDataProp = oSettings.aoColumns[i].mD
aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } );
/* Filtering */
if ( oSettings.oFeatures.bFilter !== false )
aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } );
aoData.push( { "name": "bRegex",
"value": oSettings.oPreviousSearch.bRegex } );
for ( i=0 ; i&iC i++ )
aoData.push( { "name": "sSearch_"+i,
"value": oSettings.aoPreSearchCols[i].sSearch } );
aoData.push( { "name": "bRegex_"+i,
"value": oSettings.aoPreSearchCols[i].bRegex } );
aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } );
/* Sorting */
if ( oSettings.oFeatures.bSort !== false )
var iCounter = 0;
aaSort = ( oSettings.aaSortingFixed !== null ) ?
oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
oSettings.aaSorting.slice();
for ( i=0 ; i&aaSort. i++ )
aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataS
for ( j=0 ; j&aDataSort. j++ )
aoData.push( { "name": "iSortCol_"+iCounter,
"value": aDataSort[j] } );
aoData.push( { "name": "sSortDir_"+iCounter,
"value": aaSort[i][1] } );
iCounter++;
aoData.push( { "name": "iSortingCols",
"value": iCounter } );
for ( i=0 ; i&iC i++ )
aoData.push( { "name": "bSortable_"+i,
"value": oSettings.aoColumns[i].bSortable } );
return aoD
* Add Ajax parameters from plug-ins
@param {object} oSettings dataTables settings object
@param array {objects} aoData name/value pairs to send to the server
@memberof DataTable#oApi
function _fnServerParams( oSettings, aoData )
_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] );
* Data the data from the server (nuking the old) and redraw the table
@param {object} oSettings dataTables settings object
@param {object} json json data return from the server.
@param {string} json.sEcho Tracking flag for DataTables to match requests
@param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
@param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
@param {array} json.aaData The data to display on this page
@param {string} [json.sColumns] Column ordering (sName, comma separated)
@memberof DataTable#oApi
function _fnAjaxUpdateDraw ( oSettings, json )
if ( json.sEcho !== undefined )
/* Protect against old returns over-writing a new one. Possible when you get
* very fast interaction, and later queries are completed much faster
if ( json.sEcho*1 & oSettings.iDraw )
oSettings.iDraw = json.sEcho * 1;
if ( !oSettings.oScroll.bInfinite ||
(oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) )
_fnClearTable( oSettings );
oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10);
oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10);
/* Determine if reordering is required */
var sOrdering = _fnColumnOrdering(oSettings);
var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering );
if ( bReOrder )
aiIndex = _fnReOrderIndex( oSettings, json.sColumns );
var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json );
for ( var i=0, iLen=aData. i&iL i++ )
if ( bReOrder )
/* If we need to re-order, then create a new array with the correct order and add it */
var aDataSorted = [];
for ( var j=0, jLen=oSettings.aoColumns. j&jL j++ )
aDataSorted.push( aData[i][ aiIndex[j] ] );
_fnAddData( oSettings, aDataSorted );
/* No re-order required, sever got it "right" - just straight add */
_fnAddData( oSettings, aData[i] );
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
oSettings.bAjaxDataGet =
_fnDraw( oSettings );
oSettings.bAjaxDataGet =
_fnProcessingDisplay( oSettings, false );
* Generate the node required for filtering text
@returns {node} Filter control element
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnFeatureHtmlFilter ( oSettings )
var oPreviousSearch = oSettings.oPreviousS
var sSearchStr = oSettings.oLanguage.sS
sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ?
sSearchStr.replace('_INPUT_', '&input type="text" /&') :
sSearchStr==="" ? '&input type="text" /&' : sSearchStr+' &input type="text" /&';
var nFilter = document.createElement( 'div' );
nFilter.className = oSettings.oClasses.sF
nFilter.innerHTML = '&label&'+sSearchStr+'&/label&';
if ( !oSettings.aanFeatures.f )
nFilter.id = oSettings.sTableId+'_filter';
var jqFilter = $('input[type="text"]', nFilter);
// Store a reference to the input element, so other input elements could be
// added to the filter wrapper if needed (submit button for example)
nFilter._DT_Input = jqFilter[0];
jqFilter.val( oPreviousSearch.sSearch.replace('"','&') );
jqFilter.bind( 'keyup.DT', function(e) {
/* Update all other filter input elements for the new display */
var n = oSettings.aanFeatures.f;
var val = this.value==="" ? "" : this. // mental IE8 fix :-(
for ( var i=0, iLen=n. i&iL i++ )
if ( n[i] != $(this).parents('div.dataTables_filter')[0] )
$(n[i]._DT_Input).val( val );
/* Now do the filter */
if ( val != oPreviousSearch.sSearch )
_fnFilterComplete( oSettings, {
"sSearch": val,
"bRegex": oPreviousSearch.bRegex,
"bSmart": oPreviousSearch.bSmart ,
"bCaseInsensitive": oPreviousSearch.bCaseInsensitive
.attr('aria-controls', oSettings.sTableId)
.bind( 'keypress.DT', function(e) {
/* Prevent form submission */
if ( e.keyCode == 13 )
* 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.oPreviousS
var aoPrevSearch = oSettings.aoPreSearchC
var fnSaveFilter = function ( oFilter ) {
/* Save the filtering values */
oPrevSearch.sSearch = oFilter.sS
oPrevSearch.bRegex = oFilter.bR
oPrevSearch.bSmart = oFilter.bS
oPrevSearch.bCaseInsensitive = oFilter.bCaseI
/* In server-side processing all filtering is done by the server, so no point hanging around here */
if ( !oSettings.oFeatures.bServerSide )
/* Global filter */
_fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive );
fnSaveFilter( oInput );
/* Now do the individual column filter */
for ( var i=0 ; i&oSettings.aoPreSearchCols. i++ )
_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex,
aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
/* Custom filtering */
_fnFilterCustom( oSettings );
fnSaveFilter( oInput );
/* Tell the draw function we have been filtering */
oSettings.bFiltered =
$(oSettings.oInstance).trigger('filter', oSettings);
/* Redraw the table */
oSettings._iDisplayStart = 0;
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
/* Rebuild search array 'offline' */
_fnBuildSearchArray( oSettings, 0 );
* Apply custom filtering functions
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnFilterCustom( oSettings )
var afnFilters = DataTable.ext.afnF
var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );
for ( var i=0, iLen=afnFilters. i&iL i++ )
var iCorrector = 0;
for ( var j=0, jLen=oSettings.aiDisplay. j&jL j++ )
var iDisIndex = oSettings.aiDisplay[j-iCorrector];
var bTest = afnFilters[i](
oSettings,
_fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ),
/* Check if we should use this row based on the filtering function */
if ( !bTest )
oSettings.aiDisplay.splice( j-iCorrector, 1 );
iCorrector++;
* Filter the table on a per-column basis
@param {object} oSettings dataTables settings object
@param {string} sInput string to filter on
@param {int} iColumn column to filter
@param {bool} bRegex treat search string as a regular expression or not
@param {bool} bSmart use smart filtering or not
@param {bool} bCaseInsensitive Do case insenstive matching or not
@memberof DataTable#oApi
function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive )
if ( sInput === "" )
var iIndexCorrector = 0;
var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
for ( var i=oSettings.aiDisplay.length-1 ; i&=0 ; i-- )
var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ),
oSettings.aoColumns[iColumn].sType );
if ( ! rpSearch.test( sData ) )
oSettings.aiDisplay.splice( i, 1 );
iIndexCorrector++;
* Filter the data table based on user input and draw the table
@param {object} oSettings dataTables settings object
@param {string} sInput string to filter on
@param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)
@param {bool} bRegex treat as a regular expression or not
@param {bool} bSmart perform smart filtering or not
@param {bool} bCaseInsensitive Do case insenstive matching or not
@memberof DataTable#oApi
function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive )
var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
var oPrevSearch = oSettings.oPreviousS
/* Check if we are forcing or not - optional parameter */
if ( !iForce )
iForce = 0;
/* Need to take account of custom filtering functions - always filter */
if ( DataTable.ext.afnFiltering.length !== 0 )
iForce = 1;
* If the input is blank - we want the full data set
if ( sInput.length &= 0 )
oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
* We are starting a new search or the new search string is smaller
* then the old one (i.e. delete). Search from the master array
if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
oPrevSearch.sSearch.length & sInput.length || iForce == 1 ||
sInput.indexOf(oPrevSearch.sSearch) !== 0 )
/* Nuke the old display array - we are going to rebuild it */
oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
/* Force a rebuild of the search array */
_fnBuildSearchArray( oSettings, 1 );
/* Search through all records to populate the search array
* The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
for ( i=0 ; i&oSettings.aiDisplayMaster. i++ )
if ( rpSearch.test(oSettings.asDataSearch[i]) )
oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );
/* Using old search array - refine it - do it this way for speed
* Don't have to search the whole master array again
var iIndexCorrector = 0;
/* Search the current results */
for ( i=0 ; i&oSettings.asDataSearch. i++ )
if ( ! rpSearch.test(oSettings.asDataSearch[i]) )
oSettings.aiDisplay.splice( i-iIndexCorrector, 1 );
iIndexCorrector++;
* Create an array which can be quickly search through
@param {object} oSettings dataTables settings object
@param {int} iMaster use the master data array - optional
@memberof DataTable#oApi
function _fnBuildSearchArray ( oSettings, iMaster )
if ( !oSettings.oFeatures.bServerSide )
/* Clear out the old data */
oSettings.asDataSearch = [];
var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );
var aiIndex = (iMaster===1) ?
oSettings.aiDisplayMaster :
oSettings.aiD
for ( var i=0, iLen=aiIndex. i&iL i++ )
oSettings.asDataSearch[i] = _fnBuildSearchRow(
oSettings,
_fnGetRowData( oSettings, aiIndex[i], 'filter', aiFilterColumns )
* Create a searchable string from a single data row
@param {object} oSettings dataTables settings object
@param {array} aData Row data array to use for the data to search
@memberof DataTable#oApi
function _fnBuildSearchRow( oSettings, aData )
var sSearch = aData.join('
/* If it looks like there is an HTML entity in the string, attempt to decode it */
if ( sSearch.indexOf('&') !== -1 )
sSearch = $('&div&').html(sSearch).text();
// Strip newline characters
return sSearch.replace( /[\n\r]/g, " " );
* Build a regular expression object suitable for searching a table
@param {string} sSearch string to search for
@param {bool} bRegex treat as a regular expression or not
@param {bool} bSmart perform smart filtering or not
@param {bool} bCaseInsensitive Do case insensitive matching or not
@returns {RegExp} constructed object
@memberof DataTable#oApi
function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive )
var asSearch, sRegExpS
if ( bSmart )
/* Generate the regular expression to use. Something along the lines of:
* ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' );
sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';
return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" );
sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch );
return new RegExp( sSearch, bCaseInsensitive ? "i" : "" );
* Convert raw data into something that the user can search on
@param {string} sData data to be modified
@param {string} sType data type
@returns {string} search string
@memberof DataTable#oApi
function _fnDataToSearch ( sData, sType )
if ( typeof DataTable.ext.ofnSearch[sType] === "function" )
return DataTable.ext.ofnSearch[sType]( sData );
else if ( sData === null )
return '';
else if ( sType == "html" )
return sData.replace(/[\r\n]/g," ").replace( /&.*?&/g, "" );
else if ( typeof sData === "string" )
return sData.replace(/[\r\n]/g," ");
* scape a string such that it can be used in a regular expression
@param {string} sVal string to escape
@returns {string} escaped string
@memberof DataTable#oApi
function _fnEscapeRegex ( sVal )
var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ];
var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' );
return sVal.replace(reReplace, '\\$1');
* Generate the node required for the info display
@param {object} oSettings dataTables settings object
@returns {node} Information element
@memberof DataTable#oApi
function _fnFeatureHtmlInfo ( oSettings )
var nInfo = document.createElement( 'div' );
nInfo.className = oSettings.oClasses.sI
/* Actions that are to be taken once only for this feature */
if ( !oSettings.aanFeatures.i )
/* Add draw callback */
oSettings.aoDrawCallback.push( {
"fn": _fnUpdateInfo,
"sName": "information"
/* Add id */
nInfo.id = oSettings.sTableId+'_info';
oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' );
* Update the information elements in the display
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnUpdateInfo ( oSettings )
/* Show information about the table */
if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 )
oLang = oSettings.oLanguage,
iStart = oSettings._iDisplayStart+1,
iEnd = oSettings.fnDisplayEnd(),
iMax = oSettings.fnRecordsTotal(),
iTotal = oSettings.fnRecordsDisplay(),
if ( iTotal === 0 )
/* Empty record set */
sOut = oLang.sInfoE
/* Normal record set */
sOut = oLang.sI
if ( iTotal != iMax )
/* Record set after filtering */
sOut += ' ' + oLang.sInfoF
// Convert the macros
sOut += oLang.sInfoPostF
sOut = _fnInfoMacros( oSettings, sOut );
if ( oLang.fnInfoCallback !== null )
sOut = oLang.fnInfoCallback.call( oSettings.oInstance,
oSettings, iStart, iEnd, iMax, iTotal, sOut );
var n = oSettings.aanFeatures.i;
for ( var i=0, iLen=n. i&iL i++ )
$(n[i]).html( sOut );
function _fnInfoMacros ( oSettings, str )
iStart = oSettings._iDisplayStart+1,
sStart = oSettings.fnFormatNumber( iStart ),
iEnd = oSettings.fnDisplayEnd(),
sEnd = oSettings.fnFormatNumber( iEnd ),
iTotal = oSettings.fnRecordsDisplay(),
sTotal = oSettings.fnFormatNumber( iTotal ),
iMax = oSettings.fnRecordsTotal(),
sMax = oSettings.fnFormatNumber( iMax );
// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
// internally
if ( oSettings.oScroll.bInfinite )
sStart = oSettings.fnFormatNumber( 1 );
return str.
replace(/_START_/g, sStart).
replace(/_END_/g,
replace(/_TOTAL_/g, sTotal).
replace(/_MAX_/g,
* Draw the table for the first time, adding all required features
@param {object} oSettings dataTables settings object
@memberof DataTable#oApi
function _fnInitialise ( oSettings )
var i, iLen, iAjaxStart=oSettings.iInitDisplayS
/* Ensure that the table data is fully initialised */
if ( oSettings.bInitialised === false )
setTimeout( function(){ _fnInitialise( oSettings ); }, 200 );
/* Show the display HTML options */
_fnAddOptionsHtml( oSettings );
/* Build and draw the header / footer for the table */
_fnBuildHead( oSettings );
_fnDrawHead( oSettings, oSettings.aoHeader );
if ( oSettings.nTFoot )
_fnDrawHead( oSettings, oSettings.aoFooter );
/* Okay to show that something is going on now */
_fnProcessingDisplay( oSettings, true );
/* Calculate sizes for columns */
if ( oSettings.oFeatures.bAutoWidth )
_fnCalculateColumnWidths( oSettings );
for ( i=0, iLen=oSettings.aoColumns. i&iL i++ )
if ( oSettings.aoColumns[i].sWidth !== null )
oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth );
/* If there is default sorting required - let's do it. The sort function will do the
* drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows
* the table to look initialised for Ajax sourcing data (show 'loading' message possibly)
if ( oSettings.oFeatures.bSort )
_fnSort( oSettings );
else if ( oSettings.oFeatures.bFilter )
_fnFilterComplete( oSettings, oSettings.oPreviousSearch );
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
/* if there is an ajax source load the data */
if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
var aoData = [];
_fnServerParams( oSettings, aoData );
oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) {
var aData = (oSettings.sAjaxDataProp !== "") ?
_fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) :
/* Got the data - add it to the table */
for ( i=0 ; i&aData. i++ )
_fnAddData( oSettings, aData[i] );
/* Reset the init display for cookie saving. We've already done a filter, and
* therefore c

我要回帖

更多关于 centos 计划任务 的文章

 

随机推荐