-1

I asked a question How to fire Ajax request after user inactivity in 1.5 seconds on how to update user data after user has finished typing instead on every key up, the I was referred to a post where they recommended using javascript debounce, which I love How to implement debounce fn into jQuery keyup event? but I can't seem to find a way to implement it into my code, this is what the solution I was referred to said I should do

 $('input').keyup(debounce(function(){
 var $this=$(this);
 //alert( $this.val() );
 var n1 = $this.val();
 var n2 = $('#n2').val();
 var n3 = $('#n3').val();
 var calc = n1 * n2 * n3;
 alert(calc);
 },500));

my function works perfectly but I dont want it running every time, so I don't know how to implement debounce in this case, this is the code that I want to add debounce to

//cart.php

<input type="text" class="count_cart content_to_cart oninput qty-remove-defaults" onkeyup="setcart(this)" onkeydown="autoSave(this)" id="updates_486" >

function autoSave(e){ //JS where I want to implement debounce    
setTimeout(function(){
var getsizes_response = $(e).attr("id");
var getsave_response_quantity = $("#"+getsizes_response).val();
$.ajax({
type: "POST",
url: "functions.php",
data: {getsizes_response: getsizes_response, getsave_response_quantity: getsave_response_quantity},
cache: false,
timeout: 5000,
success: function(r){   
$("#ajax_responses_get_positioner").show(); 
$("#ajax_responses_get_positioner").html(r);
},
error: function(){      
$("#ajax_responses_get_positioner").show(); 
$("#ajax_responses_get").html("Error saving order, please reload page and try again."); 
$("#ajax_responses_get").css({'background': 'red', 'display': 'block'});
$("#ajax_responses_get_positioner").delay(6000).fadeOut("fast");
}
}); 
}, 1500);   
} 
Shasha
  • 439
  • 8
  • 26

2 Answers2

2

Debounce takes a function as an argument, and returns a function (the debounced version of the original function). Functions that do this are called "higher order functions". In the first example, the function isn't named, and it is passed directly to debounce as soon as it is created. In the second example, you've named the function autosave (which is a great thing to do), but it doesn't make it any harder. All you have to do is call debounce before using your function name. So when you use it on keyup:

$('input').keyup(debounce(autoSave, 500))

If you wanted to always debounce autosave, you could save the debounced function to the variable autoSave, so after that point, it is always debounced. (Or you could use a different name - up to you).

autoSave = debounce(autoSave, 500)

$('input').keyup(autoSave)

Re-assigning a decorated function to the original function name is called "decorating", and the higher order function is called the decorator. Some languages provide a special syntax for this, and javascript is considering adding one as well:

@debounce(500)
function autoSave() { … }

That would do the same as the previous example: call debounce with autoSave and then assign it to autoSave. However, if you want to do that today, you need to use babel or typescript and the right plugins.

Garrett Motzner
  • 3,021
  • 1
  • 13
  • 30
  • Thanks for your answr but, I can't seem to understand how to implement it into the function, I have editted my code. – Shasha May 04 '20 at 20:51
  • what exactly in my answer do you not understand? – Garrett Motzner May 04 '20 at 21:00
  • the input you are using is from the answer that was given to be from my previoous question, I edited the my question code with my own input type which has keydown-autosave() calling autosave function, I want to use the autosave function to fire ajax, please look at my question again, – Shasha May 04 '20 at 21:08
  • I believe I _have_ answered your question: "All you have to do is call debounce before using your function name." Does this not help? Why? – Garrett Motzner May 04 '20 at 21:10
  • Ok letme try that. – Shasha May 04 '20 at 21:11
  • Also, did you mean to say that you would rather use http attributes to bind the `keyup` event rather than using jquery? If that's the case, then sure, do that. It doesn't really change my answer, but it prevents you from copy and pasting my example :). However, it's [better to not use html attributes to bind javascript](https://stackoverflow.com/questions/11737873/why-are-inline-event-handler-attributes-a-bad-idea-in-modern-semantic-html) – Garrett Motzner May 04 '20 at 21:16
  • thanks, learnt something new today, let me edit my code to fit. – Shasha May 04 '20 at 21:31
0

After help from garrett motzner, I figured it out.

<input type="text" class="count_cart autow content_to_cart oninput qty-remove-defaults" onkeyup="setcart(this)" id="updates_486" >

$('.autow').keydown(debounce(function(){
var qthis=$(this);  
var getsizes_response = $(qthis).attr("id");
var getsave_response_quantity = $("#"+getsizes_response).val();
$.ajax({
type: "POST",
url: "functions.php",
data: {getsizes_response: getsizes_response, getsave_response_quantity: getsave_response_quantity},
cache: false,
timeout: 5000,
success: function(r){   
$("#ajax_responses_get_positioner").show(); 
$("#ajax_responses_get_positioner").html(r);
},
error: function(){      
$("#ajax_responses_get_positioner").show(); 
$("#ajax_responses_get").html("Error saving order, please reload page and try again."); 
$("#ajax_responses_get").css({'background': 'red', 'display': 'block'});
$("#ajax_responses_get_positioner").delay(6000).fadeOut("fast");
}
});
},500));

function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};

This allows it to call only once, after user finish typing.

Shasha
  • 439
  • 8
  • 26