Adding a delay to JQuery keyup() after Ajax call - javascript

I'm having a quite tough problem and I'm not sure how to approach it. I have a few textboxes in a row and I need to fill in these textboxes. Every time a textbox is filled, I grab the value and make an Ajax call that uses the value. The response determines whether or not that very textbox is colored red or green(using the Jquery css() function).
Now here's the problem. Let's say I have 5 textboxes in a row. Let's say I type 1-tab, 2-tab, 2-tab, 1-tab, 1-tab. All of this very fast. 1-tab, for example, means I type 1 followed by the Tab button to move to the next textbox. I realized that if I go too fast, some of the textboxes don't get updated and their colors do not change. I assumed this is due to the ajax taking some time to process.
I thought about the problem and came up with an idea that might solve the problem. That is add a delay after each Ajax call and then tab to the next. I search around S.O and found this solution. However, it's not really working for me(basically it breaks and the JS doesn't work at all).
Here's a snippet of my AJAX. I stripped it down and removed the unnecessary pieces of code.
$( ".myTextbox" ).keyup(function() {
//Defining my variables here
$.ajax({
//Perform First Ajax request
$.ajax({
//Perform Second Ajax Request
});
});
});
Here's the solution I tried using what I found from S.O, but it doesn't work.
var timer = null;
$( ".myTextbox" ).keyup(function() {
clearTimeout(timer);
timer = setTimeout(
function(){
.ajax({
//Perform First Ajax request
$.ajax({
//Perform Second Ajax Request
});
});
}, 200);
//Defining my variables here
});
Now, there are 2 options:
My logic is wrong about delaying the tab key. Could there be some better logic to overcome my initial problem?
I'm using the solution posted above wrongly.
Hope to get some constructive answers.
Thanks.
EDIT: Here's the full code, upon request.
$( ".getqty" ).keyup(function() {
var split = this.id.split(":");
var color = split[0];
var size = split[1];
var prodID = split[2];
var $this = $(this);
var value = $this.val();
var stock = 0;
var price = split[3];
var originalProd = split[4];
var dataStock = $this.attr("data-stock");
if(value.length > 0){
value = parseInt(value);
}else{
value = "";
}
$.ajax({ //create an ajax request
type: 'POST',
url: 'includes/add.php',
dataType: 'html', //expect html to be returned
data:'color='+color+'&size='+size+'&prodID='+prodID+'&qty='+value+'&originalProd='+originalProd+'&dataStock='+dataStock,
success: function(response){
if(response == "breakOut"){
$this.css('background-color', '#F87171').css('border', '1px solid #B42C2C');
$("#"+originalProd+"-"+color).text("Not enough in stock.").css('color', '#B42C2C');
$("#"+originalProd+"-totalPrice").text("");
}else{
stock = response;
if((value > 0 && value <= stock) || (value > 0 && dataStock == 'yes')){
$this.css('background-color', '#66CF66').css('border', '1px solid #277230');
}else{
$this.css('background-color', '#fff').css('border', '1px solid #ccc');
}
var count = 0;
$("."+color+"-" + originalProd).each(function(){
if($(this).val() == 0){
count = count + 0;
}else{
count = count + parseFloat($(this).val(), 10);
}
});
//Single Item Total
if(count > 0){
var totalPrice = (price * count).toFixed(2);
$("#"+originalProd+"-"+color).text(count + " - " + totalPrice.toString().replace(/\./g, ',') + " Eur").css('color', '#CCC');
}else{
$("#"+originalProd+"-"+color).text("");
}
$.ajax({ //create an ajax request
type: 'POST',
url: 'includes/cart.php',
dataType: 'html', //expect html to be returned
success: function(response){
if(response > 0){
$("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");
}else{
$("#cart_price").text("Cart:0,00 Eur");
}
},
error:function (xhr, ajaxOptions, thrownError){
// alert(thrownError);
}
});
if(pathname == 'mycart.php'){
location.reload();
}
}
},
error:function (xhr, ajaxOptions, thrownError){
//alert(thrownError);
}
});

You should use the change event instead of keyup. From the docs:
The keyup event is sent to an element when the user releases a key on
the keyboard. It can be attached to any element, but the event is only
sent to the element that has the focus.
When you press tab your elements will change focus quickly and maybe the keyup event will not be fired for that input text with the right value content.
So try:
$( ".getqty" ).change(...)
Update:
Since the change event just fires when the input text loses focus, you could write instead:
$( ".getqty" ).on('input', function() {
var $this = $(this);
var value = $this.val();
if (value.length > 0) {
value = parseInt(value);
}
else {
value = "";
}
$.ajax({
type: 'POST',
url: 'data.txt',
dataType: 'text',
success: function(response){
$this.css('background-color', '#66CF66').css('border', '1px solid #277230');
$.ajax({
type: 'POST',
url: 'data.txt',
dataType: 'text',
success: function(response){
$("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");
},
error:function (xhr, ajaxOptions, thrownError){
console.log(thrownError);
}
});
},
error: function (xhr, ajaxOptions, thrownError){
console.log(thrownError);
}
});
});
Or with pure javascript event listeners:
var elemList = document.getElementsByClassName('getqty');
for (var i = 0; i < elemList.length; i++) {
elemList[i].addEventListener('input', function(e) {
var $this = $(e.target);
var value = $this.val();
if (value.length > 0) {
value = parseInt(value);
}
else {
value = "";
}
$.ajax({
type: 'POST',
url: 'data.txt',
dataType: 'text',
success: function(response){
$this.css('background-color', '#66CF66').css('border', '1px solid #277230');
$.ajax({
type: 'POST',
url: 'data.txt',
dataType: 'txt',
success: function(response){
$("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");
},
error:function (xhr, ajaxOptions, thrownError){
console.log(thrownError);
}
});
},
error: function (xhr, ajaxOptions, thrownError){
console.log(thrownError);
}
});
});
}

You can try this to delay on keyup
$('input').keyup(function() {
delay(function(){
alert('Time elapsed!');
}, 1000 );
});

Related

Need to be able to run an ajax call with element loaded after document.ready()

I've got checkbox inputs on a page and am filtering the results using ajax.
One search option is type and the vendors option updates depending on the type selected. But this means that the change function used to update the actual results no longer works within the document.ready(). To rectify this, I also call the function within .ajaxComplete().
But as an ajax call is being called within the ajaxComplete(), it is causing an infinite loop and crashing the site.
$(document).ready(function(){
$('input[type=radio]').change(function(){
var type = $(this).attr('data-id');
$.ajax({
method: 'POST',
url: 'assets/ajax/update-filters.php',
data: {type : type},
success: function(data)
{
$('#vendor-filter input[type=checkbox]').prop('checked', false);
vendors = [];
$('#vendor-filter').empty();
$('#vendor-filter').html(data);
}
});
$('#vendor-filter input[type=checkbox]').change(function(){
filterResults(this);
});
});
$(document).ajaxComplete(function(){
$('#vendor-filter input[type=checkbox]').click(function(){
filterResults(this);
});
});
function filterResults($this)
{
var type = $('input[type=radio]:checked').attr("data-id");
var vendor = $($this).attr('data-id');
if($($this).prop('checked'))
{
var action = 'add';
vendors.push(vendor);
}
else
{
var action = 'remove';
var index = vendors.indexOf(vendor);
if(index >= 0)
{
vendors.splice(index, 1);
}
}
$.ajax({
method: 'POST',
url: 'assets/ajax/filter-results.php',
data: {'vendor' : vendor, 'action' : action, 'vendors' : vendors, 'filter_type' : type},
success: function(data)
{
$('#results').empty();
if(action == 'add')
{
window.history.pushState("", "Title", window.location.href+"&v[]="+vendor);
}
else if(action == 'remove')
{
var newUrl = window.location.href.replace("&v[]="+vendor, "");
window.history.replaceState("", "Title", newUrl);
}
$('#results').html(data);
}
});
}
How do I get the .change function to still work after the input checkbox has been called via ajax previously and without causing a loop with .ajaxComplete() ?
Any help would be greatly appreciated.
Thanks
Please try by change function as follow :
$(document.body).on("change",'input[type=radio]',function(){
var type = $(this).attr('data-id');
$.ajax({
method: 'POST',
url: 'assets/ajax/update-filters.php',
data: {type : type},
success: function(data)
{
$('#vendor-filter input[type=checkbox]').prop('checked', false);
vendors = [];
$('#vendor-filter').empty();
$('#vendor-filter').html(data);
}
});

How to refresh the page with updated data when click update button

function update(){
var name= document.getElementById("TextBox").value;
$.ajax({
url: '....',
type: 'post',
data: {....//many data include// 'name' : name, ....},
success: function(data) {
var replacevalue=data.replace(/[\[\]']/g,'' );
alert(replacevalue);
var stringstatus=replacevalue.replace(/['"]+/g, '');
alert(stringstatus);
if(stringstatus == "success"){
alert ("Successfully Update ")
}
else{
alert("Failed!");
return ;
}
returnToDisplayPage();
},
error: function(xhr, desc, err) {
console.log(xhr);
console.log("Details: " + desc + "\nError:" + err);
}
});
}
function returnToDisplayPage(){
var id = document.getElementById("TextBox").text;
window.location = './DisplayPage.php?Name='+id;
}
Please suggest me. How should I do to get the updated data when click update button and refresh or reload page ? In function returnToDisplayPage() methods. I got only the name of update data and other related fields data didn't get back.
Try something like this:
$.post('url', {params}, function(response){
//Here you check if you got response from url
// And then you can do whatever you like to do with received data
if(response == 'ok'){
//do your stuff
//then
window.location.reload();
}
}
When we will get result in response then After 5 seconds page will be refresh..
success: function(data){
if(data.success == true){ // if true (1)
setTimeout(function(){// wait for 5 secs(2)
location.reload(); // then reload the page.(3)
}, 5000);
}
}

Reduce number of ajax calls in instant search

I am trying to make an instant search drop down for my site. All work fine, except for this.
var timeOut;
$('#search input[name=\'search\']').on('keyup', function(e) {
// If enter - submit the search field
if (e.keyCode == 13) {
$('header input[name=\'search\']').parent().find('button').trigger('click');
}
// Call only when length is at least 2 and the key pressed is alphanumeric
else if ($('#search input[name=\'search\']').val().length>2 && ((e.keyCode>=65 && e.keyCode<=90) || (e.keyCode>=97 && e.keyCode<=122))) {
timeOut = null;
//alert(timeOut);
if (!timeOut) {
timeOut = setTimeout(function() {
$.ajax({
url: 'ajax.php',
type: 'post',
async: false,
data: 'ACTION=SEARCH&search='+$('#search input[name=\'search\']').val(),
dataType: 'json',
beforeSend: function() {
$('#loader-icon').show();
},
complete: function() {
$('#loader-icon').hide();
},
success: function(json) {
//$('.product-list-row').html(json);
$('#search-listing').html(json['html']);
},
error: function(xhr, ajaxOptions, thrownError) {
alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
timeOut = null;
}, 500);
}
}
});
Problem 1: My script ends up making too many calls to the server, for some reason setTimeOut isn't working as I expected it to. Ajax call should only be made when the user has done typing or something like that and not at every key press.
Problem 2: For some reason when I type fast the input bar doesn't get edited. The ajax however works, but with the last textual input.
Instead of trying to tackle this with setTimeout, you can abort the previous call using the jqXHR object returned by the AJAX. It is more clean and simple to use this. Remove async: false, too.
var timeOut;
var xhr;
$('#search input[name=\'search\']').on('keyup', function(e) {
// If enter - submit the search field
if (e.keyCode == 13) {
$('header input[name=\'search\']').parent().find('button').trigger('click');
}
// Call only when length is at least 2 and the key pressed is alphanumeric
else if ($('#search input[name=\'search\']').val().length>2 && ((e.keyCode>=65 && e.keyCode<=90) || (e.keyCode>=97 && e.keyCode<=122))) {
if(xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: 'ajax.php',
type: 'post',
data: 'ACTION=SEARCH&search='+$('#search input[name=\'search\']').val(),
dataType: 'json',
beforeSend: function() {
$('#loader-icon').show();
},
complete: function() {
$('#loader-icon').hide();
},
success: function(json) {
//$('.product-list-row').html(json);
$('#search-listing').html(json['html']);
},
error: function(xhr, ajaxOptions, thrownError) {
alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
}
});
The right solution is combination of both, abort running request, if new one should be made, and also, tackle firing of the new request. You can use underscore library, which has nice function for that, called debounce (see http://underscorejs.org/#debounce) and your code should looks like this:
// This is your xhr, each request save into this
// variable, in order to be able to abort it if needed
var xhr;
// Wrap your event handler using the debounce function
$("#search").on("keyup", _.debounce(function(e) {
// Abort running request
if(xhr) {
xhr.abort();
xhr = null;
}
// Store the new request
xhr = $.ajax({
// Search for the term $(this).val()
});
},500));
There is no need to fire the search for each keyup, but only when user stopped typing - debounce will do it for you. And there is no need to handle previous results if the request should be made.

how to handle encoding while sending value via ajax

In wordpress, i am making an ajax call and sending this value
blow = \'blo\
But when i receive the value at the server end it has one \ extra
blow = \\'blo\
As you can see a \ is extra. I used urldecode but it is also giving me the same result
Please help me to find out what i am doing wrong
this is my script here are i serialize the form and in form i place in a text box blow = \'blo\
jQuery.ajax({
type: 'POST',
beforeSend: function () {
var Container = jQuery("#mainContainer");
var height = Container.height();
var width = Container.width();
jQuery('#le_form_container').css("display", "none");
Container.append('<div class="loadingOverlay" style="width: 100%; height: 100%;" ><img class="ajaxLoading" src="' + url + '/leasson_Evalution/images/ajax_loader_blue_512.gif" /></div>');
},
url: ajaxcontactajax.ajaxurl,
data: {
action: 'ajaxcontact_send_mail',
values: jQuery('#le_form').serialize().replace(/\+/g, '%20')
},
success: function (data, textStatus, XMLHttpRequest) {
//console.log(data);
if (data == 0) {
jQuery("#le_SucessDialog").html('');
jQuery('#le_SucessDialog').append("<p>Data is Submited</p>"); //alert(data is );
jQuery("#le_SucessDialog").dialog({
draggable: true
});
//console.log("tenp");
jQuery("#le_form")[0].reset();
//console.log("tenp");
}
//console.log(data);
},
error: function (MLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
},
complete: function () {
jQuery('#le_form_container').css("display","block");
jQuery("#mainContainer").find(".loadingOverlay").hide().remove();
jQuery("#le_form")[0].reset();
}
});}
Use stripslashes:
$values = stripslashes($_POST["values"]);
Try this : reset your variable with the escape
escape(blow)

Why trigger and click do not work in this case?

I have a piece of code that does:
$('td.unique').live('click', function () {
//function logic here
});
This works fine on I click on the td of my table. All fine!
Now I would like to be able to have the same functionality programatically in certain cases without the user actually pressing click.
I have tried:
$(document).ready(function() {
$(".clearButton").click( function () {
var username = $(this).closest('tr').find('input[type="hidden"][name="uname"]').val();
var user_id = $(this).closest('tr').find('label').val();
var input = [];
input[0] = {action:'reset', id:user_id,user:username,};
$.ajax({
url: 'updateprofile.html',
data:{'user_options':JSON.stringify(input)},
type: 'POST',
dataType: 'json',
success: function (res) {
if (res.status >= 1) {
//all ok
console.log("ALL OK");
$(this).closest('tr').find('.unique').trigger('click');
$(this).closest('tr').find('td.unique').trigger('click');
$(this).closest('tr').find('td.unique').click();
}
else {
alert('failed');
}
}
});
This button is in the same row that the td.unique is
None of these work. Why? Am I doing it wrong? Is the function that I have bind in live not taken into account when I click this way?
You need to cache the $(this) inside the ajax function.
var $this = $(this);
the $(this) inside the ajax function will not refer to the element that is clicked
$(".clearButton").click(function () {
var $this = $(this);
var username = $this.closest('tr').find('input[type="hidden"][name="uname"]').val();
var user_id = $this.closest('tr').find('label').val();
var input = [];
input[0] = {
action: 'reset',
id: user_id,
user: username,
};
$.ajax({
url: 'updateprofile.html',
data: {
'user_options': JSON.stringify(input)
},
type: 'POST',
dataType: 'json',
success: function (res) {
if (res.status >= 1) {
console.log("ALL OK");
$this.closest('tr').find('.unique').trigger('click');
$this.closest('tr').find('td.unique').trigger('click');
$this.closest('tr').find('td.unique').click();
} else {
alert('failed');
}
}
});
});

Categories

Resources