使用纯JavaScript

时间:2015-05-05 16:55:23

标签: javascript formatting

我的文档正文中有一个输入字段,我需要在用户输入时对其进行格式化。区域代码周围应该有括号,之后应该有三位和四位之间的短划线。

例如:(123) 456 - 7890

当用户输入时,它应该类似于:

(12
(123)
(123) 456
(123) 456 - 78
(123) 456 - 7890

10 个答案:

答案 0 :(得分:35)

新ES6答案

您仍然可以使用一些简单的JavaScript来完成此操作。

HTML

<input id="phoneNumber" maxlength="16" />

JavaScript(ES6)

const isNumericInput = (event) => {
    const key = event.keyCode;
    return ((key >= 48 && key <= 57) || // Allow number line
        (key >= 96 && key <= 105) // Allow number pad
    );
};

const isModifierKey = (event) => {
    const key = event.keyCode;
    return (event.shiftKey === true || key === 35 || key === 36) || // Allow Shift, Home, End
        (key === 8 || key === 9 || key === 13 || key === 46) || // Allow Backspace, Tab, Enter, Delete
        (key > 36 && key < 41) || // Allow left, up, right, down
        (
            // Allow Ctrl/Command + A,C,V,X,Z
            (event.ctrlKey === true || event.metaKey === true) &&
            (key === 65 || key === 67 || key === 86 || key === 88 || key === 90)
        )
};

const enforceFormat = (event) => {
    // Input must be of a valid number format or a modifier key, and not longer than ten digits
    if(!isNumericInput(event) && !isModifierKey(event)){
        event.preventDefault();
    }
};

const formatToPhone = (event) => {
    if(isModifierKey(event)) {return;}

    // I am lazy and don't like to type things more than once
    const target = event.target;
    const input = target.value.replace(/\D/g,'').substring(0,10); // First ten digits of input only
    const zip = input.substring(0,3);
    const middle = input.substring(3,6);
    const last = input.substring(6,10);

    if(input.length > 6){target.value = `(${zip}) ${middle} - ${last}`;}
    else if(input.length > 3){target.value = `(${zip}) ${middle}`;}
    else if(input.length > 0){target.value = `(${zip}`;}
};

const inputElement = document.getElementById('phoneNumber');
inputElement.addEventListener('keydown',enforceFormat);
inputElement.addEventListener('keyup',formatToPhone);

如果你想摆弄它:
https://jsfiddle.net/rafj3md0/

声明:
值得注意的是,如果您尝试修改数字的中间部分,由于浏览器在设置元素值后处理克拉位置的方式,这会有点奇怪。解决这个问题是可行的,但是需要的时间比我现在要多,并且有些库可以处理这样的问题。


旧ES5答案

您可以使用快速javascript函数执行此操作。

如果你的HTML看起来像:
<input type="text" id="phoneNumber"/>

您的JavaScript功能可以简单地为:

// A function to format text to look like a phone number
function phoneFormat(input){
        // Strip all characters from the input except digits
        input = input.replace(/\D/g,'');

        // Trim the remaining input to ten characters, to preserve phone number format
        input = input.substring(0,10);

        // Based upon the length of the string, we add formatting as necessary
        var size = input.length;
        if(size == 0){
                input = input;
        }else if(size < 4){
                input = '('+input;
        }else if(size < 7){
                input = '('+input.substring(0,3)+') '+input.substring(3,6);
        }else{
                input = '('+input.substring(0,3)+') '+input.substring(3,6)+' - '+input.substring(6,10);
        }
        return input; 
}

当然,您需要一个事件监听器:

document.getElementById('phoneNumber').addEventListener('keyup',function(evt){
        var phoneNumber = document.getElementById('phoneNumber');
        var charCode = (evt.which) ? evt.which : evt.keyCode;
        phoneNumber.value = phoneFormat(phoneNumber.value);
});

除非您将电话号码存储为格式化字符串(我不建议这样做),否则您需要在提交值之前清除非数字字符:<登记/> document.getElementById('phoneNumber').value.replace(/\D/g,'');

如果您希望通过奖金输入过滤看到这一点,请查看这个小提琴:
http://jsfiddle.net/rm9vg16m/

答案 1 :(得分:7)

早期的答案没有考虑当用户犯错并删除一些输入的数字时会发生什么。

对于那些寻找jQuery解决方案的人来说,这会重新格式化每个keyup事件,并在用户编辑数字时删除其他字符和空格。

$('#phone').keyup(function(e){
    var ph = this.value.replace(/\D/g,'').substring(0,10);
    // Backspace and Delete keys
    var deleteKey = (e.keyCode == 8 || e.keyCode == 46);
    var len = ph.length;
    if(len==0){
        ph=ph;
    }else if(len<3){
        ph='('+ph;
    }else if(len==3){
        ph = '('+ph + (deleteKey ? '' : ') ');
    }else if(len<6){
        ph='('+ph.substring(0,3)+') '+ph.substring(3,6);
    }else if(len==6){
        ph='('+ph.substring(0,3)+') '+ph.substring(3,6)+ (deleteKey ? '' : '-');
    }else{
        ph='('+ph.substring(0,3)+') '+ph.substring(3,6)+'-'+ph.substring(6,10);
    }
    this.value = ph;
});

答案 2 :(得分:1)

我不喜欢切片的东西。我建议使用.replace(),传递一个正则表达式,捕获电话号码,然后按照你需要的方式输出。如果您可以阅读正则表达式,那么它是一种更好的编程方式来解决这个问题,并且很容易改变格式。

var phoneNumber = "1234567899";

var formatted = phoneNumber.replace(/(\d{1,2})(\d{1})?(\d{1,3})?(\d{1,4})?/, function(_, p1, p2, p3, p4){
  let output = ""
  if (p1) output = `(${p1}`;
  if (p2) output += `${p2})`;
  if (p3) output += ` ${p3}`
  if (p4) output += ` ${p4}`
  return output;
});

注意:我没有添加任何类型的空格,非数字剥离,但您也可以添加它。

答案 3 :(得分:1)

我最近偶然发现了同样的问题,这是我使用的解决方案。非常简单,在用户提交表单之前也会检查表单。

function myFunction() {
  var inpField = document.getElementById("myInput");
  var l = inpField.value.length;
  var key = event.inputType;
  var toDelete = (key == 'deleteContentBackward' || key == 'deleteContentForward') ? 'delete' : 'keep';
  //deleteContentBackward and deleteContentForward are obtained when user hits backspace or delete keys. To get extra info from inputType, check: InputEvent https://www.w3schools.com/jsref/obj_inputevent.asp
  if (toDelete === 'delete') {
    alert('Please, enter your number again.');
    // clears the whole input field
    inpField.value = "";
  }
  // then, checks the inputs to add the required pattern. Also helps the user to check if number is typed correctly
  switch (l) {
    case 1:
      inpField.value = "(" + inpField.value;
      break
    case 4:
      inpField.value = inpField.value + ") ";
      break
    case 9:
      inpField.value = inpField.value + " - ";
      break
    case 17:
      // prevents user from typing more numbers than necessary:
      inpField.value = inpField.value.slice(0, l - 1)
  }
}
<form>
  <input type="tel" id="myInput" oninput="myFunction()" placeholder="(###) ### - ####" required pattern="\([0-9]{3}\) [0-9]{3} - [0-9]{4}">
  <!-- oninput is trigued when the input changes, check https://www.w3schools.com/jsref/event_oninput.asp -->
  <!-- Used regex to check the input value before submit from user -->
  <input type="submit">
</form>
(123) 456 - 7890

答案 4 :(得分:0)

为了给用户添加一些额外的便利,我实际上会更新字符串,以便在用户到达某些字符时自动包含“)”或“ - ”,以防止它们添加,比如说两个破折号。 (555)555--5555

if(size === 0) {
    input = input;
} 
else if (size === 3) {
    input = '('+input.substring(0,3)+') '
}
else if (size < 4) {
    input = '('+input;
}
else if (size === 6) {
    input = '('+input.substring(0,3)+') '+input.substring(3,6)+' -';
}
else if (size > 6) {
    input = '('+input.substring(0,3)+') '+input.substring(3,6)+' - '+input.substring(6,10);
}
return input

答案 5 :(得分:0)

let telEl = document.querySelector('#phoneNum')

telEl.addEventListener('keyup', (e) => {
  let val = e.target.value;
  e.target.value = val
    .replace(/\D/g, '')
    .replace(/(\d{1,4})(\d{1,3})?(\d{1,3})?/g, function(txt, f, s, t) {
      if (t) {
        return `(${f}) ${s}-${t}`
      } else if (s) {
        return `(${f}) ${s}`
      } else if (f) {
        return `(${f})`
      }
    });
})
Phone Number: <input type="text" id="phoneNum" maxlength="14" />

答案 6 :(得分:0)

我的观点不足以对@Rey的答案添加评论,但是您无需为了考虑退格键或删除密钥而进行所有操作。您所要做的就是,如果按下了Delete或Backspace键,则按原样返回字符串,因为格式已经存在。

OP要求使用纯JavaScript解决方案,因此我包含了一个用于捕获事件keyCode的函数。如果您遵循@Rey的答案,则可以在jQuery中做到这一点。

document.getElementById('phoneNumber').addEventListener('keyup', function(evt) {
    var charCode = (evt.which) ? evt.which : evt.keyCode;
    if(charCode == 8 || charCode == 46) return true;
    else this.value = formatPhone(this.value);
}, false);

function formatPhone(str) {
    if(str.length == 0) return str;
    if(delKey) return str;
    var phone = '(';
    str = str.replace(/\D/g, '').substring(0,10);
    if(str.length < 3) {
        phone += str;
    } else if(str.length < 6) {
        phone += str.substring(0, 3) + ') ';
        if(str.length > 3) phone += str.substring(3, str.length);
    } else {
        phone += str.substring(0, 3) + ') ' + str.substring(3, 6) + '-' + str.substring(6, 10);
    }
                
    return phone;
}

答案 7 :(得分:0)

这是 React 中的一个简单解决方案。

getFormattedPhonegetDigitOnlyPhone 来自@Legendary_Linux 给出的答案)

我们将格式化的 value 传递给我们的输入,以便它正确显示如下:(123) 456 - 7890

onChange 中,我们使用 getDigitOnlyPhone 传递一串数字,而不是我们格式化的电话号码。

import React from 'react'

const getDigitOnlyPhone = value =>
  value.toString().replace(/\D/g, '').substring(0, 10)

const getFormattedPhone = value => {
  if (!value) return ''

  const phone = getDigitOnlyPhone(value)
  const areaCode = phone.substring(0, 3)
  const middle = phone.substring(3, 6)
  const last = phone.substring(6, 10)

  let formattedPhone = ''
  if (phone.length > 6) {
    formattedPhone = `(${areaCode}) ${middle} - ${last}`
  } else if (phone.length > 3) {
    formattedPhone = `(${areaCode}) ${middle}`
  } else if (phone.length > 0) {
    formattedPhone = `(${areaCode}`
  }

  return formattedPhone
}

export const PhoneInput = ({ value, onChange, ...props }) => (
  <input
    {...props}
    maxLength={16}
    pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
    value={getFormattedPhone(value)}
    onChange={e => {
      const phone = getDigitOnlyPhone(e.target.value)
      if (value || phone) onChange(phone)
    }}
  />
)

答案 8 :(得分:0)

let telEl = document.querySelector('#phoneNum')

telEl.addEventListener('keyup', (e) => {
  let val = e.target.value;
  e.target.value = val
    .replace(/\D/g, '')
    .replace(/(\d{1,4})(\d{1,3})?(\d{1,3})?/g, function(txt, f, s, t) {
      if (t) {
        return `(${f}) ${s}-${t}`
      } else if (s) {
        return `(${f}) ${s}`
      } else if (f) {
        return `(${f})`
      }
    });
})
Phone Number: <input type="text" id="phoneNum" maxlength="14" />

答案 9 :(得分:0)

这个已经发布的方法有效

    const isNumericInput = (event) => {
        const key = event.keyCode;
        return ((key >= 48 && key <= 57) || // Allow number line
            (key >= 96 && key <= 105) // Allow number pad
        );
    };

    const isModifierKey = (event) => {
        const key = event.keyCode;
        return (event.shiftKey === true || key === 35 || key === 36) || // Allow Shift, Home, End
            (key === 8 || key === 9 || key === 13 || key === 46) || // Allow Backspace, Tab, Enter, Delete
            (key > 36 && key < 41) || // Allow left, up, right, down
            (
                // Allow Ctrl/Command + A,C,V,X,Z
                (event.ctrlKey === true || event.metaKey === true) &&
                (key === 65 || key === 67 || key === 86 || key === 88 || key === 90)
            )
    };

    const enforceFormat = (event) => {
        // Input must be of a valid number format or a modifier key, and not longer than ten digits
        if(!isNumericInput(event) && !isModifierKey(event)){
            event.preventDefault();
        }
    };

    const formatToPhone = (event) => {
        if(isModifierKey(event)) {return;}

        const input = event.target.value.replace(/\D/g,'').substring(0,10); // First ten digits of input only
        const areaCode = input.substring(0,3);
        const middle = input.substring(3,6);
        const last = input.substring(6,10);

        if(input.length > 6){event.target.value = `(${areaCode}) ${middle} - ${last}`;}
        else if(input.length > 3){event.target.value = `(${areaCode}) ${middle}`;}
        else if(input.length > 0){event.target.value = `(${areaCode}`;}
    };

    const inputElement = document.getElementById('phoneNumber');
    inputElement.addEventListener('keydown',enforceFormat);
    inputElement.addEventListener('keyup',formatToPhone);

但这要简单得多

    const formatToPhone = (event) => {

        event.target.value=event.target.value.replace(/\D/g,'');//this enforces that input is numeric

        const input = event.target.value.substring(0,10); // First ten digits of input only
        const areaCode = input.substring(0,3);
        const middle = input.substring(3,6);
        const last = input.substring(6,10);

        if(input.length > 6){event.target.value = `(${areaCode}) ${middle} - ${last}`;}
        else if(input.length > 3){event.target.value = `(${areaCode}) ${middle}`;}
        else if(input.length > 0){event.target.value = `(${areaCode}`;}
    };