My problem is so simple and yet, i can’t figure out what going on.
My scenario:
- Vanilla JS and HTML
- A text input has an onChange event for validation. Every time you press a key a regex analises it and if its an special char it makes the input invalid.
- Regex:
/[!@#$%^&*()_+-=[]{};':"\|,.<>/?~]/g
And the snippet below:
const noSymbolsRegex = /[`!@#$%^&*()_+-=[]{};':"\|,.<>/?~]/g;
const onChange = (event) => {
const value = event.target.value;
const hasError = noSymbolsRegex.test(value);
console.log(
`Value => ${value} n Has forbidden symblos ? ${hasError ? "YES" : "NO"}`
);
if (hasError) {
console.log("<< == hasError");
document.querySelector("#my-test-input").dataset.valid = "false";
} else {
document.querySelector("#my-test-input").dataset.valid = "true";
console.log("<< == DOES NOT haveError");
}
};
const input = document.querySelector("#my-test-input");
input?.addEventListener("keyup", onChange);
input[data-valid="false"] {
background-color: red;
}
input[data-valid="true"] {
background-color: green;
}
<label for="test">Test input</label>
<input name="test " type="text" id="my-test-input" data-valid="true">
Expected behavior
Every time you insert a special char the regex must test it and return if its valid.
Actual behavior
- Randomly, but specially if you enter many special chars and then begins to erase them, regex test the input and returns that it haven’t the special chars.
- Pressing special keys like Control or Alt toggle the valid/invalid state.
I suppose the problem is the regex but i don’t understand why it works only some times
2
Answers
Yes, problem is in regex
You can try below regex
This is a refactored regex, and no need for the global flag with test().
Edit 3/10/23, using the global flag
//g
in test() and exec() JS functions sets the regex objectslastindex
member to the last matched position.Thats why the repeated runs of this regex cause it to flip flop the match
from the strings beginning, to the strings end where one matched and the other didn’t.
Works but your onChange event handler doesn’t seem to get called on a paste from context menu.
If doing keystrokes ctrl-v works fine. But if from the context menu, doesn’t get called.
Extra info
[!-/:-@[-`{-~]
matches these 32 codepoints!"#$%&'()*+,-./:;<=>?@[]^_`{|}~
These codepoints correspond to
[x21-x7e](?<![^W_])
as well.Info on JS lastindex regex member can be founh here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex
Excerpt: