jQuery Datatables prevent scroller reset on table reload - javascript

I finally got my datatable to reload on intervals. But what I'm noticing now is if you scrolled to the right, the table reload will reset the scroll back to the left. The same if you are scrolled down, it will reset back to the top.
I need to stop this from happening.
I've tried all the answers from this post: How to maintain jQuery DataTables scroll position after .draw()
Nothing seems to work. Maybe I'm missing something.
I noticed on this post, the question is using a datatables.scroller.min.js: DataTables save state scroll position
This led me to this: https://cdn.datatables.net/scroller/1.4.2/
But there are so many CSS files there. I'm not sure which one to use, if any should be used at all.
Maybe I do not need any of the above, and I just need to adjust my code below to prevent the scroll reset from happening:
Click event:
$('.searchSubmit').on('click', function() {
updateDataTable();
var idle = 0;
var idleInterval = setInterval(timer, 5000);
$(this).mousemove(function(e){idle = 0;});
$(this).keypress(function(e){idle = 0;});
function timer()
{
idle = idle + 1;
if(idle > 2)
{
updateDataTable();
console.log('table reloaded');
}
}
});
Datatable:
function updateDataTable() {
$.ajax({
url: 'api/railmbs.php',
type: 'POST',
data: data,
dataType: 'html',
success: function(data, textStatus, jqXHR)
{
var jsonObject = $.parseJSON(data);
var table = $('#example1').DataTable({
"data": jsonObject,
"columns": [
{ "data": "BILL" },
{ "data": "CONTAINER" },
// few more columns
],
"iDisplayLength": 25,
"paging": true,
"scrollY": 550,
"scrollX": true,
"bDestroy": true,
"stateSave": true,
"autoWidth": true
});
},
error: function(jqHHR, textStatus, errorThrown)
{
console.log('fail');
}
});
}

DOM elements have their current scroll state in elem.scrollLeft/scrollTop,further reading
try this code it rescued me.
var startPos = document.body.scrollLeft
$(selector).DataTable().clear();
$(selector).DataTable().ajax.reload(() => {
document.body.scrollLeft = startPos;
},false);
and for keeping maintaining vertical scroll state try this
var startPos = document.body.scrollTop
$(selector).DataTable().clear();
$(selector).DataTable().ajax.reload(() => {
document.body.scrollTop = startPos;
},false);

Using the DataTable().ajax.reload() will just init the datatable and then make it to reload on a interval (as you're doing currently)
setInterval(function() {
$('#example1').DataTable().ajax.reload(null, false);
}, 5000);
$('#example1').DataTable({
ajax: {
url: "api/railmbs.php",
type: 'POST',
data: data,
dataSrc: function(data) {
return $.parseJSON(data);
}
},
"columns": [{
"data": "BILL"
}, {
"data": "CONTAINER"
},
// few more columns
],
"iDisplayLength": 25,
"paging": true,
"scrollY": 550,
"scrollX": true,
"bDestroy": true,
"stateSave": true,
"autoWidth": true
});
As per DataTables Documents resetPaging (the second parameter on false)
Reset (default action or true) or hold the current paging position
(false). A full re-sort and re-filter is performed when this method is
called, which is why the pagination reset is the default action.
This means that neither the pagination(None than it matters if you have scrollY) nor the position of the scroll (X or Y) should reset.

Related

DataTables - stateSaveCallback and other functions to activate on click

How can I implement stateSaveCallback / "colReorder" / "buttons": ['colvis'] to be enable when the user clicks on a button?
Basically, I need the user to be able to edit the datatable only when he clicks an edit button and the changes to be saved when he press the save button... if the user doesn't press the save button no change will be saved and if he doesn't click on the edit button he won't be able to make any changes... any ideas how to do this?
Currently I have the code below for my dataTable.
$('#resultsTable').DataTable({
"stateSave": true,
// "serverSide": true,
// Rows per page
"lengthMenu": [
[25, 50, 100, 150, 200, 250, -1],
[25, 50, 100, 150, 200, 250, "All"]
],
"dom": '<"top"Bfi>rt<"bottom"lp><"clear">', // Show entries on bottom
// Scrolling table
"scrollY": 600, // Constrain the DataTable to the given height
"deferRender": true, // Elements will be created only when the are required
"scroller": true, // Enable vertical scrolling in DataTables
"scrollX": true, // Scroll horizontal
"colReorder": true, // Column reordering
"buttons": ['colvis'], // Enable column visibility button
// Grouping table
"columnDefs": [{ "visible": false, "targets": 0 }], // Mades target column hidden // if commented ---> Uncaught TypeError: Cannot read property 'style' of undefined
"order": [
[0, 'asc']
], // Sorting based on column
'stateSaveParams.dt': function(e, settings, data) {
data.search.search = "";
// table.columns.visible();
},
// SaveState
'stateSaveCallback': function(settings, data) {
$.ajax({
'url': 'saveDtableState.php',
'data': { name: 'resultsTable', 'state': data },
'dataType': 'json',
'method': 'POST',
"success": function() {},
error: function(xhr, ajaxOptions, thrownError) {
console.log(thrownError);
}
});
},
'stateLoadCallback': function(settings, callback) {
$.ajax({
'url': 'loadDtableState.php',
'data': { name: 'resultsTable' },
'dataType': 'json',
'type': "POST",
success: function(data) {
callback(data);
console.log('test: ' + data);
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(thrownError);
}
});
}
})
will it work if I use this?
$('#saveEdit').on("click", function(){
table.state.save();
});
or will it keep saving the state of the table every time I make a change? (I don't want that). and how to implement the other things? *any tips? *
var run = false;
run = true;
table.state.save(run); // runs the state save function
// SaveState
'stateSaveCallback': function (settings, data) {
if (run == true) {
$.ajax({
'url': 'hfdjs.php',
'data': data,
'dataType': 'json',
'method': 'POST',
"success": function () {},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError);
}
});
}
run = false;
}

jQuery datatable retain row highlight after reload

I am reloading my datatable on 10 second intervals. When a user clicks on a row, that row will highlight. But when the datatable reloads, the highlight is gone.
Here is the shortened code for my datable:
$(document).ready(function()
{
// set datatable
$('#example1').DataTable({
"ajax": {
"url": "api/process.php",
"type": "POST",
"dataSrc": ''
},
"columns": [
{ "data": "" },
{ "data": "column1" },
{ "data": "column2" },
{ "data": "column3" }
],
"iDisplayLength": 25,
"order": [[ 6, "desc" ]],
"scrollY": 600,
"scrollX": true,
"bDestroy": true,
"stateSave": true
});
// reload datatable every 30 seconds
setInterval(function()
{
var table = $('#example1').DataTable();
table.ajax.reload();
}, 30000);
// highlight row
$('#example1 tbody').on('click', 'tr', function()
{
$('#example1 tbody > tr').removeClass('selected');
$(this).addClass('selected');
});
});
All of the above works exactly how it's supposed to work. I just need to retain the row highlight after the datatable reloads.
Also, I attempted the answer from this post, but I scrapped it as the row no longer highlights.
Kindly update js file with below changes. Below code will save row clicked in global parameter and then focus the clicked row after ajax call.
var gblIndex = 0; //this will save row clicked index
function setFocus(){
$($('#example1 tbody > tr')[gblIndex]).addClass('selected');
}
$(document).ready(function()
{
// set datatable
$('#example1').DataTable({
"ajax": {
"url": "api/process.php",
"type": "POST",
"dataSrc": ''
},
"columns": [
{ "data": "" },
{ "data": "column1" },
{ "data": "column2" },
{ "data": "column3" }
],
"iDisplayLength": 25,
"order": [[ 6, "desc" ]],
"scrollY": 600,
"scrollX": true,
"bDestroy": true,
"stateSave": true
});
// reload datatable every 30 seconds
setInterval(function()
{
var table = $('#example1').DataTable();
table.ajax.reload();
setFocus(); // this will set focus/highlight row
}, 30000);
// highlight row
$('#example1 tbody').on('click', 'tr', function()
{
$('#example1 tbody > tr').removeClass('selected');
$(this).addClass('selected');
gblIndex = $(this).index(); // this will save the index clicked
});
});
You should review their actual selection documentation to manipulate this. This feature is already built in and setup so on ajax.reload() it will keep your selections.
You can apply classes/styling with their methods as well.
https://datatables.net/reference/option/#select

Jquery.Datatable.js is taking time to render the records

I have a MVC application and I am fetching 5000 records from the database and returns in the JSOn format format in the action and rendering a Jquery.DataTable.js version 1.9.0 grid. The application is returning the data with no delay but it is taking time to render in the grid. Below is the code
$.ajax({
url: "http://locationhost/Mycontroller/myacton", type: "Get", contentType: "application/json; charset=utf-8",
data: { 'param': param1, 'param2': param2, },
dataType: "json",
success: function (data) {
$('#DisableDiv').html("");
var items = '';
var rows = '';
$('#divGrid').DataTable().fnClearTable();
$('#divGrid').DataTable().fnDestroy();
if (data.length > 0) {
$.each(data, function (i, item) {
rows = "<tr>........records......</tr>"
$('#divGrid tbody').append(rows);
});
table = $('#divGrid').DataTable({
"aoColumnDefs": [
{
'bSortable': false,
'aTargets': [0, 8],
}],
"aoColumns": [{ "bSortable": false }, null, null, null, null, null, { "sType": "currency" }, null, { "bSortable": false }],
"bPaginate": true,
"bInfo": true,
"bFilter": false,
"bLengthChange": true,
"sPaginationType": "full_numbers",
"iDisplayLength": 10
});
table.fnSort([[7, 'desc']]);
}
else {
$('#DisableDiv').html("No data available.");
$("#btnDownload").attr("href", "#");
}
}
},
error: function (data) {
$('#DisableDiv').html("");
}
});
Server-side processing is best because when you render a large no of data set records client side
it makes it slow if you want to see please follow below links in that case
http://datatables.net/usage/server-side
example (http://datatables.net/release-datatables/examples/data_sources/server_side.html).

DataTables Dynamic displayStart

I'm trying to get my javascript to use a dynamic value for "displayStart". I'm getting the data from a php script that returns JSON.
Here is my js:
balance.list = function () {
$('#balance').dataTable({
processing: true,
ajax: {
url: 'php/list.php',
dataSrc: 'data'
},
dom: '<"top"flp<"clear">>rt<"bottom"ip<"clear">>',
pageLength: 50,
autoWidth: false,
displayStart: '100',
columns: [
{
width: "10%",
data: "date"
}, {
width: "5%",
data: "checknum"
}, {
width: "75%",
data: "description"
}, {
width: "5%",
data: "debit"
}, {
width: "5%",
data: "credit"
}, {
width: "5%",
data: "balance"
}]
});
};
instead of
displayStart: '100',
I want it be something like:
displayStart: displayStart.displayStart,
But I'm setting the dataSrc to data, which is another branch of the JSON
And here is the JSON data:
{
"displayStart":"100",
"data": [
{
"date":"2015-03-27",
"checknum":null,
"description":null,
"debit":"50.00",
"credit":"0.00",
"balance":"500.00"
},
{
"date":"2015-03-28",
"checknum":null,
"description":null,
"debit":"0.00",
"credit":"250.00",
"balance":"750.00"
}
]
}
I've messed around with the ajax portion using a success/error function, but then it doesn't continue on to finish the table.
How do I set the value?
You can change the page after the data has been loaded by adding two event handlers after you DataTables initialization code as shown below.
// Handles DataTables AJAX request completion event
$('#balance').on('xhr.dt', function( e, settings, json){
$(this).data('is-loaded', true);
});
// Handles DataTables table draw event
$('#balance').on('draw.dt', function (){
if($(this).data('is-loaded')){
$(this).data('is-loaded', false);
var api = $(this).DataTable();
var json = api.ajax.json();
var page_start = json['displayStart'];
// Calculate page number
var page = Math.min(Math.max(0, Math.round(page_start / api.page.len())), api.page.info().pages);
// Set page
api.page(page).draw(false);
}
});

Datatables I can't call an onclick event after I paginate?

I am using http://datatables.net/
The demo table on their homepage resembles pretty much the exact same thing that i'm using (pagination, specifically), except each row has an area to click:
<%= Post.title %>
This link opens a jquery UI modal dialog which displays some information which is ajax requested.
Part 1 (solved), see part 2 below
I'm trying to run an onclick event which works normally on page one, but as soon as i go to page 2 (or any others) it stops working. I checked the source to make sure it wasnt doing anything funny in all the code is infact there (all the rows, even the ones hidden by the pagination)
Any ideas?
$(function() {
$('#dialog').dialog({
autoOpen: false,
resizable: false,
maxHeight: 600,
width: 650,
modal: true,
beforeClose: function close() {
$('#dialog').html('');
}
});
$('.show-post').click(function() {
clickLink(this);
return false;
});
});
Thanks to those who answered my question! I fixed that issue.
Part 2
my next 'issue' id like to get to work is... I'm using the left and right arrow keys to allow them to 'scan' to the next or previous row, and display the information. This is as opposed to closing it and then having to click the next one.
I'd like to make it so when you get to the bottom of page one, or top of page two, hidding next/previous respectively will automatically load that page, go to the top (or bottom), then open that dialog for that row on the other page.
heres my click function (i know its kind of probably not structured the best... im new to jquery)
$(document).ready(function() {
oTable = $('#posts').dataTable({
"bJQueryUI": true,
"iDisplayLength": 400,
"bAutoWidth": false,
"sPaginationType": "full_numbers",
"aLengthMenu": [[-1, 400, 100, 50], ["All", 400, 100, 50]]
});
$(this).keydown(function(e) {
var id = $("#dialog").attr("data-id");
currentPost = $("#posts tr[data-id=" + id + "]");
if (e.keyCode == 39 && $('#dialog').html() != "") {
/* Remove current background */
$(currentPost).blur()
$(currentPost).removeClass("current");
$(currentPost).find("td.sorting_1").removeClass("current");
var next = currentPost.next().find(".show-post");
clickLink(next);
} else if (e.keyCode == 37 && $('#dialog').html() != "") {
/* Remove current background */
$(currentPost).removeClass("current");
$(currentPost).find("td.sorting_1").removeClass("current");
var prev = currentPost.prev().find(".show-post");
clickLink(prev)
}
});
});
heres the actual click function
function clickLink(src) {
var post = $(src);
var id = $(post).parent().parent().attr('data-id');
/* Set background for current line */
$(post).parent().parent().find("td.sorting_1").addClass("current");
$(post).parent().parent().addClass("current");
$('#dialog').attr("data-id", id);
$('#dialog').load('/show-post/' + id, function() {
$.ajax({
type: "POST",
url: "/checkstatus/" + id,
dataType: "html",
error: function(data){
$("#dialog").fadeOut("fast", function() {
$("#dialog").html("<img src='/img/invalid.jpg' alt='invalid' style='margin: 40px auto; display: block;'>").fadeIn("slow");
});
}
});
/* Set Visited */
$(post).parent().parent().removeClass("visited").addClass("visited");
$('#dialog').dialog({
title: post.html(),
beforeClose: function close() {
$(post).parent().parent().find("td.sorting_1").removeClass("current");
$(post).parent().parent().removeClass("current");
},
buttons: {
"Email 1": function() {
$.ajax({
type: "POST",
url: "/get-email/" + id + "/" + "1",
dataType: "html",
success: function(data) {
window.location.href = data + "&subject=" + post.html();
}
});
},
}
});
$('#dialog').dialog('open');
});
return false;
};
The example on the link you provided appears to be adding/removing DOM elements, meaning that elements on subsequent pages probably are not in the DOM on page load. Have you tried using event delegation?
$(<root element>).delegate('.show-post', 'click', function() {
clickLink(this);
return false;
});
Where <root element> can be document but should be set to an ancestor element that is always in the DOM.
.delegate():
Attach a handler to one or more events for all elements that match the
selector, now or in the future, based on a specific set of root
elements.
Source: http://api.jquery.com/delegate
UPDATE
Note that .delegate() is an alias of .on() now, so if you're using jQuery 1.7+ I would just use .on() right from the get-go. Almost the same syntax except the selector and event are swapped: $(<root element>).on('click', '.show-post', function() { ... });
Source: Thanks Greg Pettit, Excellent Comment
Below Code is working Perfectly. When you click the pagination button 'drawCallback' class Call some function after table load.
$("#YourTableID").dataTable({
bJQueryUI: false,
bFilter: false,
bSearchable: false,
bInfo: false,
bAutoWidth: false,
bDestroy: true,
"oLanguage": {
"sEmptyTable": "No Records Found"
},
"sPaginationType": "full_numbers",
"bLengthChange": false,
"iDisplayLength": 5,
aaData: arrv,
aoColumns: [{
sTitle: "Select",
orderable: false,
className: 'select-checkbox',
targets: 0
},
{
sTitle: "Course name"
}, {
sTitle: "Level"
}, {
sTitle: "Study Mode"
}, {
sTitle: "Entry Year"
}, {
sTitle: "Point of Entry"
}, {
sTitle: "Awarding qualification"
}],
drawCallback: function () {
//Some function...
},
select: {
style: 'os',
background: 'color:gray',
selector: 'td:first-child'
},
order: [[1, 'asc']],
});
As #scrappedcola pointed out in the comments, your click handler is lost after pagination. There is a drawCallback function for DataTables you can implement which will fire after the table is "re-drawn" (hence drawCallback). Here is an example:
$('#someId').DataTable({
lengthMenu: [ 25, 50, 100, 200 ],
order: [[ 0, 'asc' ]],
processing: true,
serverSide: true,
stateSave: true,
responsive: true,
bDestroy: true,
columns: [
{ data: 'id', name: 'id' },
{ data: 'name', name: 'name' },
],
drawCallback: function() {
var api = this.api();
api.$('#someBtnId').click(function() {
// do some click handler stuff
});
}
});

Categories