0

So far I use this to call the function:

 document.getElementById("dzCalculator").addEventListener("keydown", isNumberKey);
   function isNumberKey(txt, evt) {
      let charCode = (evt.which) ? evt.which : evt.keyCode;
      if (charCode == 46) {
          evt.preventDefault();
        //Check if the text already contains the . character
        if (txt.value.indexOf('.') === -1) {
          return true;
        } else {
          return false;
        }
      } else {
        if (charCode > 31 &&
          (charCode < 48 || charCode > 57))
          return false;
      }
      return true;
    }

But unfortunately I get errors: Uncaught TypeError: evt is undefined

I am still very much in the learning phase, so I am not seeing what I am missing yet. Thanks very much for your help.

Paul Davis
  • 495
  • 4
  • 14

2 Answers2

2

The addEventListener passes only the event that triggered it to the passed callback so in your case txt is holding the event and evt is undefined.

You can extract the txt value of the input by using evt.target.value.

document.getElementById("dzCalculator").addEventListener("keydown", isNumberKey);
   function isNumberKey(evt) {
      let txt = evt.target.value;

      //...

As for the rest of your logic, there are some good answers already available:

HTML text input allow only numeric input


Since you are still looking for a solution to limit input I will offer this. Instead of controlling the keys allowed, you can validate the value after keyup. Using an input listener we can watch for changes and validate without seeing invalid characters show while also solving the overarching problem of maintaining expected functionality and accessibility without having to specify all key responses.

This snippet listens for changes using input. When triggered it extracts the current value using event.target.value and stores the current cursor position. It then recasts the string to an array using destructuring [...value]. This array is then filtered using filter()so that it only contains characters that appear in the validKeys string. It is then reduced back to a string using reduce() at which time it accounts for duplicate decimal points. If the resulting editedValue is different than the initial value the evt.target.value is updated and the cursor is set back to where it was (minus one because we have removed a character);

document.getElementById("dzCalculator").addEventListener("input", isNumberKey);

function isNumberKey(evt) {
  const validKeys = '1234567890.';
  
  const cursorLocation = evt.target.selectionStart;
  const value = evt.target.value;
  
  let editedValue = [...value]
    .filter(char => validKeys.includes(char))
    .reduce((acc, char) => { return acc.includes('.') && char === '.' ? acc : acc + char}, '');
    
  if (editedValue !== value) {
    evt.target.value = editedValue;
    evt.target.selectionStart = cursorLocation-1;
    evt.target.selectionEnd = cursorLocation-1;
  }
}
<input id="dzCalculator" value="" />

To accomodate negative values you can adjust validKeys and the reduce() callback thus:

const validKeys = '-1234567890.';
  let editedValue = [...value]
    .filter(char => validKeys.includes(char))
    .reduce((acc, char, i) => { 
        if (acc.includes('.') && char === '.' || char === '-' && i !== 0) {
        return acc
      } else {
        return acc + char
      }
    }, '');
pilchard
  • 12,414
  • 5
  • 11
  • 23
  • ok, I did this but it prevents "." (decimal points) – Paul Davis Sep 13 '20 at 09:56
  • Yes, the rest of your logic is in need of work `.which()` and `.keyCode()` are both deprecated. You might want to look at using [Number Input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) – pilchard Sep 13 '20 at 10:38
  • I am taking a look at Number Input, that's interesting. Seems like a lot more work and I am not 100% sure I understand it yet. – Paul Davis Sep 13 '20 at 12:02
  • This is why I don't use that logic https://gyazo.com/793135b22aee23ad2d9077a586ced7f9 - and ironically, it is Firefox that is the fault! Otherwise I would. But maybe I will try and break into the warning box and fix it so it doesn't float and then use this undeprecated method that Firefox is not fixing! – Paul Davis Sep 13 '20 at 12:05
  • @PaulDavis I believe my last edits provide a solution to the entirety of your question. – pilchard Sep 13 '20 at 17:50
  • Thanks - your way does appear to work, but (I know, I can not win here) I can't seem to get the submit button to work now. *sigh* it never ends :P If you know what I could be doing to prevent the submit button working, I would love to know! – Paul Davis Sep 13 '20 at 18:51
  • I fixed the code to work... but... even though I can submit, it submits no matter what is in the input. :( – Paul Davis Sep 13 '20 at 18:56
0

I have written pretty simple logic to allow only numerical input and restrict inputs with one dot only.

document.getElementById("dzCalculator").addEventListener("keydown", isNumberKey);

function isNumberKey(evt) {
  let passCode = '0123456789.'
    if (passCode.indexOf(evt.key)===-1 && evt.key !=='Backspace' && evt.key !== 'Tab'&&
  evt.key !=='Delete'){
  evt.preventDefault();
  return false;
  }else{
  //contains numbers && dots
    if (evt.target.value.indexOf('.') >= 0 && (evt.key === ".")) {
      //check for multiple dots
      evt.preventDefault();
      return false;
    } else
      return true;
  }
}
<input id='dzCalculator' type='text'>
sandeep joshi
  • 1,991
  • 1
  • 8
  • 13
  • Thank you for this... this is perfect, but I am crying because: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode keyCode is deprecated and so I am not meant to use it :( I feel a bit stuck! – Paul Davis Sep 13 '20 at 13:46
  • Unfortunately this blocks all other key functionality including Backspace, Delete and Tab (necessary for accessibility). – pilchard Sep 13 '20 at 13:47
  • How do you get it so that backspace, delete and tab are ok to use? – Paul Davis Sep 13 '20 at 13:59
  • I have updated my code (assuming that your target browsers supports key and not keyCode). it allows delete backspace keys and numbers with one dot. i wonder why you want tab inside this as well since tab will shift focus to next element/control. – sandeep joshi Sep 13 '20 at 14:09
  • or you can merge my both solution in one like Mozilla documentation says to provide backward compatibility. – sandeep joshi Sep 13 '20 at 14:13
  • The problem is, once you start controlling key input you need to control **ALL** key input in order to maintain expected functionality and accessibility. Your edited code now accommodates the three keys I mentioned, but I can't use arrow keys to reposition the cursor, nor can I copy or paste, etc. etc. – pilchard Sep 13 '20 at 14:14
  • yes but the question is to restrict key input apart from certain specific keys. for copy paste and navigation you always have mouse/right click. I am assuming user does have a mouse :) and restricting user on pasting invalid is another different question. – sandeep joshi Sep 13 '20 at 14:21
  • You should not assume that the user has a mouse, this is also the reason to never restrict `Tab` as it is a primary, non-mouse navigation key. – pilchard Sep 13 '20 at 14:48