提问人:Freddan 提问时间:8/30/2023 最后编辑:Freddan 更新时间:8/30/2023 访问量:92
粘贴长数字并将其拆分为多个输入
Paste and split long number to multiple input
问:
我正在尝试开发一种多输入形式,其中我粘贴了一个长数字,该数字自动拆分为每个输入,每个输入有 2 个数字。
一切正常,直到用户粘贴一个只有 5 位数字的数字,例如,而不是报告错误,而是在第一个输入中创建另一个数字。我无法理解表单如何在第一个输入中留下空白,然后通过发明一个数字来填充空白,而不是在最后一个输入中留下空白。45896
此外,如果输入只有一个数字,但仅当用户输入数字时,我开发在数字前面添加一个。else if (input.value.length !== 2 ) input.value = '0' + input.value;
0
我希望粘贴函数显示错误,如果其中一个输入包含少于 2 位数字,并且当粘贴长度小于 6 位的数字时,空格保留在最后一个输入上,而不是第一个输入上。
我的代码是否有问题,或者我应该改进它以达到我的目标?
<style>
.circle input {
border-radius: 999px;
float: left;
max-width: 100px;
font-size: 2em;
text-align: center;
height: 100px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="tkt_1">
<div class="circle">
<input type="tel" min="1" max="99" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" placeholder="00" />
</div>
<div class="circle">
<input type="tel" min="1" max="99" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" placeholder="00" />
</div>
<div class="circle">
<input type="tel" min="1" max="99" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" placeholder="00" />
</div>
</form>
<script>
// Paste numbers from clipboard in multiple input
document.addEventListener("paste", function (e) {
// if the target is a text input
if (e.target.type === "tel") {
var data = e.clipboardData.getData('Text');
// split clipboard text into single characters
data = data.replace(/[^0-9]/g, "").split(/(?=(?:..)*$)/g);
// find all other text inputs
[].forEach.call(document.querySelectorAll("input[type=tel]"), (node, index) => {
// And set input value to the relative character
node.value = data[ index ] ?? "";
});
}
});
// Validation
function handleChange(input) {
if (input.value < 0) input.value = "";
else if (input.value.length !== 2 ) input.value = '0' + input.value;
else if (input.value < 0.9 || input.value > 99 || input.value.length === 1 || input.value.length === 0) {
input.style.backgroundColor = 'red';
return false;
} else {
input.style.backgroundColor = '';
return true;
}
}
// Input only Numbers
$('.circle input').keypress(function (event) {
event = event || window.event;
var charCode = event.which || event.keyCode;
var charStr = String.fromCharCode(charCode);
// FireFox key Del - Supr - Up - Down - Left - Right
if (event.key !== undefined && event.charCode === 0) {
return;
}
//Only Num
if (!/^([0-9])*$/.test(charStr)) {
event.preventDefault();
}
//Num and letters
if (!/^[a-zA-Z0-9]+$/.test(charStr)) {
event.preventDefault();
}
});
</script>
答:
拆分描述的主要问题是由于正则表达式拆分而发生的,它留下了第一个输入单个而不是最后一个输入。
此外,另一个问题是粘贴值不会触发,因此在粘贴值时永远不会调用该函数。onchange
handleChange
<style>
.circle input {
border-radius: 999px;
float: left;
max-width: 100px;
font-size: 2em;
text-align: center;
height: 100px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="tkt_1">
<div class="circle">
<input type="tel" value="00" min="0" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" />
</div>
<div class="circle">
<input type="tel" value="00" min="0" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" />
</div>
<div class="circle">
<input type="tel" value="00" min="0" minlength="2" maxlength="2" oninput="if((this.value.length) > 2) {this.value = this.value.substring(0, 2);}" onchange="handleChange(this);" />
</div>
</form>
<script>
// Paste numbers from clipboard in multiple input
document.addEventListener("paste", function (e) {
// if the target is a text input
if (e.target.type === "tel") {
var data = e.clipboardData.getData('Text');
// split clipboard text into single characters
data = data.replace(/[^0-9]/g, "");
// Modified approach to split data into pairs
var pairs = [];
for (var i = 0; i < data.length; i += 2) {
pairs.push(data.slice(i, i + 2));
}
data = pairs;
// find all other text inputs
[].forEach.call(document.querySelectorAll("input[type=tel]"), (node, index) => {
// And set input value to the relative character
node.value = data[ index ] ?? "";
handleChange(node); //Added to trigger validation rules for pasted data
});
}
});
// Validation
function handleChange(input) {
if (input.value < 0) input.value = "";
else if (input.value.length !== 2 ) input.value = '0' + input.value;
else if (input.value < 0.9 || input.value > 99 || input.value.length === 1 || input.value.length === 0) {
input.style.backgroundColor = 'red';
return false;
} else {
input.style.backgroundColor = '';
return true;
}
}
var pasteModifier = false; // Store if control or the meta key is pressed state
// Need to handle the paste functionality
$('.circle input').keydown(function (event) {
if (event.metaKey || event.ctrlKey){
pasteModifier = true;
}
});
$('.circle input').keyup(function (event) {
if (event.metaKey || event.ctrlKey){
pasteModifier = false;
}
});
// Input only Numbers
$('.circle input').keypress(function (event) {
event = event || window.event;
var charCode = event.which || event.keyCode;
var charStr = String.fromCharCode(charCode);
// FireFox key Del - Supr - Up - Down - Left - Right
if (event.key !== undefined && event.charCode === 0) {
return;
}
// Handle paste command
if (charCode == 118 && pasteModifier){
return;
}
//Only Num
else if (!/^([0-9])*$/.test(charStr)) {
event.preventDefault();
}
//Num and letters
else if (!/^[a-zA-Z0-9]+$/.test(charStr)) {
event.preventDefault();
}
});
</script>
我修改了代码,使用常规切片方法将数据字符串拆分为 2 位数字,并在最后一个输入中保留一个数字(如果适用)。该函数也在循环中触发,为每个输入设置值,以便它可以对粘贴的数据采取行动。handleChange
目前,如果您粘贴 5 位数字,它不会给出错误,但由于函数中设置的规则,它会在最后一个输入的开头附加一个 0。handleChange
如果删除此行
else if (input.value.length !== 2 ) input.value = '0' + input.value;
您将遇到红色错误。
在某些浏览器(包括 Safari)中,按键事件的优先级高于粘贴命令,在这种情况下会导致粘贴功能中断。
此外,只能看到可见的按键触发器,这与 和 不同。因此,我包含了附加和事件处理程序,以检查按下的键是 Mac 的键还是 Windows 的键,并将其作为状态存储在变量中。keypress
keydown
keyup
keydown
keyup
Meta
Ctrl
pasteModifier
这可以是处理程序中的一个条件,如果仍然按下键(未触发)然后按下 a,它会返回,因为粘贴处理程序不需要执行任何操作。keypress
Meta or Ctrl
keyup
V
评论
document.querySelectorAll("input[type=tel]")
.forEach
node.value = data[ index ] ||= ""; node.value = data[ index ];
<script src="myfile.js" async defer></script>
a = b ?? "something else"