Validation input full name - javascript

There is a task: The field “First Name Last Name” can only consist of 2 words (first name and last name). Min length of each word is 3 characters, max 30. There is only 1 space between words.
The problem is that after the first word, when you put a space, it already returns true. Why? And how to check the 1 space in this input?
const validateInput = (value) => {
const lengthValue = value.split(' ').length
if (lengthValue !== 2) {
return false
} else {
return value.split(' ').filter(el => el.length > 3 && el.length <= 30) ?
value.search(/[A-Za-z]+(\s+[A-Za-z]+)?/gi) !== -1 ?
true :
false :
''
}
}

Use trim to remove spaces from around the words before testing
No need for else after a return. Makes it easier to read too
Why are you testing the words in the name for whitespace? That only works if the user pasted a newline or a tab, since you split on space
You have a nested ternary, why would you return an empty string there?
Also please read this for the future falsehoods programmers believe about names
const re = /[A-Za-z]{3,30}/;
const validateInput = (value) => {
const val = value.trim();
if (val === "") return false;
const arr = value.split(' ');
if (arr.length != 2) return false;
const [firstName, lastName] = arr;
return re.test(firstName) && re.test(lastName); // we could use .every here but you only have two
}
console.log(validateInput("Hans Anders"));
console.log(validateInput("Prince"));
console.log(validateInput("X Æ A-12"));
console.log(validateInput(" A "));

You can check if the no. of words are less than equal to two and the length of all the words fall within the specified range.
const message = document.querySelector("small");
document.querySelector("input").addEventListener("keyup", (e) => {
const isValid = validateInput(e.target.value);
if (isValid) {
message.textContent = "Valid input";
} else {
message.textContent = "Invalid input";
}
});
const validateInput = (input) => {
const words = input.split(" ");
return words.length <= 2 && words.every((w) => /^[A-Za-z]{3,30}$/.test(w));
};
<div>
<label>
Name:
<input type="text" />
</label>
</div>
<small>Invalid input</small>

Related

How to sanitize (digits and hyphen only) and auto-format (hyphen and leading zeros insertion) a text input value while typing and/or pasting text?

There are similar questions on SO, but mine is a bit unique. I want to limit an input text field to 9 characters in length (currently solved with maxlength attribute), only allow typing in numeric values and the hyphen character. Sort of handled with this code returning "True":
/^\d*\-?\d*$/.test(value)
Where I'm stuck is, I want the input text field to auto-format the value as the user types in the format:
12345-123
Where it's 5 digits (may have leading zeros or not depending on how user inputs it), followed by a hyphen, then always 3 digits. I'd like it to pad the first 5 with zeros if user enters something like "123-495" manually, so it would become "00123-495".
I'm not sure how to add in the auto-zero padding, or placement of the hyphen automatically.
Not opposed to using jQuery, but would prefer vanilla.
EDIT: Thought it might be useful to add. This is for an access card number entry box. So value will always be a positive number, and will always have 3 digits after the single hyphen. The card number will always be 5-digits in length, but again, may be padded with zeros to make it that length. Ideal output should always be "xxxxx-xxx".
EDIT 2: This seems to work, but there's an issue where user can enter non-numeric characters at first and after the 1st entry, only then does it clear it out. It also doesn't seem to let me hit backspace past the hyphen... Is there a way to prevent it from allowing alpha characters completely?
// Restricts input for the given textbox to the given inputFilter function.
function setInputFilter(textbox, inputFilter) {
["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop"].forEach(function(event) {
textbox.addEventListener(event, function() {
if (inputFilter(this.value)) {
// Current value
new_val = '';
if (this.value.includes('-') && this.value.slice(this.value.indexOf('-')).length == 4) {
console.log("Value not hyphenated yet");
pad_needed = 5 - this.value.indexOf('-');
console.log('Pad needed: ' + pad_needed);
new_val = this.value.padStart(9, '0');
this.value = new_val;
} else if (this.value.length >= 5 && this.value.includes('-') && this.value.slice(this.value.indexOf('-')).length == 4) {
if (this.value.slice(5, 1) == '-') {
// Already a hyphen added, just add rest of numbers
new_val = this.value.slice(0, 6) + this.value.slice(6);
} else {
// Needs hyphen added
new_val = this.value.slice(0, 5) + '-' + this.value.slice(6);
}
this.value = new_val;
} else if (this.value.length >= 5 && !this.value.includes('-')) {
// Needs hyphen added
new_val = this.value.slice(0, 5) + '-' + this.value.slice(6);
this.value = new_val;
}
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
} else if (this.hasOwnProperty("oldValue")) {
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
} else {
this.value = "";
}
});
});
}
setInputFilter(document.getElementById("card-number"), function(value) {
return /^\d*\-?\d*$/.test(value); // Allow digits and '-' only
});
function getSanitizedInputValue(value) {
value = value
.trim()
.replace(/^[-]+/, '')
.replace(/[-]+/, '-');
let [
first,
...rest
] = (value.match(/[-\d]+/g) ?? [])
.join('')
.split('-')
let joiner = '';
if (first.length >= 6) {
joiner = '-';
rest.unshift(first.slice(5));
first = first.slice(0, 5);
} else if (rest.length >= 1) {
joiner = '-';
first = first.padStart(5, '0');
}
return [
first,
rest.join(''),
]
.join(joiner)
.slice(0,9);
}
function handleInput({ currentTarget: control }) {
const { value: recentValue, selectionStart, selectionEnd } = control;
const regXHasHyphen = /-/;
const sanitizedValue = getSanitizedInputValue(recentValue);
const sanitizedLength = sanitizedValue.length;
const recentLength = recentValue.length;
const positionDelta = (
(recentLength <= 5) &&
(sanitizedLength >= 6) &&
(sanitizedLength - recentLength)
) || (
!regXHasHyphen.test(recentValue) &&
regXHasHyphen.test(sanitizedValue) &&
1
) || 0;
control.value = sanitizedValue;
control.selectionStart =
Math.min(sanitizedLength, (selectionStart + positionDelta));
control.selectionEnd =
Math.min(sanitizedLength, (selectionEnd + positionDelta));
}
document
.querySelector('[type="text"]')
.addEventListener('input', handleInput);
<input type="text" maxlength="9" />

How to check for special characters in password

I am trying to validate a given password by checking for uppercase, lowercase, and special characters. The program is suppose to store true for each requirement found and false for each not found. If anyone of the requirements are not found then the program prints an error message as well as the finding results for each requirement. The problem is the special character variable keeps returning as false even when there's a special character in the password. It seems that the function special that calls for the special character to get checked never gets called but I don't know why. Can anybody help?
// Assume password input is "Patick_"
const passwordForSignup = document.getElementById("input-password");
const arrayOfSp = ["!", "#", "#", "$", "%", "&", "*", "_", "-", "?"];
const special = (c) => {
console.log(c);
for (let i = 0; i < arrayOfSp.length; i++)
{
if (c === arrayOfSp[i])
{
return true;
}
}
return false;
}
if (passwordForSignup.value.length >= 6 && passwordForSignup.value.length <= 17)
{
let upperCaseCheck = false;
let lowerCaseCheck = false;
let specialCharacterCheck = false;
let passwordValue = "";
for (let i = 0; i < passwordForSignup.value.length; i++)
{
passwordValue = passwordForSignup.value[i];
if (passwordForSignup.value[i] === passwordValue.toUpperCase())
{
upperCaseCheck = true;
}
else if (passwordForSignup.value[i] === passwordValue.toLowerCase())
{
lowerCaseCheck = true;
}
else if (special(passwordValue))
{
specialCharacterCheck = true;
}
}
if (!upperCaseCheck || !lowerCaseCheck || !specialCharacterCheck)
{
console.log("Something is wrong");
console.log(upperCaseCheck);
console.log(lowerCaseCheck);
console.log(specialCharacterCheck);
}
}
// else
// {
// message.push("Password must contain 6 - 17 characters");
// errorFound(message, e);
// }
The rason is that your special check is made for last and
"_".toUpperCase()
for example return "_"
Try:
if (special(passwordValue))
{
specialCharacterCheck = true;
}
else if (passwordForSignup.value[i] === passwordValue.toUpperCase())
{
upperCaseCheck = true;
}
else if (passwordForSignup.value[i] === passwordValue.toLowerCase())
{
lowerCaseCheck = true;
}
However this isn't the way to do. Instead use regular expressions.
Try the Regular Expression patterns, like this example.
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[-+_!##$%^&*., ?]).+$/;
function check_pass(){
var pass=document.getElementsByName("pass")[0].value;
console.log(regex.test(pass));
}
<input type='text' name='pass'><button id='test' onclick='check_pass()'>Check</button>
where:
^ represents the starting of the string.
(?=.*[a-z]) represent at least one lowercase character.
(?=.*[A-Z]) represents at least one uppercase character.
(?=.*\d) represents at least one numeric value.
(?=.*[-+_!##$%^&*., ?]) represents at least one of the special character.
And if you want separeted checks, can be made like this:
const lower = /^(?=.*[a-z])/;
const upper = /^(?=.*[A-Z])/;
const nums = /^(?=.*\d)/;
const special = /^(?=.*[-+_!##$%^&*., ?]).+$/;
function check_pass() {
var pass = document.getElementsByName("pass")[0].value;
console.log('Lower: ' + lower.test(pass));
console.log('Upper: ' + upper.test(pass));
console.log('Numbers: ' + nums.test(pass));
console.log('Specials: ' + special.test(pass));
}
<input type='text' name='pass'><button id='test' onclick='check_pass()'>Check</button>

is there a way to check if a string is of this *x.xx.xxxx* format in JavaScript?

I want a function to check if a string is of format x.xx.xxxx in javascript. For example, s.xf.ssfs should return true. And sx.xf.hsdf should return false. Also s.fsd.sfdf should return false.
Here's a reducer version
const isValid = s => s.split('.').reduce((b,a,i) => a.length === [1,2,4][i] ? b+1 : b, 0) === 3
console.log(isValid('s.xf.ssfs'));
console.log(isValid('ds.xf.ssfs'));
console.log(isValid('5.32.9850'))
For a non-regex, for loop option:
const test1 = 's.xf.ssfs';
const test2 = 'sx.xf.hsdf';
function correctFormat(str) {
if (str.length !== 9) {
return false;
}
if (str[1] !== '.' || str[4] !== '.') {
return false;
}
for (let i = 0; i < 9; i++) {
if (i !== 1 && i !== 4 && str[i] === '.') {
return false;
}
}
return true;
}
console.log(correctFormat(test1));
console.log(correctFormat(test2));
You can try using regex:
const regex = new RegExp('[a-z][.][a-z]{2}[.][a-z]{4}');
console.log(regex.test('s.xf.ssfs'));
console.log(regex.test('s.fsd.sfdf'));
As an alternative you can also split the string by periods and check the length of each individual item:
function check(s){
let a = s.split('.');
return a.length == 3 && a[0].length == 1 && a[1].length == 2 && a[2].length == 4;
}
console.log(check('s.xf.ssfs'));
console.log(check('sx.xf.hsdf'));
Regular Expressions are what you are looking for here. Simply define a regex and use the test() method to evaluate a string. For example:
const regex = /^[a-z][.][a-z]{2}[.][a-z]{4}$/
console.log(regex.test('s.xf.ssfs'))
console.log(regex.test('sx.xf.hsdf'))
If you require to accept letters and numbers you could use this regular expression instead to test against:
const regex = /^.[.].{2}[.].{4}$/
console.log(regex.test('s.5f.s9fs'))
console.log(regex.test('sx.xf.hsdf'))
From a brute force approach you could split the string by . into an array and check the length of the array, and each element within the array as follows:
let myArray = myString.split(".");
if(myArray.length !== 3){
return false
}
else if(myArray[0] !== 1 || myArray[1] !== 2 || myArray[3] != 4){
return false
}
else{return true}
Using regular expression you can achieve it.
1) This example work for letters from "a" to "z"
const format = /^[a-z]\.[a-z]{2}\.[a-z]{4}$/; //x.xx.xxxx
let test1 = format.test('s.xf.ssfs');
let test2 = format.test('sx.xf.hsdf');
console.log("test1: " + test1);
console.log("test2: " + test2);
2) This example work for letters from "a" to "z" and "A" to "Z"
const format = /^[a-zA-Z]\.[a-zA-Z]{2}\.[a-zA-Z]{4}$/; //X.Xx.xXXx
let test1 = format.test('S.Xf.sSFs');
let test2 = format.test('sx.XF.Hsdf');
console.log("test1: " + test1);
console.log("test2: " + test2);

JavaScript IF statement and While loop not working properly

Okay now I have been able to solve the Length problem by adding the length property to the while loop. However, when i generate the noSpecialCharacter(), it gives me NaN in front of the generated password.
this is the function:
const noSpecialCharacters = () => {
let password;
for (let i = 0; i < askUser; i++) {
let result3 = characterSet[randomCharacter()];
password += result3;
}
return password;
}
let askUser;
// create a function for prompts
const prompts = () => {
const minLength = 8;
const maxLength = 128;
askUser = null
while (askUser === null || askUser.length < minLength || askUser.length > maxLength) {
// ask the user again
askUser = prompt('Enter a password character length. Character length must be at least 8 and between 128.');
let confirmSpecialCharacter;
// if password is between length range
if (askUser >= minLength && askUser <= maxLength) {
// ask for special characters
confirmSpecialCharacter = confirm('Would you like for your password to include special characters?');
// if yes, call combine random
let pass = confirmSpecialCharacter === true ? combineRandom() : noSpecialCharacters();
alert(pass);
}
}
return askUser;
}
prompts();
When you check the length, use askUser.length
But with this logic, when the user input is correct on the first time, nothing in the wile loop will run.
A better approach is to initialize askUser = null
and set the condition in while to:
while (askUser === null || askUser.length < minLength || askUser.length > maxLength)
To check first if the askUser is null
let askUser;
// create a function for prompts
const prompts = () => {
const minLength = 8;
const maxLength = 128;
askUser = null
while (askUser === null || askUser.length < minLength || askUser.length > maxLength) {
// ask the user again
askUser = prompt('Enter a password character length. Character length must be at least 8 and between 128.');
let confirmSpecialCharacter;
// if password is between length range
if (askUser.length >= minLength && askUser.length <= maxLength) {
// ask for special characters
confirmSpecialCharacter = confirm('Would you like for your password to include special characters?');
// if yes, call combine random
if (confirmSpecialCharacter === 'yes') {
let pass = combineRandom();
alert(pass);
} else {
let pass = noSpecialCharacters();
alert(pass);
}
}
}
return askUser;
}
prompts()
Since people solved your question by adding .length to the askUser, I'm here to suggest you to reconstruct the code from while loop to recursive by keep calling the function itself until it passed the validation. (code untested)
with this method you can prevent the nested condition by return early.
// create a function for prompts
const prompts = () => {
const minLength = 8;
const maxLength = 128;
// ask the user
let askUser = prompt('Enter a password character length. Character length must be at least 8 and between 128.');
// keep asking the function itself until it passed the validation
if (askUser.length <= minLength || askUser.length >= maxLength || askUser === null) {
return prompts()
}
// ask for special characters
let confirmSpecialCharacter = confirm('Would you like for your password to include special characters?');
let pass;
// if yes, call combine random
if (confirmSpecialCharacter) {
pass = combineRandom();
} else {
pass = noSpecialCharacters();
}
alert(pass);
return askUser;
}
With ternary condition you can get much more shorter code.
// if yes, call combine random
let pass = confirmSpecialCharacter ? combineRandom() : noSpecialCharacters();
In your while condition, you are not actually checking for askUser length. Change it to this line: while (askUser.length < minLength || askUser === null || askUser.length > maxLength) { /... And it will work.

I keep getting false and not true in this javascript anagram problem

Hi Im using Javascript to work on an anagram problem. I am having issues comparing the 2 objects I have made out of the 2 strings that were put into the function.
The function should return true if the 2 strings have the same letters occurring the same number of times. Regardless of order in the string. You ignore the casing of the letters too, to do that I made all strings lowercase. Here is my code:
//example:
//validAnagram('', '') //true
//validAnagram('aaz', 'zza') //false
const validAnagram = (str1, str2) => {
str1 = str1.toLowerCase()
str2 = str2.toLowerCase()
const frequency1 = {}
const frequency2 = {}
//if lengths of string isnt the same automatically make it false
if(str1.length !== str2.length){
return false
}
//putting letters of the strings with their frequencies in the objects
for(let letter of str1){
if(!frequency1[letter]){
frequency1[letter] = 1
}
else {
frequency1[letter]++
}
}
for(let letter of str2){
if(!frequency2[letter]){
frequency2[letter] = 1
}
else {
frequency2[letter]++
}
}
for(let char in frequency1){
if(!(frequency2[char])){
return false
}
else if(frequency2[char] !== frequency1[char]){
console.log(char)
return false
}
else{
return true
}
}
}
First: I searched all unique characters from 2 string and saved then in array
Second: I concat 2 arrays and then using set, removed all duplicate items (characters)
Third: I loop through each character and find the occurrence of that item
forth: if occurrence matched or not, or if the character actually not exists in any of the string, can be found in the console.
const string1 = 'dafdsef dgrg tdyhjTdh drdd# dgrgrth-grth'
const string2 = '#dafdsef dgrg tdyhjtdh drdd dgrgr;thgrth'
console.log("strings matched : "+test_string(string1 , string2));
function test_string(string1 , string2){
jointArray = [...unique_char(string1.toLowerCase()), ...unique_char(string2.toLowerCase())]
neewarray = [...new Set([...jointArray])]
ok = true;
neewarray.forEach( v=> {
var re = new RegExp(v, 'g');
if(string1.match(re) && string2.match(re) ){
if( string1.match(re).length == string2.match(re).length ) {
console.log(` ${v} => matched in 2 strings`)
}
else{
ok = false;
console.log(` ${v} => not matched in 2 strings`)
}
}
else if(string1.match(re)){
ok = false;
console.log(` ${v} => not avialable in a string1 `)
}
else if(string2.match(re)){
ok = false;
console.log(` ${v} => not avialable in a string2 `)
}
})
return ok;
}
function unique_char(str1){
var str=str1;
var uniq_array=[];
for (var x=0;x < str.length;x++){
if(uniq_array.indexOf(str.charAt(x))==-1){
uniq_array.push(str[x]);
}
}
return uniq_array;
}

Categories