0

So I have a function, that is called "inGame()" and right after creating the function I let JavaScript create a button with the onClick-Event "inGame()". But when I click the button the console tells me

Uncaught ReferenceError: inGame is not defined at HTMLButtonElement.onclick (index.html:1)

(index.html:1 is <!DOCTYPE html> ...)

This is the code I am working with:

var i = 0;
function inGame() {
    try {
        removeElement("nextPlayer");
    } catch (e) {/*First time the function gets called -> Button doesn't exist yet*/}
    
    document.getElementById("title").innerText = players[i] + " ist dran!"; //Just a title, don't worry
    rollDice(i);
    i++;
    if (i == players.length) {i = 0;}
}

inGame();
setTimeout(addElement("game", "button", "nextPlayer", "Nächster Spieler"), 2000);
setTimeout(document.getElementById("nextPlayer").classList.add("btn"), 2000);
setTimeout(document.getElementById("nextPlayer").classList.add("btn-success"), 2000);
setTimeout(document.getElementById("nextPlayer").setAttribute("onClick", "inGame()"), 2000);

BTW: The reason I am not using a for-loop but a function is, that I want the loop to wait until a button is pressed to continue with the next round.

EDIT: Some general information about the code. I am using the standard html-Framework Visual Studio Code gives you, when you type an exclamation-mark into an emtpy HTML-file and press enter.

The script is in the head-tag, I also tried to put it in the body but nothing changed.

I am using a Button-Tag (<button>) since Bootstrap used a button-tag in it's examples. I changed it to a div but it didn't change anything so I am back at a button.

It's not the first time in the code where I add the onClick-event via attributes. addElement("content", "button", "Play", "Spielen"); document.getElementById("Play").setAttribute("onclick", "Play()");

This is the addElement-Function:

function addElement(parentId, elementTag, elementId, html) {/*CODE*/}
Contrean
  • 64
  • 7
  • The function doesn't exist, or it's not a global function at the time you're calling it (when clicking on a button). Why is that can't be explained based on the provided example. We need to know how and where the JS is loaded to the document. – Teemu Jul 04 '20 at 20:07
  • @Teemu I added some information to the Question, see "EDIT: Some general information about the code" – Contrean Jul 05 '20 at 06:29

3 Answers3

1

are you using any framework?? one solution is to put your script inside the body.

but this works fine, see this:

var i = 0;
function inGame() {
    try {
      document.getElementById("title").innerText = " ist dran!"; 
    } catch (e) {/*First time the function gets called -> Button doesn't exist yet*/}
    
}

  setTimeout(document.getElementById("myButton").setAttribute("onClick", "inGame()"), 2000);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

</head>
<body>
      <h1 id="title">nothing</h1>

    <input type="button" value="do somthing" id="myButton">
</body>
</html>
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I am using the standard html frame around it but the button doesn't exist from beginning and is created by JavaScript. I am using a button-tag since Bootstrap uses button-tags in its examples. – Contrean Jul 05 '20 at 06:09
0

The reason this doesn't work, is that onClick is not an attribute, but rather an event listener.

Just use addEventListener() for the onClick-event (https://www.w3schools.com/jsref/met_element_addeventlistener.asp)

Also: Just check whether the element exists instead of using try/catch.

genius42
  • 243
  • 1
  • 6
  • Can you explain this answer with more details. As it is, it doesn't answer the question, and also doesn't make any sense. – Teemu Jul 04 '20 at 20:13
  • Sure. Instead of using "setAttribute" in the last line of the snippet "addEventListener" should be used: document.getElementById("nextPlayer").addEventListener("click", inGame) Reason is that you want to register an event-listener that handles the onClick-event and not just add an attribute. – genius42 Jul 04 '20 at 20:26
  • Any reason why setting the attribute wouldn't work? I'm not saying it's a good practice, but that code works as it is, only that JS can't find `inGame` function ... – Teemu Jul 04 '20 at 20:29
  • Hm, thats true. I just did not thought about this, as I never saw a click-listener added like this and my mind was like: "That's the mistake." – genius42 Jul 04 '20 at 20:36
0

I fixed the Problem:

The function I called was created in another function. I don't know why that is a problem to JavaScript or HTML but after I moved the declaration of the function outside the other function everything worked!

Still thanks for all your answers, I actually learned new stuff by that :)

Contrean
  • 64
  • 7
  • An inline listener in HTML can find only global functions (see my [first comment](https://stackoverflow.com/questions/62733835/javascript-html-not-finding-a-function-onclick-event/62733891#comment110938261_62733835) on the question). See also https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript – Teemu Jul 06 '20 at 16:57
  • Ah now I see it, I didn't know what you meant by that while reading and then forgot about it but still thanks :) – Contrean Jul 06 '20 at 18:50