Format the phone number as a custom type using pure JavaScript
I have an input field in the body of my document and I need to format it by the user type. It should have parentheses around the area code and a dash between three and four digits after that.
Example: (123) 456 - 7890
As a custom type, it should look something like this:
(12
(123)
(123) 456
(123) 456 - 78
(123) 456 - 7890
source to share
New ES6 answer
You can still do this using plain 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);
And if you want to mess around with this:
https://jsfiddle.net/rafj3md0/
Disclaimer:
It's worth noting that it is a little weird if you are trying to change the midpoint of a number due to the way browsers handle carat placement after setting the value of an element. The solution to this problem is doable, but it would take more time than I have now, and there are libraries that handle this kind of thing.
Old ES5 Answer
You can do this with a quick JavaScript function. If your HTML looks like this: <input type="text" id="phoneNumber"/>
Your JavaScript function could simply be:
// 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;
}
Of course, you need an event listener:
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);
});
And if you can't store phone numbers as formatted strings (I don't recommend that), you should strip the non-numeric characters before sending the value something like this: document.getElementById('phoneNumber').value.replace(/\D/g,'');
If you want to see this in action with bonus input filtering check out this fiddle:
http://jsfiddle.net/rm9vg16m/
source to share
Previously, the answers did not take into account what happens when the user makes a mistake and deletes some of the numbers entered.
For those looking for a jQuery solution, it reformats on every keyup event and removes extra characters and spaces when the user edits the number.
$('#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;
});
source to share
I'm not a fan of slicing. My advice would be to use .replace (), pass a regex to it, grab the phone number snippets and then output it however you need it. If you can read the regex, this is a much better programmatic way to approach the problem, and it's dead just to change the format.
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;
});
Note. I haven't added any spaces, but not numbers, but you can add that as well.
source to share
To add some extra lightness to the user, I would actually update the line to automatically include ")" or "-" when the user reaches certain characters so that they don't add, say, two dashes. (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
source to share
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" />
source to share