Allow only regex pattern in javascript - javascript

I want the user to input a number with format:
##/####
Where the "#" are numbers.
Here is the sample code:
(function() {
var previousValue = document.getElementById('myInput').value;
var pattern = /^\d{2}(\/\d{4})?$/;
function validateInput(event) {
event = event || window.event;
var newValue = event.target.value || '';
if (newValue.match(pattern)) {
// Valid input; update previousValue:
previousValue = newValue;
} else {
// Invalid input; reset field value:
event.target.value = previousValue;
}
}
document.getElementById('myInput').onkeyup = validateInput;
}());
<input id="myInput" type="text" maxlength=7 value="" />
I can only write the first two numbers, but I can't type anything else after that, even though the regular expression seems correct to me.
---EDIT---
After all the answers, I want to point out that I already have a validator that fires on the submit, which tells the user if they have typed in the correct form; I just wanted to somehow "guide" the user in the typing of the input.

Use this var pattern = /^\d{0,2}(\/\d{0,4})?$/; when user is typing which basically allow to type the pattern you want. And when input become blur check length of input field and validate accordingly.(or you can use minlength(make it equal to maxlength) if you are using input field in form then you will not require blur method)
(function() {
var previousValue = document.getElementById('myInput').value;
var pattern = /^\d{0,2}(\/\d{0,4})?$/;
function validateInput(event) {
len = event.target.value.length;
event = event || window.event;
var newValue = event.target.value || '';
if (newValue.match(pattern)) {
// Valid input; update previousValue:
previousValue = newValue;
} else {
// Invalid input; reset field value:
event.target.value = previousValue;
}
}
document.getElementById('myInput').onkeyup = validateInput;
}());
(function() {
function validateInput(event) {
len = event.target.value.length;
(len===7) ? console.log("Success") : console.log("fail");
}
document.getElementById('myInput').onblur = validateInput;
}());
<input id="myInput" type="text" milength=7 maxlength=7 value="" />
<button>1</button>

Probably you want to allow regex to validate correct when the user is still not finished with writing it down.
var pattern = /^\d{0,2}(\/\d{0,4})?$/;
But you would still need to validate it after that, so onblur check might be better.

First of all, you can analyze your regex here.
You will find that your regex:
/^\d{2}\/\d{4}?$/
matches a string that begins with two digits, followed by a slash and then 4 digits repeated zero or one time (the question mark).
Just remove the question mark in order to match the exact pattern.

From my point of view your problem is in event that you handle. Onkeyup fired after any key up. And if the current value of input field is not matched with your pattern you replace it with old one value. I think you need to handle change event instead of keyup: codepen

To me, your approach of validating seems wrong! You have to wait to do the validation until the user blurs away from the input field.
What I am suggesting is to use the event onblur instead of onkeyup, to perform your validation. How can you validate an input which is not completed?
Or else, you could program the event onkeypress, to check the key which is struck is one you need. You will have to deal with key codes and all.
EDIT
Managed to tackle the problem! Check if the following helps.
(function() {
var previousValue = document.getElementById('myInput').value;
function validateInput(event) {
event = event || window.event;
var newValue = event.target.value || '';
var previousValueLength = document.getElementById('myInput').value.length;
var pattern = /^\d{2}\/\d{4}$/;
switch(previousValueLength){
case 0:
pattern = /^$/;
break;
case 1:
pattern = /^\d{1}$/;
break;
case 2:
pattern = /^\d{2}$/;
break;
case 3:
pattern = /^\d{2}\/$/;
break;
case 4:
pattern = /^\d{2}\/\d{1}$/;
break;
case 5:
pattern = /^\d{2}\/\d{2}$/;
break;
case 6:
pattern = /^\d{2}\/\d{3}$/;
break;
}
if (newValue.match(pattern)) {
// Valid input; update previousValue:
previousValue = newValue;
} else {
// Invalid input; reset field value:
event.target.value = previousValue;
}
}
document.getElementById('myInput').onkeyup = validateInput;
}());
https://jsfiddle.net/zjg6azjn/9/

Related

Force first letter uppercase in input field

I'm practicing some JavaScript and would love to hear your thoughts regarding this script I wrote. I've managed to make this work. The script makes the first letter of the input value uppercase using the script below. I'm just wondering if this is a good method of doing this/if my steps are in good order just to get better
love to hear more ways of doing so, even making an option to eliminate the caps-lock via keyboard thanks,
// my input var
var strInput =document.querySelector("#inputText > input");
// my function and eventlistener
strInput.addEventListener('input',function() {
//upper case first letter with concatenate string input
var outputString = strInput.value.charAt(0).toUpperCase() + strInput.value.slice(1);
this.value = outputString;
});
As in the comments requested
Here is an example to bind the event to ALL text-inputs (except <textarea> and contenteditable="true")
var txtInputs = document.querySelectorAll("input[type='text'");
//just a simple validation if its not null, undefined or empty
if (txtInputs && txtInputs.length > 0) {
for (var i = 0; i < txtInputs.length; i++) {
var txtInput = txtInputs[i];
txtInput.addEventListener('input', function() {
var outputString = this.value.charAt(0).toUpperCase() + this.value.slice(1);
});
}

jquery run conditional validation inside .on

I have a form with the ID #primarySearch. It has 3 text inputs, all of which have their own ID as follows: #ecNumber, #casNumber, #substanceName.
I have the following js. If the user enters anything in a text input in #primarySearch it runs a function called processPrimarySearch and sends the appropriate input value to it:
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
// Ignore tab key
if (e.which != 9) {
processPrimarySearch.call(this);
}
}
});
function processPrimarySearch() {
// ...
}
I've also got some other js (which is just inside document.ready) which stops the user entering anything other than numbers and dashes - but only in the #ecNumber and #casNumber fields (please note I adapted this from jQuery only allow numbers,letters and hyphens). Although this code fires if the user is entering things into these 2 fields, it also results in processPrimarySearch running irrespective of whether the user input is valid. This is because there is no connection between the code above, and the following code:
$('#ecNumber, #casNumber').keypress(function (e) {
var allowedChars = new RegExp("^[0-9\-]+$");
var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
if (allowedChars.test(str)) {
return true;
}
e.preventDefault();
return false;
}).keyup(function() {
// the addition, which will check the value after a keyup (triggered by Ctrl+V)
// We take the same regex as for allowedChars, but we add ^ after the first bracket : it means "all character BUT these"
var forbiddenChars = new RegExp("[^0-9\-]", 'g');
if (forbiddenChars.test($(this).val())) {
$(this).val($(this).val().replace(forbiddenChars, ''));
}
});
The result of what's happening at the moment is that if a character was entered such as "z" in #ecNumber, the validation regex code will fire and stop the character "z" appearing in the input - good. However, processPrimarySearch() will also fire because it's defined inside the .on for any input in the #primarySearch form.
My problem:
What I want to do is run the validation regex inside my .on but only if it's the #ecNumber or #casNumber fields (#substanceName must not be validated here).
I've managed to write the following which uses an array to say which field the user is entering input on. Where I'm doing the console.log is where I need the validation regex to occur
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
// Ignore tab key
if (e.which != 9) {
var arr = ["ecNumber", "casNumber"];
if ($.inArray($(this).attr('id'), arr)!== -1) {
console.log($(this).attr('id'));
}
processPrimarySearch.call(this);
}
}
});
What is the best way to do this? I'm unsure whether to move the code which does the regex into a function, and then call it (with .call?) or some other method? And are there any issues with this being asynchronous in nature?
It's all about program flow and how you want to handle it. Your problem is not really an async problem in the last way that you presented your code. Here is one solution (of many possible ones). I put some comments in the code to explain the basics.
$('#primarySearch input[type="text"]').on({
"keyup": function(e) {
// if this is not the tab key and the input contains valid characters
if (e.which != 9 && isThisValid($(this), e)) {
processPrimarySearch.call(this);
}
else {
e.preventDefault();
}
}
});
function isThisValid($elem, event) {
var ids = ["ecNumber", "casNumber"], // ids to validate, everything else is valid
result = true; // default result
// is this one of the id's to validate?
if(ids.indexOf($elem.attr('id')) !== -1) {
// do some validation
var allowedChars = new RegExp("^[0-9\-]+$"),
str = String.fromCharCode(!event.charCode ? event.which : event.charCode);
// is it valid?
if (!allowedChars.test(str)) {
result = false;
}
}
return result;
}
function processPrimarySearch() {
// ...
}

should not allow more than one space in between words

function stripspaces(input)
{
input.value = input.value.replace(/\s+/gi," ");
}
I written this function. It is working but when I point the mouse pointer or moving with left arrow in between word and giving space it is jumping to the last. Can anyone give me the solution?
You can prevent the input by calling e.preventingDefault we can simply test if the space key has been pressed and if there's a space either side of the cursor then prevent entry.
document.addEventListener('DOMContentLoaded', function() {
var input = document.getElementById('myInput');
input.addEventListener('keydown', function(e){
var input = e.target;
var val = input.value;
var end = input.selectionEnd;
if(e.keyCode == 32 && (val[end - 1] == " " || val[end] == " ")) {
e.preventDefault();
return false;
}
});
});
<input type="text" id="myInput">
This still has the issue that it won't prevent pastes into the box with double spaces. So it may be worth still replacing multiple spaces on focus loss to be sure that the input never contains multiple contiguous spaces.
I just came across the same use case. If you also want to handle copy/paste or any other way the input's value could change, use the input event:
document.addEventListener('DOMContentLoaded', function() {
// get a reference to the input element
const input = document.querySelector('#myInput');
// guard clause to check if `#myInput' actually exists in the current DOM
if(!input) return
// Run this every time the input's value changes
input.addEventListener('input', e => {
// get the value
const value = e.target.value
// check if the value isn't exactly ' ' and ends with a space
const hasTrailingSpace = value !== ' ' && value.charAt(value.length-1) === ' '
// extract words, remove empty words (handles double spaces)
const words = value.split(' ').filter(el => el !== '')
// create the sanitized value
let sanitizedValue = words.join(' ')
// add a trailing space if there was one
if( hasTrailingSpace ) sanitizedValue += ' '
// apply the sanitized value to the input's value
e.target.value = sanitizedValue
})
})
<p>Try inserting double spaces now! Also try copy/paste from somewhere else</p>
<input type="text" id="myInput">

Validate email as you type

I want to validate input as I type so I use onkeyup event to do so, but if I validate an email regex "name#domain.com", as soon as user starts to type it throws an error - first character doesnt match regex...
So I wrote this:
var addValidation = function (patterns) {
var index = patterns.length; //I know I can avoid this
while (index--) {
patterns[index] = new RegExp(patterns[index]);
}
index = 0;
var current = patterns[index],
matchExact = function (patt, str) {
var match = str.match(patt);
return match !== null && str === match[0];
};
return function () {
var str = this.value;
if (!matchExact(current, str) ) {
var tmp = patterns[index + 1] ?
new RegExp(current.source + patterns[index + 1].source) :
false;
if (tmp && matchExact(tmp, str)) {
current = tmp;
index++;
}
else {
alert("Wrong");
}
}
}
};
document.getElementById("x").onkeyup = addValidation(["[a-zA-Z0-9\\.]+", "#{1}", "[a-zA-Z0-9]+", "\\.{1}", "[a-zA-Z]{1,3}"]);
It seems to work, but... it's ugly and it will alert you if you do step back (eg. "name#" and you press backspace).
I know that Dojo's validation is great, but I do not want to use Dojo. Are there any better ways to achieve that?
//EDIT: http://livedocs.dojotoolkit.org/dijit/form/ValidationTextBox this is an example, but you can define your own pattern (like email regex) and it will validate it perfectly.
Add interval before validation will start:
var t;
document.getElementById("x").onkeyup = function () {
if (t) {
clearTimeout(t);
}
t = setTimeout(function () {
//do validation
}, 1000)
}
Don't ever try to validate an email address with a regualr expression. You'll either end up allowing addresses which are not valid, or block email addresses which are perfectly valid and just annoy your visitors. It's also worth bearing in mind that the best regex so far for validating email addresses is this:
http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html

testing user entry on keyup and regex

In my case the requirement is like -
The first name should allow alphabets, some chars like comma, dash and ascent chars.
The code works fine when we try to paste the ascent chars or use "abctajpu" add on in firefox. But as soon as user types in ALT+0192 or any ALT key with num pad.
The keyup function does not work. It lets the user to key in every possible combination with the ALT key.
Here is the sample code..
var namePattern = /^[a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]$/g;
var negateNamePattern = /[^a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]/g;
$("#First_Name").bind('keyup paste altKey', function(event) {
var obj = $(this);
if (event.type == 'paste') {
setTimeout(function() {
validateRealTime(event, obj, namePattern, negateNamePattern)
}, 1);
} else {
validateRealTime(event, obj, namePattern, negateNamePattern);
}
});
The key up event will still be fired when they do any ALT key with num pad, however only when they stop typing will the new character be appended.
Is there a specific reason why you need to do a key up event?
You could validate your field whenever they lose focus on the input.
Also, can we see your validateRealTime function?
EDIT
I think I've figured out a way to accomplish what you want.
We'll have to change your function to validate a string passed instead of getting the value of the object:
function validateRealTime(str, regExPattern, negateRegExPattern) {
var fieldVal = str;
fieldVal = fieldVal.replace(/^(\s+)/g,'');
fieldVal = validateInput(fieldVal, regExPattern, negateRegExPattern);
// return the new and validated value
return fieldVal;
}
I've removed the event from the function, but you can add it if you are using it somewhere else.
Also, we need to change from a keyup to a keypress event. This will allow us to determine when the ALT is pressed (ALT + # = one keypress, whereas ALT + # = # keyups)
Futhermore, since the value of the input gets updated on keyup, we need to make sure that on keyup only the validated string appears.
var validatedValue; // Store validate value to display on 'keyup'
var namePattern = /^[a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]$/g;
var negateNamePattern = /[^a-zA-Z,-. \'ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüŸçÇŠšŽžÅå]/g;
$("#First_Name").bind('keyup', function(event){
$(this).val(validatedValue);
})
.bind('keypress paste', function(event){
var obj = $(this);
var char;
var string;
var newval;
if (event.type == 'paste'){
setTimeout(function(){validateRealTime(obj.val(), namePattern, negateNamePattern)}, 1);
} else {
// Get the ASCII code of the key pressed and get the Char representation of it
// When we do an ALT+#, it returns only one ASCII value
char = String.fromCharCode(event.keyCode);
// Get the current string and append the character added by the ALT
// We need to do this, because the val() is not updated yet, it still contains
// the old value
string = obj.val() + char;
validatedValue= validateRealTime(string, namePattern, negateNamePattern);
}
});
Also, I have not tested the paste event.
Finally its working....here is the working code...
$("#First_Name").bind('keyup paste', function(event){
var obj = $(this);
if(event.altKey) {
$("#First_Name").bind('keypress', function(event){
setTimeout(function(){validateRealTime(event, obj, namePattern, negateNamePattern)}, 1);
});
} else if (event.type == 'paste'){
setTimeout(function(){validateRealTime(event, obj, namePattern, negateNamePattern)}, 1);
} else {
validateRealTime(event, obj, namePattern, negateNamePattern);
}
});
Thanks a lot for the guidance...the trick was to delay the time so that keyup gets the typed in character.

Categories