3

So I had this button element that would refuse to fire its onclick() function whatever I did and it drove me crazy for a while :

<button type="button" id="newTreatment" name="newTreatment" onclick="newTreatment()" >Add a treatment</button>

I ended up simply changing the name of the function and it worked immediatly :

<button type="button" id="newTreatment" name="newTreatment" onclick="addTreatment()" >Add a treatment</button>

I've since then tested it on several other buttons and I've had similar issues all the time.

So is this really what's happening? The onclick() function can't have the same name as the id if its element? Why is that? I've tried looking for this online but I couldn't find any information about it.

CoqPwner
  • 913
  • 1
  • 11
  • 24

2 Answers2

6

Assuming you have your elements wrapped in a form, this happens because named elements are added as properties to the form.

When you were trying to call newTreatement, there already existed a property newTreatment in that scope. It thought you were referring to the property and gave you an error of

newTreatment is not a function

See Why JS function name conflicts with element ID? and Do DOM tree elements with ids become global variables?

Community
  • 1
  • 1
AmmarCSE
  • 30,079
  • 5
  • 45
  • 53
6

Inline event handlers are magical (i.e. not intuitive).

The properties of the enclosing <form> element are in scope of the inline event handlers. And since the name of each form control element becomes a property of the form element, using such a name inside the event handler will refer to the element instead.

The scope chain of the inline event handler is roughly:

Global scope / properties of window
^
|
Properties of document (e.g. body)
^
|
Properties of enclosing form (e.g. newTreatment or submit)
^
|
Properties of <button id="newTreatment" /> (e.g. type, onclick)
^
|
Function scope of inline event handler

Bindings in closer scopes (e.g. the form) shadow bindings in higher scopes, e.g. the global scope.

A simple solution would be explicitly refer to the global variable via window.newTreatment.

I described this in more detail here.

This seems to be formalized in the HTML5 spec.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143