')
.addClass(classes.container)
.append(str.replace(/_INPUT_/, input));
// add for and id to label and input
filter.find('label').attr('for', 'dt-search-' + __searchCounter);
filter.find('input').attr('id', 'dt-search-' + __searchCounter);
__searchCounter++;
var searchFn = function(event) {
var val = this.value;
if(previousSearch.return && event.key !== "Enter") {
return;
}
/* Now do the filter */
if ( val != previousSearch.search ) {
previousSearch.search = val;
_fnFilterComplete( settings, previousSearch );
// Need to redraw, without resorting
settings._iDisplayStart = 0;
_fnDraw( settings );
}
};
var searchDelay = settings.searchDelay !== null ?
settings.searchDelay :
0;
var jqFilter = $('input', filter)
.val( previousSearch.search )
.attr( 'placeholder', opts.placeholder )
.on(
'keyup.DT search.DT input.DT paste.DT cut.DT',
searchDelay ?
DataTable.util.debounce( searchFn, searchDelay ) :
searchFn
)
.on( 'mouseup.DT', function(e) {
// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
// checks the value to see if it has changed. In other browsers it won't have.
setTimeout( function () {
searchFn.call(jqFilter[0], e);
}, 10);
} )
.on( 'keypress.DT', function(e) {
/* Prevent form submission */
if ( e.keyCode == 13 ) {
return false;
}
} )
.attr('aria-controls', tableId);
// Update the input elements whenever the table is filtered
$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
if ( settings === s && jqFilter[0] !== document.activeElement ) {
jqFilter.val( typeof previousSearch.search !== 'function'
? previousSearch.search
: ''
);
}
} );
return filter;
}, 'f' );
// opts
// - type - button configuration
// - buttons - number of buttons to show - must be odd
DataTable.feature.register( 'paging', function ( settings, opts ) {
// Don't show the paging input if the table doesn't have paging enabled
if (! settings.oFeatures.bPaginate) {
return null;
}
opts = $.extend({
buttons: DataTable.ext.pager.numbers_length,
type: settings.sPaginationType,
boundaryNumbers: true
}, opts);
// To be removed in 2.1
if (opts.numbers) {
opts.buttons = opts.numbers;
}
var host = $('
').addClass( settings.oClasses.paging.container + ' paging_' + opts.type );
var draw = function () {
_pagingDraw(settings, host, opts);
};
settings.aoDrawCallback.push(draw);
// Responsive redraw of paging control
$(settings.nTable).on('column-sizing.dt.DT', draw);
return host;
}, 'p' );
function _pagingDraw(settings, host, opts) {
if (! settings._bInitComplete) {
return;
}
var
plugin = DataTable.ext.pager[ opts.type ],
aria = settings.oLanguage.oAria.paginate || {},
start = settings._iDisplayStart,
len = settings._iDisplayLength,
visRecords = settings.fnRecordsDisplay(),
all = len === -1,
page = all ? 0 : Math.ceil( start / len ),
pages = all ? 1 : Math.ceil( visRecords / len ),
buttons = plugin()
.map(function (val) {
return val === 'numbers'
? _pagingNumbers(page, pages, opts.buttons, opts.boundaryNumbers)
: val;
})
.flat();
var buttonEls = [];
for (var i=0 ; i
1 && // prevent infinite
$(host).height() >= ($(buttonEls[0]).outerHeight() * 2) - 10
) {
_pagingDraw(settings, host, $.extend({}, opts, { numbers: opts.numbers - 2 }));
}
}
/**
* Get properties for a button based on the current paging state of the table
*
* @param {*} settings DT settings object
* @param {*} button The button type in question
* @param {*} page Table's current page
* @param {*} pages Number of pages
* @returns Info object
*/
function _pagingButtonInfo(settings, button, page, pages) {
var lang = settings.oLanguage.oPaginate;
var o = {
display: '',
active: false,
disabled: false
};
switch ( button ) {
case 'ellipsis':
o.display = '…';
o.disabled = true;
break;
case 'first':
o.display = lang.sFirst;
if (page === 0) {
o.disabled = true;
}
break;
case 'previous':
o.display = lang.sPrevious;
if ( page === 0 ) {
o.disabled = true;
}
break;
case 'next':
o.display = lang.sNext;
if ( pages === 0 || page === pages-1 ) {
o.disabled = true;
}
break;
case 'last':
o.display = lang.sLast;
if ( pages === 0 || page === pages-1 ) {
o.disabled = true;
}
break;
default:
if ( typeof button === 'number' ) {
o.display = settings.fnFormatNumber( button + 1 );
if (page === button) {
o.active = true;
}
}
break;
}
return o;
}
/**
* Compute what number buttons to show in the paging control
*
* @param {*} page Current page
* @param {*} pages Total number of pages
* @param {*} buttons Target number of number buttons
* @param {boolean} addFirstLast Indicate if page 1 and end should be included
* @returns Buttons to show
*/
function _pagingNumbers ( page, pages, buttons, addFirstLast ) {
var
numbers = [],
half = Math.floor(buttons / 2),
before = addFirstLast ? 2 : 1,
after = addFirstLast ? 1 : 0;
if ( pages <= buttons ) {
numbers = _range(0, pages);
}
else if (buttons === 1) {
// Single button - current page only
numbers = [page];
}
else if (buttons === 3) {
// Special logic for just three buttons
if (page <= 1) {
numbers = [0, 1, 'ellipsis'];
}
else if (page >= pages - 2) {
numbers = _range(pages-2, pages);
numbers.unshift('ellipsis');
}
else {
numbers = ['ellipsis', page, 'ellipsis'];
}
}
else if ( page <= half ) {
numbers = _range(0, buttons-before);
numbers.push('ellipsis');
if (addFirstLast) {
numbers.push(pages-1);
}
}
else if ( page >= pages - 1 - half ) {
numbers = _range(pages-(buttons-before), pages);
numbers.unshift('ellipsis');
if (addFirstLast) {
numbers.unshift(0);
}
}
else {
numbers = _range(page-half+before, page+half-after);
numbers.push('ellipsis');
numbers.unshift('ellipsis');
if (addFirstLast) {
numbers.push(pages-1);
numbers.unshift(0);
}
}
return numbers;
}
var __lengthCounter = 0;
// opts
// - menu
// - text
DataTable.feature.register( 'pageLength', function ( settings, opts ) {
var features = settings.oFeatures;
// For compatibility with the legacy `pageLength` top level option
if (! features.bPaginate || ! features.bLengthChange) {
return null;
}
opts = $.extend({
menu: settings.aLengthMenu,
text: settings.oLanguage.sLengthMenu
}, opts);
var
classes = settings.oClasses.length,
tableId = settings.sTableId,
menu = opts.menu,
lengths = [],
language = [],
i;
// Options can be given in a number of ways
if (Array.isArray( menu[0] )) {
// Old 1.x style - 2D array
lengths = menu[0];
language = menu[1];
}
else {
for ( i=0 ; i outside of the label if it is at the start or
// end which helps improve accessability (not all screen readers like
// implicit for elements).
var end = opts.text.match(/_MENU_$/);
var start = opts.text.match(/^_MENU_/);
var removed = opts.text.replace(/_MENU_/, '');
var str = '';
if (start) {
str = '_MENU_';
}
else if (end) {
str = '_MENU_';
}
// Wrapper element - use a span as a holder for where the select will go
var div = $('')
.addClass( classes.container )
.append(
str.replace( '_MENU_', '' )
);
// Save text node content for macro updating
var textNodes = [];
div.find('label')[0].childNodes.forEach(function (el) {
if (el.nodeType === Node.TEXT_NODE) {
textNodes.push({
el: el,
text: el.textContent
});
}
})
// Update the label text in case it has an entries value
var updateEntries = function (len) {
textNodes.forEach(function (node) {
node.el.textContent = _fnMacros(settings, node.text, len);
});
}
// Next, the select itself, along with the options
var select = $('', {
'name': tableId+'_length',
'aria-controls': tableId,
'class': classes.select
} );
for ( i=0 ; i