Search code examples
jqueryfunctioncalling-convention

Function in jQuery no longer works when called


I wrote a jQuery function that calculates the total for dynamic divs. When I execute the function directly in the event handler, it works fine:

$(document).on('keyup', '.priceText:not(:last)', function() {
var total = 0;
$(this).each(function() {
        if ((this.value) != '') {
            total += parseFloat(this.value);
        }
    }
)
if (isNaN(total) == false) {
    $('#total-price').html(total);
}
else {
    total = 0;
}
});

However, if I try to run the same function by calling it, it no longer works properly:

function calcTotal(pricesToAdd, divToUpdate) {
var total = 0;
$(pricesToAdd).each(function() {
        if ((pricesToAdd.value) != '') {
            total += parseFloat(pricesToAdd.value);
        }
    }
)
if (isNaN(total) == false) {
    $(divToUpdate).html(total);
}
else {
    total = 0;
}
}

$(document).on('keyup', '.priceText:not(:last)', function() {
calcTotal(this, '#total-price');
});

Am I missing something?


Solution

  • You have 2 issues

    1. this line: calcTotal(this, '#total-price'); . this in this context is the element that triggered the keyup event not the collection matched by '.priceText:not(:last)'. Change your code to pass the whole collection like this: calcTotal($('.priceText:not(:last)'), $('#total-price'));
    2. this bit $(pricesToAdd).each(function() { if ((pricesToAdd.value) != '') you're attempting to loop over a collection but inside the loop you're referring to the collection again and not the object at the current index.

    Also, I would pass the objects themselves to the function instead of just the selectors, just my preference though.

    Here is an example:

    function calcTotal(pricesToAdd, divToUpdate) {
        var total = 0;
        pricesToAdd.each(function (e,thisPrice) { // reference the element you iterate
            if ((thisPrice.value) != '') { // work with the current price
                total += parseFloat(thisPrice.value);
            }
        })
        if (isNaN(total) == false) {
           divToUpdate.html(total);
        } else {
            total = 0; 
        }
    }
    
    $(document).on('keyup', '.priceText:not(:last)', function () {
        // calcTotal(this, '#total-price'); // this was only sending the clicked element not the collection
         calcTotal($('.priceText:not(:last)'), $('#total-price')); // Pass the whole matched collection instead
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <input type="text" class="priceText">
    <br>
    <input type="text" class="priceText">
    <br>
    <input type="text" class="priceText">
    <br>
    <input type="text" class="priceText">
    <span id="total-price"></span>