Event Handler Function Runs Without Condition Met

Hi all,

I’m trying to assign an event handler to a button, but for some reason it always fires immediately when the page loads – even though the button hasn’t been pressed. I can get it to “work” if I put the event handler directly into the HTML, ie:

 <button onclick="myFunction()">

But that’s going to become really unwieldy if I want multiple different things to happen depending on different events.

Here’s my HTML:

<!DOCTYPE html>
<html>

<header>
<title>Webpage!</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="main.css">
</header>

<body onload="main()">

<div class="center">
<input class="inputBox" id="inputBox" type="text" placeholder="Enter words here!"></input>
<button id="button">Button!</button>
</div>

<script src="script.js"></script>
</body>

</html>

Here’s my JS:

  function main(){
  console.log("Main function loaded!");
  var inputBox = document.getElementById("inputBox");
  var button = document.getElementById("button");
  button.onpress = myFunction(inputBox.id);
}

function myFunction(x){
  console.log("My function called!");
  console.log("Arg passed is:",x);
  document.getElementById(x).style.background = "yellow";
  document.getElementById(x).value="Function has fired!";
}

I don’t have anything to back this up, but my feeling is that you shouldn’t be setting the onpress attribute in the JS, but rather using JS to add an event listener. I think there’s something weird (I don’t quite know) about buttons and all that that makes it so they run once on load or something… please someone correct me if I’m wrong.

anyway, I would change it to:

button.addEventListener(“click”, myfunction(inputBox.id);

Don’t think anything else would need to be changed.

Link to w3schools with syntax rules for event listeners. The syntax for your event handler on the button is correct. The syntax for the event listener in your javascript is not.

function main() {
  // some code
  button.onpress = myFunction( inputBox.id ); // this is calling the function myFunction with inputBox.id            
}

You just need to assign the function to the event listener not call it.

 button.onpress = myFunction;

@gtrabbit - Tried giving that a go, but it unfortunately seems to be doing the same thing with an event listener. Here’s a plnkr link of what the code currently looks like, with the eventListner and button.onpress options:

http://plnkr.co/edit/TgZOR9?p=preview

@Reggie01 - I tried changing the code to your suggestion (see plnkr link above), but when the button is pressed, nothing happens. I think because I designed the function to work with any element that it is called on, (ie, it needs an argument passed to it to do something with) and does not exclusively execute on one thing like the W3 schools examples.

I also noticed that the W3 schools example use inline script tags at the bottom of their examples, does pointing to an external script have ~any~ differences? I thought they were the same.

Line 15 of your script.js should be:

button.addEventListener("click", myFunction.bind(null, inputBox['id']));
2 Likes

That works! I’m a bit confused about how bind is solving the problem and why null is used as the “thisArg” param noted in the MDN documentation here: https://mzl.la/2kdDZz8 .

As best I understand: Your statement adds an event listener to the button variable that waits for a click, when one happens, myFunction is called with a .bind wrapper that has a “this” bound to the inputBox.id

Am I roughly correct?

why null is used as the “thisArg”

. https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#binding-exceptions

Your statement adds an event listener to the button variable that waits for a click, when one happens, myFunction is called with a .bind wrapper that has a “this” bound to the inputBox.id

bind creates a copy of the original function with preset arguments (in this case inputBox.id) and when it gets called it executes that function with that argument.

We don’t care about this in this example.

1 Like