1

I get the following error and I can't find why:

TypeError: object is not a function

Here is my html:

<td><input type="text" value="" id="cash_retained" name="cash_retained" onkeyup="net_cash()" size="25"></td>
<td><input type="text" value="" id="cash_change" name="cash_change" onkeyup="net_cash()" size="25"></td>
<td><input type="text" value="0" id="net_cash" name="net_cash"></td>

Here is my js function:

function net_cash() {
    var cash = 0;
    var retained = document.getElementById("cash_retained");
    var change = document.getElementById("cash_change");

    cash += parseInt(retained.value);
    cash += parseInt(change.value);

    if (isNaN(cash)) {
        document.getElementById("net_cash").value = "0";
    } else {
        document.getElementById("net_cash").value = cash;
    }
}

I can't see for the life of me why this is not working. I have other similar js functions that are finding it just fine.

j0k
  • 22,600
  • 28
  • 79
  • 90
Amy Neville
  • 10,067
  • 13
  • 58
  • 94

2 Answers2

9

It appears the problem here is that you have a form element with the same name as your function:

<td><input type="text" value="0" id="net_cash" name="net_cash"></td>

So when you call net_cash() in your onkeyup event, it thinks you are referring to this input DOM object rather than the function of the same name. I suggest coming up with separate names for these two things.

Inline event handlers have the enclosing <form> element as their executing scope. Each form control with a name attribute is treated as though it's a variable in that scope and that's where the conflict comes from.

This is also yet another great reason to use unobtrusive JavaScript instead of inline event handlers. If you do that, you don't have to worry about your function names conflicting with your element names. See onclick=“” vs event handler for more information on the pitfalls of using inline event handlers.

Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • 2
    @eicto: The `window` object is *ridiculously* crowded. That's why I avoid creating *any* globals in my code if I can help it; the markup creates enough of them as it is. – T.J. Crowder Jan 20 '13 at 09:55
  • I'd expected the function declaration to shadow this element-name-as-global-variable quirks? – Bergi Jan 20 '13 at 09:57
  • @T.J.Crowder same here, but still wow :) where that documented ? – zb' Jan 20 '13 at 09:57
  • @eicto: There was a [`window` object spec](http://www.w3.org/TR/Window/) being worked on for a while, but it was abandoned in favor of [this section of the HTML5 spec](http://www.w3.org/TR/html5/browsers.html#window). This part of it is in [§5.2.4](http://www.w3.org/TR/html5/browsers.html#named-access-on-the-window-object). – T.J. Crowder Jan 20 '13 at 10:02
  • 1
    @eicto A bit of a clarification (20 months late): the name isn't added to `window.var`. What's happening here is that inline event handlers are executed in a certain scope where all of the containing `form`'s named elements exist as variables. The `net_cash()` function is in the global scope, so that's why the `net_cash` element supercedes (hides) it. – JLRishe Sep 01 '14 at 05:33
2

Your code is working fine for me. See demo here

So make sure of the following

  1. Make sure that you are including the script before calling the function.
  2. Also, it is not a good idea to keep the ids/names and function names same

    <td><input type="text" value="0" id="net_cash" name="net_cash"></td>
    

    // Change the idand name here

Wolf
  • 2,150
  • 1
  • 15
  • 11
  • Your demo works, and this would have been my answer too. But at the same time, @JLRishe is right too. The JavaScript DOM is really an enigma... – Manuel Leuenberger Jan 20 '13 at 10:03
  • Yea.. +1 for JLRishe... I just mentioned that they are repeating.. I didn't think this will create an issue, since I never faced it. :) Thanks... – Wolf Jan 20 '13 at 10:05