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

Posted

技术标签:

【中文标题】HTML5 输入类型=数字更改步骤行为【英文标题】:HTML5 input type=number change step behavior 【发布时间】:2012-07-29 03:18:30 【问题描述】:

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

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

如果用户输入值“199”并提交,他/她会收到错误,因为该值不能被 100 整除。 但是我想要的步长值只是控制微调器的行为,例如如果用户点击向上,我希望值 199 变为 200,如果他/她点击向下,我希望它变为 100。或者理想情况下,我希望值增加或减少 100。

我该怎么做? 我尝试像这样使用无效事件(使用 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 的微调器 (tjvantoll.com/2012/07/15/…)。 这也可能有帮助 - ***.com/questions/3090369/…. @mabs 你检查我的答案了吗?我想我设法让它像你“理想地”想要的那样工作。 @TakitIsy 抱歉,我还没有检查出来。这个问题是 6 岁,我已经忘记了。 【参考方案1】:

我不认为你可以,step 和验证是closely tied together。将来您可能能够覆盖stepUp() and stepDown() functions 以获得您描述的行为,但我尚未研究这是否是这些事情的预期用例。我建议在WHATWG mailing list 上发帖,专门询问这些功能并描述您的用例。

对于当前的实际目的,您是否尝试过设置 step=1 并绑定到要捕获的 click 事件?我可以看到区分“向上”和“向下”点击可能会有问题,但这可能是可以克服的。不过,使用text 输入、适当设置pattern 属性并实现您自己的微调器可能更容易。

【讨论】:

【参考方案2】:

只有一步,但您可以使用范围并为滑块添加标记,然后使用 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" />

【讨论】:

【参考方案3】:

我一直在玩你的代码,试图实现这一点:

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

…最后得到了一些脚本:

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

在这个工作的 sn-p 中,尝试使用箭头(在键盘上或使用鼠标)修改输入值,从一个不能被 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>

希望对你有帮助。

【讨论】:

@hev1 现在是。感谢您的评论。 :) 您可以通过去掉第二个$("[type='number']") 并将绑定直接附加到第一个以及仅绑定到具有正确属性的输入来稍微提高性能(例如:@987654332 @)【参考方案4】:

嗯,首先感谢您提出这个非常有趣的问题。通过搜索您的问题的解决方案,我学到了很多关于 html5 验证的知识。

我的研究使我发现 HTML5 表单验证 API 有一个 interesting set of properties,它是只读的,但对于做你想做的事情非常有用。

我对您的问题的处理方法是首先将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() 而不是捕获表单提交事件会更干净 我当时试过那个,但我不记得为什么它会导致问题。 如果您只有一个控件,这很好,但是将novalidate 添加到整个表单会导致您必须手动验证所有其他控件!最好只在特定输入元素上禁用验证。【参考方案5】:

这是实现您所要求的所需的代码,我试图避免重新计算和更改标准行为,因此这对于任何其他将设置的约束(必需、模式、范围......)应该是透明的。

我只在 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>

【讨论】:

【参考方案6】:

在“更改”事件中四舍五入到最接近的有效值

$( "[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)
)

【讨论】:

【参考方案7】:

尝试使用 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");
        
    )
);

我正在使用引导程序对其进行测试,就像您想要的示例一样,当用户单击时,值将变为 200(从 199),当用户单击时,值将变为 100

改变可分性:

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

【讨论】:

【参考方案8】:

这是一个简单的javascript函数,可以帮助你 其中 prev_num 是全局变量 这适用于 incrementdecrement 两者

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)">

小提琴是https://jsfiddle.net/ecpy5gr0/1

【讨论】:

以上是关于HTML5 输入类型=数字更改步骤行为的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 jQuery DataTables 输入行为

如何更改 HTML5 日期输入字段的模式? [复制]

如果有空格或非数字字符,HTML5 输入类型 = 数字值在 Webkit 中为空?

更改 AngularJS ngTrim 行为

HTML输入类型编号 - 如何知道“步骤”功能触发更改事件?

闪亮的反应式下拉菜单行为不端(带有数字输入)