window.onload =function() { document.getElementById("input_num").oninput =function() { this.value =this.value.replace(/\s/g,'').replace(/\D/g,'').replace(/(\d{4})(?=\d)/g,"$1 ");; }; };
方案一: 缺点,光标不能定位
handleKeyUp = () => { const target = document.getElementsByClassName('cardNumber')[0].firstChild target.onkeyup = e => { // 只对输入数字时进行处理 if ((e.which >= 48 && e.which <= 57) || (e.which >= 96 && e.which <= 105)) { // 获取当前光标的位置 const caret = target.selectionStart // 获取当前的value const value = target.value // 从左边沿到坐标之间的空格数 const sp = (value.slice(0, caret).match(/\s/g) || []).length // 去掉所有空格 const nospace = value.replace(/\s/g, '') // 重新插入空格 const curVal = target.value = nospace.replace(/(\d{4})/g, '$1 ').trim() // 从左边沿到原坐标之间的空格数 const curSp = (curVal.slice(0, caret).match(/\s/g) || []).length // 修正光标位置 target.selectionEnd = target.selectionStart = caret + curSp - sp } } }
方案二: 缺点(某些浏览器不工作,部分浏览器删除时光标跳动,如支付宝默认浏览器)
let isDelete = false; // globle param // getCursortPosition const getCursortPosition = (textDom) => { let cursorPos = 0 if (document.selection) { // ie 10 9 8 7 6 5 // IE Support textDom.focus() let selectRange = document.selection.createRange() selectRange.moveStart('character', -textDom.value.length) cursorPos = selectRange.text.length } else if (textDom.setSelectionRange) { // ie 11 10 9 ff safiri chrome // webkit support textDom.focus() cursorPos = textDom.selectionStart } return cursorPos } // setCursorPosition const setCursorPosition = (textDom, pos) => { if (textDom.setSelectionRange) { textDom.focus() textDom.setSelectionRange(pos, pos) } else if (textDom.createTextRange) { // IE Support const range = textDom.createTextRange() range.collapse(true) range.moveEnd('character', pos) range.moveStart('character', pos) range.select() } } export const handleKeyUp = target => { target.onkeyup = () => { const elem = target //for some andriod system keyboard can not input (eg: vivo) setTimeout(() => { const str = elem.value let currentPos = getCursortPosition(elem) let posAfterText = '' let posPreText = '' let isNextBlank = false//the next is blank or not let isPreBlank = false let isLastPos = true if (currentPos != str.length) { // not the last one posAfterText = str.substr(currentPos, 1) posPreText = str.substr(currentPos - 1, 1) isNextBlank = /^\s+$/.test(posAfterText) isPreBlank = /^\s+$/.test(posPreText) isLastPos = false } if (elem.value.length <= 255) { // maxlength elem.value = elem.value.replace(/\s/g, '').replace(/(\w{4})(?=\w)/g, '$1 ') } if (isDelete) { if (isPreBlank) { setCursorPosition(elem, currentPos - 1) } else { setCursorPosition(elem, currentPos) } } else if (!isLastPos) { if (isNextBlank) { setCursorPosition(elem, currentPos + 1) } else { setCursorPosition(elem, currentPos) } } else { setCursorPosition(elem, elem.value.length) } }, 0) } } export const handleKeyDown = target => { target.onkeydown = () => { isDelete = window.event.keyCode == 8// the flag of delete } }
方案三,比较完美的解决方案,支持各种终端浏览器输入, 任意位置删除输入且光标不会跳动。
export const getCursorPosition = textDom => { let cursorPos = 0 if (textDom.setSelectionRange) { // webkit support textDom.focus() cursorPos = textDom.selectionStart } return cursorPos } export const setCursorPosition = (textDom, pos) => { if (textDom.setSelectionRange) { textDom.focus() textDom.setSelectionRange(pos, pos) } } const handleKeyUp = e => { const { target } = e const elem = target // for some andriod system keyboard can not input (eg: vivo) setTimeout(() => { const str = elem.value const currentPos = getCursorPosition(elem) let posAfterText = '' let posPreText = '' let isNextBlank = false// the next is blank or not let isPreBlank = false let isLastPos = true if (currentPos !== str.length) { // not the last one posAfterText = str.substr(currentPos, 1) posPreText = str.substr(currentPos - 1, 1) isNextBlank = /^\s+$/.test(posAfterText) isPreBlank = /^\s+$/.test(posPreText) isLastPos = false } if (elem.value.length <= 50) { // maxlength elem.value = elem.value.replace(/\s/g, '').replace(/(\w{4})(?=\w)/g, '$1 ') } if (e.keyCode === 8) { // delete key if (isPreBlank) { setCursorPosition(elem, currentPos - 1) } else { setCursorPosition(elem, currentPos) } } else if (!isLastPos) { if (isNextBlank) { setCursorPosition(elem, currentPos + 1) } else { setCursorPosition(elem, currentPos) } } else { setCursorPosition(elem, elem.value.length) } }, 0) }
方案三(优化方案, 不支持低版本ie, 支持低版本ie见方案三)