Skip to content

Instantly share code, notes, and snippets.

@kevinweber
Last active October 20, 2017 00:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevinweber/427deafbfb629f8160b109cffa0fdd6c to your computer and use it in GitHub Desktop.
Save kevinweber/427deafbfb629f8160b109cffa0fdd6c to your computer and use it in GitHub Desktop.
Enforcer.js: Address validation
import {
debounce as T_DEBOUNCE,
} from 'utils/methods';
/**
* T-ENFORCER provides methods to validate strings.
* This is developed with input fields in mind, but it shouldn't be limited to them.
*
* Author: Kevin Weber
*
* Every enforcement method (enforce.zipUs, enforce.phoneNumber, ...) is debounced.
* Thus, if the method is called repeatedly, its execution gets delayed.
*
* "enforce" usage:
* - Call the method of your choice (T_ENFORCER.enforce.methodName).
* - Pass two arguments:
* -- {string} The string to be enforced.
* -- {function} Callback to be called. Enforced string will be passed.
*
* "isValid" usage:
* - Call the method of your choice (T_ENFORCER.isValid.methodName).
* - Pass one argument:
* -- {string} The string to be validated.
*/
let T_ENFORCER = {};
T_ENFORCER._help = {
/**
* Debounce method is used to not immediately enforce changes but wait for a short time.
* @private
*/
debounce: T_DEBOUNCE(function (callback) {
callback();
}, 250),
/**
* Looks for all matches using pattern and concatenates them to a single string.
* @private
*
* @param {string} string Term to be filtered
* @param {string} pattern RegExp-compatible pattern
*
* @returns {string}
*/
filter_concatRegex: function (string, pattern, flags = 'ig') {
let regex = new RegExp(pattern, flags);
let newString = string.match(regex);
if (newString === null) {
return '';
}
// Join parts returned from RegEx match
newString = newString.join('');
return newString;
},
filter_shrinkWhitespace: function (string) {
return string.replace(/\s\s+/g, ' ');
}
};
T_ENFORCER.enforce = {
zipCa: function (originalValue, callback) {
function filter(string) {
let newString = string;
let pattern = '[\\w\\d]';
// Allow only digits (to support 5-letter code and 5+4 codes)
newString = T_ENFORCER._help.filter_concatRegex(string, pattern);
// Enforce maximum of 6 characters
newString = newString.substring(0, 6);
// Enforce uppercase
newString = newString.toUpperCase();
// Add " " after three characters
if (newString.length > 3) {
newString = newString.substr(0, 3) + ' ' + newString.substr(3);
}
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
},
zipUs: function (originalValue, callback) {
function filter(string) {
let newString = string;
let pattern = '[0-9]';
// Allow only digits (to support 5-letter code and 5+4 codes)
newString = T_ENFORCER._help.filter_concatRegex(string, pattern);
// Enforce maximum of 9 digits
newString = newString.substring(0, 9);
// Add "-" if we have a 9-digit zip code
if (newString.length > 5) {
newString = newString.substr(0, 5) + '-' + newString.substr(5);
}
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
},
/**
* Only allow digits, word characters, white spaces, dashes ("-"), slashes ("/").
*/
general: function (originalValue, callback) {
function filter(string) {
let pattern = '[\\w\\d\\s\\-\\/]';
let newString = string.trim();
newString = T_ENFORCER._help.filter_shrinkWhitespace(newString);
newString = T_ENFORCER._help.filter_concatRegex(newString, pattern);
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
},
/**
* Only allow digits, a starting "+", and limit length.
*/
phoneNumber: function (originalValue, callback) {
function filter(string) {
let pattern1 = '[0-9\\+]';
let pattern2 = '(^\\+)?[0-9]?';
let newString = string;
// Only allow digits and "+"
newString = T_ENFORCER._help.filter_concatRegex(newString, pattern1);
// If string has "+", only allow it in first position
newString = T_ENFORCER._help.filter_concatRegex(newString, pattern2);
// Limit length to 19 characters (15 digits + max. 4 international call prefix)
newString = newString.substring(0, 19);
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
},
/**
* Only allow digits.
*/
creditCard: function (originalValue, callback) {
function filter(string) {
let pattern = '[0-9]';
let newString = string;
// Only allow digits
newString = T_ENFORCER._help.filter_concatRegex(newString, pattern);
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
},
/**
* Only allow up to a certain amount of any characters.
*/
maxlength: function (originalValue, limit = null, callback) {
if (limit === null) {
console.warn('No character limit defined.');
}
function filter(string) {
let pattern = `.{0,${limit}}`;
let newString = string;
// Only allow digits
newString = T_ENFORCER._help.filter_concatRegex(newString, pattern, '');
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
},
/**
* Only allow a valid CVV code (i.e. up to four digits).
*/
cvv: function (originalValue, callback) {
function filter(string) {
let pattern = '[0-9]{0,4}';
let newString = string;
// Only allow four digits
newString = T_ENFORCER._help.filter_concatRegex(newString, pattern);
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
},
/**
* Only allow digits, word characters, and:
* !#$%&'*+-/=?^_`{|}~.@
*/
email: function (originalValue, callback) {
function filter(string) {
let pattern = '[\\w\\d!#$%&\'*+-/=?^_\\`{|}~.@]';
let newString = string;
// Validate using pattern from http://emailregex.com/
newString = T_ENFORCER._help.filter_concatRegex(newString, pattern);
return newString;
}
T_ENFORCER._help.debounce(function () {
let enforcedValue = filter(originalValue);
callback(enforcedValue);
});
}
};
T_ENFORCER.isValid = {
general: function (string) {
// Allowed: All digits, word characters, whitespaces, "-", "/"
return !!string.match(/^[\w\d\s\-/]+$/);
},
zipCa: function (string) {
// Allowed formats: K8N 5W6 || K8N5W6
return !!string.match(/^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ](\s)?\d[ABCEGHJKLMNPRSTVWXYZ]\d$/);
},
zipUs: function (string) {
// Allowed formats: 12345 || 12345-6789
return !!string.match(/^[0-9]{5}(?:-[0-9]{4})?$/);
}
};
export default T_ENFORCER;
import Enforcer from './enforcer.js';
T_ENFORCER.enforce.zipUs('stringToBeValidated', function (enforcedString) {
// Callback
console.log(enforcedString);
});
T_ENFORCER.enforce.phoneNumber(element.value, function (value) {
element.value = value;
});
T_ENFORCER.isValid.zipUs('stringToBeValidated');
/**
* Debounce function
* based on https://davidwalsh.name/essential-javascript-functions
*/
var T_DEBOUNCE = function (func, wait, immediate) {
var timeout;
return function () {
var context = this,
args = arguments,
later,
callNow;
later = function () {
timeout = null;
if (!immediate) {
func.apply(context, args);
}
};
callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
func.apply(context, args);
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment