The code I'm working with will highlight the corresponding row in the data tables after clicking on the map marker.
The problem is that when sorting is applied, the selection of the page with the selected row is incorrect or does not occur at all.
If I cancel the pagination by displaying all the lines, then the line selection works perfectly fine. How to make correct page selection when selecting row after sorting?
// Add markers and event listeners
for (var i = 0; i < dataArray.length; i++) {
var marker = L.marker([dataArray[i][5], dataArray[i][6]]).addTo(map);
marker.bindPopup("Book: " + dataArray[i][2] + "<br>" + "Pages: " + dataArray[i][3]);
var currentMarker = null;
var currentTableRow = null;
marker.on("click", function(e) {
var popup = e.target.getPopup();
var content = popup.getContent();
var table = $('#data-table').DataTable();
var rowData = table.rows().data().toArray();
// Find the row that matches the content of the popup
var tr = null;
for (var i = 0; i < rowData.length; i++) {
if (rowData[i][2] == content.split("<br>")[0].split(": ")[1]) {
// Use the "index" option to get the index of the row in the original loading order
var index = table.column(2, {order:'index'}).data().indexOf(rowData[i][2]);
tr = table.row(index).node();
break;
}
}
if (tr !== null) {
// Add a "highlight" class to the new table row
$(tr).addClass("highlight");
// Remove the "highlight" class from the previous table row (if any)
if (currentTableRow !== null) {
$(currentTableRow).removeClass("highlight");
}
// Update the currently selected marker and its corresponding table row
currentMarker = marker;
currentTableRow = tr;
// Get the page index of the selected row
var pageInfo = table.page.info();
var rowPage = Math.floor(table.row(tr).index() / pageInfo.length);
// Set the page index as the active page
table.page(rowPage).draw(false);
}
});
}
Solution:
Instead of this:
tr = table.row(index).node();
use this:
tr = table.row(index, {order:'index'}).node();
Explanation:
Your code is using the following:
var index = table.column(2, {order:'index'})
This retrieves the index value assigned to the row in DataTables. This value is assigned when the DataTable is first initialized and represents the original order in which data was loaded into your DataTable. This assigned value does not change, regardless of what filtering or sorting you apply.
You therefore need to use this same index
value with the same selector-modifier when you select the node to be highlighted.
If you only use tr = table.row(index).node();
, then this defaults to {order:'current'}
- which is why you get the wrong (or no) row highlighted.
Demo:
I added lengthMenu: [ 2, 10 ],
to my demo, just to show multiple pages for my test data.
var dataArray = [
['111', '1111', 'AAA', '752', 'Hardcover', '51.55', '-0.11'],
['222', '5555', 'BBB', ' 1040', 'Hardcover', '51.55', '-0.10'],
['333', '777', 'CCC', '846', 'Hardcover', '51.565', '-0.11'],
['444', '888', 'DDD', '258', 'Paperback', '51.56', '-0.12'],
['555', '555', 'FFF', ' 789', 'Hardcover', '51.55', '-0.13']
];
var map = L.map('viewmap').setView([51.56, -0.12], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
for (var i = 0; i < dataArray.length; i++) {
var marker = L.marker([dataArray[i][5], dataArray[i][6]]).addTo(map);
marker.bindPopup("Book: " + dataArray[i][2] + "<br>" + "Pages: " + dataArray[i][3]);
var currentMarker = null;
var currentTableRow = null;
marker.on("click", function(e) {
var popup = e.target.getPopup();
var content = popup.getContent();
var table = $('#data-table').DataTable();
var rowData = table.rows().data().toArray();
// Find the row that matches the content of the popup
var tr = null;
for (var i = 0; i < rowData.length; i++) {
if (rowData[i][2] == content.split("<br>")[0].split(": ")[1]) {
// Use the "index" option to get the index of the row in the original loading order
var index = table.column(2, {order: 'index'}).data().indexOf(rowData[i][2]);
tr = table.row(index, {order: 'index'}).node();
break;
}
}
if (tr !== null) {
// Add a "highlight" class to the new table row
$(tr).addClass("highlight");
// Remove the "highlight" class from the previous table row (if any)
if (currentTableRow !== null) {
$(currentTableRow).removeClass("highlight");
}
// Update the currently selected marker and its corresponding table row
currentMarker = marker;
currentTableRow = tr;
// Get the page index of the selected row
var pageInfo = table.page.info();
var rowPage = Math.floor(table.row(tr).index() / pageInfo.length);
// Set the page index as the active page
table.page(rowPage).draw(false);
}
});
}
$(document).ready(function() {
$('#data-table').DataTable({
data: dataArray,
lengthMenu: [ 2, 10 ],
columns: [{
"title": "Rating"
},
{
"title": "Reviews"
},
{
"title": "Book"
},
{
"title": "Pages"
},
{
"title": "Type"
},
{
"title": "Longitude"
},
{
"title": "Latitude"
},
]
});
});
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.23/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.23/js/dataTables.bootstrap4.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.23/css/dataTables.bootstrap4.min.css">
<?!= include('Scriptdata'); ?>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Document</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style>
body {
margin: 0;
padding: 0;
}
#viewmap {
width: 60%;
height: 60vh;
left: 0%;
margin: auto;
}
#text {
font-family: Georgia, 'Times New Roman', Times, serif;
}
.highlight {
background-color: yellow !important;
;
}
</style>
</head>
<body>
<div class="container">
<br>
<div class="row">
<table id="data-table" class="table table-striped table-sm table-hover table-bordered">
</table>
</div>
</div>
<div id="viewmap"></div>
</body>
</html>
Update
Regarding your comment:
I click the "Pages" filter ... does not go to the page with the highlighted line.
You can use the DataTables length
event to know when the user changes the DataTable "rows per page" drop-down. You can then use similar code to what you already have in your demo (and in my demo) to ensure the required row is still visible after a page length change:
$('#data-table').on( 'length.dt', function ( e, settings, len ) {
if (tr !== null) {
var table = $('#data-table').DataTable();
var pageInfo = table.page.info();
var rowPage = Math.floor(table.row(tr).index() / pageInfo.length);
table.page(rowPage).draw(false);
}
} );
For example:
I show all 10 pages in my demo.
I highlight row DDD
.
I change the drop-down from 10 pages to 2 pages.
Row DDD
is still visible.
Some additional re-organization is needed from my original demo. Here is the new <script>
code:
var tr = null;
var dataArray = [
['111', '1111', 'AAA', '752', 'Hardcover', '51.55', '-0.11'],
['222', '5555', 'BBB',' 1040', 'Hardcover', '51.55', '-0.10'],
['333', '777','CCC', '846', 'Hardcover', '51.565', '-0.11'],
['444', '888', 'DDD','258','Paperback', '51.56', '-0.12'],
['555', '555', 'FFF',' 789','Hardcover', '51.55', '-0.13']
];
var map = L.map('viewmap').setView([51.56, -0.12], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
for (var i = 0; i < dataArray.length; i++) {
var marker = L.marker([dataArray[i][5], dataArray[i][6]]).addTo(map);
marker.bindPopup("Book: " + dataArray[i][2] + "<br>" + "Pages: " + dataArray[i][3]);
var currentMarker = null;
var currentTableRow = null;
marker.on("click", function(e) {
var popup = e.target.getPopup();
var content = popup.getContent();
var table = $('#data-table').DataTable();
var rowData = table.rows().data().toArray();
// Find the row that matches the content of the popup
//var tr = null;
for (var i = 0; i < rowData.length; i++) {
if (rowData[i][2] == content.split("<br>")[0].split(": ")[1]) {
// Use the "index" option to get the index of the row in the original loading order
var index = table.column(2, {order:'index'}).data().indexOf(rowData[i][2]);
tr = table.row(index, {order:'index'}).node();
break;
}
}
if (tr !== null) {
// Add a "highlight" class to the new table row
$(tr).addClass("highlight");
// Remove the "highlight" class from the previous table row (if any)
if (currentTableRow !== null) {
$(currentTableRow).removeClass("highlight");
}
// Update the currently selected marker and its corresponding table row
currentMarker = marker;
currentTableRow = tr;
// Get the page index of the selected row
var pageInfo = table.page.info();
var rowPage = Math.floor(table.row(tr).index() / pageInfo.length);
// Set the page index as the active page
table.page(rowPage).draw(false);
}
});
}
$(document).ready(function(){
$('#data-table').DataTable({
data: dataArray,
"lengthMenu": [ 2, 10 ],
columns: [
{"title":"Rating"},
{"title":"Reviews"},
{"title":"Book"},
{"title":"Pages"},
{"title":"Type"},
{"title":"Longitude"},
{"title":"Latitude"},
]
});
});
$('#data-table').on( 'length.dt', function ( e, settings, len ) {
if (tr !== null) {
var table = $('#data-table').DataTable();
var pageInfo = table.page.info();
var rowPage = Math.floor(table.row(tr).index() / pageInfo.length);
table.page(rowPage).draw(false);
}
} );
I am sure you could refactor this to improve it (e.g. by moving common code into a function). But this should give you a starting point.