How to make autospace after every 4 digit in React - javascript

I'm trying to make credit/debit card form with React. I want to make autoinsert space after every 4 digit and to force the user type numbers only. For example, if input 1234567891234567 it will become with spaces 1234 5678 9123 4567.
The problem is when I press backspace the spaces can't be deleted because I use onChange event. I'm new to React, probably need a different approach. What else I can use to make the backspace working properly and how to forbid writing of letters (digits only)?
const [cardNumber, setCardNumber] = useState('')
const handleChange = async (e) => {
if (e.target.value.length === 4) {
e.target.value += ' '
} else if (e.target.value.length === 9) {
e.target.value += ' '
} else if (e.target.value.length === 14) {
e.target.value += ' '
}
setCardNumber(e.target.value)
}

Id create a state variable to hold the cc-number
const [ccNumber, setCcNumber] = useState("");
And set the ccNumber onChange of the input
<input type="text" value={ccNumber} onChange={formatAndSetCcNumber} />
And inside fn formatAndSetCcNumber I'd handle the logic
const formatAndSetCcNumber = e => {
const inputVal = e.target.value.replace(/ /g, ""); //remove all the empty spaces in the input
let inputNumbersOnly = inputVal.replace(/\D/g, ""); // Get only digits
if (inputNumbersOnly.length > 16) {
//If entered value has a length greater than 16 then take only the first 16 digits
inputNumbersOnly = inputNumbersOnly.substr(0, 16);
}
// Get nd array of 4 digits per an element EX: ["4242", "4242", ...]
const splits = inputNumbersOnly.match(/.{1,4}/g);
let spacedNumber = "";
if (splits) {
spacedNumber = splits.join(" "); // Join all the splits with an empty space
}
setCcNumber(spacedNumber); // Set the new CC number
};
Here is a demo

Try this:
const handleChange = async (e) => {
setCardNumber(e.target.value)
}
useEffect(()=>{
if(cardNumber.length===4)
setcardNumber(cardNumber+" ")
else if (cardNumber.length === 9) {
setcardNumber(cardNumber+" ")
} else if (cardNumber.length === 14) {
setcardNumber(cardNumber+" ")
}
}, [cardNumber]);
Sorry for any typos.

Related

JS - Remove all spaces and insert space three characters from end

I'm trying to format postcode entries in a form correctly so that they have a space in the correct location, which is always three characters from the end. E.g.:
AA1 1AA
A1A 1AA
AA11 1AA
A1 1AA
const addSpace = (str, fromEnd) => `${str.slice(0, -1 * fromEnd)} ${str.slice(-1 * fromEnd)}`;
['word', 'longword'].forEach(word => console.log(addSpace(word, 3)));
var el = document.getElementById('input_1_14');
el.addEventListener('keyup', function () {
this.value = addSpace(this.value, 3);
});
However, if I type a series of characters into the relevant field it is inserting spaces every other character, in addition to one three characters from the end, e.g.:
1 1 1 1 1 1 111
Where am I going wrong?
It is becous of the event onKeyUp, you place an extra letter and it keeps adding spaces after every event without removing them.
const addSpace = (str, fromEnd) => `${str.slice(0, -1 * fromEnd)} ${str.slice(-1 * fromEnd)}`;
const removeSpace = (str) => str.replace(/ /g, "");
const editString = (str, fromEnd) => addSpace(removeSpace(str), fromEnd);
['word', 'longword'].forEach(word => console.log(editString(word, 3)));
var el = document.getElementById('input_1_14');
el.addEventListener('keyup', function () {
this.value = editString(this.value, 3);
});
<input type="tex" id="input_1_14">
Try This
function addSpace(str,fromEnd) {
var result ='';
fromEnd += 1;
for (i=0;i<str.length;i++) {
if (i >= str.length - fromEnd) {
result += str[i]+' ';
} else if (str[i] == ' '){
continue;
} else {
result += str[i];
}
}
return result;
}
['word', 'longword'].forEach(word => console.log(addSpace(word, 3)));
var el = document.getElementById('input_1_14');
el.addEventListener('keyup', function () {
this.value = addSpace(this.value, 3);
});
It Is Now Fully Compatible With Your Code Just Replace It With Your Code And It Will Work

How to format half size with <sup> tag?

Below is a function for joining words. Given the first or last word could be a string like 7 1/2, how would I ensure that; if the word contains a fraction, format the fraction with (superscript) tags.. so it shows nicely like below?
export const joinWords = (words: string[]): string => {
if (words.length === 1) {
return words[0];
}
const firstWords = words.slice(0, words.length - 1);
const lastWord = words[words.length - 1];
const oxfordComma = words.length > 2;
//if firstWords or lastword contains "/"...Logic???
return firstWords.join(', ') + `${oxfordComma ? ', ' : ''} and ${lastWord}`;
};
I found an alternate way, where I use the replace method. I am using svelte hence the onmount..
onMount(() => {
//join the words
const test = joinWords(optionNames);
//replace the "1/2" since I am only using 1/2 for clothing sizes...this may not work for other fractions..
const newTest = test.replace('1/2', '½');
testWord = newTest;
});
//be sure to return as html...again im in svelte.
<span>{#html testWord} </span><br />

Prompt a request and reassign the value according to condition

Im using Javascript/Node.js
i want to ask the user to input a number.
I want to check some condition on it: it should not be a string and it should be a number greater than 25. Until the condition is met, the question "input a number..." should be prompted.
When the condition is met, it should exit the loop and the new value of "P" should be assigned.
The loop works fine, but when it ends and i console.log(p), the value is not updated. If i console.log(a) inside the loop, the value is logged correctly.
What im doing wrong?
let p = prompt('Input a number => ');
const checkP = (a) => {
while (isNaN(a%2) || a > 25) {
a = prompt('Input a number or a number less than 25 => ');
}
};
checkP(p);
console.log(p);
You are modifying variable a, which is passed parameter, therefore it is only available inside checkP function, nor it can mutate p
Change this:
let p = prompt('Input a number => ');
const checkP = (a) => {
while (isNaN(a % 2) || a > 25) {
a = prompt('Input a number or a number less than 25 => ');
}
};
checkP(p);
console.log(p);
To this:
let p = prompt('Input a number => ');
const checkP = () => {
while (isNaN(p % 2) || p > 25) {
p = prompt('Input a number or a number less than 25 => ');
}
};
checkP();
console.log(p);

Predict JavaScript string from incorect input

I'm currently programming a Discord bot, and was wondering if it is possible to predict the wanted command if the input was incorrect.
For example, I have this list of words :
['help','meme','ping'],
and if the user inputs "hepl", would it somehow be possible to "guess" they meant to type help ?
One option would be to find a command whose levenshtein distance from the input is 2 or less:
// https://gist.github.com/andrei-m/982927
const getEditDistance=function(t,n){if(0==t.length)return n.length;if(0==n.length)return t.length;var e,h,r=[];for(e=0;e<=n.length;e++)r[e]=[e];for(h=0;h<=t.length;h++)r[0][h]=h;for(e=1;e<=n.length;e++)for(h=1;h<=t.length;h++)n.charAt(e-1)==t.charAt(h-1)?r[e][h]=r[e-1][h-1]:r[e][h]=Math.min(r[e-1][h-1]+1,Math.min(r[e][h-1]+1,r[e-1][h]+1));return r[n.length][t.length]};
const commands = ['help','meme','ping'];
const getCommand = (input) => {
if (commands.includes(input)) return input;
return commands.find(command => getEditDistance(input, command) <= 2);
};
console.log(getCommand('hepl'));
(2 is just a number, feel free to pick the tolerance you want - the higher it is, the more commands will be guessed at, but the more false positives there will be)
You can find hits and show many words in suggestion. If you want same you can use to show most hit word.
const words = ["help", "meme", "ping"];
const getHits = (word, wordToMatch, hits = 0) => {
if (!word.length || !wordToMatch.length) return hits;
let charW = word.slice(0, 1);
let index = wordToMatch.indexOf(charW);
if (index !== -1) {
return getHits(
word.slice(1),
String(wordToMatch.slice(0, index) + wordToMatch.substr(index + 1)),
hits + 1
);
}
return getHits(word.slice(1), wordToMatch, hits);
};
const getMatch = mword => {
return words.reduce((m, word) => {
m[word] = getHits(mword, word);
return m;
}, {});
};
const sort = obj => {
return Object.entries(obj).sort(
([_, value1], [__, value2]) => value2 - value1
);
};
console.log(getMatch("help"));
console.log(sort(getMatch("help")));
console.log(getMatch("me"));
console.log(sort(getMatch("me")));
.as-console-row {color: blue!important}

if Input: 8-e Expected Output: 2|4|6|8

Question 2: The input consist of a string, "o" represents odd number, "e" represents even number to be printed
Example 1.
Input: 8-e
Expected Output: 2|4|6|8
Example 2.
Input: 6-o
Expected Output: 1|3|5
Example 3.
Input: 1-o
Expected Output: 1
if have tried with for loop, but I'am a beginner so I'am confused with(-e)
const evenOdd = (number) => {
let evenvalue = [];
let oddValue=[];
for(let i =0; i<=number; i++){
if(number%i==0)
evenvalue.push(i);
console.log(evenvalue);
}if(number%i!=0){
oddValue.push(i);
console.log(oddValue);
}
};
evenOdd(9);
You could take a while statement and get a start value of one plus an offset of one if the wanted type is even. Then iterate and add the value to the result set until the value is greater than the maximum value.
function fn(request) {
var [max, type] = request.split('-'),
i = 1 + (type === 'e'),
result = [];
while (i <= max) {
result.push(i);
i += 2;
}
return result;
}
console.log(...fn('8-e'));
console.log(...fn('6-o'));
console.log(...fn('1-o'));
You will need to extract the letter and the number from you string first. One easy way to do that :
const evenOdd = (s) => {
let odd = s.length-1 ==='o';
let number = Number(s.substring(0, s.length-2));
let evenvalue = [];
...
if(odd){...} else {...}
};
You could also use split() or if the pattern was more complicated, a Regex.
You can split on - and add based on type add values upto the number
Split the given input by -, first value represents max number and second represents it's type
Check the type if it is even add the even values start from 2 and upto to the max number else start from 1, and join them with | in the end
let func = (input) => {
let [num, type] = input.split('-')
let arr = []
let i = 1 + (type === 'e')
while (i <= num) {
arr.push(i)
i += 2
}
return arr.join('|')
}
console.log(func('8-e'))
console.log(func('1-o'))
console.log(func('6-o'))
Basically, don't supply a number to the function, supply a string and then parse the string. That is, don't try and give the function 9-e, give it '9-e'.
Get the parts of the input by splitting on -.
Turn the number into a number.
Give 0 for even, 1 for odd (x % 2 is 0 for even number, 1 for odd).
Build the results.
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
let result = [];
for(let i = 1; i <= number; i++)
{
if(i%2 === numberType)
{
result.push(i);
}
}
return result;
}
console.log(listNumbers('8-e'));
Or if you want make the code look clever:
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
return Array.from(Array(number), (x,i) => i + 1 ).filter(x => x%2 == numberType);
}
console.log(listNumbers('8-e'));

Categories