Skip to content

Instantly share code, notes, and snippets.

@joepuzzo
Last active October 27, 2020 14:10
Show Gist options
  • Save joepuzzo/47a158632530d7726b19d4b60773e2b2 to your computer and use it in GitHub Desktop.
Save joepuzzo/47a158632530d7726b19d4b60773e2b2 to your computer and use it in GitHub Desktop.
const getFormatter = (formatter, value) => {
// If mask is a string turn it into an array;
if (typeof formatter === 'string') {
return formatter.split('').map((char) => {
if (char === '#') {
return /\d/;
}
if (char === '*') {
return /[\w]/;
}
return char;
});
}
// If mask is a function use it to genreate current mask
if(typeof formatter === 'function'){
return formatter(value);
}
if(Array.isArray(formatter)){
return formatter;
}
// Should never make it here throw
throw new Error('Formatter must be string, array, or function')
}
const matchingIndex = ( a, b ) => {
let i = 0;
let mi = -1;
let matching = true;
// a = "+1 "
// b = "+12"
while(matching && i < a.length ){
if( a[i] == b[i] ){
mi = i;
} else {
matching = false;
}
i = i +1;
}
return mi;
}
const format = ( value, frmtr ) => {
console.log('Formatting', value);
// Null check
if( !value ){
return value;
}
// Generate formatter array
const formatter = getFormatter( frmtr, value );
// Start to fill in the array
// Example: phone formatter
// formatter =['+', '1', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/]
// value examples:
// "1231231234 ----> +1 123-123-1234
// "+" ----> +
// "+1" ----> +1
// "+2" ----> +1 2
// "1" ----> +1 1
// "1234" ----> +1 123-4
// "123a" ----> +1 123
// Determine prefix length and suffix start
const prefixLength = formatter.findIndex( v => typeof v != 'string');
const suffixStart = formatter.length - [...formatter].reverse().findIndex( v => typeof v != 'string');
// Formatted value
let formatted = [];
// The characters from the current value
const chars = value.split('');
// To track the value index during itteration
let vIndex = 0;
let start = 0;
// If the value matches part of the prefix take it out
// Example prefix = "+1 " value = ["+1 123-123-1234", "+12", "+2"]
const matchIndex = matchingIndex(formatter.slice(0, prefixLength), chars.slice(0, prefixLength));
console.log('Matching index', matchIndex);
if( matchIndex > -1 ) {
//vIndex = prefixLength;
vIndex = matchIndex + 1;
formatted = formatted.concat(formatter.slice(0,matchIndex + 1));
start = matchIndex + 1;
}
// Example prefix = "+1 " value=["1", "1234"]
if( matchIndex < 0 ){
// Start past the prefix
formatted = formatted.concat(formatter.slice(0,prefixLength));
start = prefixLength;
}
// console.log('start', start, formatted);
// console.log('PREFIX_LENGTHT', prefixLength);
// console.log('SUFIX_START', suffixStart);
// console.log('FORMATTER_LENGTH', formatter.length);
// To track if we have made it past the prefix
let pastPrefix = false;
// Fill in the stuff
for(let i = start; i < formatter.length; i++ ){
// Get current formatter location matcher
const matcher = formatter[i];
// We get past the prefix if matcher is not a string
if( !pastPrefix && typeof matcher != "string" ){
pastPrefix = true;
}
// Chec to see if there is more value to look at
if( vIndex != chars.length ){
// Get the current value character
const curChar = chars[vIndex];
// If type is string normal compare otherwise regex compare
const match = typeof matcher === "string" ? matcher === curChar : matcher.test(curChar);
// If the current character of the value matches and matcher is a string
// "1" === "1"
if( match && typeof matcher === "string" ){
formatted.push(matcher);
//if( pastPrefix ){
vIndex = vIndex + 1;
//}
}
// If the current character does not match and matcher is a stirng
// "1" != "+"
else if( !match && typeof matcher === "string"){
// Special check for 123a ---> dont want "+1 123-"
// Special check for 1234 ---> DO want "+1 123-4"
if( vIndex != chars.length) formatted.push(matcher);
}
// If the current character matches and the matcher is not a string
// /\d/.test("2")
else if( match && typeof matcher != "string" ) {
formatted.push(curChar);
vIndex = vIndex + 1;
}
// If the current character does NOT match and the matecer is regex
// /\d/.test("a")
else if( !match && typeof matcher != "string" ){
// Throw out this value
vIndex = vIndex + 1;
i = i - 1;
}
} else {
// If mattcher is a string and we are at suffix keep going
if( typeof matcher === "string" && i >= suffixStart ){
formatted.push(matcher);
} else {
// Otherwise we want to break out
break;
}
}
}
return formatted.join("");
}
const fmtr = ['+', '1', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/];
// undefiend ----> undefined
console.log( format(undefined, fmtr) );
console.log('\n');
// "1231231234 ----> +1 123-123-1234
console.log( format("1231231234", fmtr) );
console.log('\n');
// "+" ----> +
console.log( format("+", fmtr) );
console.log('\n');
// "+1" ----> +1
console.log( format("+1", fmtr) );
console.log('\n');
// "+11" ----> +1 1
console.log( format("+11", fmtr) );
console.log('\n');
// "+2" ----> +1 2
console.log( format("+2", fmtr) );
console.log('\n');
// "1" ----> +1 1
console.log( format("1", fmtr) );
console.log('\n');
// "1234" ----> +1 123-4
console.log( format("1234", fmtr) );
console.log('\n');
// "+1 123-456" ----> +1 123-456
console.log( format("+1 123-456", fmtr) );
console.log('\n');
// "+1 123-456-" ----> +1 123-456-
console.log( format("+1 123-456-", fmtr) );
console.log('\n');
// "123-456-" ----> +1 123-456-
console.log( format("123-456-", fmtr) );
console.log('\n');
// "123a" ----> +1 123
console.log( format("123a", fmtr) );
console.log('\n');
// "123a456B78" ----> +1 123-456-78
console.log( format("123a456b78", fmtr) );
console.log('\n');
// "123abc456B78" ----> +1 123-456-78
console.log( format("123abc456b78", fmtr) );
console.log('\n');
// "+1 123-a" ----> +1 123-
console.log( format("+1 123-a", fmtr) );
console.log('\n');
// "123-a" ----> +1 123-
console.log( format("123-a", fmtr) );
console.log('\n');
// "1234567812345678" ----> "1234-5678-1234-5678"
console.log( format("1234567812345678", "####-####-####-####") );
console.log('\n');
// "3000" ----> "$3,000.00&"
console.log( format("3000", "$#,###.00&") );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment