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及以下
2、问题梳理不支持number类型
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。
3、解决问题注:数据库应该是支持科学计数法的,我用MySQL做了下测试,效果如图所示。对于哪种算数字,我想浏览器厂商和数据库厂商都应该是考虑统一的。另外,末尾以点结尾也是支持的。
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]为什么只支持十进制?因为其它进制没什么应用场景?