0

I have a form which has input fields that expect numbers only.

I'm using javascript to validate the form when the value of the field changes. If the value is numeric, do nothing.

If the value is not numeric, set it to zero and put focus in that text field. Essentially, I'm trying to trap the cursor in that field until a numeric value is entered. For some unknown reason, focus is not being placed on that form element. cell.focus() does not work. I've even tried document.getElementById(cel.getAttribute("ID")).focus(); What might I be doing wrong?

<html>        
<head>
    <script>
        function NAN(cell){
          if (cell.value != "") {
              var re = /^(0|[1-9][0-9]*)$/;
               if (re.test(cell.value) == false) {
                 alert('You must supply a numeric value greater than 0.');
                 cell.value = "0";
             cell.focus();

           }
          }
        }
    </script>
</head>

<body>
<input type="text" name="num" value="" onchange="NAN(cell)"/>
</body>
</html>
Michael Lihs
  • 7,460
  • 17
  • 52
  • 85

2 Answers2

1

There are two things done:

  • You have to change cell to this with onchange.
  • According to this question at least with Firefox setTimeout has to wrap this focus-method so that it works as expected.

And a more user-friendly approach is inserted as well at the second input-field.

Hope this example helps you:

function NAN(cell) {
  if (cell.value != '') {
    var re = /^(0|[1-9][0-9]*)$/;
    cell.value = cell.value[0]=='0'?+cell.value:cell.value;
    if (re.test(cell.value) == false) {
      alert('You must supply a numeric value greater than 0.');
      cell.value = '0';
      setTimeout(function () { 
        cell.select();
        cell.focus();
      }, 0); 
    }
  }
}

/*
* a more user friendly approach
*/
function NAN2(cell) {
  if (cell.value != '') {
    var re = /^(0|[1-9][0-9]*)$/;
    cell.value = cell.value[0]=='0'?+cell.value:cell.value;
    if (re.test(cell.value) == false) {
      alert('You must supply a numeric value greater than 0.');
      cell.value = '0';
      setTimeout(function () { 
        cell.select();
        cell.focus();
        markElement(cell);
      }, 0); 
    }
    else{
        tickElement(cell);  
    }
  }
}

function tickElement(cell){
  cell.setAttribute('style','border: 1px solid green');   
}

function markElement(cell){
  cell.setAttribute('style','border: 1px solid red');   
}
<p>
  Your approach(onchange): 
  <input type="text" name="num" value="" onchange="NAN(this)"/>
</p>

<p>
  Or you can use a more user friendly approach to notify an user right now when they are tipping something wrong (onkeyup):
  <input type="text" name="num" value="" onkeyup="NAN2(this)"/>
  
</p>
Community
  • 1
  • 1
Blauharley
  • 4,186
  • 6
  • 28
  • 47
  • Now focus works as well. Please have a look on this answer. And tell me whether it is what you want. – Blauharley Jan 27 '17 at 21:39
  • Supplying an integer value like 01, 02 etc fails. Please verify. – JGV Jan 27 '17 at 21:47
  • 1
    @VimalanJayaGanesh: You are right. I've adapted my code accordingly. Thanks. – Blauharley Jan 27 '17 at 21:51
  • Yes, this is what I want. I did not understand why cell.focus() was not placing focus. I've used it many times before. I did not know that I needed to add cell.select() before calling focus(). Why I need to select the cell first, I do not know, but it works and I am happy. As far as this being a client side script, I will test the value on the server and if it is not a number, not try to insert it into an integer field in my database. That's what caused the error in the first place. Someone tried to enter '1 or 2' instead of a number. – RCDAWebmaster2 Jan 30 '17 at 15:41
  • Its kind of practise to use cell.select() cell.focus() in combination, you could also use cell.focsu() alone. If you accept this answer to be right, then please tick it to make it explicitly. – Blauharley Jan 30 '17 at 15:48
1

Your problem is in the onchange attribute:

<input type="text" name="num" value="" onchange="NAN(cell)"/>

The value is executed as JavaScript code directly. You're passing code, not just a generic signature or prototype.

Inside those event handler snippets, there's a special object this defined, referring to the current DOM element (the input tag in this example).

(Just to mention it, there is also a second predefined object event, which most likely caused your confusion.)

As a simple fix for your issue, replace cell with this in the call and it should work:

<input type="text" name="num" value="" onchange="NAN(this)"/>

It's also important to note that you should keep in mind that this verification requires JavaScript to be executed. If it's disabled, the user might still pass any values, so you should check the value server side as well (assuming this isn't just client-only code).

As an alternative to using JavaScript, you could just use HTML5 to force a specific pattern on inputs. In this case this would be trivial to do:

<input type="text" name="num" value="" pattern="(?!0)\d+" title="Quantity">

The user won't be able to submit the form unless the pattern is validated, so there's no need to force the input focus. The pattern always has to match the full value, from beginning to the end. The title attribute is typically used to provide more information in the error popup.

Mario
  • 35,726
  • 5
  • 62
  • 78
  • I would even mark your answer as right, but form-patterns are supported by IE 11 that is still too high. I can not wait until this day comes :) – Blauharley Jan 27 '17 at 22:04