问题
I have a dataTable with hundreds of items with a fixed 50 iDisplayLength option. I need to be able to find what page a specific row is within the loaded nodes.
All I've managed is to get the position, unfortunately that internal row position does not correspond to the row index with the current sorting and filtering.
As an example here on jsFiddle. I can retrieve the position or row #tr4 (position 3) but the iDisplayStart I need is 2.
<table id="example">
<thead>
<tr>
<th>ID</th>
<th>Rendering engine</th>
<th>Browser</th>
<th>Platform(s)</th>
<th>Engine version</th>
<th>CSS grade</th>
</tr>
</thead>
<tbody>
<tr id="tr1" class="odd gradeX">
<td>1</td>
<td>Trident</td>
<td>Internet Explorer 4.0</td>
<td>Win 95+</td>
<td class="center"> 4</td>
<td class="center">X</td>
</tr>
<tr id="tr2" class="even gradeC">
<td>2</td>
<td>Trident</td>
<td>Internet Explorer 5.0</td>
<td>Win 95+</td>
<td class="center">5</td>
<td class="center">C</td>
</tr>
<tr id="tr3" class="odd gradeA">
<td>3</td>
<td>Trident</td>
<td>Internet Explorer 5.5</td>
<td>Win 95+</td>
<td class="center">5.5</td>
<td class="center">A</td>
</tr>
<tr id="tr4" class="even gradeA">
<td>4</td>
<td>Trident</td>
<td>Internet Explorer 6</td>
<td>Win 98+</td>
<td class="center">6</td>
<td class="center">A</td>
</tr>
<tr id="tr5" class="odd gradeA">
<td>5</td>
<td>Trident</td>
<td>Internet Explorer 7</td>
<td>Win XP SP2+</td>
<td class="center">7</td>
<td class="center">A</td>
</tr>
</tbody>
</table>
var oTable = $("#example").dataTable({
"sDom": '<"clear">rtip<"clear">',
"bPaginate": true,
"iDisplayLength": 2,
});
var row = $(oTable.fnGetNodes()).filter("#tr4");
console.log(row[0]);
var position = oTable.fnGetPosition(row[0]);
console.log(position);
console.log(oTable.fnSettings()._iDisplayStart);;
// position is 3 but the page displayStart I need is 2.
回答1:
I ended up writing a small dataTable plugins for it:
// get the page of a given item in order to paginate to it's page on load
$.fn.dataTableExt.oApi.fnGetPageOfRow = function (oSettings, iRow) {
// get the displayLength being used
var displayLength = oSettings._iDisplayLength;
// get the array of nodes, sorted (default) and using current filters in place for all pages (default)
// see http://datatables.net/docs/DataTables/1.9.beta.1/DataTable.html#%24_details for more detals
var taskListItems = this.$("tr", { "filter": "applied" });
// if there's more than one page continue, else do nothing
if (taskListItems.length <= displayLength) return;
// get the index of the row inside that sorted/filtered array
var index = taskListItems.index(iRow);
// get the page by removing the decimals
var page = Math.floor(index / displayLength);
// paginate to that page
this.fnPageChange(page);
};
Pass in the iRow and it'll paginate to that item's page.
回答2:
I've written a function to move you to the page with the given row. However, it uses newer API. The part inside the if is what you want.
function moveToPageWithSelectedItem() {
var numberOfRows = itemsTable.data().length;
var rowsOnOnePage = itemsTable.page.len();
if (rowsOnOnePage < numberOfRows) {
var selectedNode = itemsTable.row(".selectedItem").node();
var nodePosition = itemsTable.rows({order: 'current'}).nodes().indexOf(selectedNode);
var pageNumber = Math.floor(nodePosition / rowsOnOnePage);
itemsTable.page(pageNumber).draw(false); //move to page with the element
}
}
回答3:
In 1.10 you could simply do:
table.rows( { order: 'applied' } ).nodes().indexOf( ... );
Assuming you are working with a tr
node.
edit - sorry that gets the position in the data set. You would need to use the information from page.info().len
to then divide that index and get the page number.
回答4:
Use fnPagingInfo
$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )
{
return {
"iStart": oSettings._iDisplayStart,
"iEnd": oSettings.fnDisplayEnd(),
"iLength": oSettings._iDisplayLength,
"iTotal": oSettings.fnRecordsTotal(),
"iFilteredTotal": oSettings.fnRecordsDisplay(),
"iPage": Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),
"iTotalPages": Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )
};
};
$(document).ready(function() {
$('#example').dataTable( {
"fnDrawCallback": function () {
alert( 'Now on page'+ this.fnPagingInfo().iPage );
}
} );
} );
http://datatables.net/plug-ins/api
回答5:
I needed to programmatically find a row in the datatable, paginate the table to the page of concerned row, and to expand that row. I know some people have created custom libraries to handle it but I would expect such basic functionality out of the box. In any case, here's what I did. It's not ideal but might help.
- Use jquery to get the table object
- Get the nodes of the table (rows) and number of nodes; it's important and required because the table object has only those rows loaded which you see on the current page.
- Since pagesize of the table can be changed by the user and there's no function to retrieve the pagesize, I had it saved in local storage that I could retrieve it. I know I could get it with something like var pageSize = oTable.fnSettings()._iDisplayLength; But I prefer not to reference internal implementation of an object.
- Find the column number of the column you're looking for
- Find the row # for the row that has the matching column (first) in this case.
- Calculate the page #
- Go to the page and use timeout to load the page
- Use jquery to trigger whatever action you want to trigger on the concerned row (e.g. expand).
Here is the code sample:
let oTable = $('table#transactions').dataTable(),
nodes = oTable.fnGetNodes(),
totalRows = oTable.fnGetData().length,
pageSize = vmTable.pageLength,
idColumn = Object.keys(vmTable.columns).indexOf('column_name_to_be_matched'),
matchedPage = 0;
for (var i=0; i<totalRows; i++){
if (searchValue) === parseInt(nodes[i].cells[idColumn].innerHTML)) {
matchedPage = Math.floor(i/pageSize);
break;
}
}
if (matchedPage > 0)
oTable.fnPageChange(matchedPage);
$timeout(function() {
$(`table#transactions ul[aria-labelledby="dd${searchValue}"] span.expand`).parent().trigger('click');
}, 800);
回答6:
I have solution for similar requirement. In my scenario request=row. And datatable is not processing server-side (ajax). The @if
, @model
and <text>
is syntax of C# Razor, so you might replace it with your programming language. The table contains column with id attribute of requestId (rowId). Table is hidden when page is loaded, and displayed after javascript is done.
View
<table id="ResultTable" style="display: none">
...
<tr id="@item.Id">
JS
// When other page redirect to this page with request id parameter, we want to highlight the request
// (switch to proper datatable page, highlight row representing request and display details).
@if (Model.RequestId != null)
{
<text>
// Get index of future datatable row.
// After table is transformed to datatable, probably there is no way to get an index.
var selectedRequestRowIndex = $('#' + @Model.RequestId).index();
</text>
}
// Transform table to datatable.
var table = $('#ResultTable').DataTable({
"paging": true,
"ordering": true,
"info": false
});
@if (Model.RequestId != null)
{
<text>
// Get index of page, where request is located.
var selectedRequestPageIndex = Math.floor(selectedRequestRowIndex / table.page.info().length);
// Switch to page where request is located.
table.page(selectedRequestPageIndex).draw('page');
// Click on row, which represent request.
$('#' + @Model.RequestId).trigger('click');
</text>
}
// Display datatable to user.
$('#ResultTable').show();
回答7:
Given variables table
and tr
:
Math.floor(
table.rows({
page: 'all',
order: 'current',
search: 'applied'
}).nodes().indexOf( tr ) / table.page.info().length
)
Note that you might not need to apply the current search if you don't use filtering.
来源:https://stackoverflow.com/questions/16826580/jquery-datatables-get-page-of-a-given-row