1

I am attempting to implement an auto-formatter in JS, such that if I have a given value (e.g. 12345678) and I have a given format (e.g. XX.XX.XX OR XX-XX-XX OR XX/XX/XX OR XXX-XXXX), I can auto-format my initial value to any of the given formats.

The required format will vary, so it needs to be able to take any given format and reformat the original value to match.

I have no idea if its possible or how to go about it. Any help appreciated.

Thanks,

Clara

2
  • 3
    What makes you think a regex could be useful ? And please precise what would be the results with the format you give. Commented Jan 9, 2013 at 8:45
  • thanks guys, in the end I went with dystroy's solution because that is what I used to implement the requirement this time. Macek's version will come in handy soon enough, so thank you also macek. Commented Jan 9, 2013 at 23:25

3 Answers 3

18

This should work for you

var value = '12345678';

// 12345678 => 12.34.56.78
console.log(value.replace(/(\d{2})(?=\d)/g, '$1.'));

// 12345678 => 12/34/56/78
console.log(value.replace(/(\d{2})(?=\d)/g, '$1/'));

// 12345678 => 12-34-56-78
console.log(value.replace(/(\d{2})(?=\d)/g, '$1-'));

// 12345678 => 1234-5678
console.log(value.replace(/(\d{4})(?=\d)/g, '$1-'));

// a more complex format (create US phone number)
// 1234567890 => +1 (123)-456-7890
console.log('1234567890'.replace(/^(\d{3})(\d{3})(\d{4})$/g, '+1 ($1)-$2-$3'));
Sign up to request clarification or add additional context in comments.

1 Comment

I think this is the best answer for the original question (using regex that is).
12

Something like this ?

function format(mask, number) {
   var s = ''+number, r = '';
   for (var im=0, is = 0; im<mask.length && is<s.length; im++) {
     r += mask.charAt(im)=='X' ? s.charAt(is++) : mask.charAt(im);
   }
   return r;
}    

console.log(format('XX.XX.XX', 12345678)); // logs "12.34.56" 
console.log(format('XXX-XXXX', 12345678)); // logs "123-4567"
console.log(format('XX-XX-XX', 12345678)); // logs "12-34-56 "
console.log(format('XX/XX/XX', 12345678)); // logs "12/34/56"
console.log(format('XX/XX/XX/XX/XX', 12345678)); // logs "12/34/56/78"

No regex engine was harmed in the making of this code.

Fiddle

3 Comments

You may want to mention that array-like access to strings (string[x]) doesn't work on older browsers. .charAt() is a alternative.
Works great in many browsers but on iOS (iphone, ipad, etc) do not work. Returns empty.
If anyone is looking for a version of this to use in React's onChange you can use this: const format = (mask: string, value: string) => { const formatChars = mask .split("") .filter((c) => c !== "X") .join(""); let s = "" + value, r = ""; for (let im = 0, is = 0; im < mask.length && is < s.length; im++) { r += mask.charAt(im) == "X" || formatChars.includes(s.charAt(im)) ? s.charAt(is++) : mask.charAt(im); } return r; }; export default format;
0

You can build a regex from a format, automatically, like this:

var format = 'XX-XX-XX';
var string = '111111';
var regex = '';

for(var i = 1; format.indexOf('X') >= 0; i++){
    format = format.replace('X', '$'+i);
    regex += '(\\d)'; // to match a digit enclosed in ()
}

Or as a function:

function format(string, format){
    var regex = '';

    for(var i = 1; format.indexOf('X') >= 0; ++i){
        format = format.replace('X', '$'+i);
        regex += '(\\d)';
    }
    regex += '[^]*'; // Match the rest of the string to crop characters overflowing the format.
// Remove this ^ line if you want `format('12345678', 'XX/XX/XX')` to return `12/34/5678` instead of `12/34/56`;
    return string.replace(new RegExp(regex), format);
}


console.log(format('111111', 'XX-XX-XX'));  // 11-11-11
console.log(format('111111', 'XX.XX.XX'));  // 11.11.11 
console.log(format('1111111', 'XXX-XXXX')); // 111-1111
console.log(format('111111', 'XX-XX-XX'));  // 11-11-11
console.log(format('111111', 'XX/XX/XX'));  // 11/11/11
console.log(format('123456789', 'XX/XX/XX'));  // 12/34/56 (789 are cropped off.)

1 Comment

format('12345678', 'XX/XX/XX') gives 12/34/5678. Is that intended ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.