Detecting keypress inside a function not working

53 views Asked by At

I'm trying to make a calculator that calculates slope from two points. I couldn't figure out how to clear text from one text input box, so I have four text input boxes but just one showing at a time. After pressing enter,the y1 function is called. Once you press enter again, the y1 function should call the x2 function, but it doesn't. I used console.log to figure out that the y1 function isn't detecting the keypress. I copy-pasted the detect keypress code from Stack Overflow and I don't really understand it that well, so that might be part of it.

I tried getting rid of the function and moving the y1 code directly inside the if statement of the x1 part, but that didn't work either. Here is the HTML:

 <p id="prompt">Loading...</p> <input type="text" id="input"> <input type="text" id="input2"> <input type="text" id="input3"> <input type="text" id="input4">

and here is the Javascript:

var x4 = document.getElementById('input4');
  x4.style.display = "none";
  var x3 = document.getElementById('input3');
  x3.style.display = "none";
  var x2 = document.getElementById('input2');
  x2.style.display = "none";
  var x = document.getElementById('input');
  x.style.display = "inline";

   document.getElementById("prompt").innerHTML = ("Please Enter x1");

   const x1 = document.getElementById('input');
   x1.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
    y1()
     }
   });
    
   function y1() {
   document.getElementById('prompt').innerHTML = ("Please Enter y1");
    x.style.display = "none";
    x2.style.display = "inline";
      const y1 = document.getElementById('input2');
   x1.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
    x2()
     }
   });
   }
      function x2() {
   document.getElementById('prompt').innerHTML = ("Please Enter x2");
    x2.style.display = "none";
    x3.style.display = "inline";
    const x2 = document.getElementById('input3');
    x2.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
    y2()
     }
   });
   }
      function y2() {
   document.getElementById('prompt').innerHTML = ("Please Enter y1");
    x3.style.display = "none";
    x4.style.display = "inline";
      const y2 = document.getElementById('input4');
   y2.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
    x3.style.display = "none"
    document.getElementById('prompt').innerHTML = ("Loading");
     }
   });
   
   }

I keep finding things that say I should use jquery but I don't know much about it and would prefer not to.

2

There are 2 answers

0
FurtiveStranger On

Avoid naming your variables and functions the same. In the future, post the error messages you encountered

const x1 = document.getElementById('input'); // already store under variable "x"
   x1.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
    y1()
     }
   });

const x1 = document.getElementById('input'); - no need to store it again, just use x.addEventListener('keydown'....

    function y1() {
        document.getElementById("prompt").innerHTML = "Please Enter y1";
        x.style.display = "none";
        x2.style.display = "inline";
        const y1 = document.getElementById("input2");
        x1.addEventListener("keydown", (e) => { // you didn't add event listener to y1, but to x1 that's it doesn't call it after you press enter
            if (e.key === "Enter") {
                x2();
            }
        });
    }

On function y1

x1.addEventListener("keydown", (e) => { - you didn't add event listener to y1, but to x1 that's it doesn't call it after you press enter

0
atteggiani On

If you are ok with having 4 different boxes, you could implement something like this (it is only an idea):

DEMO:

//JS
calcSlope();
function setInputFilter(textbox, inputFilter, errMsg) {
  ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout"].forEach(function(event) {
    textbox.addEventListener(event, function(e) {
      if (inputFilter(this.value)) {
        // Accepted value
        if (["keydown","mousedown","focusout"].indexOf(e.type) >= 0){
          this.classList.remove("input-error");
          this.setCustomValidity("");
        }
        this.oldValue = this.value;
        this.oldSelectionStart = this.selectionStart;
        this.oldSelectionEnd = this.selectionEnd;
      } else if (this.hasOwnProperty("oldValue")) {
        // Rejected value - restore the previous one
        this.classList.add("input-error");
        this.setCustomValidity(errMsg);
        this.reportValidity();
        this.value = this.oldValue;
        this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
      } else {
        // Rejected value - nothing to restore
        this.value = "";
      }
    });
  });
}

function calcSlope() {
  x1=document.getElementById("x1").value
  x2=document.getElementById("x2").value
  y1=document.getElementById("y1").value
  y2=document.getElementById("y2").value
  if ([x1,x2,y1,y2].some(p => p === '')) {
    slope = "NaN"
  } else {
    slope = (y2 - y1)/(x2 - x1)
  }
  document.getElementById("slope").innerHTML = slope
}

document.querySelectorAll("input").forEach(inp => {
  setInputFilter(inp, value => {
    return /^-?\d*\.?\d*$/.test(value);
  },
  "Must be a floating (real) number (floating points added with '.')"
  )
})
/*CSS*/
input {
  margin: 1em 0.5em 1em 0;
}
<!--HTML-->
<div>SLOPE CALCULATOR</div>
<p id="prompt">Please insert points P1(x1,y1) and P2(x2,y2):</p> 
<div>
  <div>P1</div>
  <label for="x1">x1:</label>
  <input type="text" id="x1" onkeyup="calcSlope()">
  <label for="y1">y1:</label>
  <input type="text" id="y1" onkeyup="calcSlope()">
</div>
<div>
  <div>P2</div>
  <label for="x2">x2:</label>
  <input type="text" id="x2" onkeyup="calcSlope()">
  <label for="y2">y2:</label>
  <input type="text" id="y2" onkeyup="calcSlope()">
</div>
<div>SLOPE: <span id="slope"></span></div>

The JavaScript function to check for input and allow only float numbers (which I believe is what you want) is extrapolated from this answer: https://stackoverflow.com/a/469362/21024780