Refreshing Pagination in DataTables? - javascript

I'm having a strange issue that's only arising in my dataTable in select environments. I've written a function that allows the user to delete a row, then if it's the last row on that particular page, reload the Table and send the user to the 'new' last page.
However, on some servers, it's not working properly -- I think it has to do with the fact that with after using fnClearTable and fnDraw, the pagination of the table still holds the last 'empty' page.
Here's the function I'm working with now:
function fnDelete(elem) {
if (selected.length > 0) {
var c;
c = confirm("Are you sure you want to delete the selected Agency?");
if (c) {
var deleteURL = urlstr.substring(0, urlstr.lastIndexOf("/") + 1) + "delete.do";
deleteRecord(deleteURL, selected[0]);
if ($(".tableViewer tbody tr:visible").length === 1) {
oTable.fnClearTable();
oTable.fnDraw();
oTable.fnPageChange("last");
}}}}
In addition, here's my delet function.
function deleteRecord(deleteURL, iid){
var didDelete = false;
jQuery.ajax({
type: "POST",
url: deleteURL,
dataType:"html",
data:"recordID="+iid,
async : false,
success:function(response){
didDelete = true;
oTable.fnDraw(true);
selected = [];
selectedRecord = [];
enableButtons(selected);
},
error:function (xhr, ajaxOptions, thrownError){
<%-- is the message in a range we can handle? --%>
if ((xhr.status >=400) && (xhr.status < 500)) {
alert(xhr.responseText);
}
else {
alert('<spring:message arguments="" text="Internal Server Error" code="ajax.internal.server.error"/>');
}
}
});
return didDelete;
}
Again, this issue is only coming up on certain computers. Can anyone help?
Also, here's the configuration for my DataTable::
oTable = $('#${tableName}_grid').dataTable({
bDestroy: true,
bSort: true,
bFilter: true,
bJQueryUI: true,
bProcessing: true,
bAutoWidth: true,
bInfo: true,
bLengthChange: true,
iDisplayLength: ${sessionScope.displayLength},
sPaginationType: 'full_numbers',
bServerSide: true,
sAjaxSource: "<c:url value='${dataUrl}'/>",
aaSorting: [<c:forEach items="${sortInfo}" var="oneSort"> [${oneSort.columnIndex},'${oneSort.ascending ? "asc":"desc"}']</c:forEach>],
aoColumns: [
<c:forEach items="${columns}" var="curCol" varStatus="colLoop">
{sName: '${curCol.fieldName}', bSortable: ${curCol.sortable}, bSearchable: false, sTitle: "<c:out value='${curCol.title}'/>", sType: '${curCol.displayType}', bVisible:${curCol.visible}, vdbType:'${curCol.vdbType}', sClass:'${curCol.displayType}'}${colLoop.last ? '' : ','}
</c:forEach>
],
aoColumnDefs:[{sClass:"color_col", aTargets:['color']}],
fnRowCallback: function( nRow, aData, iDisplayIndex ) {
$('#${tableName}_grid tbody tr').each( function () {
if ($.inArray(aData[0], selected)!=-1) {
$(this).addClass('row_selected');
}
});
return nRow;
},
fnInfoCallback: function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
if(myPos>=iStart && myPos<=iEnd){
//alert(myPos+" visible")
}else{
selected = [];
selected = [];
selectedRecord = [];
$('tr').removeClass('row_selected');
enableButtons(selected);
}
},
fnDrawCallback: function ( oSettings ) {
$('#${tableName}_grid tbody tr').each( function () {
var iPos = myPos = oTable.fnGetPosition( this );
if (iPos!=null) {
var aData = oTable.fnGetData( iPos );
if ($.inArray(aData[0], selected)!=-1) {
$(this).addClass('row_selected');
}
}
var htxt = '';
$(this).find('.color').filter(function(i,tdata){
htxt = '';
htxt = '#'+($(tdata).text());
return true;
}).css("background",htxt);
$(this).dblclick( function(){
var iPos = myPos = oTable.fnGetPosition(this);
var aData = oTable.fnGetData(iPos);
var iId = aData[0];
selected = [];
selectedRecord = [];
selected.push(iId);
selectedRecord.push(aData);
$('tr').removeClass('row_selected');
$(this).addClass('row_selected');
enableButtons(selected);
<%-- in case there is no edit button or its enablement is more complex,
// click the button instead of assuming it will call fnEdit.
// Do first() because jQuery is returning the same element multiple times.--%>
$(".${tableName}_bttns > span.edit-doubleclick:not(.disabld)").first().click();
});
$(this).click( function () {
var iPos = myPos = oTable.fnGetPosition(this);<%-- row index on_this_page --%>
var aData = oTable.fnGetData(iPos);
var iId = aData[0];
var is_in_array = $.inArray(iId, selected);
<%-- alert("iPos: " + iPos + "\nData: " + aData + "\niId: " + iId + "\nselected: " + selected + "\nis_in_array: " + is_in_array); --%>
selected = [];
selectedRecord = [];
if (is_in_array==-1) {
selected.push(iId);
selected.sort(function(a,b){return a-b});
selectedRecord.push(aData);
selectedRecord.sort(function(a,b){return a[0]-b[0]});
}
else {
selected = $.grep(selected, function(value) {
return value != iId;
});
selectedRecord = $.grep(selectedRecord, function(value) {
return value != aData;
});
}
if ( $(this).hasClass('row_selected') ) {
$(this).removeClass('row_selected');
}
else {
$('#${tableName}_grid tr').removeClass('row_selected');
$(this).addClass('row_selected');
}
enableButtons(selectedRecord);
});
});
} ,
"sDom": '<"H"lTfr>t<"F"ip>',
"oTableTools":{
"aButtons":[ {
"sExtends":"print",
"bShowAll": true,
"sInfo": printmsg,
"sButtonClass":"ui-icon fg-button ui-button edit-print DTTT_button_print",
"sButtonClassHover":"ui-icon fg-button ui-button edit-print DTTT_button_print"
} ] }
});
$('#${tableName}_grid_filter input').attr("maxlength", "255").attr("size", "35");
$('#${tableName}_grid').ready(function(){
$(".DTTT_containerc").remove();
BuildToolBarButtons();
var tt;
$(".DTTT_containerc").each(function(){
tt = $(this).find("#Print").attr("title");
$(this).find("#Print").remove();
$(this).find(".DTTT_container").remove();
}
);
$(".DTTT_container > button").attr("title",tt).css("border","1px solid #9597A3").removeClass("ui-state-default");
$(".DTTT_containerc").append($(".DTTT_container").removeAttr("style"));
});
});

Your datatable is configured to load data using ajax. This means that any action against the data happens asynchronously. Specifically, the fnDraw() function allows control to go to the statement where you change the page page before the new data is back from the server. You should move the logic that takes you to the last page to the fnDrawCallback. I believe that should resolve your issue.

Thought I'd write a response to help others to show how I fixed it.
#Gavin was correct in that it was in the wrong place -- I moved the function in question to the sucess callback in AJAX. However, to fix it fully, I had to 'premptively' read what page the deletion was happening on (using fn.PageChange plugin), subtract 1 (bc DataTables is zero-based) and send the user there.
Hope this helps anyone! #Gavin, thank you for your help and for leading me int he right direction!

you can keep on the same page after the table refreshed. you need to use the following snippet to keep your pagination same after refreshing datatable. just copy paste following js code on a separate file and hook it with your current page.
$.fn.dataTableExt.oApi.fnStandingRedraw = function(oSettings) {
if(oSettings.oFeatures.bServerSide === false){
var before = oSettings._iDisplayStart;
oSettings.oApi._fnReDraw(oSettings);
oSettings._iDisplayStart = before;
oSettings.oApi._fnCalculateEnd(oSettings);
}
oSettings.oApi._fnDraw(oSettings);
};
and now, you might be used the "fnDraw" to refresh the dataTable. So now, instead of that code. change it like this.
oTable1.fnStandingRedraw();
Now, your dataTable will keep the same page after refreshing it.

Related

Failed to execute postMessage on window on Ajax

I've made a custom throttle for ajax requests.
Problem is I keep getting this error?
Uncaught TypeError: Failed to execute 'postMessage' on 'Window': 1 argument required, but only 0 present.
The line points to $.ajax({.
HTML:
<input class="image_title" />
<span class="the_title"></span>
JS:
$(function() {
var aj_count = 0;
var aj_flag = false;
var aj_flag2 = false;
var run_on = -1;
setInterval(function() {
aj_count++;
if (aj_flag === true) {
run_on = aj_count + 250;
aj_flag = false;
aj_flag2 = true;
}
if (run_on < aj_count && aj_flag2 === true) {
var $t = $(this);
var daid = $('.image_id').val();
aj_flag2 = false;
$.ajax({
type: "POST",
url: '/ajax/set_title.php',
data: {
'title' : $t,
'id' : daid
},
success: function(data) {
var data = JSON.parse(data);
$('.the_title').html( '<small>Title:</small> <strong>' + data.title + '</strong>' );
}
});
}
}, 1);
$('.image_title').on('input', function(e) {
aj_flag = true;
e.preventDefault();
return false;
});
$('.image_title').on('keydown', function(e) {
if (e.which == 13) {
e.preventDefault();
return false;
}
});
});
As you can see I have tried moving direct form vals into variables etc but I cannot get it to work anymore. When I replace the ajax section with a console.log it runs as expected. I've been looking around but I don't really understand what the error means still as ajax has an array passed to it.
Thank you for your time
The error is probably because of
var $t = $(this);
You're trying to send $t as the value of the title: parameter with
data: {
title: $t,
id: daid
},
But a jQuery object can't be serialized into a POST parameter.
You need to set $t to a proper title string. I don't know where that is in your application, but that should fix it.

Getting data from datatable then passing it to php with ajax

I am using jQuery DataTables, I can get data from selected row using this code
var str = $.map(table.rows('.selected').data(), function (item) {
return item[5]+" "+item[0]
});
where item[5] is id, item[0] is a string.
I want to split return string for passing id and string.
the error founded in ajax code specifically in
data : {}
where is the problem in this code.
<script>
$(document).ready(function() {
var table = $('#liveSearch').DataTable();
$('#liveSearch tbody').off('click', 'tr').on( 'click', 'tr', function () {
if ( $(this).hasClass('selected') ) {
$(this).removeClass('selected');
}
else {
table.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
}
} );
$('.example3-1').on('click', function () {
if ((table.rows('.selected').data().length) > 0) {
var str = $.map(table.rows('.selected').data(), function (item) {
return item[5]+" "+item[0]
});
console.log(str);
$.confirm({
confirmButtonClass: 'btn-info',
cancelButtonClass: 'btn-danger',
confirm: function () {
$.ajax({
type: 'post',
url: 'delete.php',
data: {
str1 : str.substr(0,str.indexOf(' ')),
str2 : str.substr(str.indexOf(' ')+1)
},
success: function( data ) {
console.log( data );
}
});
table.row('.selected').remove().draw(false);
}
});
}
});
} );
CAUSE
You're only allowing only one row selected. But you're using $.map which returns Array not a string as you expect. There is no sense in using $.map for just one row.
SOLUTION
Use the following code instead to get data for selected row and produce the string needed.
var rowdata = table.row('.selected').data();
var str = rowdata[5] + " " + rowdata[0];
It could be simplified further:
var rowdata = table.row('.selected').data();
// ... skipped ...
$.ajax({
// ... skipped ...
data: {
str1: rowdata[5],
str2: rowdata[0]
}
// ... skipped ...
});
NOTES
The solution would be different if you allow multiple row selection.

event handler are not working in asynchronous ajax call

i am filling up my dropdowns using this ajax call ..selectItems create select option tags in html using attribute_map
var $el = this.$el(model);
var rule_title = "Job Family: ";
var attribute_map = [];
var current_object = this;
$el.append(this.getRuleTitle(rule_title, model));
jQuery.ajax({
url : "<%= Rails.configuration.url_prefix %>/team/index/get_rule_attribute_values",
type : "GET",
data : { name : "jobFamily" },
dataType : "json",
success : function(data){
var attribute_array = data.value.rule_attribute_values;
attribute_array.sort(function(a,b){
if(a.display_name > b.display_name){
return 1;
}
if(a.display_name < b.display_name){
return -1;
}
return 0;
});
var index = 0;
var obj;
for (obj in attribute_array){
attribute_map[index] = [];
attribute_map[index][0] = attribute_array[index].display_name + " ( " + attribute_array[index].internal_name + " ) " ;
attribute_map[index][1] = attribute_array[index].internal_name;
index++;
}
current_object.selectItems($el,
attribute_map,
"jobFamily", model.jobFamily, {multiple : "multiple", "data-placeholder" : "Add Constraint..."}, "400px");
},
complete : function() {
console.log("completed");
},
error : function(jqXHR, textStatus,errorThrown){
var requestResponse = {
httpStatus: jqXHR.status,
error:jqXHR.statusText,
};
}
});
when i put async as false ..event handler works fine but in synchronous call , the just doesn't do anything
event handler looks like
$('.chosen-select jobFamily').on('change',function(evt, params){
console.log("completeddddddd");
var value = $('.chosen-select jobFamily').val();
console.log(value);
if (value == null) {
// Input is empty, so uncheck the box.
$('.jobFamily').prop("checked", false);
} else {
// Make sure the box is checked.
$('.jobFamily').prop("checked", true);
}
});
});
where '.chosen-select jobFamily' is class of select tag and '.jobFamily' is class of check box ... i have tried writing my jquery inside complete argument of ajax call , i tried writing my jquery inside
$('document).bind('ajaxComplete',function({
//above jquery
});
please help . i have spent more than 2 days on that . all code lies inside ready function.

DataTables sAjaxSource Json higlight search data

I am trying to implement search highlight on data table ( JSON data is coming and filling up the table from serverside through "sAjaxSource"), Please see the below code for details.
search is working by default, BUT highlight is not working at all.
I alerted data of searchTxt+=$('#search_input').val(); alert("txt" + searchTxt);
and alert is displaying search input box text.
Alert for " alert(""+ aData[j]); " displaying "undefined rather than column data and highlight is not working.
Could anyone shed some light on this ?
Thank you,
Sri
jQuery(document).ready(function() {
var oTable = jQuery('#example').dataTable({
"sDom": '<"#table_header"<"#inner_table_header"<"filtertx">fCT<"filterbtn">>>tipl',
"sAjaxSource": ajaxURL,
"bDeferRender": true,
"bProcessing" : true,
"bJQueryUI": true,
"sScrollY": 500,
"aaSorting": [[0, 'desc']],
"aoColumns": [
{ "mData": "name" },
{ "mData": "flag" }
],
"oSearch": {"sSearch": "",
"bSmart": true,
"bRegex": false},
"sPaginationType": "paginate",
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
$(nRow).addClass('clickable');
$(nRow).attr('onClick', "editPopup(" + aData['conditionId'] + ")");
},
"fnDrawCallback": function( oSettings ) {
$(expandWrapper);
}
});
$("#example_filter label").attr("for", "search_input");
$("#example_filter input").attr({
"id": "search_input",
"placeholder" : 'search'
});
oTable.fnSearchHighlighting();
});
jQuery.fn.dataTableExt.oApi.fnSearchHighlighting = function(oSettings) {
oSettings.oPreviousSearch.oSearchCaches = {};
oSettings.oApi._fnCallbackReg( oSettings, 'aoRowCallback', function( nRow, aData, iDisplayIndex, iDisplayIndexFull) {
var searchStrings = [];
var oApi = this.oApi;
var cache = oSettings.oPreviousSearch.oSearchCaches;
// Global search string
// If there is a global search string, add it to the search string array
if (oSettings.oPreviousSearch.sSearch) {
searchStrings.push(oSettings.oPreviousSearch.sSearch);
}
// Individual column search option object
// If there are individual column search strings, add them to the search string array
searchTxt=$('#filter_input input[type="text"]').val();
searchTxt+=$('#search_input').val();
alert("txt" + searchTxt);
if ((oSettings.aoPreSearchCols) && (oSettings.aoPreSearchCols.length > 0)) {
for (var i in oSettings.aoPreSearchCols) {
if (oSettings.aoPreSearchCols[i].sSearch) {
searchStrings.push(searchTxt);
}
}
}
// Create the regex built from one or more search string and cache as necessary
if (searchStrings.length > 0) {
var sSregex = searchStrings.join("|");
if (!cache[sSregex]) {
// This regex will avoid in HTML matches
cache[sSregex] = new RegExp("("+escapeRegExpSpecialChars(sSregex)+")(?!([^<]+)?>)", 'i');
}
var regex = cache[sSregex];
}
// Loop through the rows/fields for matches
jQuery('td', nRow).each( function(i) {
// Take into account that ColVis may be in use
var j = oApi._fnVisibleToColumnIndex( oSettings,i);
// Only try to highlight if the cell is not empty or null
alert(""+ aData[j]);
if (aData[j]) {
// If there is a search string try to match
if ((typeof sSregex !== 'undefined') && (sSregex)) {
alert("here");
this.innerHTML = aData[j].replace( regex, function(matched) {
return "<span class='filterMatches'>"+matched+"</span>";
});
}
// Otherwise reset to a clean string
else {
this.innerHTML = aData[j];
}
}
});
return nRow;
}, 'row-highlight');
return this;
};
Wherever the search functionality is and if you are using mData to populate json data, use mData information to retrieve the column data and highlight ( DO NOT use indexes to retrieve column data for search and highlight)
var colProp = oSettings.aoColumns[i].mData;
jQuery('td', nRow).each( function(i) {
/* Take into account that ColVis may be in use
var j = oApi._fnVisibleToColumnIndex( oSettings,i);
Only try to highlight if the cell is not empty or null
*/
var colProp = oSettings.aoColumns[i].mData;
if (aData[colProp] !== undefined && aData[colProp] !== null && aData[colProp] !== "") {
// If there is a search string try to match
if ((typeof sSregex !== 'undefined') && (sSregex)) {
var mapObj = {
'®' : "\u00AE",
'™' : "\u2122",
'"' : "\u201C",
' ' : " "
};
aData[colProp] = aData[colProp].replace(/(®)|(™)|(")|( )/gi, function(matched){
return mapObj[matched];
});
this.innerHTML = aData[colProp].replace( regex, function(matched) {
return "<span class='filterMatches'>"+matched+"</span>";
});
}
else {
this.innerHTML = aData[colProp];
}
}
});
return nRow;
}, 'row-highlight');
return this;

My table get duplicated rows with Jquery Table Sorter

I have search field in my project, which uses $.post for getting the results for the search query.
My problem: When a user click on the search button it works correctly, however when a user click on the search button again, and then click on my thead columns jquery sorter duplicates it with the previous search shows in the table.
How can I solve this so my sorter function does not duplicate?
this is the Jquery code for the search button click.
$(function () {
$('#submitfloat').click(function () {
$('#loading').show();
setTimeout(function () { $("#loading").hide(); }, 800);
var SubjectTypes = $('#SubjectTypes').val();
var Teams = $('#Teams').val();
var Companies = $('#Companies').val();
var Consultants = $('#Consultants').val();
var PlannedDates = $('#PlannedDates').val();
var CompletedDates = $('#CompletedDates').val();
var DateTypes = $('#DateTypes').val();
var data = {
Subjectypes: SubjectTypes,
Companies: Companies,
Teams: Teams,
Consultants: Consultants,
PlannedDates: PlannedDates,
CompletedDates: CompletedDates,
DateTypes: DateTypes
};
var fromDate = $('#PlannedDates').val();
var endDate = $('#CompletedDates').val();
if (Date.parse(fromDate) > Date.parse(endDate)) {
jAlert("End date must be later than start date", "Warning");
return false;
} else {
$('#GoalcardSearchResult tbody').hide();
setTimeout(function () { $("#GoalcardSearchResult tbody").show(); }, 800);
$.post('#Url.Action("Search", "SearchNKI")', data, function (result) {
$("#GoalcardSearchResult tbody").empty();
result.forEach(function (goalcard) {
$("#GoalcardSearchResult tbody").append(
$('<tr/>', {
click: function () {
id = goalcard.Id;
var url = '#Url.Action("AnswerForm", "AnswerNKI", new { id = "__id__"})';
window.location.href = url.replace('__id__', id);
},
html: "<td>" + goalcard.Name + "</td><td>" + goalcard.Customer + "</td><td>" + goalcard.PlannedDate + "</td><td>" + goalcard.CompletedDate + "</td>"
}));
});
$("#GoalcardSearchResult").tablesorter();
});
return false;
}
});
});
Your help is appreciated, thanks in advance!
I'm guessing tablesorter has already been initialized before the user clicks on the sort button. In that case, replace this code:
$("#GoalcardSearchResult").tablesorter();
with this:
$("#GoalcardSearchResult").trigger('update');

Categories

Resources