动手写个数字输入框1:input[type=number]的遗憾

前言

 最近在用Polymer封装纯数字的输入框,开发过程中发现不少坑,也有很多值得研究的地方。本系列打算分4篇来叙述这段可歌可泣的踩坑经历:

  1. 《动手写个数字输入框1:input[type=number]的遗憾》
  2. 《动手写个数字输入框2:起手式——拦截非法字符》
  3. 《动手写个数字输入框3:痛点——输入法是个魔鬼》
  4. 《动手写个数字输入框4:魔鬼在细节——打磨光标位置》

HTML5带来的福利-input[type=number]

<input
    id="age" name="age"
    type="number" step="1" min="0" max="120">
<input
    id="inc"
    type="button" value="增加">
<input
    id="dec"
    type="button" value="减少">

<script>
    /* 工具函数...无视我吧:D */
    const comp =
           (...fns) =>
           (...args) => {
             let len = fns.length
             while (len--){
               args = [fns[len].apply(null, args)]
             }
             return args.length > 1 ? args : args[0]
           }
    const isSome = x => 'undefined' !== typeof x && x !== null
    const invokerImpl =
            n =>
        o =>
            m =>
            (...args) => {
              let args4m = args.splice(0, n)
                , times = parseInt(args[0]) || 1
                , ret = []
              while (times--){
                ret.push(o[m].apply(o, args4m))
              }
              return ret.length > 1 ? ret : ret[0]
            }
    const curry2Partial =
        fn =>
        (...args) => {
            let c = true
                , i = 0
                , l = args.length
                , f = fn
            for (;c && i < l; ++i){
                c = isSome(args[i])
                if (c){
                    f = f(args[i])
                }
            }
            return f
        }
    const invoker = curry2Partial(invokerImpl)
    const invoker0 = invoker(0)
    const $ = invoker(1, document, "querySelectorAll")
    const invoker0AtEl = comp(invoker0, $)

    /* 继续无视我吧:D */
    const invoker0AtAge = invoker0AtEl('#age')

    // input[type=number]提供stepUp和stepDown两个方法来增加和减少数字
    const incAge = invoker0AtAge('stepUp')
            , decAge = invoker0AtAge('stepDown')
    $('#inc').addEventListener('click', incAge)
    $('#dec').addEventListener('click', decAge)
</script>

input[type=number]为我们提供了如下特性:

  1. 限制只能输入[+-0-9.]这几个字符
  2. 输入法(IME)也无法输入非[+-0-9.]的字符
  3. 自动的表单验证
  4. minmax来限制数值的下限和上限;
  5. 提供stepUp和stepDown两个方法实现以编程方式控制数值的增加和减少;
  6. 移动设备上当它获得焦点时,会出现数字键盘;
  7. step设置点击右侧微调按钮的步长(默认为1),可设置为小数、整数或anystep的值除了影响微调按钮的步长外,还影响表单验证信息。
<!-- step为整数时 -->
<input name="age1" type="number"
    step="1" value="1">
<input name="age1" type="number"
    step="1" value="1.1">

<!-- step为小数时 -->
<input name="age2" type="number"
    step="0.1" value="1">
<input name="age2" type="number"
    step="0.1" value="1.1">
<input name="age2" type="number"
    step="0.1" value="1.11">

<!-- step为any时 -->
<input name="age3" type="number"
    step="any" value="1">
<input name="age3" type="number"
    step="any" value="1.1">
<input name="age3" type="number"
    step="any" value="1.11">

<script>
  // 显示 true false
    $('[name=age1]').forEach(el => console.log(el.validity.valid))
  // 显示 true true false
    $('[name=age2]').forEach(el => console.log(el.validity.valid))
  // 显示 true true true
    $('[name=age3]').forEach(el => console.log(el.validity.valid))
</script>

另外,设置为any是让表单验证不受精度限制而已,实际上步长依然为1。

遗憾了我的哥

 到这里我想大家都会发现怎么少了个精度设置呢?确实,input[type=number]并没有为我们提供设置精度的属性或方法。但遗憾的何止是这个呢?

  1. 木有精度精度设置;
  2. 不想要右侧的微调按钮还不行了...
  3. 点击微调按钮和调用stepUpstepDown设置数值确实被限制在minmax区间,但直接输入却不受限制...
  4. 可以输入多个小数点,如2012.12.12;
  5. 设置step=any后,chrome on android的数字键盘居然没了小数点按键。
  6. 设置step=any后,点击微调按钮步长为1,但调用stepUpstepDown则报
Uncaught DOMException: Failed to execute 'stepUp' on 'HTMLInputElement': This form element does not have an allowed value step.

隐藏右侧微调按钮不完全解决方法

Webkit和Gecko下可通过以下的CSS来隐藏右侧微调按钮

/* chrome */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{
    -webkit-appearance: none!important;
    margin: 0;
}
/* Firefox */
input[type=number]{
    -moz-appearance: textfield;
}

IE就没辙了:-(

总结

 也许你会问既然HTML5愿意为我们新增一个全新的input[type=number],为什么偏偏提供一个缺胳膊少腿的呢?只能说得哥情时失嫂意,既然它不满足,那就自己写写看咯:)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Google Dart

Flutte部件目录-基本部件(一)

一个容器首先用padding包围子组件(由decoration中出现的所有边框填满),然后将附加constraints应用于填充范围(将width和height...

3282
来自专栏阿凯的Excel

让你的Excel表动起来!!!

本次是第二次分享广大网友向我提问的经典问题。 本周问题,利用名称管理器完成二维表的匹配返回!让你的表格动起来! 话说!本次解决方案相对复杂,能看明白并且自己会...

2984
来自专栏流媒体人生

mpg文件切片之后,不能播放问题分析

对于大部分mpg文件切片都能正常播放,而少部分mpg切片之后只有第一个切片能播放,后续的切片视频播放均失败,只能播放视频。

932
来自专栏机器学习算法与Python学习

Python:matplotlib

原文链接:http://blog.csdn.net/ywjun0919/article/details/8692018 来源于书籍:《Python科学计算》 ...

3928
来自专栏阿凯的Excel

动态显示下拉框内容

过了冬至,你在北方瑟瑟发抖,我在广东秋风瑟瑟~ 最近小编经常梦回母校~放一张母校的美图! 年底了,又到了预订报刊的时候! 肯定有人会问,这年头还有谁看报刊...

2983
来自专栏Nian糕的私人厨房

《精通CSS:高级Web标准解决方案》 知识点汇总

本篇的内容到这里就全部结束了,常用的 CSS 样式重置文件我已经发到了 GitHub Reset.css,本篇文章知识点来源 精通CSS:高级Web标准解决方案...

853
来自专栏练小习的专栏

可视化格式模型基础应用实例

今天在群里看到一个需求,先放demo <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> ...

19610
来自专栏十月梦想

CSS3动画animation

        animation和上次说的transform动画有点不同,需要进行定义动画规则,而animation则无需受体,自动执行动画,translat...

953
来自专栏牛客网

新鲜出炉的百度-春招-前端面经

1. 自我介绍 2. 项目经验,我说项目名说错了,然后又说了一遍,面试官不知道什么心态的鬼魅一下 3. Html5不同于以前版本的特点 4. Html5新增ap...

36711
来自专栏数据的力量

10个提高你工作效率的Excel技巧

2894

扫码关注云+社区