0

I'm very new to JavaScript and I'm having a hard time understanding why my code is coming back as undefined. I also can't seem to get the dropdown to function as it should.

My CodePen: https://codepen.io/TiffSmith126/pen/KKZxdma

Problem 1) When I move the variable for the dropdown to above window.firstFunction instead of placing it below window.firstFunction and above window.secondFunction, window.secondFunction becomes undefined. I would like to know what's wrong and why this keeps happening in my code even though the function is defined.

Problem 2) This is my first time creating a dropdown and it's not working as desired. I would like it to select an option and have it display one of two results of the first function. For example, in my code the two results are item1 and item2. I want my user to be able to select which item they want.

const fruits = ["apple", "orange", "banana"];
const vegetables = ["carrot", "corn", "kale"];
const subjects = ["math", "science", "reading", "writing"];

let item1;
let item2;

var menu = document.getElementById("dropdown");
menu.addEventListener("change", firstFunction());
if (menu.value == "1") {
  void 0;
} else if (menu.value == "2") {
  document.getElementById("instance").innerHTML = item1;
} else if (menu.value == "3") {
  document.getElementById("instance").innerHTML = item2;
}

window.firstFunction = function () {
  var ranFruit = Math.floor(Math.random() * 3);
  var ranVegetable = Math.floor(Math.random() * 3);
  let bowl = [];
  let plate = [];

  var situation1 =
    "some text " +
    fruits[ranFruit] +
    "some more text " +
    vegetables[ranVegetable];
  bowl.push(situation1);

  var situation2 =
    "some text " +
    fruits[ranFruit] +
    "some more text" +
    vegetables[ranVegetable];
  plate.push(situation2);

  var situation3 =
    "some text " +
    fruits[ranFruit] +
    "some more text" +
    vegetables[ranVegetable];
  bowl.push(situation3);

  var situation4 =
    "some text " +
    fruits[ranFruit] +
    "some more text" +
    vegetables[ranVegetable];
  plate.push(situation4);

  var ranBowls = Math.floor(Math.random() * 2);
  var ranPlates = Math.floor(Math.random() * 2);

  var item1 = bowl[ranBowls];
  var item2 = plate[ranPlates];
};

firstFunction();

window.secondFunction = function () {
  var ranSubject = Math.floor(Math.random() * 4);
  var sentence =
    "some more text" + subjects[ranSubject] + "even more great text";
  document.getElementById("sentence").innerHTML = sentence;
};
secondFunction();
<head>
  <title>Generator</title>

  <head>
    <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
  </head>

<body>
  <div class="generator-container">
    <div class="title">Generator
    </div>

    <div class="container-one">
      <span>Details</span>
      <select id="dropdown">
        <option value="1">Select</option>
        <option value="2">Bowls</option>
        <option value="3">Plates</option>
      </select>
      <button type="button" onclick="firstFunction()">Generate<i class=" fa fa-generate" aria-hidden="true"></i></button>
      <br>
      <span id='instance'></span>
    </div>
    <div class="container-two"><span>Additional Data</span>
      <button type="button" onclick="secondFunction()">Generate<i class=" fa fa-generate" aria-hidden="true"></i></button>
      <br>
      <span>Subject Sentence:</span>
      <br>
      <span id="sentence"></span><br><br>
    </div>
</body>
  • 1
    `menu.addEventListener("change", firstFunction());` (which by the way should be `menu.addEventListener("change", firstFunction);`) is clearly not going to work if you execute that before `firstFunction` has been defined as a function, so in your code it needs to be below the definition of `window.firstFunction = ...`. Note that had you defined this as `function firstFunction() {...}` then the positions would not matter (if you fix the `addEventListener` call as I pointed out above) due to what is known as "hoisting". You should prefer this anyway to making the function global via `window`. – Robin Zigmond Apr 12 '22 at 19:18
  • 2
    Change `window.firstFunction = function. . . ` (a function expression) to `function firstFunction(){. . .}` (a function declaration) and then the declaration will be hoisted to the top of the enclosing scope and you'll be able to reference it correctly. Also, when assigning a callback function, don't include `()` as this will invoke the function right there instead of just referencing it. – Scott Marcus Apr 12 '22 at 19:34

1 Answers1

0

Since JavaScript is an script language & is run in order it does not know about functions that it hasn't read yet.

Your calling firstFunction before it is defined when you add the listener to the menu.
Moving

menu.addEventListener("change", firstFunction());

to the end makes it work

const fruits = ["apple", "orange", "banana"];
const vegetables = ["carrot", "corn", "kale"];
const subjects = ["math", "science", "reading", "writing"];

let item1;
let item2;

var menu = document.getElementById("dropdown");
if (menu.value == "1") {
  void 0;
} else if (menu.value == "2") {
  document.getElementById("instance").innerHTML = item1;
} else if (menu.value == "3") {
  document.getElementById("instance").innerHTML = item2;
}


window.firstFunction = function () {
  var ranFruit = Math.floor(Math.random() * 3);
  var ranVegetable = Math.floor(Math.random() * 3);
  let bowl = [];
  let plate = [];

  var situation1 =
    "some text " +
    fruits[ranFruit] +
    "some more text " +
    vegetables[ranVegetable];
  bowl.push(situation1);

  var situation2 =
    "some text " +
    fruits[ranFruit] +
    "some more text" +
    vegetables[ranVegetable];
  plate.push(situation2);

  var situation3 =
    "some text " +
    fruits[ranFruit] +
    "some more text" +
    vegetables[ranVegetable];
  bowl.push(situation3);

  var situation4 =
    "some text " +
    fruits[ranFruit] +
    "some more text" +
    vegetables[ranVegetable];
  plate.push(situation4);

  var ranBowls = Math.floor(Math.random() * 2);
  var ranPlates = Math.floor(Math.random() * 2);

  var item1 = bowl[ranBowls];
  var item2 = plate[ranPlates];
};

firstFunction();


window.secondFunction = function () {
  var ranSubject = Math.floor(Math.random() * 4);
  var sentence =
    "some more text " + subjects[ranSubject] + " even more great text";
  document.getElementById("sentence").innerHTML = sentence;
};

secondFunction();
menu.addEventListener("change", firstFunction());
Cheshiremoe
  • 792
  • 1
  • 5
  • 14