我正在try 开发一种多输入表单,在该表单中我粘贴一个长数字,该数字会自动拆分 for each 输入的两个数字.

一切都很正常,直到用户粘贴了一个只有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>

我已经修改了代码,使用常规的切片方法将数据字符串分割为两位数字,如果适用,在最后一次输入中保留一位数字.handleChange函数也是在循环内触发的,设置每个输入的值,以便它可以对粘贴的数据起作用.

目前,如果粘贴5位数字,由于handleChange函数中设置的规则,它不会给出错误,但会在最后一次输入的开始处附加一个0.

如果删除此行

else if (input.value.length !== 2 ) input.value = '0' + input.value;

相反,您将遇到红色错误.

在包括Safari在内的某些浏览器中,按键事件的优先级高于粘贴命令,导致在这种情况下中断粘贴功能.

此外,与keydownkeyup不同,keypress只看到可见的按键触发器.因此,我包含了额外的keydownkeyup事件处理程序,以判断按下的键是Mac的Meta键还是Windows的Ctrl键,并将其作为状态存储在pasteModifier变量中.

这可能是keypress处理程序中的一种情况,其中如果Meta or Ctrl键仍然被按下(keyup没有触发),然后V被按下,则它作为粘贴处理程序返回,不需要做任何事情.

Javascript相关问答推荐

React存档iframe点击行为

当promise 在拒绝处理程序被锁定之前被拒绝时,为什么我们会得到未捕获的错误?

在React中获取数据后,如何避免不必要的组件闪现1秒?

在页面上滚动 timeshift 动垂直滚动条

在这种情况下,如何 for each 元素添加id?

将现场录音发送到后端

无法读取未定义错误的属性路径名''

如何在coCos2d-x中更正此错误

ChartJs未呈现

JQuery Click事件不适用于动态创建的按钮

如何在使用rhandsontable生成表时扩展数字输入验证?

TypeError:无法分解';React2.useContext(...)';的属性';basename';,因为它为空

创建以键值对为有效负载的Redux Reducer时,基于键的类型检测

如何在 Select 文本时停止Click事件?

Reaction Redux&Quot;在派单错误中检测到状态Mutations

有没有一种直接的方法可以深度嵌套在一个JavaScript对象中?

为什么延迟在我的laravel项目中不起作用?

如何在尚未创建的鼠标悬停事件上访问和着色div?

如何检测当前是否没有按下键盘上的键?

如何向内部有文本输入字段的HTML表添加行?