1

I'm a Java programmer trying to write a little javaScript. Bear with me.

I would like a function that updates a total when a digit is entered in any one of the input fields in a table. I have the following line in $(document).ready(function() { ... }

$("#lineCountTable").find('input').each().bind('keyup', function() { 
    updateTotal(this); 
});

In Chrome's debug screen, I get:

Uncaught TypeError: cannot read property 'call' of undefined". The line number pointed to is jQuery-1.8.2.js:611.

I figure I have a syntax error in defining the function to be called. The updateTotal(inputVar) function is duly defined later in the JS file; in case someone's interested, it is:

function updateTotal(inputVar) {
    var row = inputVar.closest('tr');
    var lineCharge = row.find("dlsRowCharge").html().trim();
    var total = 0.0
    var lineCount = inputVar.val();
    if (isNumeric(lineCount)) {
        total = math.abs(lineCount * lineCharge).toFixed(2);
        row.children(".dlsRowTotal").html("$ " + total);
    }
}

I know these functions are usually put inline; I would rather define them separately and call them, unless that's impossible.

8
  • 3
    Remove the empty each() and use on() instead of bind() Commented Oct 20, 2016 at 10:14
  • 1
    Function parameter to $.fn.each() is mandatory and anyway, just using .each() doesn't make sense Commented Oct 20, 2016 at 10:16
  • 1
    @arcy Ya, like most prototype jQuery method, it internally loops through matched set Commented Oct 20, 2016 at 10:17
  • 1
    Also, this will be a DOM Element which you can't call closest() on - you need to wrap it in a jQuery object. Your find() selector also is incorrect, presumably it needs a . class prefix Commented Oct 20, 2016 at 10:22
  • 1
    @RoryMcCrossan On some browsers, you can but you are right, obviously not what OP was expecting (because then he calls find()/html()/val()) Commented Oct 20, 2016 at 10:24

1 Answer 1

3

You have a few issues here:

  • each() requires a handler function and is the cause of your error. That said, it's not needed in this instance.
  • you should use on() over bind() since jQuery 1.7.
  • this will be a DOM Element which you cannot call jQuery's closest() method on. Admittedly there is a native closest() method, but it's not well supported yet. For the code to work reliably you need to wrap this in a jQuery object.
  • find() requires a valid selector, which dlsRowCharge is not. Presumably this should be .dlsRowCharge
  • math should be Math

With all that said, try this:

$("#lineCountTable").find('input').on('keyup', function() { 
    updateTotal($(this)); 
});

function updateTotal($inputVar) {
    var $row = $inputVar.closest('tr');
    var lineCharge = $row.find("dlsRowCharge").html().trim();
    var lineCount = parseFloat($inputVar.val()) || 0;
    var total = Math.abs(lineCount * lineCharge).toFixed(2);
    $row.children('.dlsRowTotal').html('$ ' + total);
}
Sign up to request clarification or add additional context in comments.

4 Comments

What a nice full answer -- wish clicking the upvote button worked more than once. Thanks. I'm afraid I don't know what 'wrap this in a jQuery object" means, but will assume it's embodied in your example.
ah, almost certainly the $() around 'this' in the call. I'll really have to sit down with a jQuery book since the job is otherwise good and I keep being expected to do these things...
If you get a chance, have a quick scan through the method list of jQuery: api.jquery.com. Even if you don't go in to detail, just the names of the methods give you a clue about what can be done.
To nitpick - the lineCharge should be handled the same way as lineCount. As such it can be a number, non-number string and empty - so the values it will have will be: float, NaN or 0. Also, the OP's check if the value of total is a number should be kept, but per isNaN (currently - user puts in the value "a" in input box, total evaluates to "NaN"; ideally it should present some kind of message). It can also be handled if input is of number type, which is more elegant I guess

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.