(function(){ function count(val, rxp){ const match = val.match(rxp) return match ? match.length : 0 } function passwordStrength(password, options={}) { const opt = Object.assign(options,{ "minLength": 10, "minOther": 3, "texts" : [ 'Too weak', 'Weak password', 'Normal strength', 'Strong password', 'Very strong password' ] }) const len = password.length if (len < opt["minLength"]) { return opt["texts"][0]; } const num = count(password, /\d/g), lower = count(password, /[a-z]/g), upper = count(password, /[A-Z]/g), special = len - num - lower - upper, other = num + special if (lower == 0 || upper == 0 || other < opt["minOther"]) { return opt["texts"][0]; } // Strength is just based on password length if (len < 11) { return opt["texts"][1]; }else if (len < 13) { return opt["texts"][2]; }else if (len < 16) { return opt["texts"][3]; }else if (len >= 16) { return opt["texts"][4]; } // falltrough return opt["texts"][1]; } // auto setup for data-password-strength document.querySelectorAll("input[data-password-strength]").forEach( ($elm) => { $elm.addEventListener("keyup", (e) => { const val = $elm.value; if (val.length > 0) { // check if we have a .password_strength beside the field let $info = $elm.parentNode.querySelector(".password_strength") if (!$info) { $info = document.createElement("span"); $info.classList.add("password_strength"); $elm.parentNode.appendChild($info); } $info.textContent = passwordStrength(val); } }, false) }) document.querySelectorAll("input[data-same-as]").forEach( ($elm) => { const $target = document.querySelector("#"+$elm.dataset.sameAs) if ($target) { $elm.addEventListener("keyup", (e) => { if ($elm.value != $target.value) { $elm.setCustomValidity("Passwords do not match") }else{ $elm.setCustomValidity(""); } }) } }); })();