I have an HTML input and this input just accept the string of number character,
Example:
input value: 0123.534534
or -234234.543345 or -13453
, these input values are valid.
The characters or - just exist one and at first position in string value
I want every typing character the input value should keep the current valid string and replace the invalid input character with an empty character
Example:
When I typed : 123.g
==> the value should replace immediately 123
.
Or when I typed: g ==> the value should replace immediately with an empty value.
I found an implementation with this, but It lack of ( /-/.) character
const getDigitsOnly = (value) => String(value).replace(NOT_NUMBERS, '');
CodePudding user response:
From the above comments ...
"Why does the OP not restrict the user input by a number type input field like with ...
<input type="number"/>
?"
"Any
type="text"
and custom validation based approach, if done properly, has the tendency to grow more complex since, from a UX perspective, an immediate value sanitizing (while typing or pasting) also has to take care of reestablishing the user's most recent caret position."
Proving the above mentioned complexity ...
function stripNeedlessDataFromBoundFieldValue() {
this.value = this.value.replace((/[- .]$/), '');
}
function getSanitizedValue(value) {
value = value
// remove any leading and trailng whitespace (sequences).
.trim()
// remove any character not equal to minus, plus, dot and digit.
.replace((/[^- .\d] /g), '');
if (value.length >= 1) {
let partials = value.split(/(^[ -]?)/);
if (partials.length === 1) {
partials.unshift('');
} else {
partials = partials.slice(1);
}
let [ first, last ] = partials;
last = last.replace((/[ -] /g), '');
// console.log([ first, last ]);
partials = last.split('.');
if (partials.length === 1) {
partials.unshift('');
} else {
partials = [
partials.shift(),
['.', partials.join('')].join(''),
];
}
first = [first, partials[0]].join('');
last = partials[1];
value = [first, last]
.join('')
.replace(
// trim any sequence of leading zeros into a single one.
(/(^[ -]?)0 /),
(match, sign) => [(sign || ''), 0].join('')
)
.replace(
// always ensure a single zero before a leading sole decimal point.
(/(^[ -]?)\. /),
(match, sign) => [(sign || ''), '0.'].join('')
);
}
return value;
}
function sanitizeInputValue(evt) {
const elmNode = evt.currentTarget;
const currentValue = elmNode.value;
const sanitizedValue = getSanitizedValue(currentValue);
if (currentValue !== sanitizedValue) {
const diff = sanitizedValue.length - currentValue.length;
const { selectionStart, selectionEnd } = elmNode;
elmNode.value = sanitizedValue;
elmNode.selectionStart =
(selectionStart diff > 0) ? selectionStart diff : selectionStart;
elmNode.selectionEnd =
(selectionEnd diff > 0) ? selectionEnd diff : selectionEnd;
}
}
function main() {
const textInput = document.querySelector('[type="text"]');
const finalizeBoundFieldValueDebounced = _.debounce(
stripNeedlessDataFromBoundFieldValue.bind(textInput), 1200
);
textInput.addEventListener('input', evt => {
sanitizeInputValue(evt);
finalizeBoundFieldValueDebounced();
});
// // whithout delayed trimming of trailing dot.
//
// document
// .querySelector('[type="text"]')
// .addEventListener('input', sanitizeInputValue);
}
main();
<script src="https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js"></script>
<input type="text" placeholder="... number only ..."/>
... and comparing it directly to the number type field ...
<input type="number" placeholder="native number type"/>
... and to Micahel Hamami's approach, which hereby got brought into action ...
function sanitizeInputValue({ currentTarget }) {
currentTarget.value = currentTarget.value.replace(/[^0-9, ,-,.] /g, "");
}
function main() {
document
.querySelector('[type="text"]')
.addEventListener('input', sanitizeInputValue);
}
main();
<input type="text" placeholder="... number only ..."/>
CodePudding user response:
Here is my solution for it.
We add an input
event listener to the input box and for every input we format the entire input value.
Note: Don't forget to trim trailing decimal point (e.g. "123."
to "123"
) if exists when submitting the value.
const inputBox = document.getElementById("inputBox");
inputBox.addEventListener("input", () => {
inputBox.value = format(inputBox.value);
});
function format(str) {
if (!str.length) return str;
str = str.replace(/[^. -\d]/g, "");
const firstChar = str.charAt(0);
str = str.slice(1).replace(/[ -]/g, "");
// Bug fix. Credit goes to @Peter Seliger
// For pointing out the bug
const charArray = [];
let hasDecimalPoint = false;
if (firstChar === ".") {
if (!str.includes(".")) {
hasDecimalPoint = true;
charArray.push("0.");
}
} else charArray.push(firstChar);
// End bug fix
for (let i = 0; i < str.length; i ) {
const char = str.charAt(i);
if (char === ".") {
if (hasDecimalPoint) continue;
if (!i && firstChar !== "0") charArray.push("0");
hasDecimalPoint = true;
}
charArray.push(char);
}
return charArray.join("");
}
<p>Enter your number here</p>
<input id="inputBox" type="text" />
The algorithm of the format function.
1: If the input is empty then return the input 2: Remove all characters except "-", " ", "." and digits 3: Store the first character in a variable 4: Remove all " " and "-" (if exists) after the first character 5: if the first character is "." then replace it with "0." 6. Finally remove any duplicate decimal point (".") if exists
And here are some dummy data to test the format function
const dummyData = [
"",
" ",
"-",
".",
".123",
" .123",
"123.3.23",
"12sfdlj3lfs.s d_f",
"12-- .123",
];
CodePudding user response:
this will do what you want
let someString = " 123.g";
let result = someString.replace(/[^0-9, ,-,.] /g, "");
console.log(result);
for more info on how to use regex check here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions