Skip to content

Instantly share code, notes, and snippets.

@hartzis
Created September 5, 2014 15:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hartzis/6ae1980d3e90faf2c969 to your computer and use it in GitHub Desktop.
Save hartzis/6ae1980d3e90faf2c969 to your computer and use it in GitHub Desktop.
Beautiful password validation from stackexchange, 8 chars, 1 upper, 1 lower, 1 special
// Hold functions related to client side password validation
var password = function () {
var minPasswordLength = 8;
var _hasLowerCase = /[a-z]/;
var _hasUpperCase = /[A-Z]/;
var _hasDigit = /\d/;
var _hasNonWord = /(_|[^\w\d])/;
var password = [];
var password2 = [];
var email = [];
var vanity = [];
var error = $('<span class="pw-error"></span>');
var error2 = $('<span class="pw-error">Passwords do not match.</span>');
var enableForm = function () {
$('input[type="submit"]').removeAttr('disabled');
};
// Enforces that password2 = password, and display an error message if it does not
var mustMatch = function () {
error2.detach();
if (password.val().length == 0) { return; }
if (password.val() != password2.val()) {
password2.after(error2);
return;
}
enableForm();
};
// Counts the # of unique characters in this password
var uniqueCharacters = function (pw) {
var hash = {};
for (var i = 0; i < pw.length; i++)
hash[pw[i]]++;
var ret = 0;
for (var p in hash) {
if (hash.hasOwnProperty(p)) {
ret++;
}
}
return ret;
};
// Enforces server side password rules, inline on the client for convenience
var enforceRules = function () {
error.detach();
var pw = password.val().toLowerCase();
if (pw.length == 0) { return; }
var hasLower = _hasLowerCase.test(password.val());
var hasUpper = _hasUpperCase.test(password.val());
var hasDigit = _hasDigit.test(password.val());
var hasNonWord = _hasNonWord.test(password.val());
var charClassCount = 0;
if (hasLower) charClassCount++;
if (hasUpper) charClassCount++;
if (hasDigit) charClassCount++;
if (hasNonWord) charClassCount++;
if (charClassCount < 3) {
var nag = 'Add';
if (!hasUpper) nag += ' upper case,';
if (!hasLower) nag += ' lower case,';
if (!hasDigit) nag += ' numbers,';
if (!hasNonWord) nag += ' special characters,';
nag = nag.substr(0, nag.length - 1) + '.';
nag = nag.replace(/(.*),/, '$1, or');
error.text(nag);
password.after(error);
return;
}
if (email.length != 0 && email.val().length > 0 && (pw.indexOf(email.val().toLowerCase()) != -1 || email.val().toLowerCase().indexOf(pw) != -1)) {
error.text('Cannot match your account name.');
password.after(error);
return;
}
if (vanity.length != 0 && vanity.val().length != 0 && (pw.indexOf(vanity.val().toLowerCase()) != -1 || vanity.val().toLowerCase().indexOf(pw) != -1)) {
error.text('Cannot match your vanity identifier.');
password.after(error);
return;
}
var uniqueChars = uniqueCharacters(password.val());
if (uniqueChars < minPasswordLength) {
var remaining = minPasswordLength - uniqueChars;
error.text('Must contain at least ' + remaining + ' more unique characters.');
password.after(error);
return;
}
// don't bother enforcing this until the password is actually *good*
mustMatch();
};
return {
// hook all password/password2 fields on a page
init: function () {
password = $('input[name="password"]');
password2 = $('input[name="password2"]');
email = $('input[name="email"]');
vanity = $('input[name="vanity"]');
if (password.length == 0 || password2.length == 0) return;
password.keyup(enforceRules);
password2.keyup(enforceRules);
if (vanity.length != 0) vanity.blur(enforceRules);
}
};
} ();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment