HTML5输入类型为数字的步数更改行为

39

如果我使用type="number"和step="100"的输入字段。 我不希望奇数无效。 我只想让增加或减少的值为100。

<input type="number" min="100" max="999999" step="100" />
如果用户输入了值"199"并提交,由于该值不可被100整除,他/她将会收到一个错误提示。 但是,我使用step值的唯一目的是控制微调框的行为,例如,如果用户点击上方按钮,我希望值199变成200,如果用户点击下方按钮,我希望它变成100。或者最好是将值增加或减少100个单位。 我该如何实现这个功能呢? 我试过像这样使用invalid事件(使用jQuery 1.7.2):
$( "[type='number']" ).bind( 'invalid', function( e ) {
    var el = $( this ),
      val = el.val( ),
      min = el.attr( 'min' ),
      max = el.attr( 'max' );

    if ( val >= min && val <= max ) {
        return false;
    }
} );

但是这会导致表单无法提交。

PS:这是在Fedora 16上使用Google Chrome 20.0.1132.57的情况。


我不确定你能否解决这个问题。你可能需要考虑使用jQuery UI的spinner代替(http://tjvantoll.com/2012/07/15/native-html5-number-picker-vs-jquery-uis-spinner-which-to-use/)。 - TJ VanToll
此外,这可能会有所帮助 -https://dev59.com/D3A75IYBdhLWcg3w0cnx. - TJ VanToll
@mabs 你检查了我的答案吗?我认为我成功地让它按照你“理想”的要求工作了。 - Takit Isy
1
@TakitIsy 抱歉我还没有检查它。 这个问题已经六年了,我已经忘记了。 - mabs
8个回答

9

首先感谢您提出这个非常有趣的问题。在寻找解决方案的过程中,我学到了很多关于HTML5验证的知识。

我的研究发现,HTML5表单验证API具有一组只读的有趣属性,但非常有用,可以实现您想要的功能。

我解决您的问题的方法是首先向表单元素添加novalidate属性,以便我可以控制何时触发验证,然后读取附加到输入的validity对象,以便我可以准确地知道哪些验证错误存在,如果唯一的错误是stepMismatch(这会触发类似199这样的数字的无效性),我可以绕过所有验证过程。否则,我可以使用reportValidity()方法显示正常的HTML验证行为。

这是我想出来的代码,希望能够满足您的需求:

var form = document.querySelector("form")       // Get the form
var input = document.querySelector("#myInput")  // Get the input to validate

form.addEventListener("submit", function(e) {
 e.preventDefault()  // Catch the submit
  // Do the magic
  if(onlyStepMatters(input.validity)){
   form.submit()
  }else {
   form.reportValidity()
  }
})

function onlyStepMatters(validityState) {
  return !(
    validityState.badInput || validityState.customError || validityState. patternMismatch || validityState.rangeOverflow || validityState.rangeUnderflow || validityState.tooLong || validityState.tooShort || validityState.typeMismatch || validityState.valueMissing
    )
    
  /* This is what the object looks like, notice I just skipped the stepMismatch */
  /*
  {
    badInput,
    customError,
    patternMismatch,
    rangeOverflow,
    rangeUnderflow,
    stepMismatch,
    tooLong,
    tooShort,
    typeMismatch,
    valid,
    valueMissing,
  }
  */
}
<form novalidate>
<input type="number" id="myInput" min="0" max="1000" step = "100" placeholder="Enter a number" required/>
<button type="submit">Send</button> 
</form>

我相信这段代码可以根据相同的逻辑进行重构,变得更加简洁,但是我没有足够的时间去思考它。
欢迎提出建设性意见。
希望这有所帮助。

这是一个好主意,但可能使用 setCustomValidity() 而不是捕获表单提交事件会更加简洁。 - phil294
我以前尝试过那个,但是我不记得它为什么会引起问题了。 - Rafik Tighilt
如果您只有一个控件,那么这很好,但是将 novalidate 添加到整个表单会导致您必须手动验证所有其他控件!最好只在特定的输入元素上禁用验证。 - virtualdj

7
我认为你做不到,step和验证紧密联系在一起。将来,您可以覆盖stepUp()stepDown()函数以获得所描述的行为,但我尚未研究过这是否是这些功能的预期用例。我建议在WHATWG邮件列表上发布帖子,特别询问有关这些功能并描述您的用例。
对于当前实际目的,您是否尝试设置step=1并绑定到click事件进行捕捉?我可以看出,在区分“上”和“下”单击之间可能会遇到问题,但这可能是可以克服的。然而,更容易的方法可能是使用text输入,适当设置pattern属性并实现自己的旋转器。

2

我已经试着使用你的代码,尝试实现以下功能:

理想情况下,我希望值可以增加或减少100

最终我编写了一些脚本来完成以下任务:

  • 通过键盘或鼠标检测步进增量或减量,
  • 使用一个remainder变量来存储计算结果:value % 100,
  • 修改inputstep参数和value,
  • 当键盘或鼠标事件结束时,添加回remainder变量,并将step参数重置为1(需要能够提交)。

在此工作片段中,尝试使用箭头(键盘或鼠标)修改输入值,从一个不可被100整除的数字开始:

var remainder = false;
var stepbefore;

$("[type='number']").bind('keydown mousedown', function() {
  // If keyboard Up or Down arrow keys or mouse left button on the arrows
  if (event.keyCode == 38 || event.keyCode == 40 || event.button === 0) {
    // If there is already a change running, exit the function
    if (remainder !== false) return;

    var myStep = this.getAttribute("stepcustom"); // Get my "stepcustom" attribute
    remainder = this.value % myStep;
    this.value = Math.floor(this.value / myStep) * myStep;
    stepbefore = this.step;
    this.step = myStep;
  }
});

$("[type='number']").bind('keyup mouseup', function() {
  if (remainder !== false) {
    this.value = +(this.value) + remainder;
    this.step = stepbefore;
    remainder = false;
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<form>
  <input type="number" min="100" max="999999" step="1" stepcustom="100" />
  <input type="submit" />
</form>

希望这能有所帮助。

现在是这样的。感谢您的评论。 :) - Takit Isy
你可以通过摆脱第二个 $("[type='number']") 并将绑定直接附加到第一个上,以及仅绑定具有正确属性的输入(例如:$("input[type='number'][stepcustom]").bind(...).bind(...))来稍微提高性能。 - Tofandel

1

只需使用step属性,但您可以使用range并在滑块上添加标记,然后使用JavaScript检查附近的值并将其设置。

例如:

function updateTextInput(val) {
  if      (val > 36)  val = 50;
  else if (val > 26)  val = 36;
  else if (val > 20)  val = 26;
  else if (val > 15)  val = 20;
  else if (val >  1)  val = 15;
  document.getElementById('textInput').value = val;
}
<input type='range' min='0' max='50' step='1' name='slide' list="settings" onchange="updateTextInput(this.value);">
<datalist id="settings">
    <option>15</option>
    <option>20</option>
    <option>26</option>
    <option>36</option>
    <option>50</option>
</datalist>
<input type="text" id="textInput" />


0

这里是实现您所需功能所需的代码,我尝试避免重新计算和更改标准行为,因此这应该对其他任何设置(必填、模式、范围等)都是透明的。

我只在Firefox和Chrome上进行了测试,但我相信它应该在任何最近的浏览器上都可以运行。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Disable validity constrains</title>
<!-- avoid highlight due to constrains -->
<style>#qty { box-shadow: unset; }</style>
</head>
<body>
<form>
        <input id="qty" name="num" type="number" min="100" max="1000" step="100">
        <input type="submit">
</form>
<script>
(function() {
        var el = document.getElementById('qty');
        el && el.addEventListener('invalid', function(event) {
                if ('validity' in el) {
                        for (var state in el.validity) {
                                if (state == 'stepMismatch') { continue; }
                                if (el.validity[state]) { return true; }
                        }
                        event.preventDefault();
                        el.form.submit();
                }
        }, true);
})();
</script>
</body>
</html>

0

在 "change" 事件内四舍五入到最接近的有效值

$( "[type='number']" ).change(function () {
   var value = $(this).val());
   var newValue = Math.round(value/100)*100
   if (newValue < 100) {
      newValue = 100;
   }
   if (newValue > 999999) {
      newValue = 999999;
   }
   if (newValue === value ) {
      return;
   }
   $(this).val(newValue)
})

0

尝试使用change()函数...

<form>
    <input type="number" id="number" min="100" max="999999" step="100" />
</form>

$(document).ready(function(){
    $("#number").change(function(a){
        if ($(this).val() % 100 === 0) {
            /* Do something when the number is even */ 
            console.log("EVEN");
        } else {
            /* Or when it's odd (isn't dividable by 100), do ... whatever */ 
            console.log("ODD");
        }
    })
});

我正在使用Bootstrap进行测试,就像您想要的示例一样,当用户点击上升时,值将变为200(从199),当用户点击下降时,值将变为100。

更改可分割性:

if ($(this).val() % 100 === 0) { //Change 100 with what ever you want

0

这是一个简单的JavaScript函数,可以帮助您解决问题
其中prev_num是全局变量
这将适用于增量减量

var perv_num=0;
function ax(z)
{

     let def;
     let mul=10;
     let valu;
     let valucopy=parseInt(z.value);
     let  frst;
     valucopy=((valucopy+100)%100);


         if (parseInt( z.value)<100) 
         {
                  document.getElementById("myNumber").value="";
                  document.getElementById("myNumber").value=100;
         }
         else if(parseInt( z.value)<perv_num)
        {
                  def=parseInt( z.value.length);
                  mul=Math.pow(mul,def-1);
                  frst=(parseInt(z.value[0])*mul);
                  document.getElementById("myNumber").value="";
                  document.getElementById("myNumber").value=frst;
         }
         else if(valucopy  ==0)
         {
                  document.getElementById("myNumber").value="";
                 document.getElementById("myNumber").value=parseInt(z.value)+100;
          }
          else{
                  def=parseInt( z.value.length);
                  mul=Math.pow(mul,def-1);
                  frst=(parseInt(z.value[0])*mul);
                  valu=Math.abs( parseInt(z.value)-frst);
                  valu=100-valu;
                  var number=(parseInt(z.value)+valu);
                  document.getElementById("myNumber").value="";
                  document.getElementById("myNumber").value= number;
              }
              perv_num=parseInt( z.value);
}

而HTML就像这样

    <input type="number" id="myNumber" onchange="ax(this)">

fiddle是https://jsfiddle.net/ecpy5gr0/1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接