/* =========================================================
* bootstrap-slider.js v2.0.0
* http://www.eyecon.ro/bootstrap-slider
* =========================================================
* Copyright 2012 Stefan Petre
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================= */
!function( $ ) {
var Slider = function(element, options) {
this.element = $(element);
this.picker = $('
'+
'
'+
''+
''+
''+
'
'+
'
'+
'
')
.insertBefore(this.element)
.append(this.element);
this.id = this.element.data('slider-id')||options.id;
if (this.id) {
this.picker[0].id = this.id;
}
if (typeof Modernizr !== 'undefined' && Modernizr.touch) {
this.touchCapable = true;
}
var tooltip = this.element.data('slider-tooltip')||options.tooltip;
this.tooltip = this.picker.find('.tooltip');
this.tooltipInner = this.tooltip.find('div.tooltip-inner');
this.orientation = this.element.data('slider-orientation')||options.orientation;
switch(this.orientation) {
case 'vertical':
this.picker.addClass('slider-vertical');
this.stylePos = 'top';
this.mousePos = 'pageY';
this.sizePos = 'offsetHeight';
this.tooltip.addClass('right')[0].style.left = '100%';
break;
default:
this.picker
.addClass('slider-horizontal')
.css('width', this.element.outerWidth());
this.orientation = 'horizontal';
this.stylePos = 'left';
this.mousePos = 'pageX';
this.sizePos = 'offsetWidth';
this.tooltip.addClass('top')[0].style.top = -this.tooltip.outerHeight() - 14 + 'px';
break;
}
this.min = this.element.data('slider-min')||options.min;
this.max = this.element.data('slider-max')||options.max;
this.step = this.element.data('slider-step')||options.step;
this.value = this.element.data('slider-value')||options.value;
if (this.value[1]) {
this.range = true;
}
this.selection = this.element.data('slider-selection')||options.selection;
this.selectionEl = this.picker.find('.slider-selection');
if (this.selection === 'none') {
this.selectionEl.addClass('hide');
}
this.selectionElStyle = this.selectionEl[0].style;
this.handle1 = this.picker.find('.slider-handle:first');
this.handle1Stype = this.handle1[0].style;
this.handle2 = this.picker.find('.slider-handle:last');
this.handle2Stype = this.handle2[0].style;
var handle = this.element.data('slider-handle')||options.handle;
switch(handle) {
case 'round':
this.handle1.addClass('round');
this.handle2.addClass('round');
break
case 'triangle':
this.handle1.addClass('triangle');
this.handle2.addClass('triangle');
break
}
if (this.range) {
this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
} else {
this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
this.handle2.addClass('hide');
if (this.selection == 'after') {
this.value[1] = this.max;
} else {
this.value[1] = this.min;
}
}
this.diff = this.max - this.min;
this.percentage = [
(this.value[0]-this.min)*100/this.diff,
(this.value[1]-this.min)*100/this.diff,
this.step*100/this.diff
];
this.offset = this.picker.offset();
this.size = this.picker[0][this.sizePos];
this.formater = options.formater;
this.layout();
if (this.touchCapable) {
// Touch: Bind touch events:
this.picker.on({
touchstart: $.proxy(this.mousedown, this)
});
} else {
this.picker.on({
mousedown: $.proxy(this.mousedown, this)
});
}
if (tooltip === 'show') {
this.picker.on({
mouseenter: $.proxy(this.showTooltip, this),
mouseleave: $.proxy(this.hideTooltip, this)
});
} else {
this.tooltip.addClass('hide');
}
};
Slider.prototype = {
constructor: Slider,
over: false,
inDrag: false,
showTooltip: function(){
this.tooltip.addClass('in');
//var left = Math.round(this.percent*this.width);
//this.tooltip.css('left', left - this.tooltip.outerWidth()/2);
this.over = true;
},
hideTooltip: function(){
if (this.inDrag === false) {
this.tooltip.removeClass('in');
}
this.over = false;
},
layout: function(){
this.handle1Stype[this.stylePos] = this.percentage[0]+'%';
this.handle2Stype[this.stylePos] = this.percentage[1]+'%';
if (this.orientation == 'vertical') {
this.selectionElStyle.top = Math.min(this.percentage[0], this.percentage[1]) +'%';
this.selectionElStyle.height = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
} else {
this.selectionElStyle.left = Math.min(this.percentage[0], this.percentage[1]) +'%';
this.selectionElStyle.width = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
}
if (this.range) {
this.tooltipInner.text(
this.formater(this.value[0]) +
' : ' +
this.formater(this.value[1])
);
this.tooltip[0].style[this.stylePos] = this.size * (this.percentage[0] + (this.percentage[1] - this.percentage[0])/2)/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
} else {
this.tooltipInner.text(
this.formater(this.value[0])
);
this.tooltip[0].style[this.stylePos] = this.size * this.percentage[0]/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
}
},
mousedown: function(ev) {
// Touch: Get the original event:
if (this.touchCapable && ev.type === 'touchstart') {
ev = ev.originalEvent;
}
this.offset = this.picker.offset();
this.size = this.picker[0][this.sizePos];
var percentage = this.getPercentage(ev);
if (this.range) {
var diff1 = Math.abs(this.percentage[0] - percentage);
var diff2 = Math.abs(this.percentage[1] - percentage);
this.dragged = (diff1 < diff2) ? 0 : 1;
} else {
this.dragged = 0;
}
this.percentage[this.dragged] = percentage;
this.layout();
if (this.touchCapable) {
// Touch: Bind touch events:
$(document).on({
touchmove: $.proxy(this.mousemove, this),
touchend: $.proxy(this.mouseup, this)
});
} else {
$(document).on({
mousemove: $.proxy(this.mousemove, this),
mouseup: $.proxy(this.mouseup, this)
});
}
this.inDrag = true;
var val = this.calculateValue();
this.element.trigger({
type: 'slideStart',
value: val
}).trigger({
type: 'slide',
value: val
});
return false;
},
mousemove: function(ev) {
// Touch: Get the original event:
if (this.touchCapable && ev.type === 'touchmove') {
ev = ev.originalEvent;
}
var percentage = this.getPercentage(ev);
if (this.range) {
if (this.dragged === 0 && this.percentage[1] < percentage) {
this.percentage[0] = this.percentage[1];
this.dragged = 1;
} else if (this.dragged === 1 && this.percentage[0] > percentage) {
this.percentage[1] = this.percentage[0];
this.dragged = 0;
}
}
this.percentage[this.dragged] = percentage;
this.layout();
var val = this.calculateValue();
this.element
.trigger({
type: 'slide',
value: val
})
.data('value', val)
.prop('value', val);
return false;
},
mouseup: function(ev) {
if (this.touchCapable) {
// Touch: Bind touch events:
$(document).off({
touchmove: this.mousemove,
touchend: this.mouseup
});
} else {
$(document).off({
mousemove: this.mousemove,
mouseup: this.mouseup
});
}
this.inDrag = false;
if (this.over == false) {
this.hideTooltip();
}
this.element;
var val = this.calculateValue();
this.element
.trigger({
type: 'slideStop',
value: val
})
.data('value', val)
.prop('value', val);
return false;
},
calculateValue: function() {
var val;
if (this.range) {
val = [
(this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step),
(this.min + Math.round((this.diff * this.percentage[1]/100)/this.step)*this.step)
];
this.value = val;
} else {
val = (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step);
this.value = [val, this.value[1]];
}
return val;
},
getPercentage: function(ev) {
if (this.touchCapable) {
ev = ev.touches[0];
}
var percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size;
percentage = Math.round(percentage/this.percentage[2])*this.percentage[2];
return Math.max(0, Math.min(100, percentage));
},
getValue: function() {
if (this.range) {
return this.value;
}
return this.value[0];
},
setValue: function(val) {
this.value = val;
if (this.range) {
this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
} else {
this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
this.handle2.addClass('hide');
if (this.selection == 'after') {
this.value[1] = this.max;
} else {
this.value[1] = this.min;
}
}
this.diff = this.max - this.min;
this.percentage = [
(this.value[0]-this.min)*100/this.diff,
(this.value[1]-this.min)*100/this.diff,
this.step*100/this.diff
];
this.layout();
}
};
$.fn.slider = function ( option, val ) {
return this.each(function () {
var $this = $(this),
data = $this.data('slider'),
options = typeof option === 'object' && option;
if (!data) {
$this.data('slider', (data = new Slider(this, $.extend({}, $.fn.slider.defaults,options))));
}
if (typeof option == 'string') {
data[option](val);
}
})
};
$.fn.slider.defaults = {
min: 0,
max: 10,
step: 1,
orientation: 'horizontal',
value: 5,
selection: 'before',
tooltip: 'show',
handle: 'round',
formater: function(value) {
return value;
}
};
$.fn.slider.Constructor = Slider;
}( window.jQuery );
/**
* @summary DataTables
* @description Paginate, search and sort HTML tables
* @version 1.9.4
* @file jquery.dataTables.js
* @author Allan Jardine (www.sprymedia.co.uk)
* @contact www.sprymedia.co.uk/contact
*
* @copyright Copyright 2008-2012 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 */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 */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
* DataTables.net.
*
* Note that the DataTable object is not a global variable but is
* aliased to jQuery.fn.DataTable and jQuery.fn.dataTable through which
* it may be accessed.
*
* @class
* @param {object} [oInit={}] Configuration object for DataTables. Options
* are defined by {@link DataTable.defaults}
* @requires jQuery 1.3+
*
* @example
* // Basic initialisation
* $(document).ready( function {
* $('#example').dataTable();
* } );
*
* @example
* // 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.columns;
var iCol = oSettings.aoColumns.length;
var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
"sSortingClass": oSettings.oClasses.sSortable,
"sSortingClassJUI": oSettings.oClasses.sSortJUI,
"nTh": nTh ? nTh : document.createElement('th'),
"sTitle": 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 );
}
else
{
var oPre = oSettings.aoPreSearchCols[ iCol ];
/* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
if ( oPre.bRegex === undefined )
{
oPre.bRegex = true;
}
if ( oPre.bSmart === undefined )
{
oPre.bSmart = true;
}
if ( oPre.bCaseInsensitive === undefined )
{
oPre.bCaseInsensitive = true;
}
}
/* 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.mDataProp;
}
if ( oOptions.sType !== undefined )
{
oCol.sType = oOptions.sType;
oCol._bAutoType = false;
}
$.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 ) : null;
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 innerData;
};
oCol.fnSetData = _fnSetObjectDataFn( oCol.mData );
/* Feature sorting overrides column specific when off */
if ( !oSettings.oFeatures.bSort )
{
oCol.bSortable = false;
}
/* 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.sSortableNone;
oCol.sSortingClassJUI = "";
}
else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 )
{
oCol.sSortingClass = oSettings.oClasses.sSortable;
oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
}
else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
{
oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
}
else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
{
oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
}
}
/**
* 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 )
{
return false;
}
_fnCalculateColumnWidths( oSettings );
for ( var i=0 , iLen=oSettings.aoColumns.length ; i=0 ; i-- )
{
/* Each definition can target multiple columns, as it is an array */
var aTargets = aoColDefs[i].aTargets;
if ( !$.isArray( aTargets ) )
{
_fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
}
for ( j=0, jLen=aTargets.length ; 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.length ; k=0 if successful (index of new aoData entry), -1 if failed
* @memberof DataTable#oApi
*/
function _fnAddData ( oSettings, aDataSupplied )
{
var oCol;
/* 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.length;
var oData = $.extend( true, {}, DataTable.models.oRow );
oData._aData = aDataIn;
oSettings.aoData.push( oData );
/* Create the cells */
var nTd, sThisType;
for ( var i=0, iLen=oSettings.aoColumns.length ; i iTarget )
{
a[i]--;
}
}
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": iRow,
"iDataColumn": iCol,
"oSettings": oSettings,
"aData": 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];
var nTd;
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 = iRow;
/* 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_RowClass;
}
/* Process each column */
for ( var i=0, iLen=oSettings.aoColumns.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 : oSettings.iInitDisplayStart;
}
oSettings.iInitDisplayStart = -1;
_fnCalculateEnd( oSettings );
}
/* Server-side processing draw intercept */
if ( oSettings.bDeferLoading )
{
oSettings.bDeferLoading = false;
oSettings.iDraw++;
}
else if ( !oSettings.oFeatures.bServerSide )
{
oSettings.iDraw++;
}
else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
{
return;
}
if ( oSettings.aiDisplay.length !== 0 )
{
var iStart = oSettings._iDisplayStart;
var iEnd = oSettings._iDisplayEnd;
if ( oSettings.oFeatures.bServerSide )
{
iStart = 0;
iEnd = oSettings.aoData.length;
}
for ( var j=iStart ; j')[0];
oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
/*
* All DataTables are wrapped in a div
*/
oSettings.nTableWrapper = $('')[0];
oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
/* Track where we want to insert the option */
var nInsertNode = oSettings.nTableWrapper;
/* Loop over the user set positioning and place the elements as needed */
var aDom = oSettings.sDom.split('');
var nTmp, iPushFeature, 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 */
if ( sAttr == "H" )
{
sAttr = oSettings.oClasses.sJUIHeader;
}
else if ( sAttr == "F" )
{
sAttr = oSettings.oClasses.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 */
}
nInsertNode.appendChild( nNewNode );
nInsertNode = nNewNode;
}
else if ( cOption == '>' )
{
/* End container div */
nInsertNode = nInsertNode.parentNode;
}
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.aoFeatures;
for ( var k=0, kLen=aoFeatures.length ; k') :
sSearchStr==="" ? '' : sSearchStr+' ';
var nFilter = document.createElement( 'div' );
nFilter.className = oSettings.oClasses.sFilter;
nFilter.innerHTML = '';
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.value; // mental IE8 fix :-(
for ( var i=0, iLen=n.length ; 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 i;
var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
var oPrevSearch = oSettings.oPreviousSearch;
/* 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();
}
else
{
/*
* 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
* mapping
*/
for ( i=0 ; i').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, sRegExpString;
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" : "" );
}
else
{
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," ");
}
return sData;
}
/**
* 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.sInfo;
/* 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' );
return nInfo;
}
/**
* 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 )
{
return;
}
var
oLang = oSettings.oLanguage,
iStart = oSettings._iDisplayStart+1,
iEnd = oSettings.fnDisplayEnd(),
iMax = oSettings.fnRecordsTotal(),
iTotal = oSettings.fnRecordsDisplay(),
sOut;
if ( iTotal === 0 )
{
/* Empty record set */
sOut = oLang.sInfoEmpty;
}
else {
/* Normal record set */
sOut = oLang.sInfo;
}
if ( iTotal != iMax )
{
/* Record set after filtering */
sOut += ' ' + oLang.sInfoFiltered;
}
// Convert the macros
sOut += oLang.sInfoPostFix;
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.length ; i';
var i, iLen;
var aLengthMenu = oSettings.aLengthMenu;
if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' &&
typeof aLengthMenu[1] === 'object' )
{
for ( i=0, iLen=aLengthMenu[0].length ; i'+aLengthMenu[1][i]+'';
}
}
else
{
for ( i=0, iLen=aLengthMenu.length ; i'+aLengthMenu[i]+'';
}
}
sStdMenu += '';
var nLength = document.createElement( 'div' );
if ( !oSettings.aanFeatures.l )
{
nLength.id = oSettings.sTableId+'_length';
}
nLength.className = oSettings.oClasses.sLength;
nLength.innerHTML = '';
/*
* Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
* and Stefan Skopnik for fixing the fix!
*/
$('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true);
$('select', nLength).bind( 'change.DT', function(e) {
var iVal = $(this).val();
/* Update all other length options for the new display */
var n = oSettings.aanFeatures.l;
for ( i=0, iLen=n.length ; i oSettings.aiDisplay.length ||
oSettings._iDisplayLength == -1 )
{
oSettings._iDisplayEnd = oSettings.aiDisplay.length;
}
else
{
oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
}
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Note that most of the paging logic is done in
* DataTable.ext.oPagination
*/
/**
* Generate the node required for default pagination
* @param {object} oSettings dataTables settings object
* @returns {node} Pagination feature node
* @memberof DataTable#oApi
*/
function _fnFeatureHtmlPaginate ( oSettings )
{
if ( oSettings.oScroll.bInfinite )
{
return null;
}
var nPaginate = document.createElement( 'div' );
nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate,
function( oSettings ) {
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
}
);
/* Add a draw callback for the pagination on first instance, to update the paging display */
if ( !oSettings.aanFeatures.p )
{
oSettings.aoDrawCallback.push( {
"fn": function( oSettings ) {
DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
} );
},
"sName": "pagination"
} );
}
return nPaginate;
}
/**
* Alter the display settings to change the page
* @param {object} oSettings dataTables settings object
* @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
* or page number to jump to (integer)
* @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
* @memberof DataTable#oApi
*/
function _fnPageChange ( oSettings, mAction )
{
var iOldStart = oSettings._iDisplayStart;
if ( typeof mAction === "number" )
{
oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() )
{
oSettings._iDisplayStart = 0;
}
}
else if ( mAction == "first" )
{
oSettings._iDisplayStart = 0;
}
else if ( mAction == "previous" )
{
oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?
oSettings._iDisplayStart - oSettings._iDisplayLength :
0;
/* Correct for under-run */
if ( oSettings._iDisplayStart < 0 )
{
oSettings._iDisplayStart = 0;
}
}
else if ( mAction == "next" )
{
if ( oSettings._iDisplayLength >= 0 )
{
/* Make sure we are not over running the display array */
if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
{
oSettings._iDisplayStart += oSettings._iDisplayLength;
}
}
else
{
oSettings._iDisplayStart = 0;
}
}
else if ( mAction == "last" )
{
if ( oSettings._iDisplayLength >= 0 )
{
var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
}
else
{
oSettings._iDisplayStart = 0;
}
}
else
{
_fnLog( oSettings, 0, "Unknown paging action: "+mAction );
}
$(oSettings.oInstance).trigger('page', oSettings);
return iOldStart != oSettings._iDisplayStart;
}
/**
* Generate the node required for the processing node
* @param {object} oSettings dataTables settings object
* @returns {node} Processing element
* @memberof DataTable#oApi
*/
function _fnFeatureHtmlProcessing ( oSettings )
{
var nProcessing = document.createElement( 'div' );
if ( !oSettings.aanFeatures.r )
{
nProcessing.id = oSettings.sTableId+'_processing';
}
nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
nProcessing.className = oSettings.oClasses.sProcessing;
oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
return nProcessing;
}
/**
* Display or hide the processing indicator
* @param {object} oSettings dataTables settings object
* @param {bool} bShow Show the processing indicator (true) or not (false)
* @memberof DataTable#oApi
*/
function _fnProcessingDisplay ( oSettings, bShow )
{
if ( oSettings.oFeatures.bProcessing )
{
var an = oSettings.aanFeatures.r;
for ( var i=0, iLen=an.length ; i 0 )
{
nCaption = nCaption[0];
if ( nCaption._captionSide === "top" )
{
nScrollHeadTable.appendChild( nCaption );
}
else if ( nCaption._captionSide === "bottom" && nTfoot )
{
nScrollFootTable.appendChild( nCaption );
}
}
/*
* Sizing
*/
/* When x-scrolling add the width and a scroller to move the header with the body */
if ( oSettings.oScroll.sX !== "" )
{
nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );
nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );
if ( nTfoot !== null )
{
nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );
}
/* When the body is scrolled, then we also want to scroll the headers */
$(nScrollBody).scroll( function (e) {
nScrollHead.scrollLeft = this.scrollLeft;
if ( nTfoot !== null )
{
nScrollFoot.scrollLeft = this.scrollLeft;
}
} );
}
/* When yscrolling, add the height */
if ( oSettings.oScroll.sY !== "" )
{
nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );
}
/* Redraw - align columns across the tables */
oSettings.aoDrawCallback.push( {
"fn": _fnScrollDraw,
"sName": "scrolling"
} );
/* Infinite scrolling event handlers */
if ( oSettings.oScroll.bInfinite )
{
$(nScrollBody).scroll( function() {
/* Use a blocker to stop scrolling from loading more data while other data is still loading */
if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 )
{
/* Check if we should load the next data set */
if ( $(this).scrollTop() + $(this).height() >
$(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )
{
/* Only do the redraw if we have to - we might be at the end of the data */
if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )
{
_fnPageChange( oSettings, 'next' );
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
}
}
}
} );
}
oSettings.nScrollHead = nScrollHead;
oSettings.nScrollFoot = nScrollFoot;
return nScroller;
}
/**
* Update the various tables for resizing. It's a bit of a pig this function, but
* basically the idea to:
* 1. Re-create the table inside the scrolling div
* 2. Take live measurements from the DOM
* 3. Apply the measurements
* 4. Clean up
* @param {object} o dataTables settings object
* @returns {node} Node to add to the DOM
* @memberof DataTable#oApi
*/
function _fnScrollDraw ( o )
{
var
nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
nScrollBody = o.nTable.parentNode,
i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
nTheadSize, nTfootSize,
iWidth, aApplied=[], aAppliedFooter=[], iSanityWidth,
nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
ie67 = o.oBrowser.bScrollOversize,
zeroOut = function(nSizer) {
oStyle = nSizer.style;
oStyle.paddingTop = "0";
oStyle.paddingBottom = "0";
oStyle.borderTopWidth = "0";
oStyle.borderBottomWidth = "0";
oStyle.height = 0;
};
/*
* 1. Re-create the table inside the scrolling div
*/
/* Remove the old minimised thead and tfoot elements in the inner table */
$(o.nTable).children('thead, tfoot').remove();
/* Clone the current header and footer elements and then place it into the inner table */
nTheadSize = $(o.nTHead).clone()[0];
o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
anHeadToSize = o.nTHead.getElementsByTagName('tr');
anHeadSizers = nTheadSize.getElementsByTagName('tr');
if ( o.nTFoot !== null )
{
nTfootSize = $(o.nTFoot).clone()[0];
o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
anFootToSize = o.nTFoot.getElementsByTagName('tr');
anFootSizers = nTfootSize.getElementsByTagName('tr');
}
/*
* 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 ( o.oScroll.sX === "" )
{
nScrollBody.style.width = '100%';
nScrollHeadInner.parentNode.style.width = '100%';
}
var nThs = _fnGetUniqueThs( o, nTheadSize );
for ( i=0, iLen=nThs.length ; i nScrollBody.offsetHeight ||
$(nScrollBody).css('overflow-y') == "scroll") )
{
o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
}
}
else
{
if ( o.oScroll.sXInner !== "" )
{
/* x scroll inner has been given - use it */
o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
}
else if ( iSanityWidth == $(nScrollBody).width() &&
$(nScrollBody).height() < $(o.nTable).height() )
{
/* There is y-scrolling - try to take account of the y scroll bar */
o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );
if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )
{
/* Not possible to take account of it */
o.nTable.style.width = _fnStringToCss( iSanityWidth );
}
}
else
{
/* All else fails */
o.nTable.style.width = _fnStringToCss( iSanityWidth );
}
}
/* Recalculate the sanity width - now that we've applied the required width, before it was
* a temporary variable. This is required because the column width calculation is done
* before this table DOM is created.
*/
iSanityWidth = $(o.nTable).outerWidth();
/* We want the hidden header to have zero height, so remove padding and borders. Then
* set the width based on the real headers
*/
// Apply all styles in one pass. Invalidates layout only once because we don't read any
// DOM properties.
_fnApplyToChildren( zeroOut, anHeadSizers );
// Read all widths in next pass. Forces layout only once because we do not change
// any DOM properties.
_fnApplyToChildren( function(nSizer) {
aApplied.push( _fnStringToCss( $(nSizer).width() ) );
}, anHeadSizers );
// Apply all widths in final pass. Invalidates layout only once because we do not
// read any DOM properties.
_fnApplyToChildren( function(nToSize, i) {
nToSize.style.width = aApplied[i];
}, anHeadToSize );
$(anHeadSizers).height(0);
/* Same again with the footer if we have one */
if ( o.nTFoot !== null )
{
_fnApplyToChildren( zeroOut, anFootSizers );
_fnApplyToChildren( function(nSizer) {
aAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) );
}, anFootSizers );
_fnApplyToChildren( function(nToSize, i) {
nToSize.style.width = aAppliedFooter[i];
}, anFootToSize );
$(anFootSizers).height(0);
}
/*
* 3. Apply the measurements
*/
/* "Hide" the header and footer that we used for the sizing. We want to also fix their width
* to what they currently are
*/
_fnApplyToChildren( function(nSizer, i) {
nSizer.innerHTML = "";
nSizer.style.width = aApplied[i];
}, anHeadSizers );
if ( o.nTFoot !== null )
{
_fnApplyToChildren( function(nSizer, i) {
nSizer.innerHTML = "";
nSizer.style.width = aAppliedFooter[i];
}, anFootSizers );
}
/* 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 ( $(o.nTable).outerWidth() < iSanityWidth )
{
/* The min width depends upon if we have a vertical scrollbar visible or not */
var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight ||
$(nScrollBody).css('overflow-y') == "scroll")) ?
iSanityWidth+o.oScroll.iBarWidth : iSanityWidth;
/* IE6/7 are a law unto themselves... */
if ( ie67 && (nScrollBody.scrollHeight >
nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") )
{
o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth );
}
/* Apply the calculated minimum width to the table wrappers */
nScrollBody.style.width = _fnStringToCss( iCorrection );
o.nScrollHead.style.width = _fnStringToCss( iCorrection );
if ( o.nTFoot !== null )
{
o.nScrollFoot.style.width = _fnStringToCss( iCorrection );
}
/* And give the user a warning that we've stopped the table getting too small */
if ( o.oScroll.sX === "" )
{
_fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
" misalignment. The table has been drawn at its minimum possible width." );
}
else if ( o.oScroll.sXInner !== "" )
{
_fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
" misalignment. Increase the sScrollXInner value or remove it to allow automatic"+
" calculation" );
}
}
else
{
nScrollBody.style.width = _fnStringToCss( '100%' );
o.nScrollHead.style.width = _fnStringToCss( '100%' );
if ( o.nTFoot !== null )
{
o.nScrollFoot.style.width = _fnStringToCss( '100%' );
}
}
/*
* 4. Clean up
*/
if ( o.oScroll.sY === "" )
{
/* 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 )
{
nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );
}
}
if ( o.oScroll.sY !== "" && o.oScroll.bCollapse )
{
nScrollBody.style.height = _fnStringToCss( o.oScroll.sY );
var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
o.oScroll.iBarWidth : 0;
if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
{
nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );
}
}
/* Finally set the width's of the header and footer tables */
var iOuterWidth = $(o.nTable).outerWidth();
nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
nScrollHeadInner.style.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 = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
if ( o.nTFoot !== null )
{
nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
}
/* Adjust the position of the header in case we loose the y-scrollbar */
$(nScrollBody).scroll();
/* If sorting or filtering has occurred, jump the scrolling back to the top */
if ( o.bSorted || o.bFiltered )
{
nScrollBody.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++;
}
}
/**
* Convert a CSS unit width to pixels (e.g. 2em)
* @param {string} sWidth width to be converted
* @param {node} nParent parent to get the with for (required for relative widths) - optional
* @returns {int} iWidth width in pixels
* @memberof DataTable#oApi
*/
function _fnConvertToWidth ( sWidth, nParent )
{
if ( !sWidth || sWidth === null || sWidth === '' )
{
return 0;
}
if ( !nParent )
{
nParent = document.body;
}
var iWidth;
var nTmp = document.createElement( "div" );
nTmp.style.width = _fnStringToCss( sWidth );
nParent.appendChild( nTmp );
iWidth = nTmp.offsetWidth;
nParent.removeChild( nTmp );
return ( iWidth );
}
/**
* Calculate the width of columns for the table
* @param {object} oSettings dataTables settings object
* @memberof DataTable#oApi
*/
function _fnCalculateColumnWidths ( oSettings )
{
var iTableWidth = oSettings.nTable.offsetWidth;
var iUserInputs = 0;
var iTmpWidth;
var iVisibleColumns = 0;
var iColums = oSettings.aoColumns.length;
var i, iIndex, iCorrector, iWidth;
var oHeaders = $('th', oSettings.nTHead);
var widthAttr = oSettings.nTable.getAttribute('width');
var nWrapper = oSettings.nTable.parentNode;
/* Convert any user input sizes into pixel sizes */
for ( i=0 ; itd', nCalcTmp);
}
/* Apply custom sizing to the cloned header */
var nThs = _fnGetUniqueThs( oSettings, nTheadClone );
iCorrector = 0;
for ( i=0 ; i 0 )
{
oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );
}
iCorrector++;
}
}
var cssWidth = $(nCalcTmp).css('width');
oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() );
nCalcTmp.parentNode.removeChild( nCalcTmp );
}
if ( widthAttr )
{
oSettings.nTable.style.width = _fnStringToCss( widthAttr );
}
}
/**
* Adjust a table's width to take account of scrolling
* @param {object} oSettings dataTables settings object
* @param {node} n table node
* @memberof DataTable#oApi
*/
function _fnScrollingWidthAdjust ( oSettings, n )
{
if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" )
{
/* When y-scrolling only, we want to remove the width of the scroll bar so the table
* + scroll bar will fit into the area avaialble.
*/
var iOrigWidth = $(n).width();
n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );
}
else if ( oSettings.oScroll.sX !== "" )
{
/* When x-scrolling both ways, fix the table at it's current size, without adjusting */
n.style.width = _fnStringToCss( $(n).outerWidth() );
}
}
/**
* Get the widest node
* @param {object} oSettings dataTables settings object
* @param {int} iCol column of interest
* @returns {node} widest table node
* @memberof DataTable#oApi
*/
function _fnGetWidestNode( oSettings, iCol )
{
var iMaxIndex = _fnGetMaxLenString( oSettings, iCol );
if ( iMaxIndex < 0 )
{
return null;
}
if ( oSettings.aoData[iMaxIndex].nTr === null )
{
var n = document.createElement('td');
n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' );
return n;
}
return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
}
/**
* Get the maximum strlen for each data column
* @param {object} oSettings dataTables settings object
* @param {int} iCol column of interest
* @returns {string} max string length for each column
* @memberof DataTable#oApi
*/
function _fnGetMaxLenString( oSettings, iCol )
{
var iMax = -1;
var iMaxIndex = -1;
for ( var i=0 ; i/g, "" );
if ( s.length > iMax )
{
iMax = s.length;
iMaxIndex = i;
}
}
return iMaxIndex;
}
/**
* Append a CSS unit (only if required) to a string
* @param {array} aArray1 first array
* @param {array} aArray2 second array
* @returns {int} 0 if match, 1 if length is different, 2 if no match
* @memberof DataTable#oApi
*/
function _fnStringToCss( s )
{
if ( s === null )
{
return "0px";
}
if ( typeof s == 'number' )
{
if ( s < 0 )
{
return "0px";
}
return s+"px";
}
/* Check if the last character is not 0-9 */
var c = s.charCodeAt( s.length-1 );
if (c < 0x30 || c > 0x39)
{
return s;
}
return s+"px";
}
/**
* Get the width of a scroll bar in this browser being used
* @returns {int} width in pixels
* @memberof DataTable#oApi
*/
function _fnScrollBarWidth ()
{
var inner = document.createElement('p');
var style = inner.style;
style.width = "100%";
style.height = "200px";
style.padding = "0px";
var outer = document.createElement('div');
style = outer.style;
style.position = "absolute";
style.top = "0px";
style.left = "0px";
style.visibility = "hidden";
style.width = "200px";
style.height = "150px";
style.padding = "0px";
style.overflow = "hidden";
outer.appendChild(inner);
document.body.appendChild(outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if ( w1 == w2 )
{
w2 = outer.clientWidth;
}
document.body.removeChild(outer);
return (w1 - w2);
}
/**
* Change the order of the table
* @param {object} oSettings dataTables settings object
* @param {bool} bApplyClasses optional - should we apply classes or not
* @memberof DataTable#oApi
*/
function _fnSort ( oSettings, bApplyClasses )
{
var
i, iLen, j, jLen, k, kLen,
sDataType, nTh,
aaSort = [],
aiOrig = [],
oSort = DataTable.ext.oSort,
aoData = oSettings.aoData,
aoColumns = oSettings.aoColumns,
oAria = oSettings.oLanguage.oAria;
/* No sorting required if server-side or no sorting array */
if ( !oSettings.oFeatures.bServerSide &&
(oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )
{
aaSort = ( oSettings.aaSortingFixed !== null ) ?
oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
oSettings.aaSorting.slice();
/* If there is a sorting data type, and a function belonging to it, then we need to
* get the data from the developer's function and apply it for this column
*/
for ( i=0 ; i/g, "" );
nTh = aoColumns[i].nTh;
nTh.removeAttribute('aria-sort');
nTh.removeAttribute('aria-label');
/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
if ( aoColumns[i].bSortable )
{
if ( aaSort.length > 0 && aaSort[0][0] == i )
{
nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" );
var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ?
aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];
nTh.setAttribute('aria-label', sTitle+
(nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
}
else
{
nTh.setAttribute('aria-label', sTitle+
(aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
}
}
else
{
nTh.setAttribute('aria-label', sTitle);
}
}
/* Tell the draw function that we have sorted the data */
oSettings.bSorted = true;
$(oSettings.oInstance).trigger('sort', oSettings);
/* Copy the master data into the draw array and re-draw */
if ( oSettings.oFeatures.bFilter )
{
/* _fnFilter() will redraw the table for us */
_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
}
else
{
oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
oSettings._iDisplayStart = 0; /* reset display back to page 0 */
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
}
}
/**
* Attach a sort handler (click) to a node
* @param {object} oSettings dataTables settings object
* @param {node} nNode node to attach the handler to
* @param {int} iDataIndex column sorting index
* @param {function} [fnCallback] callback function
* @memberof DataTable#oApi
*/
function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )
{
_fnBindAction( nNode, {}, function (e) {
/* If the column is not sortable - don't to anything */
if ( oSettings.aoColumns[iDataIndex].bSortable === false )
{
return;
}
/*
* This is a little bit odd I admit... I declare a temporary function inside the scope of
* _fnBuildHead and the click handler in order that the code presented here can be used
* twice - once for when bProcessing is enabled, and another time for when it is
* disabled, as we need to perform slightly different actions.
* Basically the issue here is that the Javascript engine in modern browsers don't
* appear to allow the rendering engine to update the display while it is still executing
* it's thread (well - it does but only after long intervals). This means that the
* 'processing' display doesn't appear for a table sort. To break the js thread up a bit
* I force an execution break by using setTimeout - but this breaks the expected
* thread continuation for the end-developer's point of view (their code would execute
* too early), so we only do it when we absolutely have to.
*/
var fnInnerSorting = function () {
var iColumn, iNextSort;
/* If the shift key is pressed then we are multiple column sorting */
if ( e.shiftKey )
{
/* Are we already doing some kind of sort on this column? */
var bFound = false;
for ( var i=0 ; i 0 && sCurrentClass.indexOf(sNewClass) == -1 )
{
/* We need to add a class */
nTds[i].className = sCurrentClass + " " + sNewClass;
}
}
}
}
/**
* Save the state of a table in a cookie such that the page can be reloaded
* @param {object} oSettings dataTables settings object
* @memberof DataTable#oApi
*/
function _fnSaveState ( oSettings )
{
if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )
{
return;
}
/* Store the interesting variables */
var i, iLen, bInfinite=oSettings.oScroll.bInfinite;
var oState = {
"iCreate": new Date().getTime(),
"iStart": (bInfinite ? 0 : oSettings._iDisplayStart),
"iEnd": (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),
"iLength": oSettings._iDisplayLength,
"aaSorting": $.extend( true, [], oSettings.aaSorting ),
"oSearch": $.extend( true, {}, oSettings.oPreviousSearch ),
"aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ),
"abVisCols": []
};
for ( i=0, iLen=oSettings.aoColumns.length ; i 4096 ) /* Magic 10 for padding */
{
for ( var i=0, iLen=aCookies.length ; i 4096 ) {
if ( aOldCookies.length === 0 ) {
// Deleted all DT cookies and still not enough space. Can't state save
return;
}
var old = aOldCookies.pop();
document.cookie = old.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
aParts.join('/') + "/";
}
}
document.cookie = sFullCookie;
}
/**
* Read an old cookie to get a cookie with an old table state
* @param {string} sName name of the cookie to read
* @returns {string} contents of the cookie - or null if no cookie with that name found
* @memberof DataTable#oApi
*/
function _fnReadCookie ( sName )
{
var
aParts = window.location.pathname.split('/'),
sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=',
sCookieContents = document.cookie.split(';');
for( var i=0 ; i=0 ; i-- )
{
aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) );
}
if ( sTrigger !== null )
{
$(oSettings.oInstance).trigger(sTrigger, aArgs);
}
return aRet;
}
/**
* JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
* library, then we use that as it is fast, safe and accurate. If the function isn't
* available then we need to built it ourselves - the inspiration for this function comes
* from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
* not perfect and absolutely should not be used as a replacement to json2.js - but it does
* do what we need, without requiring a dependency for DataTables.
* @param {object} o JSON object to be converted
* @returns {string} JSON string
* @memberof DataTable#oApi
*/
var _fnJsonString = (window.JSON) ? JSON.stringify : function( o )
{
/* Not an object or array */
var sType = typeof o;
if (sType !== "object" || o === null)
{
// simple data type
if (sType === "string")
{
o = '"'+o+'"';
}
return o+"";
}
/* If object or array, need to recurse over it */
var
sProp, mValue,
json = [],
bArr = $.isArray(o);
for (sProp in o)
{
mValue = o[sProp];
sType = typeof mValue;
if (sType === "string")
{
mValue = '"'+mValue+'"';
}
else if (sType === "object" && mValue !== null)
{
mValue = _fnJsonString(mValue);
}
json.push((bArr ? "" : '"'+sProp+'":') + mValue);
}
return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
};
/**
* From some browsers (specifically IE6/7) we need special handling to work around browser
* bugs - this function is used to detect when these workarounds are needed.
* @param {object} oSettings dataTables settings object
* @memberof DataTable#oApi
*/
function _fnBrowserDetect( oSettings )
{
/* 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
*/
var n = $(
'
'+
'
'+
''+
'
'+
'
')[0];
document.body.appendChild( n );
oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false;
document.body.removeChild( n );
}
/**
* Perform a jQuery selector action on the table's TR elements (from the tbody) and
* return the resulting jQuery object.
* @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
* @param {object} [oOpts] Optional parameters for modifying the rows to be included
* @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
* criterion ("applied") or all TR elements (i.e. no filter).
* @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
* Can be either 'current', whereby the current sorting of the table is used, or
* 'original' whereby the original order the data was read into the table is used.
* @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
* ("current") or not ("all"). If 'current' is given, then order is assumed to be
* 'current' and filter is 'applied', regardless of what they might be given as.
* @returns {object} jQuery object, filtered by the given selector.
* @dtopt API
*
* @example
* $(document).ready(function() {
* var oTable = $('#example').dataTable();
*
* // Highlight every second row
* oTable.$('tr:odd').css('backgroundColor', 'blue');
* } );
*
* @example
* $(document).ready(function() {
* var oTable = $('#example').dataTable();
*
* // Filter to rows with 'Webkit' in them, add a background colour and then
* // remove the filter, thus highlighting the 'Webkit' rows only.
* oTable.fnFilter('Webkit');
* oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
* oTable.fnFilter('');
* } );
*/
this.$ = function ( sSelector, oOpts )
{
var i, iLen, a = [], tr;
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
var aoData = oSettings.aoData;
var aiDisplay = oSettings.aiDisplay;
var aiDisplayMaster = oSettings.aiDisplayMaster;
if ( !oOpts )
{
oOpts = {};
}
oOpts = $.extend( {}, {
"filter": "none", // applied
"order": "current", // "original"
"page": "all" // current
}, oOpts );
// Current page implies that order=current and fitler=applied, since it is fairly
// senseless otherwise
if ( oOpts.page == 'current' )
{
for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i
*
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} [bRedraw=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
*
* @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( mData, bRedraw )
{
if ( mData.length === 0 )
{
return [];
}
var aiReturn = [];
var iTest;
/* Find settings from table node */
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
/* Check if we want to add multiple rows or not */
if ( typeof mData[0] === "object" && mData[0] !== null )
{
for ( var i=0 ; i= oSettings.fnRecordsDisplay() )
{
oSettings._iDisplayStart -= oSettings._iDisplayLength;
if ( oSettings._iDisplayStart < 0 )
{
oSettings._iDisplayStart = 0;
}
}
if ( bRedraw === undefined || bRedraw )
{
_fnCalculateEnd( oSettings );
_fnDraw( oSettings );
}
return oData;
};
/**
* 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} [bRemove=false] Completely remove the table from the DOM
* @dtopt API
*
* @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 ( bRemove )
{
var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
var nOrig = oSettings.nTableWrapper.parentNode;
var nBody = oSettings.nTBody;
var i, iLen;
bRemove = (bRemove===undefined) ? false : bRemove;
/* Flag to note that the table is currently being destroyed - no action should be taken */
oSettings.bDestroying = true;
/* Fire off the destroy callbacks for plug-ins etc */
_fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] );
/* If the table is not being removed, restore the hidden columns */
if ( !bRemove )
{
for ( i=0, iLen=oSettings.aoColumns.length ; itr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
/* When scrolling we had to break the table up - restore it */
if ( oSettings.nTable != oSettings.nTHead.parentNode )
{
$(oSettings.nTable).children('thead').remove();
oSettings.nTable.appendChild( oSettings.nTHead );
}
if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )
{
$(oSettings.nTable).children('tfoot').remove();
oSettings.nTable.appendChild( oSettings.nTFoot );
}
/* Remove the DataTables generated nodes, events and classes */
oSettings.nTable.parentNode.removeChild( oSettings.nTable );
$(oSettings.nTableWrapper).remove();
oSettings.aaSorting = [];
oSettings.aaSortingFixed = [];
_fnSortingClasses( oSettings );
$(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') );
$('th, td', oSettings.nTHead).removeClass( [
oSettings.oClasses.sSortable,
oSettings.oClasses.sSortableAsc,
oSettings.oClasses.sSortableDesc,
oSettings.oClasses.sSortableNone ].join(' ')
);
if ( oSettings.bJUI )
{
$('th span.'+oSettings.oClasses.sSortIcon
+ ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
$('th, td', oSettings.nTHead).each( function () {
var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this);
var kids = jqWrapper.contents();
$(this).append( kids );
jqWrapper.remove();
} );
}
/* Add the TR elements back into the table in their original order */
if ( !bRemove && oSettings.nTableReinsertBefore )
{
nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore );
}
else if ( !bRemove )
{
nOrig.appendChild( oSettings.nTable );
}
for ( i=0, iLen=oSettings.aoData.length ; i= _fnVisbleColumns( oSettings ));
/* Which coloumn should we be inserting before? */
if ( !bAppend )
{
for ( i=iCol ; i= oSettings.aoColumns.length )
{
oSettings.aaSorting[i][0] = 0;
}
var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
/* Add a default sorting index */
if ( oSettings.aaSorting[i][2] === undefined )
{
oSettings.aaSorting[i][2] = 0;
}
/* If aaSorting is not defined, then we use the first indicator in asSorting */
if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined )
{
oSettings.aaSorting[i][1] = oColumn.asSorting[0];
}
/* Set the current sorting index based on aoColumns.asSorting */
for ( j=0, jLen=oColumn.asSorting.length ; j 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 = [ document.createElement( 'tfoot' ) ];
this.appendChild( tfoot[0] );
}
if ( tfoot.length > 0 )
{
oSettings.nTFoot = tfoot[0];
_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
}
/* Check if there is data passing into the constructor */
if ( bUsePassedData )
{
for ( i=0 ; i= parseInt(sThat, 10);
};
/**
* Check if a TABLE node is a DataTable table already or not.
* @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
* node types can be passed in, but will always return false).
* @returns {boolean} true the table given is a DataTable, or false otherwise
* @static
* @dtopt API-Static
*
* @example
* var ex = document.getElementById('example');
* if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
* $(ex).dataTable();
* }
*/
DataTable.fnIsDataTable = function ( nTable )
{
var o = DataTable.settings;
for ( var i=0 ; i 0 ) {
* $(table).dataTable().fnAdjustColumnSizing();
* }
*/
DataTable.fnTables = function ( bVisible )
{
var out = [];
jQuery.each( DataTable.settings, function (i, o) {
if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )
{
out.push( o.nTable );
}
} );
return out;
};
/**
* Version string for plug-ins to check compatibility. Allowed format is
* a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
* e are optional
* @member
* @type string
* @default Version number
*/
DataTable.version = "1.9.4";
/**
* 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 = {};
/**
* DataTables extension options and plug-ins. This namespace acts as a collection "area"
* for plug-ins that can be used to extend the default DataTables behaviour - indeed many
* of the build in methods use this method to provide their own capabilities (sorting methods
* for example).
*
* Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
* and modified by plug-ins.
* @namespace
*/
DataTable.models.ext = {
/**
* Plug-in filtering functions - this method of filtering is complimentary to the default
* type based filtering, and a lot more comprehensive as it allows you complete control
* over the filtering logic. Each element in this array is a function (parameters
* described below) that is called for every row in the table, and your logic decides if
* it should be included in the filtered data set or not.
*
*
* Function input parameters:
*
*
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
*
{array|object} Data for the row to be processed (same as the original format
* that was passed in as the data source, or an array from a DOM data source
*
{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
* be useful to retrieve the TR element if you need DOM interaction.
*
*
*
* Function return:
*
*
{boolean} Include the row in the filtered result set (true) or not (false)
*
*
*
* @type array
* @default []
*
* @example
* // The following example shows custom filtering being applied to the fourth column (i.e.
* // the aData[3] index) based on two input values from the end-user, matching the data in
* // a certain range.
* $.fn.dataTableExt.afnFiltering.push(
* function( oSettings, aData, iDataIndex ) {
* var iMin = document.getElementById('min').value * 1;
* var iMax = document.getElementById('max').value * 1;
* var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
* if ( iMin == "" && iMax == "" ) {
* return true;
* }
* else if ( iMin == "" && iVersion < iMax ) {
* return true;
* }
* else if ( iMin < iVersion && "" == iMax ) {
* return true;
* }
* else if ( iMin < iVersion && iVersion < iMax ) {
* return true;
* }
* return false;
* }
* );
*/
"afnFiltering": [],
/**
* Plug-in sorting functions - this method of sorting is complimentary to the default type
* based sorting that DataTables does automatically, allowing much greater control over the
* the data that is being used to sort a column. This is useful if you want to do sorting
* based on live data (for example the contents of an 'input' element) rather than just the
* static string that DataTables knows of. The way these plug-ins work is that you create
* an array of the values you wish to be sorted for the column in question and then return
* that array. Which pre-sorting function is run here depends on the sSortDataType parameter
* that is used for the column (if any). This is the corollary of ofnSearch for sort
* data.
*
*
* Function input parameters:
*
*
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
*
{int} Target column index
*
*
*
* Function return:
*
*
{array} Data for the column to be sorted upon
*
*
*
*
* Note that as of v1.9, it is typically preferable to use mData to prepare data for
* the different uses that DataTables can put the data to. Specifically mData when
* used as a function will give you a 'type' (sorting, filtering etc) that you can use to
* prepare the data as required for the different types. As such, this method is deprecated.
* @type array
* @default []
* @deprecated
*
* @example
* // Updating the cached sorting information with user entered values in HTML input elements
* jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
* {
* var aData = [];
* $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
* aData.push( this.value );
* } );
* return aData;
* }
*/
"afnSortData": [],
/**
* Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
* available to DataTables. These feature plug-ins are accessible through the sDom initialisation
* option. As such, each feature plug-in must describe a function that is used to initialise
* itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
* of the feature (sFeature). Thus the objects attached to this method must provide:
*
*
{function} fnInit Initialisation of the plug-in
*
*
* Function input parameters:
*
*
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
*
*
*
* Function return:
*
*
{node|null} The element which contains your feature. Note that the return
* may also be void if your plug-in does not require to inject any DOM elements
* into DataTables control (sDom) - for example this might be useful when
* developing a plug-in which allows table control via keyboard entry.
*
*
*
*
*
{character} cFeature Character that will be matched in sDom - case sensitive
*
{string} sFeature Feature name
*
* @type array
* @default []
*
* @example
* // How TableTools initialises itself.
* $.fn.dataTableExt.aoFeatures.push( {
* "fnInit": function( oSettings ) {
* return new TableTools( { "oDTSettings": oSettings } );
* },
* "cFeature": "T",
* "sFeature": "TableTools"
* } );
*/
"aoFeatures": [],
/**
* Type detection plug-in functions - DataTables utilises types to define how sorting and
* filtering behave, and types can be either be defined by the developer (sType for the
* column) or they can be automatically detected by the methods in this array. The functions
* defined in the array are quite simple, taking a single parameter (the data to analyse)
* and returning the type if it is a known type, or null otherwise.
*
*
* Function input parameters:
*
*
{*} Data from the column cell to be analysed
*
*
*
* Function return:
*
*
{string|null} Data type detected, or null if unknown (and thus pass it
* on to the other type detection functions.
*
*
*
* @type array
* @default []
*
* @example
* // Currency type detection plug-in:
* jQuery.fn.dataTableExt.aTypes.push(
* function ( sData ) {
* var sValidChars = "0123456789.-";
* var Char;
*
* // Check the numeric part
* for ( i=1 ; iafnSortData for filtering data.
*
*
* Function input parameters:
*
*
{*} Data from the column cell to be prepared for filtering
*
*
*
* Function return:
*
*
{string|null} Formatted string that will be used for the filtering.
*
*
*
*
* Note that as of v1.9, it is typically preferable to use mData to prepare data for
* the different uses that DataTables can put the data to. Specifically mData when
* used as a function will give you a 'type' (sorting, filtering etc) that you can use to
* prepare the data as required for the different types. As such, this method is deprecated.
* @type object
* @default {}
* @deprecated
*
* @example
* $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
* return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
* }
*/
"ofnSearch": {},
/**
* Container for all private functions in DataTables so they can be exposed externally
* @type object
* @default {}
*/
"oApi": {},
/**
* Storage for the various classes that DataTables uses
* @type object
* @default {}
*/
"oStdClasses": {},
/**
* Storage for the various classes that DataTables uses - jQuery UI suitable
* @type object
* @default {}
*/
"oJUIClasses": {},
/**
* Pagination plug-in methods - The style and controls of the pagination can significantly
* impact on how the end user interacts with the data in your table, and DataTables allows
* the addition of pagination controls by extending this object, which can then be enabled
* through the sPaginationType initialisation parameter. Each pagination type that
* is added is an object (the property name of which is what sPaginationType refers
* to) that has two properties, both methods that are used by DataTables to update the
* control's state.
*
*
* fnInit - Initialisation of the paging controls. Called only during initialisation
* of the table. It is expected that this function will add the required DOM elements
* to the page for the paging controls to work. The element pointer
* 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging
* controls (note that this is a 2D array to allow for multiple instances of each
* DataTables DOM element). It is suggested that you add the controls to this element
* as children
*
*
* Function input parameters:
*
*
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
*
{node} Container into which the pagination controls must be inserted
*
{function} Draw callback function - whenever the controls cause a page
* change, this method must be called to redraw the table.
*
*
*
* Function return:
*
*
No return required
*
*
*
*
*
* fnInit - This function is called whenever the paging status of the table changes and is
* typically used to update classes and/or text of the paging controls to reflex the new
* status.
*
*
* Function input parameters:
*
*
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
*
{function} Draw callback function - in case you need to redraw the table again
* or attach new event listeners
{int} Sorting match: <0 if first parameter should be sorted lower than
* the second parameter, ===0 if the two parameters are equal and >0 if
* the first parameter should be sorted height than the second parameter.
*
*
*
* @type object
* @default {}
*
* @example
* // Case-sensitive string sorting, with no pre-formatting method
* $.extend( $.fn.dataTableExt.oSort, {
* "string-case-asc": function(x,y) {
* return ((x < y) ? -1 : ((x > y) ? 1 : 0));
* },
* "string-case-desc": function(x,y) {
* return ((x < y) ? 1 : ((x > y) ? -1 : 0));
* }
* } );
*
* @example
* // Case-insensitive string sorting, with pre-formatting
* $.extend( $.fn.dataTableExt.oSort, {
* "string-pre": function(x) {
* return x.toLowerCase();
* },
* "string-asc": function(x,y) {
* return ((x < y) ? -1 : ((x > y) ? 1 : 0));
* },
* "string-desc": function(x,y) {
* return ((x < y) ? 1 : ((x > y) ? -1 : 0));
* }
* } );
*/
"oSort": {},
/**
* Version string for plug-ins to check compatibility. Allowed format is
* a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
* e are optional
* @type string
* @default Version number
*/
"sVersion": DataTable.version,
/**
* How should DataTables report an error. Can take the value 'alert' or 'throw'
* @type string
* @default alert
*/
"sErrMode": "alert",
/**
* Store information for DataTables to access globally about other instances
* @namespace
* @private
*/
"_oExternConfig": {
/* int:iNextUnique - next unique number for an instance */
"iNextUnique": 0
}
};
/**
* 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,
/**
* 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 []
* @private
*/
"_aSortData": [],
/**
* Array of TD elements that are cached for hidden rows, so they can be
* reinserted into the table if a column is made visible again (or to act
* as a store if a column is made hidden). Only hidden columns have a
* reference in the array. For non-hidden columns the value is either
* undefined or null.
* @type array nodes
* @default []
* @private
*/
"_anHidden": [],
/**
* 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": ""
};
/**
* 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.columns}
* 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 = {
/**
* 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,
/**
* Deprecated When using fnRender, you have two options for what
* to do with the data, and this property serves as the switch. Firstly, you
* can have the sorting and filtering use the rendered value (true - default),
* or you can have the sorting and filtering us the original value (false).
*
* Please note that this option has now been deprecated and will be removed
* in the next version of DataTables. Please use mRender / mData rather than
* fnRender.
* @type boolean
* @deprecated
*/
"bUseRendered": null,
/**
* Flag to indicate if the column is currently visible in the table or not
* @type boolean
*/
"bVisible": null,
/**
* Flag to indicate to the type detection method if the automatic type
* detection should be used, or if a column type (sType) has been specified
* @type boolean
* @default true
* @private
*/
"_bAutoType": 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} 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,
/**
* Deprecated Custom display function that will be called for the
* display of each cell in this column.
*
* Please note that this option has now been deprecated and will be removed
* in the next version of DataTables. Please use mRender / mData rather than
* fnRender.
* @type function
* @param {object} o Object with the following parameters:
* @param {int} o.iDataRow The row in aoData
* @param {int} o.iDataColumn The column in question
* @param {array} o.aData The data for the row in question
* @param {object} o.oSettings The settings object for this DataTables instance
* @returns {string} The string you which to use in the display
* @default null
* @deprecated
*/
"fnRender": 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
};
/**
* 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
*
* @example
* // Using a 2D array data source
* $(document).ready( function () {
* $('#example').dataTable( {
* "aaData": [
* ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
* ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
* ],
* "aoColumns": [
* { "sTitle": "Engine" },
* { "sTitle": "Browser" },
* { "sTitle": "Platform" },
* { "sTitle": "Version" },
* { "sTitle": "Grade" }
* ]
* } );
* } );
*
* @example
* // Using an array of objects as a data source (mData)
* $(document).ready( function () {
* $('#example').dataTable( {
* "aaData": [
* {
* "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"
* }
* ],
* "aoColumns": [
* { "sTitle": "Engine", "mData": "engine" },
* { "sTitle": "Browser", "mData": "browser" },
* { "sTitle": "Platform", "mData": "platform" },
* { "sTitle": "Version", "mData": "version" },
* { "sTitle": "Grade", "mData": "grade" }
* ]
* } );
* } );
*/
"aaData": null,
/**
* If sorting 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 aaSorting 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
*
* @example
* // Sort by 3rd column first, and then 4th column
* $(document).ready( function() {
* $('#example').dataTable( {
* "aaSorting": [[2,'asc'], [3,'desc']]
* } );
* } );
*
* // No initial sorting
* $(document).ready( function() {
* $('#example').dataTable( {
* "aaSorting": []
* } );
* } );
*/
"aaSorting": [[0,'asc']],
/**
* This parameter is basically identical to the aaSorting 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "aaSortingFixed": [[0,'asc']]
* } );
* } )
*/
"aaSortingFixed": null,
/**
* This parameter allows you to readily specify the entries in the length drop
* down menu that DataTables shows when pagination is enabled. It can be
* either a 1D array of options which will be used for both the displayed
* option and the value, or a 2D array which will use the array in the first
* position as the value, and the array in the second position as the
* displayed options (useful for language strings such as 'All').
* @type array
* @default [ 10, 25, 50, 100 ]
* @dtopt Option
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
* } );
* } );
*
* @example
* // Setting the default display length as well as length menu
* // This is likely to be wanted if you remove the '10' option which
* // is the iDisplayLength default.
* $(document).ready( function() {
* $('#example').dataTable( {
* "iDisplayLength": 25,
* "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
* } );
* } );
*/
"aLengthMenu": [ 10, 25, 50, 100 ],
/**
* The aoColumns option in the initialisation parameter allows you to define
* details about the way individual columns behave. For a full list of
* column options that can be set, please see
* {@link DataTable.defaults.columns}. Note that if you use aoColumns to
* define your columns, you must have an entry in the array for every single
* column that you have in your table (these can be null if you don't which
* to specify any options).
* @member
*/
"aoColumns": null,
/**
* Very similar to aoColumns, aoColumnDefs allows you to target a specific
* column, multiple columns, or all columns, using the aTargets property of
* each object in the array. This allows great flexibility when creating
* tables, as the aoColumnDefs arrays can be of any length, targeting the
* columns you specifically want. aoColumnDefs may use any of the column
* options available: {@link DataTable.defaults.columns}, but it _must_
* have aTargets defined in each object in the array. Values in the aTargets
* array may be:
*
*
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
*/
"aoColumnDefs": null,
/**
* Basically the same as oSearch, 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
* "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
* accepted and the default will be used.
* @type array
* @default []
* @dtopt Option
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoSearchCols": [
* null,
* { "sSearch": "My filter" },
* null,
* { "sSearch": "^[0-9]", "bEscapeRegex": 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.sStripe*
* options
* @dtopt Option
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "asStripeClasses": [ '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 aoColumns.
* @type boolean
* @default true
* @dtopt Features
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bAutoWidth": 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
*
* @example
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "sAjaxSource": "sources/arrays.txt",
* "bDeferRender": 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sScrollY": "200px",
* "bPaginate": false
* } );
*
* // Some time later....
* $('#example').dataTable( {
* "bFilter": false,
* "bDestroy": 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.sDom}.
* @type boolean
* @default true
* @dtopt Features
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bFilter": 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
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bInfo": false
* } );
* } );
*/
"bInfo": true,
/**
* Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
* slightly different and additional mark-up from what DataTables has
* traditionally used).
* @type boolean
* @default false
* @dtopt Features
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bJQueryUI": true
* } );
* } );
*/
"bJQueryUI": false,
/**
* 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 (bPaginate).
* @type boolean
* @default true
* @dtopt Features
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bLengthChange": false
* } );
* } );
*/
"bLengthChange": true,
/**
* Enable or disable pagination.
* @type boolean
* @default true
* @dtopt Features
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bPaginate": 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
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bProcessing": 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). bDestroy can be used to reinitialise a table if
* you need.
* @type boolean
* @default false
* @dtopt Options
*
* @example
* $(document).ready( function() {
* initTable();
* tableActions();
* } );
*
* function initTable ()
* {
* return $('#example').dataTable( {
* "sScrollY": "200px",
* "bPaginate": false,
* "bRetrieve": true
* } );
* }
*
* function tableActions ()
* {
* var oTable = initTable();
* // perform API operations with oTable
* }
*/
"bRetrieve": false,
/**
* Indicate if DataTables should be allowed to set the padding / margin
* etc for the scrolling header elements or not. Typically you will want
* this.
* @type boolean
* @default true
* @dtopt Options
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bScrollAutoCss": false,
* "sScrollY": "200px"
* } );
* } );
*/
"bScrollAutoCss": true,
/**
* 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sScrollY": "200",
* "bScrollCollapse": true
* } );
* } );
*/
"bScrollCollapse": false,
/**
* Enable infinite scrolling for DataTables (to be used in combination with
* sScrollY). Infinite scrolling means that DataTables will continually load
* data as a user scrolls through a table, which is very useful for large
* dataset. This cannot be used with pagination, which is automatically
* disabled. Note - the Scroller extra for DataTables is recommended in
* in preference to this option.
* @type boolean
* @default false
* @dtopt Features
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bScrollInfinite": true,
* "bScrollCollapse": true,
* "sScrollY": "200px"
* } );
* } );
*/
"bScrollInfinite": false,
/**
* Configure DataTables to use server-side processing. Note that the
* sAjaxSource 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
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bServerSide": true,
* "sAjaxSource": "xhr.php"
* } );
* } );
*/
"bServerSide": false,
/**
* Enable or disable sorting of columns. Sorting of individual columns can be
* disabled by the "bSortable" option for each column.
* @type boolean
* @default true
* @dtopt Features
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bSort": false
* } );
* } );
*/
"bSort": 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bSortCellsTop": 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
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bSortClasses": false
* } );
* } );
*/
"bSortClasses": true,
/**
* Enable or disable state saving. When enabled a cookie 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.
* @type boolean
* @default false
* @dtopt Features
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "bStateSave": true
* } );
* } );
*/
"bStateSave": false,
/**
* Customise the cookie and / or the parameters being stored when using
* DataTables with state saving enabled. This function is called whenever
* the cookie is modified, and it expects a fully formed cookie string to be
* returned. Note that the data object passed in is a Javascript object which
* must be converted to a string (JSON.stringify for example).
* @type function
* @param {string} sName Name of the cookie defined by DataTables
* @param {object} oData Data to be stored in the cookie
* @param {string} sExpires Cookie expires string
* @param {string} sPath Path of the cookie to set
* @returns {string} Cookie formatted string (which should be encoded by
* using encodeURIComponent())
* @dtopt Callbacks
*
* @example
* $(document).ready( function () {
* $('#example').dataTable( {
* "fnCookieCallback": function (sName, oData, sExpires, sPath) {
* // Customise oData or sName or whatever else here
* return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
* }
* } );
* } );
*/
"fnCookieCallback": null,
/**
* 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} nRow "TR" element for the current row
* @param {array} aData Raw data array for this row
* @param {int} iDataIndex The index of this row in aoData
* @dtopt Callbacks
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "fnCreatedRow": function( nRow, aData, iDataIndex ) {
* // Bold the grade for all 'A' grade browsers
* if ( aData[4] == "A" )
* {
* $('td:eq(4)', nRow).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} oSettings DataTables settings object
* @dtopt Callbacks
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "fnDrawCallback": function( oSettings ) {
* 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' even.
* @type function
* @param {node} nFoot "TR" element for the footer
* @param {array} aData Full table data (as derived from the original HTML)
* @param {int} iStart Index for the current display starting point in the
* display array
* @param {int} iEnd Index for the current display ending point in the
* display array
* @param {array int} aiDisplay Index array to translate the visual position
* to the full data array
* @dtopt Callbacks
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
* nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
* }
* } );
* } )
*/
"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} iIn number to be formatted
* @returns {string} formatted string for DataTables to show the number
* @dtopt Callbacks
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "fnFormatNumber": function ( iIn ) {
* if ( iIn < 1000 ) {
* return iIn;
* } else {
* var
* s=(iIn+""),
* a=s.split(""), out="",
* iLen=s.length;
*
* for ( var i=0 ; i<iLen ; i++ ) {
* if ( i%3 === 0 && i !== 0 ) {
* out = "'"+out;
* }
* out = a[iLen-i-1]+out;
* }
* }
* return out;
* };
* } );
* } );
*/
"fnFormatNumber": function ( iIn ) {
if ( iIn < 1000 )
{
// A small optimisation for what is likely to be the majority of use cases
return iIn;
}
var s=(iIn+""), a=s.split(""), out="", iLen=s.length;
for ( var i=0 ; iA' );
* }
* }
* } );
* } );
*/
"fnRowCallback": null,
/**
* This parameter allows you to override the default function which obtains
* the data from the server ($.getJSON) 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} sSource HTTP source to obtain the data from (sAjaxSource)
* @param {array} aoData A key/value pair object containing the data to send
* to the server
* @param {function} fnCallback to be called on completion of the data get
* process that will draw the data on the page.
* @param {object} oSettings DataTables settings object
* @dtopt Callbacks
* @dtopt Server-side
*
* @example
* // POST data to server
* $(document).ready( function() {
* $('#example').dataTable( {
* "bProcessing": true,
* "bServerSide": true,
* "sAjaxSource": "xhr.php",
* "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
* oSettings.jqXHR = $.ajax( {
* "dataType": 'json',
* "type": "POST",
* "url": sSource,
* "data": aoData,
* "success": fnCallback
* } );
* }
* } );
* } );
*/
"fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) {
oSettings.jqXHR = $.ajax( {
"url": sUrl,
"data": aoData,
"success": function (json) {
if ( json.sError ) {
oSettings.oApi._fnLog( oSettings, 0, json.sError );
}
$(oSettings.oInstance).trigger('xhr', [oSettings, json]);
fnCallback( json );
},
"dataType": "json",
"cache": false,
"type": oSettings.sServerMethod,
"error": function (xhr, error, thrown) {
if ( error == "parsererror" ) {
oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+
"server could not be parsed. This is caused by a JSON formatting error." );
}
}
} );
},
/**
* 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} aoData 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 aoData array passed in,
* as this is passed by reference.
* @dtopt Callbacks
* @dtopt Server-side
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bProcessing": true,
* "bServerSide": true,
* "sAjaxSource": "scripts/server_processing.php",
* "fnServerParams": function ( aoData ) {
* aoData.push( { "name": "more_data", "value": "my_value" } );
* }
* } );
* } );
*/
"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 its state saving
* cookie, but you might wish to use local storage (HTML5) or a server-side database.
* @type function
* @member
* @param {object} oSettings DataTables settings object
* @return {object} The DataTables state object to be loaded
* @dtopt Callbacks
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bStateSave": true,
* "fnStateLoad": function (oSettings) {
* var o;
*
* // Send an Ajax request to the server to get the data. Note that
* // this is a synchronous request.
* $.ajax( {
* "url": "/state_load",
* "async": false,
* "dataType": "json",
* "success": function (json) {
* o = json;
* }
* } );
*
* return o;
* }
* } );
* } );
*/
"fnStateLoad": function ( oSettings ) {
var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );
var oData;
try {
oData = (typeof $.parseJSON === 'function') ?
$.parseJSON(sData) : eval( '('+sData+')' );
} catch (e) {
oData = null;
}
return oData;
},
/**
* 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} oSettings DataTables settings object
* @param {object} oData The state object that is to be loaded
* @dtopt Callbacks
*
* @example
* // Remove a saved filter, so filtering is never loaded
* $(document).ready( function() {
* $('#example').dataTable( {
* "bStateSave": true,
* "fnStateLoadParams": function (oSettings, oData) {
* oData.oSearch.sSearch = "";
* }
* } );
* } );
*
* @example
* // Disallow state loading by returning false
* $(document).ready( function() {
* $('#example').dataTable( {
* "bStateSave": true,
* "fnStateLoadParams": function (oSettings, oData) {
* 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} oSettings DataTables settings object
* @param {object} oData The state object that was loaded
* @dtopt Callbacks
*
* @example
* // Show an alert with the filtering value that was saved
* $(document).ready( function() {
* $('#example').dataTable( {
* "bStateSave": true,
* "fnStateLoaded": function (oSettings, oData) {
* alert( 'Saved filter was: '+oData.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 it will use a cookie, but you
* might want to use local storage (HTML5) or a server-side database.
* @type function
* @member
* @param {object} oSettings DataTables settings object
* @param {object} oData The state object to be saved
* @dtopt Callbacks
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bStateSave": true,
* "fnStateSave": function (oSettings, oData) {
* // Send an Ajax request to the server with the state object
* $.ajax( {
* "url": "/state_save",
* "data": oData,
* "dataType": "json",
* "method": "POST"
* "success": function () {}
* } );
* }
* } );
* } );
*/
"fnStateSave": function ( oSettings, oData ) {
this.oApi._fnCreateCookie(
oSettings.sCookiePrefix+oSettings.sInstance,
this.oApi._fnJsonString(oData),
oSettings.iCookieDuration,
oSettings.sCookiePrefix,
oSettings.fnCookieCallback
);
},
/**
* 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} oSettings DataTables settings object
* @param {object} oData The state object to be saved
* @dtopt Callbacks
*
* @example
* // Remove a saved filter, so filtering is never saved
* $(document).ready( function() {
* $('#example').dataTable( {
* "bStateSave": true,
* "fnStateSaveParams": function (oSettings, oData) {
* oData.oSearch.sSearch = "";
* }
* } );
* } );
*/
"fnStateSaveParams": null,
/**
* Duration of the cookie which is used for storing session information. This
* value is given in seconds.
* @type int
* @default 7200 (2 hours)
* @dtopt Options
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "iCookieDuration": 60*60*24; // 1 day
* } );
* } )
*/
"iCookieDuration": 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. iDeferLoading
* 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
*
* @example
* // 57 records available in the table, no filtering applied
* $(document).ready( function() {
* $('#example').dataTable( {
* "bServerSide": true,
* "sAjaxSource": "scripts/server_processing.php",
* "iDeferLoading": 57
* } );
* } );
*
* @example
* // 57 records after filtering, 100 without filtering (an initial filter applied)
* $(document).ready( function() {
* $('#example').dataTable( {
* "bServerSide": true,
* "sAjaxSource": "scripts/server_processing.php",
* "iDeferLoading": [ 57, 100 ],
* "oSearch": {
* "sSearch": "my_filter"
* }
* } );
* } );
*/
"iDeferLoading": null,
/**
* Number of rows to display on a single page when using pagination. If
* feature enabled (bLengthChange) 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "iDisplayLength": 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "iDisplayStart": 20
* } );
* } )
*/
"iDisplayStart": 0,
/**
* The scroll gap is the amount of scrolling that is left to go before
* DataTables will load the next 'page' of data automatically. You typically
* want a gap which is big enough that the scrolling will be smooth for the
* user, while not so large that it will load more data than need.
* @type int
* @default 100
* @dtopt Options
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bScrollInfinite": true,
* "bScrollCollapse": true,
* "sScrollY": "200px",
* "iScrollLoadGap": 50
* } );
* } );
*/
"iScrollLoadGap": 100,
/**
* 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "iTabIndex": 1
* } );
* } );
*/
"iTabIndex": 0,
/**
* 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
*/
"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
*/
"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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "oAria": {
* "sSortAscending": " - 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "oAria": {
* "sSortDescending": " - click/return to sort descending"
* }
* }
* } );
* } );
*/
"sSortDescending": ": activate to sort column descending"
},
/**
* Pagination string used by DataTables for the two built-in pagination
* control types ("two_button" and "full_numbers")
* @namespace
*/
"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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "oPaginate": {
* "sFirst": "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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "oPaginate": {
* "sLast": "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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "oPaginate": {
* "sNext": "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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "oPaginate": {
* "sPrevious": "Previous page"
* }
* }
* } );
* } );
*/
"sPrevious": "Previous"
},
/**
* This string is shown in preference to sZeroRecords 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 sZeroRecords will be used
* instead (either the default or given value).
* @type string
* @default No data available in table
* @dtopt Language
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sEmptyTable": "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 _START_, _END_ and _TOTAL_
* variables are all dynamically replaced as the table display updates, and
* can be freely moved or removed as the language requirements change.
* @type string
* @default Showing _START_ to _END_ of _TOTAL_ entries
* @dtopt Language
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
* }
* } );
* } );
*/
"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 sInfo.
* @type string
* @default Showing 0 to 0 of 0 entries
* @dtopt Language
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sInfoEmpty": "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 (sInfo) 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sInfoFiltered": " - 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 sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
* being used) at all times.
* @type string
* @default Empty string
* @dtopt Language
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sInfoPostFix": "All records shown are derived from real information."
* }
* } );
* } );
*/
"sInfoPostFix": "",
/**
* DataTables has a build in number formatter (fnFormatNumber) 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sInfoThousands": "'"
* }
* } );
* } );
*/
"sInfoThousands": ",",
/**
* 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
*
* @example
* // Language change only
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sLengthMenu": "Display _MENU_ records"
* }
* } );
* } );
*
* @example
* // Language and options change
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sLengthMenu": '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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sLoadingRecords": "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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sProcessing": "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
*
* @example
* // Input text box will be appended at the end automatically
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sSearch": "Filter records:"
* }
* } );
* } );
*
* @example
* // Specify where the filter should appear
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sSearch": "Apply filter _INPUT_ to table"
* }
* } );
* } );
*/
"sSearch": "Search:",
/**
* 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sUrl": "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. sEmptyTable 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oLanguage": {
* "sZeroRecords": "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 "sSearch" parameter must be
* defined, but all other parameters are optional. When "bRegex" is true,
* the search string will be treated as a regular expression, when false
* (default) it will be treated as a straight string. When "bSmart"
* 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "oSearch": {"sSearch": "Initial search"}
* } );
* } )
*/
"oSearch": $.extend( {}, DataTable.models.oSearch ),
/**
* By default DataTables will look for the property 'aaData' 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 aaData
* @dtopt Options
* @dtopt Server-side
*
* @example
* // Get data from { "data": [...] }
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "sAjaxSource": "sources/data.txt",
* "sAjaxDataProp": "data"
* } );
* } );
*
* @example
* // Get data from { "data": { "inner": [...] } }
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "sAjaxSource": "sources/data.txt",
* "sAjaxDataProp": "data.inner"
* } );
* } );
*/
"sAjaxDataProp": "aaData",
/**
* 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. This object must include
* the parameter 'aaData' which is the data source for the table.
* @type string
* @default null
* @dtopt Options
* @dtopt Server-side
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
* } );
* } )
*/
"sAjaxSource": null,
/**
* This parameter can be used to override the default prefix that DataTables
* assigns to a cookie when state saving is enabled.
* @type string
* @default SpryMedia_DataTables_
* @dtopt Options
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sCookiePrefix": "my_datatable_",
* } );
* } );
*/
"sCookiePrefix": "SpryMedia_DataTables_",
/**
* 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 bJQueryUI is false)or
* <"H"lfr>t<"F"ip> (when bJQueryUI is true)
* @dtopt Options
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sDom": '<"top"i>rt<"bottom"flp><"clear">'
* } );
* } );
*/
"sDom": "lfrtip",
/**
* DataTables features two different built-in pagination interaction methods
* ('two_button' or 'full_numbers') which present different page controls to
* the end user. Further methods can be added using the API (see below).
* @type string
* @default two_button
* @dtopt Options
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sPaginationType": "full_numbers"
* } );
* } )
*/
"sPaginationType": "two_button",
/**
* 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 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sScrollX": "100%",
* "bScrollCollapse": 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sScrollX": "100%",
* "sScrollXInner": "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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "sScrollY": "200px",
* "bPaginate": false
* } );
* } );
*/
"sScrollY": "",
/**
* 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
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "bServerSide": true,
* "sAjaxSource": "scripts/post.php",
* "sServerMethod": "POST"
* } );
* } );
*/
"sServerMethod": "GET"
};
/**
* Column options that can be given to DataTables at initialisation time.
* @namespace
*/
DataTable.defaults.columns = {
/**
* Allows a column's sorting to take multiple columns into account when
* doing a sort. For example first name / last name columns make sense to
* do a multi-column sort over the two columns.
* @type array
* @default null Takes the value of the column index automatically
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
* { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
* { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "aDataSort": [ 0, 1 ] },
* { "aDataSort": [ 1, 0 ] },
* { "aDataSort": [ 2, 3, 4 ] },
* null,
* null
* ]
* } );
* } );
*/
"aDataSort": null,
/**
* You can control the default sorting direction, and even alter the behaviour
* of the sort handler (i.e. only allow ascending sorting etc) using this
* parameter.
* @type array
* @default [ 'asc', 'desc' ]
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
* { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
* { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* null,
* { "asSorting": [ "asc" ] },
* { "asSorting": [ "desc", "asc", "asc" ] },
* { "asSorting": [ "desc" ] },
* null
* ]
* } );
* } );
*/
"asSorting": [ 'asc', 'desc' ],
/**
* Enable or disable filtering on the data in this column.
* @type boolean
* @default true
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "bSearchable": false, "aTargets": [ 0 ] }
* ] } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "bSearchable": false },
* null,
* null,
* null,
* null
* ] } );
* } );
*/
"bSearchable": true,
/**
* Enable or disable sorting on this column.
* @type boolean
* @default true
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "bSortable": false, "aTargets": [ 0 ] }
* ] } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "bSortable": false },
* null,
* null,
* null,
* null
* ] } );
* } );
*/
"bSortable": true,
/**
* Deprecated When using fnRender() for a column, you may wish
* to use the original data (before rendering) for sorting and filtering
* (the default is to used the rendered data that the user can see). This
* may be useful for dates etc.
*
* Please note that this option has now been deprecated and will be removed
* in the next version of DataTables. Please use mRender / mData rather than
* fnRender.
* @type boolean
* @default true
* @dtopt Columns
* @deprecated
*/
"bUseRendered": true,
/**
* Enable or disable the display of this column.
* @type boolean
* @default true
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "bVisible": false, "aTargets": [ 0 ] }
* ] } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "bVisible": 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} 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
* @param {int} iCol The column index for aoColumns
* @dtopt Columns
*
* @example
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [ {
* "aTargets": [3],
* "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
* if ( sData == "1.7" ) {
* $(nTd).css('color', 'blue')
* }
* }
* } ]
* });
* } );
*/
"fnCreatedCell": null,
/**
* Deprecated Custom display function that will be called for the
* display of each cell in this column.
*
* Please note that this option has now been deprecated and will be removed
* in the next version of DataTables. Please use mRender / mData rather than
* fnRender.
* @type function
* @param {object} o Object with the following parameters:
* @param {int} o.iDataRow The row in aoData
* @param {int} o.iDataColumn The column in question
* @param {array} o.aData The data for the row in question
* @param {object} o.oSettings The settings object for this DataTables instance
* @param {object} o.mDataProp The data property used for this column
* @param {*} val The current cell value
* @returns {string} The string you which to use in the display
* @dtopt Columns
* @deprecated
*/
"fnRender": null,
/**
* The column index (starting from 0!) that you wish a sort to be performed
* upon when this column is selected for sorting. This can be used for sorting
* on hidden columns for example.
* @type int
* @default -1 Use automatically calculated column index
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "iDataSort": 1, "aTargets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "iDataSort": 1 },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"iDataSort": -1,
/**
* This parameter has been replaced by mData in DataTables to ensure naming
* consistency. mDataProp can still be used, as there is backwards compatibility
* in DataTables for this option, but it is strongly recommended that you use
* mData in preference to mDataProp.
* @name DataTable.defaults.columns.mDataProp
*/
/**
* This property can be used to read data from any JSON data source property,
* including deeply nested objects / properties. mData 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. Note that you can
* use Javascript dotted notation to read deep properties / arrays from the
* data source.
*
null - the sDefaultContent option will be used for the cell (null
* by default, so you will need to specify the default content you want -
* typically an empty string). This can be useful on generated columns such
* as edit / delete action columns.
*
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:
*
*
{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'.
*
* 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 prior to DataTables 1.9.2 mData 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
* @dtopt Columns
*
* @example
* // Read table data from objects
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "sAjaxSource": "sources/deep.txt",
* "aoColumns": [
* { "mData": "engine" },
* { "mData": "browser" },
* { "mData": "platform.inner" },
* { "mData": "platform.details.0" },
* { "mData": "platform.details.1" }
* ]
* } );
* } );
*
* @example
* // Using mData as a function to provide different information for
* // sorting, filtering and display. In this case, currency (price)
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "aoColumnDefs": [ {
* "aTargets": [ 0 ],
* "mData": 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;
* }
* } ]
* } );
* } );
*/
"mData": null,
/**
* This property is the rendering partner to mData and it is suggested that
* when you want to manipulate data for display (including filtering, sorting etc)
* but not altering the underlying data for the table, use this property. mData
* can actually do everything this property can and more, but this parameter is
* easier to use since there is no 'set' option. Like mData is can be given
* in a number of different ways to effect its behaviour, with the addition of
* supporting array syntax for easy outputting of arrays (including arrays of
* objects):
*
*
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. Note that you can
* use Javascript dotted notation to read deep properties / arrays from the
* data source and also array brackets to indicate that the data reader should
* loop over the data source array. When characters are given between the array
* brackets, these characters are used to join the data source array together.
* For example: "accounts[, ].name" would result in a comma separated list with
* the 'name' value from the 'accounts' array of objects.
*
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:
*
*
{array|object} The data source for the row (based on mData)
*
{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 mData)
*
* The return value from the function is what will be used for the data
* requested.
*
* @type string|int|function|null
* @default null Use mData
* @dtopt Columns
*
* @example
* // Create a comma separated list from an array of objects
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "sAjaxSource": "sources/deep.txt",
* "aoColumns": [
* { "mData": "engine" },
* { "mData": "browser" },
* {
* "mData": "platform",
* "mRender": "[, ].name"
* }
* ]
* } );
* } );
*
* @example
* // Use as a function to create a link from the data source
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "aoColumnDefs": [
* {
* "aTargets": [ 0 ],
* "mData": "download_link",
* "mRender": 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
* @dtopt Columns
*
* @example
* // Make the first column use TH cells
* $(document).ready( function() {
* var oTable = $('#example').dataTable( {
* "aoColumnDefs": [ {
* "aTargets": [ 0 ],
* "sCellType": "th"
* } ]
* } );
* } );
*/
"sCellType": "td",
/**
* Class to give to each cell in this column.
* @type string
* @default Empty string
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "sClass": "my_class", "aTargets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "sClass": "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, and it is not documented on the
* general DataTables.net documentation
* @type string
* @default Empty string
* @dtopt Columns
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* null,
* null,
* null,
* {
* "sContentPadding": "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 mData
* is set to null, or because the data source itself is null).
* @type string
* @default null
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* {
* "mData": null,
* "sDefaultContent": "Edit",
* "aTargets": [ -1 ]
* }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* null,
* null,
* null,
* {
* "mData": null,
* "sDefaultContent": "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
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "sName": "engine", "aTargets": [ 0 ] },
* { "sName": "browser", "aTargets": [ 1 ] },
* { "sName": "platform", "aTargets": [ 2 ] },
* { "sName": "version", "aTargets": [ 3 ] },
* { "sName": "grade", "aTargets": [ 4 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "sName": "engine" },
* { "sName": "browser" },
* { "sName": "platform" },
* { "sName": "version" },
* { "sName": "grade" }
* ]
* } );
* } );
*/
"sName": "",
/**
* Defines a data source type for the sorting which can be used to read
* real-time information from the table (updating the internally cached
* version) prior to sorting. This allows sorting to occur on user editable
* elements such as form inputs.
* @type string
* @default std
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
* { "sType": "numeric", "aTargets": [ 3 ] },
* { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
* { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* null,
* null,
* { "sSortDataType": "dom-text" },
* { "sSortDataType": "dom-text", "sType": "numeric" },
* { "sSortDataType": "dom-select" },
* { "sSortDataType": "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.
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "sTitle": "My column title", "aTargets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "sTitle": "My column title" },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"sTitle": null,
/**
* The type allows you to specify how the data for this column will be sorted.
* Four types (string, numeric, date and html (which will strip HTML tags
* before sorting)) 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
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "sType": "html", "aTargets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "sType": "html" },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"sType": null,
/**
* Defining the width of the column, this parameter may take any CSS value
* (3em, 20px etc). DataTables apples '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
* @dtopt Columns
*
* @example
* // Using aoColumnDefs
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumnDefs": [
* { "sWidth": "20%", "aTargets": [ 0 ] }
* ]
* } );
* } );
*
* @example
* // Using aoColumns
* $(document).ready( function() {
* $('#example').dataTable( {
* "aoColumns": [
* { "sWidth": "20%" },
* null,
* null,
* null,
* null
* ]
* } );
* } );
*/
"sWidth": null
};
/**
* 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,
/**
* 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": {
/**
* Indicate if DataTables should be allowed to set the padding / margin
* etc for the scrolling header elements or not. Typically you will want
* this.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type boolean
*/
"bAutoCss": null,
/**
* 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,
/**
* Infinite scrolling enablement flag. Now deprecated in favour of
* using the Scroller plug-in.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type boolean
*/
"bInfinite": null,
/**
* Width of the scrollbar for the web-browser's platform. Calculated
* during table initialisation.
* @type int
* @default 0
*/
"iBarWidth": 0,
/**
* Space (in pixels) between the bottom of the scrolling container and
* the bottom of the scrolling viewport before the next page is loaded
* when using infinite scrolling.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type int
*/
"iLoadGap": null,
/**
* 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
},
/**
* 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": [],
/**
* 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": [],
/**
* Search data array for regular expression searching
* @type array
* @default []
*/
"asDataSearch": [],
/**
* 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
*
Index 2 - index of asSorting for this column
*
* 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|null
* @default null
*/
"aaSortingFixed": null,
/**
* 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,
/**
* 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 cookie duration (for bStateSave) 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
*/
"iCookieDuration": 0,
/**
* The cookie name prefix.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type string
* @default Empty string
*/
"sCookiePrefix": "",
/**
* Callback function for cookie creation.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type function
* @default null
*/
"fnCookieCallback": null,
/**
* 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
*
string:sName - name of callback
*
* @type array
* @default []
*/
"aoStateLoad": [],
/**
* State that was loaded from the cookie. Useful for back reference
* @type object
* @default null
*/
"oLoadedState": null,
/**
* Source url for AJAX data for the table.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type string
* @default null
*/
"sAjaxSource": null,
/**
* Property from a given object from which to read the table data from. This
* can be an empty string (when not server-side processing), in which case
* it is assumed an an array is given directly.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type string
*/
"sAjaxDataProp": null,
/**
* Note if draw should be blocked while getting data
* @type boolean
* @default true
*/
"bAjaxDataGet": true,
/**
* The last jQuery XHR object that was used for server-side data gathering.
* This can be used for working with the XHR information in one of the
* callbacks
* @type object
* @default null
*/
"jqXHR": null,
/**
* Function to get the server-side data.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type function
*/
"fnServerData": null,
/**
* Functions which are called prior to sending an Ajax request so extra
* parameters can easily be sent to the server
* @type array
* @default []
*/
"aoServerParams": [],
/**
* Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
* required).
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type string
*/
"sServerMethod": null,
/**
* Format numbers for display.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type function
*/
"fnFormatNumber": null,
/**
* List of options that can be used for the user selectable length menu.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type array
* @default []
*/
"aLengthMenu": null,
/**
* Counter for the draws that the table does. Also used as a tracker for
* server-side processing
* @type int
* @default 0
*/
"iDraw": 0,
/**
* Indicate if a redraw is being done - useful for Ajax
* @type boolean
* @default false
*/
"bDrawing": false,
/**
* Draw index (iDraw) of the last error when parsing the returned data
* @type int
* @default -1
*/
"iDrawError": -1,
/**
* Paging display length
* @type int
* @default 10
*/
"_iDisplayLength": 10,
/**
* Paging start point - aiDisplay index
* @type int
* @default 0
*/
"_iDisplayStart": 0,
/**
* Paging end point - aiDisplay index. Use fnDisplayEnd rather than
* this property to get the end point
* @type int
* @default 10
* @private
*/
"_iDisplayEnd": 10,
/**
* Server-side processing - number of records in the result set
* (i.e. before filtering), Use fnRecordsTotal rather than
* this property to get the value of the number of records, regardless of
* the server-side processing setting.
* @type int
* @default 0
* @private
*/
"_iRecordsTotal": 0,
/**
* Server-side processing - number of records in the current display set
* (i.e. after filtering). Use fnRecordsDisplay rather than
* this property to get the value of the number of records, regardless of
* the server-side processing setting.
* @type boolean
* @default 0
* @private
*/
"_iRecordsDisplay": 0,
/**
* Flag to indicate if jQuery UI marking and classes should be used.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type boolean
*/
"bJUI": null,
/**
* The classes to use for the table
* @type object
* @default {}
*/
"oClasses": {},
/**
* Flag attached to the settings object so you can check in the draw
* callback if filtering has been done in the draw. Deprecated in favour of
* events.
* @type boolean
* @default false
* @deprecated
*/
"bFiltered": false,
/**
* Flag attached to the settings object so you can check in the draw
* callback if sorting has been done in the draw. Deprecated in favour of
* events.
* @type boolean
* @default false
* @deprecated
*/
"bSorted": false,
/**
* Indicate that if multiple rows are in the header and there is more than
* one unique cell per column, if the top one (true) or bottom one (false)
* should be used for sorting / title by DataTables.
* Note that this parameter will be set by the initialisation routine. To
* set a default use {@link DataTable.defaults}.
* @type boolean
*/
"bSortCellsTop": null,
/**
* Initialisation object that is used for the table
* @type object
* @default null
*/
"oInit": null,
/**
* Destroy callback functions - for plug-ins to attach themselves to the
* destroy so they can clean up markup and events.
* @type array
* @default []
*/
"aoDestroyCallback": [],
/**
* Get the number of records in the current record set, before filtering
* @type function
*/
"fnRecordsTotal": function ()
{
if ( this.oFeatures.bServerSide ) {
return parseInt(this._iRecordsTotal, 10);
} else {
return this.aiDisplayMaster.length;
}
},
/**
* Get the number of records in the current record set, after filtering
* @type function
*/
"fnRecordsDisplay": function ()
{
if ( this.oFeatures.bServerSide ) {
return parseInt(this._iRecordsDisplay, 10);
} else {
return this.aiDisplay.length;
}
},
/**
* Set the display end point - aiDisplay index
* @type function
* @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
*/
"fnDisplayEnd": function ()
{
if ( this.oFeatures.bServerSide ) {
if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {
return this._iDisplayStart+this.aiDisplay.length;
} else {
return Math.min( this._iDisplayStart+this._iDisplayLength,
this._iRecordsDisplay );
}
} else {
return this._iDisplayEnd;
}
},
/**
* The DataTables object for this table
* @type object
* @default null
*/
"oInstance": null,
/**
* Unique identifier for each instance of the DataTables object. If there
* is an ID on the table node, then it takes that value, otherwise an
* incrementing internal counter is used.
* @type string
* @default null
*/
"sInstance": null,
/**
* tabindex attribute value that is added to DataTables control elements, allowing
* keyboard navigation of the table and its controls.
*/
"iTabIndex": 0,
/**
* DIV container for the footer scrolling table if scrolling
*/
"nScrollHead": null,
/**
* DIV container for the footer scrolling table if scrolling
*/
"nScrollFoot": null
};
/**
* Extension object for DataTables that is used to provide all extension options.
*
* Note that the DataTable.ext object is available through
* jQuery.fn.dataTable.ext where it may be accessed and manipulated. It is
* also aliased to jQuery.fn.dataTableExt for historic reasons.
* @namespace
* @extends DataTable.models.ext
*/
DataTable.ext = $.extend( true, {}, DataTable.models.ext );
$.extend( DataTable.ext.oStdClasses, {
"sTable": "dataTable",
/* Two buttons buttons */
"sPagePrevEnabled": "paginate_enabled_previous",
"sPagePrevDisabled": "paginate_disabled_previous",
"sPageNextEnabled": "paginate_enabled_next",
"sPageNextDisabled": "paginate_disabled_next",
"sPageJUINext": "",
"sPageJUIPrev": "",
/* Full numbers paging buttons */
"sPageButton": "paginate_button",
"sPageButtonActive": "paginate_active",
"sPageButtonStaticDisabled": "paginate_button paginate_button_disabled",
"sPageFirst": "first",
"sPagePrevious": "previous",
"sPageNext": "next",
"sPageLast": "last",
/* Striping classes */
"sStripeOdd": "odd",
"sStripeEven": "even",
/* Empty row */
"sRowEmpty": "dataTables_empty",
/* Features */
"sWrapper": "dataTables_wrapper",
"sFilter": "dataTables_filter",
"sInfo": "dataTables_info",
"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
"sLength": "dataTables_length",
"sProcessing": "dataTables_processing",
/* Sorting */
"sSortAsc": "sorting_asc",
"sSortDesc": "sorting_desc",
"sSortable": "sorting", /* Sortable in both directions */
"sSortableAsc": "sorting_asc_disabled",
"sSortableDesc": "sorting_desc_disabled",
"sSortableNone": "sorting_disabled",
"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
"sSortJUIAsc": "",
"sSortJUIDesc": "",
"sSortJUI": "",
"sSortJUIAscAllowed": "",
"sSortJUIDescAllowed": "",
"sSortJUIWrapper": "",
"sSortIcon": "",
/* Scrolling */
"sScrollWrapper": "dataTables_scroll",
"sScrollHead": "dataTables_scrollHead",
"sScrollHeadInner": "dataTables_scrollHeadInner",
"sScrollBody": "dataTables_scrollBody",
"sScrollFoot": "dataTables_scrollFoot",
"sScrollFootInner": "dataTables_scrollFootInner",
/* Misc */
"sFooterTH": "",
"sJUIHeader": "",
"sJUIFooter": ""
} );
$.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
/* Two buttons buttons */
"sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
"sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
"sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
"sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
"sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
"sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
/* Full numbers paging buttons */
"sPageButton": "fg-button ui-button ui-state-default",
"sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
"sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
"sPageFirst": "first ui-corner-tl ui-corner-bl",
"sPageLast": "last ui-corner-tr ui-corner-br",
/* Features */
"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
"ui-buttonset-multi paging_", /* Note that the type is postfixed */
/* Sorting */
"sSortAsc": "ui-state-default",
"sSortDesc": "ui-state-default",
"sSortable": "ui-state-default",
"sSortableAsc": "ui-state-default",
"sSortableDesc": "ui-state-default",
"sSortableNone": "ui-state-default",
"sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
"sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
"sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
"sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
"sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
"sSortJUIWrapper": "DataTables_sort_wrapper",
"sSortIcon": "DataTables_sort_icon",
/* Scrolling */
"sScrollHead": "dataTables_scrollHead ui-state-default",
"sScrollFoot": "dataTables_scrollFoot ui-state-default",
/* Misc */
"sFooterTH": "ui-state-default",
"sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
"sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
} );
/*
* Variable: oPagination
* Purpose:
* Scope: jQuery.fn.dataTableExt
*/
$.extend( DataTable.ext.oPagination, {
/*
* Variable: two_button
* Purpose: Standard two button (forward/back) pagination
* Scope: jQuery.fn.dataTableExt.oPagination
*/
"two_button": {
/*
* Function: oPagination.two_button.fnInit
* Purpose: Initialise dom elements required for pagination with forward/back buttons only
* Returns: -
* Inputs: object:oSettings - dataTables settings object
* node:nPaging - the DIV which contains this pagination control
* function:fnCallbackDraw - draw function which must be called on update
*/
"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
{
var oLang = oSettings.oLanguage.oPaginate;
var oClasses = oSettings.oClasses;
var fnClickHandler = function ( e ) {
if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
{
fnCallbackDraw( oSettings );
}
};
var sAppend = (!oSettings.bJUI) ?
''+oLang.sPrevious+''+
''+oLang.sNext+''
:
''+
'';
$(nPaging).append( sAppend );
var els = $('a', nPaging);
var nPrevious = els[0],
nNext = els[1];
oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler );
oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
/* ID the first elements only */
if ( !oSettings.aanFeatures.p )
{
nPaging.id = oSettings.sTableId+'_paginate';
nPrevious.id = oSettings.sTableId+'_previous';
nNext.id = oSettings.sTableId+'_next';
nPrevious.setAttribute('aria-controls', oSettings.sTableId);
nNext.setAttribute('aria-controls', oSettings.sTableId);
}
},
/*
* Function: oPagination.two_button.fnUpdate
* Purpose: Update the two button pagination at the end of the draw
* Returns: -
* Inputs: object:oSettings - dataTables settings object
* function:fnCallbackDraw - draw function to call on page change
*/
"fnUpdate": function ( oSettings, fnCallbackDraw )
{
if ( !oSettings.aanFeatures.p )
{
return;
}
var oClasses = oSettings.oClasses;
var an = oSettings.aanFeatures.p;
var nNode;
/* Loop over each instance of the pager */
for ( var i=0, iLen=an.length ; i'+oLang.sFirst+''+
''+oLang.sPrevious+''+
''+
''+oLang.sNext+''+
''+oLang.sLast+''
);
var els = $('a', nPaging);
var nFirst = els[0],
nPrev = els[1],
nNext = els[2],
nLast = els[3];
oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler );
oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler );
oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler );
/* ID the first elements only */
if ( !oSettings.aanFeatures.p )
{
nPaging.id = oSettings.sTableId+'_paginate';
nFirst.id =oSettings.sTableId+'_first';
nPrev.id =oSettings.sTableId+'_previous';
nNext.id =oSettings.sTableId+'_next';
nLast.id =oSettings.sTableId+'_last';
}
},
/*
* Function: oPagination.full_numbers.fnUpdate
* Purpose: Update the list of page buttons shows
* Returns: -
* Inputs: object:oSettings - dataTables settings object
* function:fnCallbackDraw - draw function to call on page change
*/
"fnUpdate": function ( oSettings, fnCallbackDraw )
{
if ( !oSettings.aanFeatures.p )
{
return;
}
var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
var iPageCountHalf = Math.floor(iPageCount / 2);
var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
var sList = "";
var iStartButton, iEndButton, i, iLen;
var oClasses = oSettings.oClasses;
var anButtons, anStatic, nPaginateList, nNode;
var an = oSettings.aanFeatures.p;
var fnBind = function (j) {
oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) {
/* Use the information in the element to jump to the required page */
oSettings.oApi._fnPageChange( oSettings, e.data.page );
fnCallbackDraw( oSettings );
e.preventDefault();
} );
};
/* Pages calculation */
if ( oSettings._iDisplayLength === -1 )
{
iStartButton = 1;
iEndButton = 1;
iCurrentPage = 1;
}
else if (iPages < iPageCount)
{
iStartButton = 1;
iEndButton = iPages;
}
else if (iCurrentPage <= iPageCountHalf)
{
iStartButton = 1;
iEndButton = iPageCount;
}
else if (iCurrentPage >= (iPages - iPageCountHalf))
{
iStartButton = iPages - iPageCount + 1;
iEndButton = iPages;
}
else
{
iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
iEndButton = iStartButton + iPageCount - 1;
}
/* Build the dynamic list */
for ( i=iStartButton ; i<=iEndButton ; i++ )
{
sList += (iCurrentPage !== i) ?
''+oSettings.fnFormatNumber(i)+'' :
''+oSettings.fnFormatNumber(i)+'';
}
/* Loop over each instance of the pager */
for ( i=0, iLen=an.length ; i y) ? 1 : 0));
},
"string-desc": function ( x, y )
{
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
/*
* html sorting (ignore html tags)
*/
"html-pre": function ( a )
{
return a.replace( /<.*?>/g, "" ).toLowerCase();
},
"html-asc": function ( x, y )
{
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
},
"html-desc": function ( x, y )
{
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
/*
* date sorting
*/
"date-pre": function ( a )
{
var x = Date.parse( a );
if ( isNaN(x) || x==="" )
{
x = Date.parse( "01/01/1970 00:00:00" );
}
return x;
},
"date-asc": function ( x, y )
{
return x - y;
},
"date-desc": function ( x, y )
{
return y - x;
},
/*
* numerical sorting
*/
"numeric-pre": function ( a )
{
return (a=="-" || a==="") ? 0 : a*1;
},
"numeric-asc": function ( x, y )
{
return x - y;
},
"numeric-desc": function ( x, y )
{
return y - x;
}
} );
$.extend( DataTable.ext.aTypes, [
/*
* Function: -
* Purpose: Check to see if a string is numeric
* Returns: string:'numeric' or null
* Inputs: mixed:sText - string to check
*/
function ( sData )
{
/* Allow zero length strings as a number */
if ( typeof sData === 'number' )
{
return 'numeric';
}
else if ( typeof sData !== 'string' )
{
return null;
}
var sValidFirstChars = "0123456789-";
var sValidChars = "0123456789.";
var Char;
var bDecimal = false;
/* Check for a valid first char (no period and allow negatives) */
Char = sData.charAt(0);
if (sValidFirstChars.indexOf(Char) == -1)
{
return null;
}
/* Check all the other characters are valid */
for ( var i=1 ; i') != -1 )
{
return 'html';
}
return null;
}
] );
// jQuery aliases
$.fn.DataTable = DataTable;
$.fn.dataTable = DataTable;
$.fn.dataTableSettings = DataTable.settings;
$.fn.dataTableExt = DataTable.ext;
// Information about events fired by DataTables - for documentation.
/**
* Draw event, fired whenever the table is redrawn on the page, at the same point as
* fnDrawCallback. This may be useful for binding events or performing calculations when
* the table is altered at all.
* @name DataTable#draw
* @event
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
*/
/**
* Filter event, fired when the filtering applied to the table (using the build in global
* global filter, or column filters) is altered.
* @name DataTable#filter
* @event
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
*/
/**
* Page change event, fired when the paging of the table is altered.
* @name DataTable#page
* @event
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
*/
/**
* Sort event, fired when the sorting applied to the table is altered.
* @name DataTable#sort
* @event
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
*/
/**
* DataTables initialisation complete event, fired when the table is fully drawn,
* including Ajax data loaded, if Ajax data is required.
* @name DataTable#init
* @event
* @param {event} e jQuery event object
* @param {object} oSettings DataTables settings object
* @param {object} json The JSON object request from the server - only
* present if client-side Ajax sourced data is used
*/
/**
* State save event, fired 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 (for plug-ins) or modification
* of a DataTables core property.
* @name DataTable#stateSaveParams
* @event
* @param {event} e jQuery event object
* @param {object} oSettings DataTables settings object
* @param {object} json The state information to be saved
*/
/**
* State load event, fired when the table is loading state from the stored data, but
* prior to the settings object being modified by the saved state - allowing modification
* of the saved state is required or loading of state for a plug-in.
* @name DataTable#stateLoadParams
* @event
* @param {event} e jQuery event object
* @param {object} oSettings DataTables settings object
* @param {object} json The saved state information
*/
/**
* State loaded event, fired when state has been loaded from stored data and the settings
* object has been modified by the loaded data.
* @name DataTable#stateLoaded
* @event
* @param {event} e jQuery event object
* @param {object} oSettings DataTables settings object
* @param {object} json The saved state information
*/
/**
* Processing event, fired when DataTables is doing some kind of processing (be it,
* sort, filter or anything else). Can be used to indicate to the end user that
* there is something happening, or that something has finished.
* @name DataTable#processing
* @event
* @param {event} e jQuery event object
* @param {object} oSettings DataTables settings object
* @param {boolean} bShow Flag for if DataTables is doing processing or not
*/
/**
* Ajax (XHR) event, fired whenever an Ajax request is completed from a request to
* made to the server for new data (note that this trigger is called in fnServerData,
* if you override fnServerData and which to use this event, you need to trigger it in
* you success function).
* @name DataTable#xhr
* @event
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
* @param {object} json JSON returned from the server
*/
/**
* Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
* the bDestroy:true parameter in the initialisation object. This can be used to remove
* bound events, added DOM nodes, etc.
* @name DataTable#destroy
* @event
* @param {event} e jQuery event object
* @param {object} o DataTables settings object {@link DataTable.models.oSettings}
*/
}));
}(window, document));
/* Set the defaults for DataTables initialisation */
$.extend( true, $.fn.dataTable.defaults, {
"sDom":
"<'row'<'col-xs-6'l><'col-xs-6'f>r>"+
"t"+
"<'row'<'col-xs-6'i><'col-xs-6'p>>",
"oLanguage": {
"sLengthMenu": "_MENU_ records per page"
}
} );
/* Default class modification */
$.extend( $.fn.dataTableExt.oStdClasses, {
"sWrapper": "dataTables_wrapper form-inline",
"sFilterInput": "form-control input-sm",
"sLengthSelect": "form-control input-sm"
} );
// In 1.10 we use the pagination renderers to draw the Bootstrap paging,
// rather than custom plug-in
if ( $.fn.dataTable.Api ) {
$.fn.dataTable.defaults.renderer = 'bootstrap';
$.fn.dataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
var api = new $.fn.dataTable.Api( settings );
var classes = settings.oClasses;
var lang = settings.oLanguage.oPaginate;
var btnDisplay, btnClass;
var attach = function( container, buttons ) {
var i, ien, node, button;
var clickHandler = function ( e ) {
e.preventDefault();
if ( e.data.action !== 'ellipsis' ) {
api.page( e.data.action ).draw( false );
}
};
for ( i=0, ien=buttons.length ; i 0 ?
'' : ' disabled');
break;
case 'previous':
btnDisplay = lang.sPrevious;
btnClass = button + (page > 0 ?
'' : ' disabled');
break;
case 'next':
btnDisplay = lang.sNext;
btnClass = button + (page < pages-1 ?
'' : ' disabled');
break;
case 'last':
btnDisplay = lang.sLast;
btnClass = button + (page < pages-1 ?
'' : ' disabled');
break;
default:
btnDisplay = button + 1;
btnClass = page === button ?
'active' : '';
break;
}
if ( btnDisplay ) {
node = $('
'
);
var els = $('a', nPaging);
$(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler );
$(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler );
},
"fnUpdate": function ( oSettings, fnDraw ) {
var iListLength = 5;
var oPaging = oSettings.oInstance.fnPagingInfo();
var an = oSettings.aanFeatures.p;
var i, ien, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);
if ( oPaging.iTotalPages < iListLength) {
iStart = 1;
iEnd = oPaging.iTotalPages;
}
else if ( oPaging.iPage <= iHalf ) {
iStart = 1;
iEnd = iListLength;
} else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {
iStart = oPaging.iTotalPages - iListLength + 1;
iEnd = oPaging.iTotalPages;
} else {
iStart = oPaging.iPage - iHalf + 1;
iEnd = iStart + iListLength - 1;
}
for ( i=0, ien=an.length ; i'+j+'
')
.insertBefore( $('li:last', an[i])[0] )
.bind('click', function (e) {
e.preventDefault();
oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
fnDraw( oSettings );
} );
}
// Add / remove disabled classes from the static elements
if ( oPaging.iPage === 0 ) {
$('li:first', an[i]).addClass('disabled');
} else {
$('li:first', an[i]).removeClass('disabled');
}
if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) {
$('li:last', an[i]).addClass('disabled');
} else {
$('li:last', an[i]).removeClass('disabled');
}
}
}
}
} );
}
/*
* TableTools Bootstrap compatibility
* Required TableTools 2.1+
*/
if ( $.fn.DataTable.TableTools ) {
// Set the classes that TableTools uses to something suitable for Bootstrap
$.extend( true, $.fn.DataTable.TableTools.classes, {
"container": "DTTT btn-group",
"buttons": {
"normal": "btn btn-default",
"disabled": "disabled"
},
"collection": {
"container": "DTTT_dropdown dropdown-menu",
"buttons": {
"normal": "",
"disabled": "disabled"
}
},
"print": {
"info": "DTTT_print_info modal"
},
"select": {
"row": "active"
}
} );
// Have the collection use a bootstrap compatible dropdown
$.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
"collection": {
"container": "ul",
"button": "li",
"liner": "a"
}
} );
}
/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version: 1.3.0
*
*/
(function($) {
jQuery.fn.extend({
slimScroll: function(options) {
var defaults = {
// width in pixels of the visible scroll area
width : 'auto',
// height in pixels of the visible scroll area
height : '250px',
// width in pixels of the scrollbar and rail
size : '7px',
// scrollbar color, accepts any hex/color value
color: '#000',
// scrollbar position - left/right
position : 'right',
// distance in pixels between the side edge and the scrollbar
distance : '1px',
// default scroll position on load - top / bottom / $('selector')
start : 'top',
// sets scrollbar opacity
opacity : .4,
// enables always-on mode for the scrollbar
alwaysVisible : false,
// check if we should hide the scrollbar when user is hovering over
disableFadeOut : false,
// sets visibility of the rail
railVisible : false,
// sets rail color
railColor : '#333',
// sets rail opacity
railOpacity : .2,
// whether we should use jQuery UI Draggable to enable bar dragging
railDraggable : true,
// defautlt CSS class of the slimscroll rail
railClass : 'slimScrollRail',
// defautlt CSS class of the slimscroll bar
barClass : 'slimScrollBar',
// defautlt CSS class of the slimscroll wrapper
wrapperClass : 'slimScrollDiv',
// check if mousewheel should scroll the window if we reach top/bottom
allowPageScroll : false,
// scroll amount applied to each mouse wheel step
wheelStep : 20,
// scroll amount applied when user is using gestures
touchScrollStep : 200,
// sets border radius
borderRadius: '7px',
// sets border radius of the rail
railBorderRadius : '7px'
};
var o = $.extend(defaults, options);
// do it for every element that matches selector
this.each(function(){
var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
barHeight, percentScroll, lastScroll,
divS = '',
minBarHeight = 30,
releaseScroll = false;
// used in event handlers and for better minification
var me = $(this);
// ensure we are not binding it again
if (me.parent().hasClass(o.wrapperClass))
{
// start from last bar position
var offset = me.scrollTop();
// find bar and rail
bar = me.parent().find('.' + o.barClass);
rail = me.parent().find('.' + o.railClass);
getBarHeight();
// check if we should scroll existing instance
if ($.isPlainObject(options))
{
// Pass height: auto to an existing slimscroll object to force a resize after contents have changed
if ( 'height' in options && options.height == 'auto' ) {
me.parent().css('height', 'auto');
me.css('height', 'auto');
var height = me.parent().parent().height();
me.parent().css('height', height);
me.css('height', height);
}
if ('scrollTo' in options)
{
// jump to a static point
offset = parseInt(o.scrollTo);
}
else if ('scrollBy' in options)
{
// jump by value pixels
offset += parseInt(o.scrollBy);
}
else if ('destroy' in options)
{
// remove slimscroll elements
bar.remove();
rail.remove();
me.unwrap();
return;
}
// scroll content by the given offset
scrollContent(offset, false, true);
}
return;
}
// optionally set height to the parent's height
o.height = (o.height == 'auto') ? me.parent().height() : o.height;
// wrap content
var wrapper = $(divS)
.addClass(o.wrapperClass)
.css({
position: 'relative',
overflow: 'hidden',
width: o.width,
height: o.height
});
// update style for the div
me.css({
overflow: 'hidden',
width: o.width,
height: o.height
});
// create scrollbar rail
var rail = $(divS)
.addClass(o.railClass)
.css({
width: o.size,
height: '100%',
position: 'absolute',
top: 0,
display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
'border-radius': o.railBorderRadius,
background: o.railColor,
opacity: o.railOpacity,
zIndex: 90
});
// create scrollbar
var bar = $(divS)
.addClass(o.barClass)
.css({
background: o.color,
width: o.size,
position: 'absolute',
top: 0,
opacity: o.opacity,
display: o.alwaysVisible ? 'block' : 'none',
'border-radius' : o.borderRadius,
BorderRadius: o.borderRadius,
MozBorderRadius: o.borderRadius,
WebkitBorderRadius: o.borderRadius,
zIndex: 99
});
// set position
var posCss = (o.position == 'right') ? { right: o.distance } : { left: o.distance };
rail.css(posCss);
bar.css(posCss);
// wrap it
me.wrap(wrapper);
// append to parent div
me.parent().append(bar);
me.parent().append(rail);
// make it draggable and no longer dependent on the jqueryUI
if (o.railDraggable){
bar.bind("mousedown", function(e) {
var $doc = $(document);
isDragg = true;
t = parseFloat(bar.css('top'));
pageY = e.pageY;
$doc.bind("mousemove.slimscroll", function(e){
currTop = t + e.pageY - pageY;
bar.css('top', currTop);
scrollContent(0, bar.position().top, false);// scroll content
});
$doc.bind("mouseup.slimscroll", function(e) {
isDragg = false;hideBar();
$doc.unbind('.slimscroll');
});
return false;
}).bind("selectstart.slimscroll", function(e){
e.stopPropagation();
e.preventDefault();
return false;
});
}
// on rail over
rail.hover(function(){
showBar();
}, function(){
hideBar();
});
// on bar over
bar.hover(function(){
isOverBar = true;
}, function(){
isOverBar = false;
});
// show on parent mouseover
me.hover(function(){
isOverPanel = true;
showBar();
hideBar();
}, function(){
isOverPanel = false;
hideBar();
});
// support for mobile
me.bind('touchstart', function(e,b){
if (e.originalEvent.touches.length)
{
// record where touch started
touchDif = e.originalEvent.touches[0].pageY;
}
});
me.bind('touchmove', function(e){
// prevent scrolling the page if necessary
if(!releaseScroll)
{
e.originalEvent.preventDefault();
}
if (e.originalEvent.touches.length)
{
// see how far user swiped
var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
// scroll content
scrollContent(diff, true);
touchDif = e.originalEvent.touches[0].pageY;
}
});
// set up initial height
getBarHeight();
// check start position
if (o.start === 'bottom')
{
// scroll content to bottom
bar.css({ top: me.outerHeight() - bar.outerHeight() });
scrollContent(0, true);
}
else if (o.start !== 'top')
{
// assume jQuery selector
scrollContent($(o.start).position().top, null, true);
// make sure bar stays hidden
if (!o.alwaysVisible) { bar.hide(); }
}
// attach scroll events
attachWheel();
function _onWheel(e)
{
// use mouse wheel only when mouse is over
if (!isOverPanel) { return; }
var e = e || window.event;
var delta = 0;
if (e.wheelDelta) { delta = -e.wheelDelta/120; }
if (e.detail) { delta = e.detail / 3; }
var target = e.target || e.srcTarget || e.srcElement;
if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
// scroll content
scrollContent(delta, true);
}
// stop window scroll
if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
if (!releaseScroll) { e.returnValue = false; }
}
function scrollContent(y, isWheel, isJump)
{
releaseScroll = false;
var delta = y;
var maxTop = me.outerHeight() - bar.outerHeight();
if (isWheel)
{
// move bar with mouse wheel
delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
// move bar, make sure it doesn't go out
delta = Math.min(Math.max(delta, 0), maxTop);
// if scrolling down, make sure a fractional change to the
// scroll position isn't rounded away when the scrollbar's CSS is set
// this flooring of delta would happened automatically when
// bar.css is set below, but we floor here for clarity
delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
// scroll the scrollbar
bar.css({ top: delta + 'px' });
}
// calculate actual scroll amount
percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight());
delta = percentScroll * (me[0].scrollHeight - me.outerHeight());
if (isJump)
{
delta = y;
var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
bar.css({ top: offsetTop + 'px' });
}
// scroll content
me.scrollTop(delta);
// fire scrolling event
me.trigger('slimscrolling', ~~delta);
// ensure bar is visible
showBar();
// trigger hide when scroll is stopped
hideBar();
}
function attachWheel()
{
if (window.addEventListener)
{
this.addEventListener('DOMMouseScroll', _onWheel, false );
this.addEventListener('mousewheel', _onWheel, false );
this.addEventListener('MozMousePixelScroll', _onWheel, false );
}
else
{
document.attachEvent("onmousewheel", _onWheel)
}
}
function getBarHeight()
{
// calculate scrollbar height and make sure it is not too small
barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
bar.css({ height: barHeight + 'px' });
// hide scrollbar if content is not long enough
var display = barHeight == me.outerHeight() ? 'none' : 'block';
bar.css({ display: display });
}
function showBar()
{
// recalculate bar height
getBarHeight();
clearTimeout(queueHide);
// when bar reached top or bottom
if (percentScroll == ~~percentScroll)
{
//release wheel
releaseScroll = o.allowPageScroll;
// publish approporiate event
if (lastScroll != percentScroll)
{
var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
me.trigger('slimscroll', msg);
}
}
else
{
releaseScroll = false;
}
lastScroll = percentScroll;
// show only when required
if(barHeight >= me.outerHeight()) {
//allow window scroll
releaseScroll = true;
return;
}
bar.stop(true,true).fadeIn('fast');
if (o.railVisible) { rail.stop(true,true).fadeIn('fast'); }
}
function hideBar()
{
// only hide when options allow it
if (!o.alwaysVisible)
{
queueHide = setTimeout(function(){
if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg)
{
bar.fadeOut('slow');
rail.fadeOut('slow');
}
}, 1000);
}
}
});
// maintain chainability
return this;
}
});
jQuery.fn.extend({
slimscroll: jQuery.fn.slimScroll
});
})(jQuery);
/*!
* Author: Abdullah A Almsaeed
* Date: 4 Jan 2014
* Description:
* This file should be included in all pages
!**/
$(function() {
"use strict";
//Enable sidebar toggle
$("[data-toggle='offcanvas']").click(function(e) {
e.preventDefault();
//If window is small enough, enable sidebar push menu
if ($(window).width() <= 992) {
$('.row-offcanvas').toggleClass('active');
$('.left-side').removeClass("collapse-left");
$(".right-side").removeClass("strech");
$('.row-offcanvas').toggleClass("relative");
} else {
//Else, enable content streching
$('.left-side').toggleClass("collapse-left");
$(".right-side").toggleClass("strech");
}
});
//Add hover support for touch devices
$('.btn').bind('touchstart', function() {
$(this).addClass('hover');
}).bind('touchend', function() {
$(this).removeClass('hover');
});
//Activate tooltips
$("[data-toggle='tooltip']").tooltip();
/*
* Add collapse and remove events to boxes
*/
$("[data-widget='collapse']").click(function() {
//Find the box parent
var box = $(this).parents(".box").first();
//Find the body and the footer
var bf = box.find(".box-body, .box-footer");
if (!box.hasClass("collapsed-box")) {
box.addClass("collapsed-box");
bf.slideUp();
} else {
box.removeClass("collapsed-box");
bf.slideDown();
}
});
/*
* ADD SLIMSCROLL TO THE TOP NAV DROPDOWNS
* ---------------------------------------
*/
$(".navbar .menu").slimscroll({
height: "200px",
alwaysVisible: false,
size: "3px"
}).css("width","100%");
/*
* INITIALIZE BUTTON TOGGLE
* ------------------------
*/
$('.btn-group[data-toggle="btn-toggle"]').each(function() {
var group = $(this);
$(this).find(".btn").click(function(e) {
group.find(".btn.active").removeClass("active");
$(this).addClass("active");
e.preventDefault();
});
});
$("[data-widget='remove']").click(function() {
//Find the box parent
var box = $(this).parents(".box").first();
box.slideUp();
});
/* Sidebar tree view */
$(".sidebar .treeview").tree();
/*
* Make sure that the sidebar is streched full height
* ---------------------------------------------
* We are gonna assign a min-height value every time the
* wrapper gets resized and upon page load. We will use
* Ben Alman's method for detecting the resize event.
**/
//alert($(window).height());
function _fix() {
//Get window height and the wrapper height
var height = $(window).height() - $("body > .header").height();
$(".wrapper").css("min-height", height + "px");
var content = $(".wrapper").height();
//If the wrapper height is greater than the window
if (content > height)
//then set sidebar height to the wrapper
$(".left-side, html, body").css("min-height", content + "px");
else {
//Otherwise, set the sidebar to the height of the window
$(".left-side, html, body").css("min-height", height + "px");
}
}
//Fire upon load
_fix();
//Fire when wrapper is resized
$(".wrapper").resize(function() {
_fix();
});
/*
* We are gonna initialize all checkbox and radio inputs to
* iCheck plugin in.
* You can find the documentation at http://fronteed.com/iCheck/
*/
$("input[type='checkbox'], input[type='radio']").iCheck({
checkboxClass: 'icheckbox_minimal',
radioClass: 'iradio_minimal'
});
});
function change_layout() {
$("body").toggleClass("fixed");
}
/*END DEMO*/
/*
* BOX REFRESH BUTTON
* ------------------
* This is a custom plugin to use with the compenet BOX. It allows you to add
* a refresh button to the box. It converts the box's state to a loading state.
*
* USAGE:
* $("#box-widget").boxRefresh( options );
* */
(function($) {
"use strict";
$.fn.boxRefresh = function(options) {
// Render options
var settings = $.extend({
//Refressh button selector
trigger: ".refresh-btn",
//File source to be loaded (e.g: ajax/src.php)
source: "",
//Callbacks
onLoadStart: function(box) {
}, //Right after the button has been clicked
onLoadDone: function(box) {
} //When the source has been loaded
}, options);
//The overlay
var overlay = $('');
return this.each(function() {
//if a source is specified
if (settings.source === "") {
if (console) {
console.log("Please specify a source first - boxRefresh()");
}
return;
}
//the box
var box = $(this);
//the button
var rBtn = box.find(settings.trigger).first();
//On trigger click
rBtn.click(function(e) {
e.preventDefault();
//Add loading overlay
start(box);
//Perform ajax call
box.find(".box-body").load(settings.source, function() {
done(box);
});
});
});
function start(box) {
//Add overlay and loading img
box.append(overlay);
settings.onLoadStart.call(box);
}
function done(box) {
//Remove overlay and loading img
box.find(overlay).remove();
settings.onLoadDone.call(box);
}
};
})(jQuery);
/*
* SIDEBAR MENU
* ------------
* This is a custom plugin for the sidebar menu. It provides a tree view.
*
* Usage:
* $(".sidebar).tree();
*
* Note: This plugin does not accept any options. Instead, it only requires a class
* added to the element that contains a sub-menu.
*
* When used with the sidebar, for example, it would look something like this:
*