JS Regex allowing incorrect characters

I have a comments field for SEPA payments and such a field has the following restrictions when it comes to what a user can type:

a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
/ – ? : ( ) . , ‘ +
Space

So I have this function to simply block the users input when it is not allowed:

    $('.no_special_chars').keypress(function (e) {          
        var regex = new RegExp("^[a-zA-Z0-9\/\-\?\:\(\)\.\,\'\+\\s]+?$");
        console.log(String.fromCharCode(!e.charCode ? e.which : e.charCode));
        var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);

        // Allow tab, left/right arrow, backspace and delete. Then proceed to validation
        if (e.keyCode == 9 || e.keyCode == 37 || e.keyCode == 39 || e.keyCode == 8 || e.keyCode == 46) {
            return true;
        }

        // Do not allow returns in the comment field
        if (e.keyCode == 13) {
            return false;
        }

        if (regex.test(str)) {
            return true;
        }

        return false;
    });

However, I notice that Chrome for example also allows the following characters: % = < > And Firefox accepts all of these as well, minus the %.

What am I doing wrong and why do these browsers respond differently?

Answers:

Answer

The problem is due to the way you declared the regex via a RegExp constructor. The hyphen should be escaped twice to be treated as a literal hyphen there.

This is the range it allowed:

enter image description here

It is advised to use a literal notation when your regex is known from the start, and best practice is to use the hyphen at the end of the character class range in order to avoid escaping it.

To match 0 or more characters in your range, you need to use

var regex = /^[a-z0-9\/?:().,\'+\s-]*$/i;

See this demo fiddle

If you plan to match at least 1 (or more), keep your +? (or +, it will work the same way in your case) quantifier.

$('.no_special_chars').keypress(function (e) {   
  var regex = /^[a-z0-9\/?:().,\'+\s-]*$/i;
  console.log(String.fromCharCode(!e.charCode ? e.which : e.charCode));
  var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);

  // Allow tab, left/right arrow, backspace and delete. Then proceed to validation
  if (e.keyCode == 9 || e.keyCode == 37 || e.keyCode == 39 || e.keyCode == 8 || e.keyCode == 46) {
     return true;
  }

  // Do not allow returns in the comment field
  if (e.keyCode == 13) {
     return false;
  }

  if (regex.test(str)) {
     return true;
  }

  return false;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="no_special_chars">
<input type="text" class="form-control" id="id_number" name="id_number" maxlength="20" required>
</div>

Answer

There are a couple of issues at work here. After escaping, your actual string is the following (you can confirm with console.log(regex);)

/^[a-zA-Z0-9\/-?:().,'+\s]+?$/

Notice that /-? is actually a valid range! This includes the characters from key code / (47) to ? (63), which includes /0123456789:;<=>?. You need to escape the hyphen -, but because you are working inside of a string which also has escaping rules, you need to "escape the escaper" with a double \\, like this:

"^[a-zA-Z0-9/\\-?:().,'+]+?$"
             ^^ string-escaped \

Secondly, your check for keyCode = 37 is what is allowing the % in Chrome. In Chrome the arrow keys, backspace, etc. are still allowed even if you remove that portion of the code entirely, so you don't even need to check those keyCodes. However, in FireFox that code is working as expected.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.