Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Advice on refactoring jQuery snippet

Hello!

I've created the following jQuery snippet for one of my Woocommerce sites. Essentially, I implemented a custom quantity selector display and this jQuery function enables the quantity to behave accordingly ('+' for increasing and '-' for decreasing). Even though it works, I feel that it could be done in a much neater and 'DRY' way.

Appreciate any inputs!

var $         = jQuery.noConflict();
var qtyInput  = $('input.qty');
var qtyAdd    = $('.quantity__spin-button-plus');
var qtyRemove = $('.quantity__spin-button-minus');

qtyAdd.each(function() {
    $(this).on('click', function() {
        var qty = $(this).siblings('input').val();
        qty++;
        $(this).siblings(qtyInput).val(qty);

        //trigger 'change' to enable 'update cart' button in cart page
        qtyInput.trigger('change');
    })
});

qtyRemove.each(function() {
    $(this).on('click', function() {
        var qty = $(this).siblings('input').val();
        if ( qty != 1 ) {
            qty--;
            $(this).siblings(qtyInput).val(qty);
        }
        $(this).siblings(qtyInput).val(qty);

        //trigger 'change' to enable 'update cart' button in cart page
        qtyInput.trigger('change');
    })
});

2 Answers

Steven Parker
Steven Parker
229,788 Points

You could have all the buttons use the same handler, and have the handler perform a function based on the class of the event target:

function handleClick(e) {
    var qty = $(this).siblings('input').val();
    if ($(this).hasClass("quantity__spin-button-minus"))
        if ( qty > 1 ) qty--;
    else if ($(this).hasClass("quantity__spin-button-plus"))
        qty++;
    $(this).siblings(qtyInput).val(qty);

    //trigger 'change' to enable 'update cart' button in cart page
    qtyInput.change{);
}

qtyAdd.click(handleClick);    // no "foreach" needed with jQuery
qtyRemove.click(handleClick);

Also, depending on how the HTML is organized, this could probably be implemeted as a designated handler.

Thanks Steven! Ive actually thought of this method as well. However I feel that doing a conditional check based on class name is a little unreliable as class names tend to change.

This is what I came up with:

/* METHODS */
function handleClick(e) {

    var qty = $(this).siblings('input').val();

    if ( e.data.quantity_selector == 'remove' ) { 
        if ( qty > 1 ) {
            qty--;  
        }
    }
    else if ( e.data.quantity_selector == 'add' ) {
        qty++;
    }
    $(this).siblings(qtyInput).val(qty);

    //trigger 'change' to enable 'update cart' button in cart page
    qtyInput.change();

}

qtyAdd.on('click', { quantity_selector: 'add'  }, handleClick);
qtyRemove.on('click', { quantity_selector: 'remove' }, handleClick);

I decided to utilise the 'data' argument in the on() method and then do a conditional check based on the event.data.quantity_selector value.

What do you think about this?

Steven Parker
Steven Parker
229,788 Points

I'm not sure what you mean by "class names tend to change". What would change them?

Hmm maybe it's just me. I sometimes have the habit of changing the way I name things. In my case, I would then have to change the classnames in multiple places for your snippet to work.

Also, what you do mean by 'designated handler'?

Thanks for your input so far. Appreciate it!

Steven Parker
Steven Parker
229,788 Points

A "designated handler" is one that is attached to a parent element, but intended to service events generated by child elements which propagate ("bubble up") to the parent. This allows a single handler to deal with multiple elements, including any that are created after the handler is established.