如何限制文本输入为HH:MM格式(最大8小时),输入错误时恢复原值并同步滑块?
问题需求
我需要限制文本输入框的内容为HH:MM格式,同时设置最大小时数(例如最多8小时),禁止输入其他格式。理想状态下,当输入数值超出限制时,不要清空字段,而是恢复到该字段之前的有效值或滑块选中的值。
疑问:是否必须提取文本字段中的第1、2、4、5位数字逐一检查,还是有其他可行方法?
我尝试过的方案
方案1:两个独立输入框
我考虑过用两个独立的文本输入框,中间放静态冒号,分别检查每个输入框的内容,但单个输入框的样式会更简洁。示例代码如下:
document.getElementById('hrs').addEventListener('keyup', function(){ this.value = (parseInt(this.value) < 0 || parseInt(this.value) > 8 || isNaN(this.value)) ? "00" : (this.value) }); document.getElementById('mins').addEventListener('keyup', function(){ this.value = (parseInt(this.value) < 0 || parseInt(this.value) > 59 || isNaN(this.value)) ? "00" : (this.value) }); // 这里需要改成恢复到之前的有效值,而不是固定设为"00" // 我也试过用单个输入框,但不知道如何单独定位前后两位数字,同时忽略冒号
方案2:滑块与文本输入框同步
目前我已经实现了滑块和文本输入框的同步功能,但还没解决格式限制的问题,代码如下:
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer" ></script> <div class="slidecontainer"> <input type="text" id="durationtimestamp" value="00:00" oninput="durationtimestamp(this.value)" required="required"> <input type="range" min="0" max="480" value="0" class="durationslider" id="durationrange" oninput="durationslider(this.value)"> </div>
JavaScript
function durationslider(value) { var hours = Math.floor(value / 60).toLocaleString('en-US', { minimumIntegerDigits: 2, //useGrouping: false }); var minutes = (value % 60).toLocaleString('en-US', { minimumIntegerDigits: 2, //useGrouping: false }); duration = hours+':'+minutes; document.getElementById("durationtimestamp").value = duration; } function durationtimestamp(value) { var myduration = moment.duration(value).asMinutes().toString(); var current = document.getElementById("durationrange").value; document.getElementById("durationrange").value = myduration; }
可行的解决方法(单个输入框实现)
不需要逐位检查数字,通过正则验证+保存历史有效值的方式就能实现,步骤如下:
- 保存输入框的历史有效值,初始值设为
00:00 - 监听输入框的
input事件,用正则匹配验证输入内容是否符合HH:MM格式(小时00-08,分钟00-59) - 输入合法则更新有效值并同步滑块;不合法则直接恢复到历史有效值
修改后的JavaScript代码如下:
// 保存历史有效值 let validDuration = "00:00"; const inputEl = document.getElementById('durationtimestamp'); const sliderEl = document.getElementById('durationrange'); function durationslider(value) { var hours = Math.floor(value / 60).toLocaleString('en-US', { minimumIntegerDigits: 2, }); var minutes = (value % 60).toLocaleString('en-US', { minimumIntegerDigits: 2, }); validDuration = hours + ':' + minutes; inputEl.value = validDuration; } function durationtimestamp(value) { // 正则匹配HH:MM格式,限制小时00-08,分钟00-59 const regex = /^(0[0-8]|[1-8]):([0-5][0-9])$/; const match = value.match(regex); if (match) { // 验证通过,更新有效值并同步滑块 validDuration = value; const totalMinutes = parseInt(match[1]) * 60 + parseInt(match[2]); sliderEl.value = totalMinutes; } else { // 验证不通过,恢复到之前的有效值 inputEl.value = validDuration; } } // 初始化滑块值 sliderEl.value = moment.duration(validDuration).asMinutes();
说明
- 正则表达式
^(0[0-8]|[1-8]):([0-5][0-9])$确保小时范围在00-08,分钟范围在00-59 validDuration变量保存每次的合法输入值,输入无效时直接恢复该值,避免清空或强制设为00- 同步滑块时,将合法的HH:MM转换为总分钟数,保证输入框和滑块状态完全一致
内容的提问来源于stack exchange,提问作者Markus
相关产品推荐
相关产品推荐

