为了账号安全,请及时绑定邮箱和手机立即绑定

数字表单数据的校验

标签:
Html5 JavaScript

Input[type=number]的兼容性一直不好,无论从样式或是功能,但我还是比较喜欢用的。手上有个项目是后台数据管理系统,业务中涉及到大量的数字数据的填写和提交。以下主要从数据的输入和获取上做了一些兼容测试和分析。

1、浏览器兼容性

1)测试内容:[10e2, 10 0 ,10.10.10,.99,99.,+.99,-.99,.+99,.-99,+-99,-+99,a9,9a]

2)测试结果:

① Chrome、Opera

只可输入“数字0到9,+,-,.,e”,其它字符禁止输入;
所见即所得,界面的显示和js获取到的数据一致。

② FireFox、Edge、Safari

可输入任意字符;
若值非数字则会弹出警告并阻止表单提交(submit事件);
所见可能非所得(如9a获取到的是空字符串)。
注:Edge与FireFox、Safari有一处不同点,就是会自动忽略value两侧的空格,而FireFox和Safari会直接给出非数字警告。

③ IE10+

可输入任意字符;
若值非数字,不会提示,而是默默做点儿隐示处理,以数字打头的内容直接通过,以+-号开头的先判断正负号是否使用正确,然后再判断后面是否以数字打头,其它字符开头貌似均为空(如9a保持原样,a9获取到的是空);
所见可能非所得(如a9获取到的是空字符串)。
图片描述

④ Safari低版本、IE9及以下

不支持number类型

2、问题梳理

1)当input的type设置为number时,IE和Safari低版本会自动将其置为text,虽然它们的用户比例较低,但毕竟是系统自带浏览器,目前还是得兼容一下的。所以首选要让它们具有min和max属性的功能;

2)关于可输入字符,显然应该以Chrome和Opera为榜样,要补足其它浏览器的短板,需要监听input或propertychange事件,当监测到非法字符时便将其丢弃。但因为我的项目中输入框太多,我觉得绑定这种事件影响性能,而且我公司的管理系统多是带着主机(预装了Chrome)一起出售,所以这个问题忽略,统一将数据校验放在提交时处理;

3)关于所见非所得,即JS获取到的input的value值与界面不一致。可以监听input的change事件,当输入无效数字时(event.currentTarget.validity.valid===false),给其添加红色边框作为警告。此处还是因为我觉得我项目中没必要,所以忽略;

4)关于提交时的数据校验,因为部分情况下浏览器自己会阻塞submit事件,所以只需对漏网之鱼进行捕杀:IE、Safari;

5)除了以上的通常情况外,我们项目中还有一些“个体特色”需要处理:

① 后端貌似对传过去的数据做了些处理,导致并不支持用科学计数法表示的数字(如1e2),所以所有浏览器都需要对此进行校验。

② 后端会将末尾以.结束的数字(如9.)认成小数,这个也需要处理。默认情况下Chrome、FireFox、Opera会自动忽略末尾的点,JS获取到的只是9。

注:数据库应该是支持科学计数法的,我用MySQL做了下测试,效果如图所示。对于哪种算数字,我想浏览器厂商和数据库厂商都应该是考虑统一的。另外,末尾以点结尾也是支持的。
图片描述

3、解决问题
var UA=navigator.userAgent;
var IsSafari=UA.indexOf("Safari")>-1 && UA.indexOf("Version")>-1;
var isIE = window.ActiveXObject != undefined && UA.indexOf("MSIE") != -1;
var hasError=false;
// Safari和IE浏览器校验非数字
if (IsSafari || isIE){
    var elements=IsSafari?$('#add_record input[type="number"]'):$('#add_record input[min]');
    elements.each(function(i,v){
        var res= $.trim($(v).val()),
            min= $(v).attr("min")==undefined?-Infinity:$(v).attr("min"),
            max= $(v).attr("max")==undefined?Infinity:$(v).attr("max"),
            step= $(v).attr("step")==undefined?1:$(v).attr("step");
        if (res!=="") {
            var num=parseFloat(res);
            if (!/^[+-\d]?\d*[\.]?\d+$/.test(res) || isNaN(num)) {
                $(v).parent().addClass("has-error");
                $(v).one("change",function(){
                    $(this).parent().removeClass("has-error");
                });
                hasError=true;
            }else if (num>=min && num<=max && (num*10000)%(step*10000)==0) {
                $(v).val(num);
            }else{
                $(v).parent().addClass("has-error");
                $(v).one("change",function(){
                    $(this).parent().removeClass("has-error");
                });
                hasError=true;
            }
        }else{
           $(v).val(""); 
        }
    });
}else{
// 其它浏览器校验科学计数法
    var elements=$('#add_record input[type="number"]');
    elements.each(function(i,v){
        var res= $.trim($(v).val());
        if (res!=="") {
            // /\.$/.test(res)是为了兼容Edge
            if (/e/.test(res)||/\.$/.test(res)) {
                $(v).parent().addClass("has-error");
                $(v).one("change",function(){
                    $(this).parent().removeClass("has-error");
                });
                hasError=true;
            }
        }else{
           $(v).val(""); 
        }
    });
}
if (hasError) {
    Messager("系统提示", "检查数据填写有误,请核实!");
    return;
}
4、花絮

1)网上看到有人说有的国家小数点是逗号,通过lang属性可以对FireFox下的input[type=number]产生作用,切换它对逗号的支持。

测试数据:“9,9”“,9”、“9,”
测试结果:
默认情况下FireFox是不支持逗号的,当将lang属性设置为fr时,它会默默将逗号等价为点,比如“9,9”用JS获取到的value为9.9。
图片描述

2)Input[type=number]为什么只支持十进制?因为其它进制没什么应用场景?

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
37
获赞与收藏
70

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消