将数字范围筛选器添加到多个 DataTable 列
Add number range filter to multiple DataTable columns
我有一个数据表,我正在尝试向其中的多个列添加过滤器。有些列是字符串,需要文本输入,而其他列是数字,需要范围输入。我向每一列添加过滤器 as described here. For the range inputs, I'm trying to add my own custom search plugin, as described here。本质上,我试图结合文档两个部分的策略:我想遍历应用过滤器的每一列,对于那些数字列,我想使用范围过滤器。他们在多列过滤文档中提供的示例 table 包括数字列,但他们用于这些列的过滤器是文本输入,坦率地说,这看起来不像大多数人在实际中采用的方式-世界实施。他们提供的用于设置数字范围过滤器的文档包括一个示例,其中只有一列要被输入过滤,这允许他们将适当的列索引硬编码到他们的自定义函数中。
我的问题是我不知道如何将我需要的变量获取到自定义范围过滤函数中。具体来说,我需要获取列索引和用户对函数的输入。我使用 this bootstrap slider 作为范围输入,所以为了获得用户输入值,我在输入上调用 .slider
并传入 'getValue'
.
如何将我的变量,特别是列索引和用户输入,放入我的自定义范围过滤器函数中?
我的代码如下。我还制作了这个 JSFiddle 来展示我正在尝试做的事情。如果注释掉自定义 DataTables 函数,请注意两个文本输入的工作方式。
function populateEntryTable() {
$('#entryTableContainer').empty();
/* put demo data in array of objects that is used to populate DataTable */
var entries = [{name: John, age: 20, salary: 40000},
{name: Bill, age: 40, salary: 200000},
{name: Amy, age: 31, salary: 150000}];
/*build my table*/
$('#entryTableContainer').append('<table id="entryTable"><thead><tr></tr></thead><tbody></tbody></table>');
for (var key in entries[0]) {
$('#entryTableContainer thead tr').append('<th>' + key + '</th>');
}
for (var i = entries.length - 1; i >= 0; i--) {
for (var key in entries[i]) {
$('#entryTableContainer tbody tr:last-child').append('<td>' + entries[i][key] + '</td>');
}
}
/* add column filters below each column, as described in DataTables documentation */
$('#entryTable thead tr').clone(true).appendTo('#entryTable thead');
var numberInputs = ['age','salary'];
$('#entryTable thead tr:eq(1) th').each(function(i) {
var title = $(this).text();
/* if the col requires a text input filter, do text input filter stuff, which works fine. Else if it requires a number range filter, do number filter stuff, which doesn't work fine. */
if (numberInputs.indexOf(title) == -1) {
$(this).html('<input type="text" placeholder="Search">');
$('input',this).on('keyup change',function() {
if (entryTable.column(i).search() !== this.value) {
entryTable.column(i).search(this.value).draw();
}
});
} else if (numberInputs.indexOf(title) > -1) {
/* get min and max values in each column to set appropriate bootstrap-slider attributes */
var min;
var max;
$('#entryTable tbody tr').each(function(j) {
var item = parseFloat($('#entryTable tbody tr:eq(' + j + ') td:eq(' + i + ')').text());
if (min == undefined || item < min) {
min = Math.floor(item);
}
if (max == undefined || item > max) {
max = Math.ceil(item);
}
});
/* create bootstrap-slider with double inputs */
$(this).html('<input id="' + title + '" data-slider-min="' + min + '" data-slider-max="' + max + '" data-slider-step="1" data-slider-value="[' + min + ',' + max + ']">');
$('#' + title).slider({});
/* add listener for bootstrap-slider change */
$('input',this).on('change',function() {
/* returns an array with the min and max user inputs*/
var userInputs = $(this).slider('getValue');
var userMin = userInputs[0];
var userMax = userInputs[1];
entryTable.draw();
});
}
});
/* call DataTable on my table and include my option settings*/
var entryTable = $('#entryTable').DataTable({
orderCellsTop: true,
paging: false,
bInfo: false,
scrollY: 400,
scrollCollapse: true,
order: [ 1, 'desc' ],
searching: true
});
/* searching must be set to true for my column searches to work, but I don't want the whole table search bar to display, so I remove it here */
$('#entryTable_filter').addClass('d-none');
}
// custom DataTables function for filtering number ranges
$.fn.dataTable.ext.search.push(
function( settings, data, dataIndex ) {
/* how do I get i (the col index of the filter that the user is engaging with), the userMin and the userMax into here??? */
var colVal = parseFloat(data[i].replace('$','')) || 0;
if ( ( isNaN( userMin ) && isNaN( userMax ) ) ||
( isNaN( userMin ) && colVal <= userMax ) ||
( userMin <= colVal && isNaN( userMax ) ) ||
( userMin <= colVal && colVal <= userMax ) )
{
return true;
}
return false;
}
);
我能够通过将自定义函数移动到 .each 循环中解决我的问题,将我需要的变量放入适当的范围。我把我的解决方案放在 JSFiddle.
$(function() {
populateEntryTable()
function populateEntryTable() {
$('#entryTableContainer').empty();
/* put demo data in array of objects that is used to populate DataTable */
var entries = [{
name: 'John',
title: 'Coordinator',
age: 20,
salary: 40000
},
{
name: 'Bill',
title: 'Manager',
age: 40,
salary: 200000
},
{
name: 'Amy',
title: 'Manager',
age: 31,
salary: 150000
}
];
/*build my table*/
$('#entryTableContainer').append('<table id="entryTable"><thead><tr></tr></thead><tbody></tbody></table>');
for (var key in entries[0]) {
$('#entryTable thead tr').append('<th>' + key + '</th>');
}
for (var i = entries.length - 1; i >= 0; i--) {
$('#entryTable tbody').append('<tr></tr>');
for (var key in entries[i]) {
$('#entryTable tbody tr:last-child').append('<td>' + entries[i][key] + '</td>');
}
}
$('#entryTable thead tr').clone(true).appendTo('#entryTable thead');
var numberInputs = ['age', 'salary'];
$('#entryTable thead tr:eq(1) th').each(function(i) {
var title = $(this).text();
// if the col requires a text input filter, do text input filter stuff, which works fine. Else if it requires a number range filter, do number filter stuff, which doesn't work fine.
if (numberInputs.indexOf(title) == -1) {
$(this).html('<input type="text" placeholder="Search">');
$('input', this).on('keyup change', function() {
if (entryTable.column(i).search() !== this.value) {
entryTable.column(i).search(this.value).draw();
}
});
} else if (numberInputs.indexOf(title) > -1) {
// get min and max values in each column to set appropriate bootstrap-slider attributes
var min;
var max;
$('#entryTable tbody tr').each(function(j) {
var item = parseFloat($('#entryTable tbody tr:eq(' + j + ') td:eq(' + i + ')').text());
if (min == undefined || item < min) {
min = Math.floor(item);
}
if (max == undefined || item > max) {
max = Math.ceil(item);
}
});
var rangeMax = title == 'age' ? 100 : 1000000;
var step = rangeMax == 100 ? 1 : 10000;
$(this).html('<input id="' + title + '" type="range" value="0" min="0" max="' + rangeMax + '" step="' + step + '">');
var userInput = $('input', this).val();
// custom DataTables function for filtering number ranges
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
var colVal = parseFloat(data[i]) || 0;
if (colVal > userInput) {
return true;
}
return false;
}
);
// add listener for bootstrap-slider change
$('input', this).on('change', function() {
userInput = $(this).val();
entryTable.draw();
});
}
});
/* call DataTable on my table and include my option settings */
var entryTable = $('#entryTable').DataTable({
orderCellsTop: true,
paging: false,
bInfo: false,
scrollY: 400,
scrollCollapse: true,
order: [1, 'desc'],
searching: true
});
/* hide whole table search bar--cannot set 'searching' to false because this also disables individual column search capabilities */
$('#entryTable_filter').hide();
}
});
我有一个数据表,我正在尝试向其中的多个列添加过滤器。有些列是字符串,需要文本输入,而其他列是数字,需要范围输入。我向每一列添加过滤器 as described here. For the range inputs, I'm trying to add my own custom search plugin, as described here。本质上,我试图结合文档两个部分的策略:我想遍历应用过滤器的每一列,对于那些数字列,我想使用范围过滤器。他们在多列过滤文档中提供的示例 table 包括数字列,但他们用于这些列的过滤器是文本输入,坦率地说,这看起来不像大多数人在实际中采用的方式-世界实施。他们提供的用于设置数字范围过滤器的文档包括一个示例,其中只有一列要被输入过滤,这允许他们将适当的列索引硬编码到他们的自定义函数中。
我的问题是我不知道如何将我需要的变量获取到自定义范围过滤函数中。具体来说,我需要获取列索引和用户对函数的输入。我使用 this bootstrap slider 作为范围输入,所以为了获得用户输入值,我在输入上调用 .slider
并传入 'getValue'
.
如何将我的变量,特别是列索引和用户输入,放入我的自定义范围过滤器函数中?
我的代码如下。我还制作了这个 JSFiddle 来展示我正在尝试做的事情。如果注释掉自定义 DataTables 函数,请注意两个文本输入的工作方式。
function populateEntryTable() {
$('#entryTableContainer').empty();
/* put demo data in array of objects that is used to populate DataTable */
var entries = [{name: John, age: 20, salary: 40000},
{name: Bill, age: 40, salary: 200000},
{name: Amy, age: 31, salary: 150000}];
/*build my table*/
$('#entryTableContainer').append('<table id="entryTable"><thead><tr></tr></thead><tbody></tbody></table>');
for (var key in entries[0]) {
$('#entryTableContainer thead tr').append('<th>' + key + '</th>');
}
for (var i = entries.length - 1; i >= 0; i--) {
for (var key in entries[i]) {
$('#entryTableContainer tbody tr:last-child').append('<td>' + entries[i][key] + '</td>');
}
}
/* add column filters below each column, as described in DataTables documentation */
$('#entryTable thead tr').clone(true).appendTo('#entryTable thead');
var numberInputs = ['age','salary'];
$('#entryTable thead tr:eq(1) th').each(function(i) {
var title = $(this).text();
/* if the col requires a text input filter, do text input filter stuff, which works fine. Else if it requires a number range filter, do number filter stuff, which doesn't work fine. */
if (numberInputs.indexOf(title) == -1) {
$(this).html('<input type="text" placeholder="Search">');
$('input',this).on('keyup change',function() {
if (entryTable.column(i).search() !== this.value) {
entryTable.column(i).search(this.value).draw();
}
});
} else if (numberInputs.indexOf(title) > -1) {
/* get min and max values in each column to set appropriate bootstrap-slider attributes */
var min;
var max;
$('#entryTable tbody tr').each(function(j) {
var item = parseFloat($('#entryTable tbody tr:eq(' + j + ') td:eq(' + i + ')').text());
if (min == undefined || item < min) {
min = Math.floor(item);
}
if (max == undefined || item > max) {
max = Math.ceil(item);
}
});
/* create bootstrap-slider with double inputs */
$(this).html('<input id="' + title + '" data-slider-min="' + min + '" data-slider-max="' + max + '" data-slider-step="1" data-slider-value="[' + min + ',' + max + ']">');
$('#' + title).slider({});
/* add listener for bootstrap-slider change */
$('input',this).on('change',function() {
/* returns an array with the min and max user inputs*/
var userInputs = $(this).slider('getValue');
var userMin = userInputs[0];
var userMax = userInputs[1];
entryTable.draw();
});
}
});
/* call DataTable on my table and include my option settings*/
var entryTable = $('#entryTable').DataTable({
orderCellsTop: true,
paging: false,
bInfo: false,
scrollY: 400,
scrollCollapse: true,
order: [ 1, 'desc' ],
searching: true
});
/* searching must be set to true for my column searches to work, but I don't want the whole table search bar to display, so I remove it here */
$('#entryTable_filter').addClass('d-none');
}
// custom DataTables function for filtering number ranges
$.fn.dataTable.ext.search.push(
function( settings, data, dataIndex ) {
/* how do I get i (the col index of the filter that the user is engaging with), the userMin and the userMax into here??? */
var colVal = parseFloat(data[i].replace('$','')) || 0;
if ( ( isNaN( userMin ) && isNaN( userMax ) ) ||
( isNaN( userMin ) && colVal <= userMax ) ||
( userMin <= colVal && isNaN( userMax ) ) ||
( userMin <= colVal && colVal <= userMax ) )
{
return true;
}
return false;
}
);
我能够通过将自定义函数移动到 .each 循环中解决我的问题,将我需要的变量放入适当的范围。我把我的解决方案放在 JSFiddle.
$(function() {
populateEntryTable()
function populateEntryTable() {
$('#entryTableContainer').empty();
/* put demo data in array of objects that is used to populate DataTable */
var entries = [{
name: 'John',
title: 'Coordinator',
age: 20,
salary: 40000
},
{
name: 'Bill',
title: 'Manager',
age: 40,
salary: 200000
},
{
name: 'Amy',
title: 'Manager',
age: 31,
salary: 150000
}
];
/*build my table*/
$('#entryTableContainer').append('<table id="entryTable"><thead><tr></tr></thead><tbody></tbody></table>');
for (var key in entries[0]) {
$('#entryTable thead tr').append('<th>' + key + '</th>');
}
for (var i = entries.length - 1; i >= 0; i--) {
$('#entryTable tbody').append('<tr></tr>');
for (var key in entries[i]) {
$('#entryTable tbody tr:last-child').append('<td>' + entries[i][key] + '</td>');
}
}
$('#entryTable thead tr').clone(true).appendTo('#entryTable thead');
var numberInputs = ['age', 'salary'];
$('#entryTable thead tr:eq(1) th').each(function(i) {
var title = $(this).text();
// if the col requires a text input filter, do text input filter stuff, which works fine. Else if it requires a number range filter, do number filter stuff, which doesn't work fine.
if (numberInputs.indexOf(title) == -1) {
$(this).html('<input type="text" placeholder="Search">');
$('input', this).on('keyup change', function() {
if (entryTable.column(i).search() !== this.value) {
entryTable.column(i).search(this.value).draw();
}
});
} else if (numberInputs.indexOf(title) > -1) {
// get min and max values in each column to set appropriate bootstrap-slider attributes
var min;
var max;
$('#entryTable tbody tr').each(function(j) {
var item = parseFloat($('#entryTable tbody tr:eq(' + j + ') td:eq(' + i + ')').text());
if (min == undefined || item < min) {
min = Math.floor(item);
}
if (max == undefined || item > max) {
max = Math.ceil(item);
}
});
var rangeMax = title == 'age' ? 100 : 1000000;
var step = rangeMax == 100 ? 1 : 10000;
$(this).html('<input id="' + title + '" type="range" value="0" min="0" max="' + rangeMax + '" step="' + step + '">');
var userInput = $('input', this).val();
// custom DataTables function for filtering number ranges
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
var colVal = parseFloat(data[i]) || 0;
if (colVal > userInput) {
return true;
}
return false;
}
);
// add listener for bootstrap-slider change
$('input', this).on('change', function() {
userInput = $(this).val();
entryTable.draw();
});
}
});
/* call DataTable on my table and include my option settings */
var entryTable = $('#entryTable').DataTable({
orderCellsTop: true,
paging: false,
bInfo: false,
scrollY: 400,
scrollCollapse: true,
order: [1, 'desc'],
searching: true
});
/* hide whole table search bar--cannot set 'searching' to false because this also disables individual column search capabilities */
$('#entryTable_filter').hide();
}
});