当前位置: 首页 > Web前端 > HTML5

手写一个数字输入框2:入门-拦截非法字符

时间:2023-04-05 00:56:09 HTML5

前言最近用Polymer封装了纯数字的输入框。开发过程中,发现不是坑,还有很多值得研究的地方。本系列将分4篇来讲述这段史诗般的踩坑经历:《动手写个数字输入框1:input[type=number]的遗憾》《动手写个数字输入框2:起手式——拦截非法字符》《动手写个数字输入框3:痛点——输入法是个魔鬼》《动手写个数字输入框4:魔鬼在细节——打磨光标位置》从源头入手——拦截非法字符从《动手写个数字输入框1:input[type=number]的遗憾》我们了解到input[type=number]基本不能满足我们的需求,为了简化,我们直接在input[type=text]上处理我们自己的数字输入框。首先很清楚,最终值可以包含以下字符[+-0-9.],可以输入的功能键有Backspace、Delete、Arrow-Left、Arrow-Right、Arrow-Up、向下箭头和制表符。所以我们可以设置如下规则//AssertionlibraryconstkeyCode=anyPass(prop('keyCode'),prop('which'))constisBackspace=eq(8),isDelete=eq(46),isArrowLeft=eq(37),isArrowRight=eq(38),isArrowUp=eq(39),isArrowDown=eq(40),isTab=eq(9),isMinus=anyPass(eq(109),eq(189)),isDot=anyPass(eq(110),eq(190)),isDigit=anyPass(allPass(lte(49),gte(57)),allPass(lte(96),gte(105))),isPlus=anyPass(comp(eq(107)),keyCode),allPass(prop('shiftKey'),comp(eq(187),keyCode)))constisValid=anyPass(comp(anyPass(isBackspace,isDelete,isArrowLeft,isArrowLeft,isArrowUp,isArrowDown,isTab,isMinus,isDot,isDigit),keyCode),isPlus)$('input[type=text]').addEventListener('keydown',e=>{如果(!isValid(e)){e.preventDefault()}})扩展非法字符集还记得最小值、最大值、精度吗?当min大于等于0时,负号应该包含在非法字符中;当max小于0时,非法字符应包含正号;精度为0时,非法字符应包含小数点所以我们添加如下规则,修改isValid。//获取最小值、最大值、精度值constlensTarget=lens(a=>a.target||a.srcElement),lensMin=lens(a=>Number(a.min)||Number(attr(a,'min'))||Number.MIN_SAFE_INTEGER),lensMax=lens(a=>Number(a.max)||Number(attr(a,'max'))||Number.MAX_SAFE_INTEGER),lensPrecision=lens(a=>Number(a.precision)||Number(attr(a,'precision'))||0),lensValue=lens(a=>a.value)constlensTargetMin=lcomp(lensTarget,lensMin),lensTargetMax=lcomp(lensTarget,lensMax),lensTargetPrecision=lcomp(lensTarget,lensPrecision)constisValid=anyPass(comp(anyPass(isBackspace,isDelete,isArrowLeft,isArrowLeft,isArrowUp,isArrowDown,isTab,isDi,keyCode),allPass(comp(gt(0),view(lensTargetMin)),comp(isMinus,keyCode)),allPass(comp(lte(0),view(lensTargetMax)),isPlus),allPass(comp(lt(0),view(lensTargetPrecision)),comp(isDot,keyCode)))预判断至此我们成功拦截了各种非法字符,即最终值必须包含[+-0-9.],但是这些是两个字符和整体要符合数值格式是不同的,所以我们需要继续添加下面两步,并且由于触发keydown事件时value值还没有被修改,所以我们需要结合value值用当前的输入值做预测,进一步扩展Illegalcharacterset。通过正则化检查最终值是否满足格式要求(是否有多个小数点也会在这一步处理);检查最终值是否在最小值和最大值范围内。constisValidStr=precision=>a=>RegExp("^[+-]?[0-9]*"+(precision?"(\\.[0-9]{0,"+precision+"})?":"")+"$").test(a)constlensValue=lens(a=>a.value),lensTargetValue=lcomp(lensTarget,lensValue)$('input[type=text]').addEventListener('keydown',e=>{varprevented=true//拦截非法字符if(isValid(e)){prevented=false//预判断if(anyPass(comp(anyPass(isMinus,isDigit,isDot),keyCode),isPlus)(e)){varstr=view(lensTargetValue)(e)+prop('key')(e)//preventedformat=!isValidStr(view(lensTargetPrecision)(e))(str)//预判断取值范围if(!prevented){if(str=='-')str='-0'if(str=='+')str='0'if(str=='.')str='0'prevented=!allPass(gte(view(lensTargetMax)(e)),lte(view(lensTargetMin)(e)))(Number(str))}}}if(prevented){e.preventDefault()}})附录:工具函数//工具函数,请忽略我:Dconstcomp=(...fns)=>(...args)=>{letlen=fns.lengthwhile(len--){args=[fns[len].apply(null,args)]}returnargs.长度>1?args:args[0]}constisSome=x=>'undefined'!==typeofx&&x!==nullconstinvokerImpl=n=>o=>m=>(...args)=>{让args4m=args.splice(0,n),时间=Number(args[0])||1,ret=[]while(times--){vartmpRettry{tmpRet=o[m].apply(o,args4m)}catch(e){tmpRet=void0}ret.push(tmpRet)}returnret.length>1?ret:ret[0]}constcurry2Partial=fn=>(...args)=>{让c=true,i=0,l=args.length,f=fnfor(;c&&iargs.reduce((accu,x)=>accu&&x,true)const或=(...args)=>args.reduce((accu,x)=>accu||x,false)constallPass=(...fns)=>v=>fns.reduce((accu,x)=>accu&&x(v),true)constanyPass=(...fns)=>v=>fns。reduce((accu,x)=>accu||x(v),false)consteq=a=>b=>a===bconstgt=a=>b=>a>bconstgte=a=>anyPass(eq(a),gt(a))constlt=a=>b=>aanyPass(eq(a),lt(a))constprop=k=>o=>o[k]constlens=(g,s)=>({getter:g,setter:s})constlensPath=(...args)=>({getter:a=>args.reduce((accu,x)=>accu&&accu[x],a)})constlcomp=(...lenses)=>({getter:a=>lens.reduce((accu,lens)=>accu&&lens.getter(accu),a)})constview=l=>a=>l.getter(a)const$=invoker(1,document,"querySelector")constattr=(o,a)=>invoker(1,o,'getAttribute')(a)总结现在你终于可以牢牢把握住用户输入了,直到用户切换到IME:-<当使用IME输入时你会发现上面的措施根本没用,别皱眉头,我们以后一起KOIME!尊重原创,转载请注明出处:http://www.cnblogs.com/fsjohn...^_^FatBoyJohn