Рассмотрим случай, когда валидация пароля и показ ошибок происходит до отправки и проверки на сервер.
Как выводить ошибку ввода пароля?
Начинаем уже по традиции с написания HTML:
<div class="personal-form-wrap"> <div class="password-title">Для зміни пароля, придумайте і введіть новий пароль</div> <div id="errors" class="error"><pre></pre></div> <form class="profile__form" method="POST" enctype="multipart/form-data"> <input type="hidden" name="profile" value="update"> <div class="profile__form-row"> <div class="form-input-item"> <input id="myPassword" type="password" placeholder="Пароль" class="form-input jqPassField" name="password" value="" style="border: 2px solid green;"> </div> <div class="form-input-item"> <input id="myConfirmPassword" type="password" placeholder="Подтвердить пароль" class="form-input jqPassConfirmField" name="confirm" value="" style="border: 2px solid green;"> </div> </div> <button class="btn-submit" type="submit">Зберегти</button> <div class="password-desc">Пароль должен состоять минимум из 8 символов, 1 заглавной буквы, 1 спец символа, 1 цифры</div> </form> </div>
Дальше будет большая простыня из JavaScript`а, но вы не пугайтесь, я сейчас всё объясню 🙂 .
(function($) { $.fn.extend({ passwordValidation: function(_options, _callback, _confirmcallback) { //var _unicodeSpecialSet = "^\\x00-\\x1F\\x7F\\x80-\\x9F0-9A-Za-z"; //All chars other than above (and C0/C1) var CHARSETS = { upperCaseSet: "A-Z", //All UpperCase (Acii/Unicode) lowerCaseSet: "a-z", //All LowerCase (Acii/Unicode) digitSet: "0-9", //All digits (Acii/Unicode) specialSet: "\\x20-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E\\x80-\\xFF", //All Other printable Ascii } var _defaults = { minLength: 8, //Minimum Length of password minUpperCase: 1, //Minimum number of Upper Case Letters characters in password minLowerCase: 2, //Minimum number of Lower Case Letters characters in password minDigits: 1, //Minimum number of digits characters in password minSpecial: 1, //Minimum number of special characters in password maxRepeats: 5, //Maximum number of repeated alphanumeric characters in password dhgurAAAfjewd <- 3 A's maxConsecutive: 3, //Maximum number of alphanumeric characters from one set back to back noUpper: false, //Disallow Upper Case Lettera noLower: false, //Disallow Lower Case Letters noDigit: false, //Disallow Digits noSpecial: false, //Disallow Special Characters //NOT IMPLEMENTED YET allowUnicode: false, //Switches Ascii Special Set out for Unicode Special Set failRepeats: true, //Disallow user to have x number of repeated alphanumeric characters ex.. ..A..a..A.. <- fails if maxRepeats <= 3 CASE INSENSITIVE failConsecutive: true,//Disallow user to have x number of consecutive alphanumeric characters from any set ex.. abc <- fails if maxConsecutive <= 3 confirmField: undefined }; //Ensure parameters are correctly defined if($.isFunction(_options)) { if($.isFunction(_callback)) { if($.isFunction(_confirmcallback)) { console.log("Предупреждение в passValidate: было определено 3 или более обратных вызова ... Будут использоваться первые два."); } _confirmcallback = _callback; } _callback = _options; _options = {}; } //concatenate user options with _defaults _options = $.extend(_defaults, _options); if(_options.maxRepeats < 2) _options.maxRepeats = 2; function charsetToString() { return CHARSETS.upperCaseSet + CHARSETS.lowerCaseSet + CHARSETS.digitSet + CHARSETS.specialSet; } //GENERATE ALL REGEXs FOR EVERY CASE function buildPasswordRegex() { var cases = []; //if(_options.allowUnicode) CHARSETS.specialSet = _unicodeSpecialSet; if (_options.noUpper) { cases.push({"regex": "(?=" + CHARSETS.upperCaseSet + ")", "message": "Пароль не может содержать заглавные буквы"}); } else { cases.push({"regex": "(?=" + ("[" + CHARSETS.upperCaseSet + "][^" + CHARSETS.upperCaseSet + "]*").repeat(_options.minUpperCase) + ")", "message": "Пароль должен содержать не менее " + _options.minUpperCase + " Заглавной буквы."}); } if (_options.noLower) { cases.push({"regex": "(?=" + CHARSETS.lowerCaseSet + ")", "message": "Пароль не может содержать строчные буквы"}); } else { cases.push({"regex": "(?=" + ("[" + CHARSETS.lowerCaseSet + "][^" + CHARSETS.lowerCaseSet + "]*").repeat(_options.minLowerCase) + ")", "message": "Пароль должен содержать не менее " + _options.minLowerCase + " Строчных букв."}); } if (_options.noDigit) { cases.push({"regex": "(?=" + CHARSETS.digitSet + ")", "message": "Пароль не может содержать число"}); } else { cases.push({"regex": "(?=" + ("[" + CHARSETS.digitSet + "][^" + CHARSETS.digitSet + "]*").repeat(_options.minDigits) + ")", "message": "Пароль должен содержать не менее " + _options.minDigits + " Цифры."}); } if (_options.noSpecial) { cases.push({"regex": "(?=" + CHARSETS.specialSet + ")", "message": "Пароль не может содержать специальный символ"}); } else { cases.push({"regex": "(?=" + ("[" + CHARSETS.specialSet + "][^" + CHARSETS.specialSet + "]*").repeat(_options.minSpecial) + ")", "message": "Пароль должен содержать не менее " + _options.minSpecial + " Специального символа."}); } cases.push({"regex":"[" + charsetToString() + "]{" + _options.minLength + ",}", "message":"Пароль должен содержать не менее " + _options.minLength + " символов."}); return cases; } var _cases = buildPasswordRegex(); var _element = this; var $confirmField = (_options.confirmField != undefined)? $(_options.confirmField): undefined; //Field validation on every captured event function validateField() { var failedCases = []; //Evaluate all verbose cases $.each(_cases, function(i, _case) { if($(_element).val().search(new RegExp(_case.regex, "g")) == -1) { failedCases.push(_case.message); } }); if(_options.failRepeats && $(_element).val().search(new RegExp("(.)" + (".*\\1").repeat(_options.maxRepeats - 1), "gi")) != -1) { failedCases.push("Пароль не может содержать " + _options.maxRepeats + " одного и того же символа без учета регистра."); } if(_options.failConsecutive && $(_element).val().search(new RegExp("(?=(.)" + ("\\1").repeat(_options.maxConsecutive) + ")", "g")) != -1) { failedCases.push("Пароль не может содержать один и тот же символ более чем " + _options.maxConsecutive + " раз подряд."); } //Determine if valid var validPassword = (failedCases.length == 0) && ($(_element).val().length >= _options.minLength); var fieldsMatch = true; if($confirmField != undefined) { fieldsMatch = ($confirmField.val() == $(_element).val()); } _callback(_element, validPassword, validPassword && fieldsMatch, failedCases); } //Add custom classes to fields this.each(function() { //Validate field if it is already filled if($(this).val()) { validateField().apply(this); } $(this).toggleClass("jqPassField", true); if($confirmField != undefined) { $confirmField.toggleClass("jqPassConfirmField", true); } }); //Add event bindings to the password fields return this.each(function() { $(this).bind('keyup focus input proprtychange mouseup', validateField); if($confirmField != undefined) { $confirmField.bind('keyup focus input proprtychange mouseup', validateField); } }); } }); })(jQuery); $(function(){ $("#myPassword").passwordValidation({"confirmField": "#myConfirmPassword"}, function(element, valid, match, failedCases) { $("#errors").html("" + failedCases.join("\n") + ""); if(valid) $(element).css("border","2px solid green"); if(!valid) $(element).css("border","2px solid red"); if(valid && match) { $("#myConfirmPassword").css("border","2px solid green"); $('.btn-submit').removeClass('disable'); } if(!valid || !match) { $("#myConfirmPassword").css("border","2px solid red"); $('.btn-submit').addClass('disable'); } }); });
По HTML думаю вопросов не должно возникнуть, но обратите внимание на id, т.к. именно к ним мы и будем привязываться.
Что касается JS:
var CHARSETS – перечень регулярных выражений
var _defaults – наши настройки по умолчанию, которые мы можем менять как нам вздумается. Именно тут и просиходит вся магия. Овладев базовыми знаниями английского языка (или воспользовавшись переводчиком 🙂 ) можно без труда понять какой параметр и что означает.
Что еще интересного в этом скрипте? Ну например, в самом его конце можно увидеть добавление класса disable. Дописав pointer-events в CSS можно отключить нажатие кнопки. На каждое несоответствие регулярному выражению – выводится своя ошибка, но немного помозговав можно переписать под одну общую фразу.