js实现卡号每四位空格分隔

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见方案三)

原文地址:https://www.cnblogs.com/weilantiankong/p/8030249.html