I have a checkout I’m playing with which has some up and down arrows next to the quantity input of each item.
I have some repeated code and it doesn’t seem that efficient. Hopefully you can help.
Each item looks something like this (please excuse my non-standard-conforming item_id attribute for now)
<div class="qty_ctrl_wrap">
<input class="bag_qty" type="text" value="4" item_id="532" name="product_quantity">
<div class="arrows">
<div class="more"></div>
<div class="less"></div>
</div>
</div>
Here’s the full jquery function:
$('#checkout .arrows div').live('click',function(){
var item_id = $(this).parent().prev('input').attr('item_id');
var current_qty = $(this).parent().prev('input').val();
if($(this).attr('class') == 'more') {
var new_qty = parseInt(current_qty) + 1;
} else {
var new_qty = parseInt(current_qty) - 1;
}
// change the input on screen for visual reasons...
$(this).parent().prev('input').val(new_qty);
// submit the changes
$.ajax({
type: 'POST',
url: '/backend/product_purchase_items.php',
data: 'qty='+new_qty+'&item_id='+item_id,
cache: false,
success: function(data) {
$('#product_purchase_items').html(data);
}
});
});
As you can see, I’m repeating the following thing 3 times:
$(this).parent().prev('input')
I’ve been trying to work out how to put that in a variable so I don’t have to repeat that code.
But in addition to that, the way this works is that if you hit the arrow 3 times, it does 3 seperate ajax posts. Ideally there would be a slight pause before sending the post.
How does one make a pause of say 300 milliseconds to see if there are further clicks of the arrows before submitting the post?
You can use
setTimeoutto debounce the event:Things that changed/should be considered:
Caching
$(this).parent().prev('input')in a variable to not traverse the DOM every time to find the same element again.Passing a function to
.val()[docs] and update the value “in one go”.Using unary
+to convert a string to a number, instead ofparseInt. If you useparseInt, you have to pass the radix as second parameter (in your case10), to prevent JS from interpreting numbers with leading zeroes as octal numbers.Using
.hasClass()[docs] instead of comparing theclassattribute. If the element has more than one class, the comparison will fail.Setting an object as value of the
dataoption instead of a string. This ensures that the data is properly encoded.You really should use HTML5 data attributes instead of custom attributes (
item_id). Even if the browser does not support HTML5 (yet), this is the safer way. With jQuery, you can even access them via the.data()method.Using
setTimeout[MDN] to delay the Ajax call and storing a reference to the timer ID in.data()[docs]. When the handler is rapidly executed, a previous timer will be cancelled withclearTimeout[MDN], to prevent too many Ajax requests.