如何通过忽略每次按键时的无效字符,使文本类型的输入元素只接受一个数值(十进制、正数和负数)?
How to make a text-type input-element accept just a numerical value (decimal, positive and negative) by ignoring invalid characters on each keypress?
我有一个 HTML 输入,这个输入只接受数字字符的字符串,
示例:
输入值:+0123.534534
或-234234.543345或-13453
,这些输入值有效。
字符 + 或 - 只存在一个并且在字符串值的第一个位置
我希望每个输入字符的输入值都应该保持当前有效的字符串,并将无效的输入字符替换为空字符
示例:
当我键入:+123.g
==> 值应立即替换 +123
。
或者当我键入:g ==> 该值应立即替换为空值。
我找到了一个实现,但是缺少 (+/-/.) 字符
const getDigitsOnly = (value) => String(value).replace(NOT_NUMBERS, '');
这会做你想做的事
let someString = "+123.g";
let result = someString.replace(/[^0-9,+,-,.]+/g, "");
console.log(result);
有关如何使用正则表达式的更多信息,请在此处查看
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
这是我的解决方案。
我们向输入框添加了一个 input
事件侦听器,对于每个输入,我们都会格式化整个输入值。
注意:提交值时不要忘记trim尾随小数点(例如"123."
到"123"
) .
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" />
格式化函数的算法。
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
这里有一些虚拟数据来测试格式化功能
const dummyData = [
"",
"+",
"-",
".",
".123",
"+.123",
"123.3.23",
"12sfdlj3lfs.s++d_f",
"12--++.123",
];
从以上评论...
"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."
证明上述复杂性...
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/underscore@1.13.1/underscore-umd-min.js"></script>
<input type="text" placeholder="... number only ..."/>
...并将其直接与数字类型字段进行比较...
<input type="number" placeholder="native number type"/>
...以及 Micahel Hamami 的方法,特此付诸实施...
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 ..."/>
我有一个 HTML 输入,这个输入只接受数字字符的字符串,
示例:
输入值:+0123.534534
或-234234.543345或-13453
,这些输入值有效。
字符 + 或 - 只存在一个并且在字符串值的第一个位置
我希望每个输入字符的输入值都应该保持当前有效的字符串,并将无效的输入字符替换为空字符
示例:
当我键入:+123.g
==> 值应立即替换 +123
。
或者当我键入:g ==> 该值应立即替换为空值。
我找到了一个实现,但是缺少 (+/-/.) 字符
const getDigitsOnly = (value) => String(value).replace(NOT_NUMBERS, '');
这会做你想做的事
let someString = "+123.g";
let result = someString.replace(/[^0-9,+,-,.]+/g, "");
console.log(result);
有关如何使用正则表达式的更多信息,请在此处查看 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
这是我的解决方案。
我们向输入框添加了一个 input
事件侦听器,对于每个输入,我们都会格式化整个输入值。
注意:提交值时不要忘记trim尾随小数点(例如"123."
到"123"
) .
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" />
格式化函数的算法。
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
这里有一些虚拟数据来测试格式化功能
const dummyData = [
"",
"+",
"-",
".",
".123",
"+.123",
"123.3.23",
"12sfdlj3lfs.s++d_f",
"12--++.123",
];
从以上评论...
"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."
证明上述复杂性...
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/underscore@1.13.1/underscore-umd-min.js"></script>
<input type="text" placeholder="... number only ..."/>
...并将其直接与数字类型字段进行比较...
<input type="number" placeholder="native number type"/>
...以及 Micahel Hamami 的方法,特此付诸实施...
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 ..."/>