Я использую плагин проверки jQuery и хочу использовать функцию errorPlacement, чтобы добавить сообщения об ошибках к полевому атрибуту заголовка и отобразить просто ✘ рядом с полем.
Это работает отлично, когда форма отправлена с кнопкой отправки, но когда любое из следующих событий инициировано: - onfocusout - щелчок - onkeyup
Проверки проверки осуществляются, но это пропускает функцию errorPlacement и добавляет полное сообщение об ошибке после поля, как поведение по умолчанию.
Я использую следующий код:
$("#send-mail").validate({
debug: true,
// set this class to error-labels to indicate valid fields
success: function(label) {
// set text as tick
label.html("✔").addClass("valid");
},
// the errorPlacement has to take the table layout into account
errorPlacement: function(error, element) {
console.log("errorPlacement called for "+element.attr("name")+" field");
// check for blank/success error
if(error.text() == "")
{
// remove field title/error message from element
element.attr("title", "");
console.log("error check passed");
}
else
{
// get error message
var message = error.text();
// set as element title
element.attr("title", message);
// clear error html and add cross glyph
error.html("✘");
console.log("error check failed: "+message);
}
// add error label after form element
error.insertAfter(element);
},
ignoreTitle: true,
errorClass: "invalid"
});
Ваша проблема в том, что плагин вызывает функцию errorPlacement
только один раз для каждого проверенного элемента. Namly, когда впервые создается метка ошибки для элемента. После этого плагин просто повторно использует уже существующую метку и просто заменяет html внутри (или скрывает метку ошибки, если элемент теперь действителен). Вот почему ваш крестик удаляется, и отображается фактическое сообщение об ошибке.
Просто чтобы убедиться, что поток плагина понятен. Элемент
errorPlacement
функцию label.html (message)
вместо удаления старого label and reading it Итак, вы видите, что ваша проблема - это своего рода оптимизация, которую плагин выполняет, чтобы сохранить некоторые ненужные вставки / удаления меток ошибок. Что тоже имеет смысл.
Вы можете проверить, что я сказал, посмотрев на исходный код плагина проверки
jquery.validate.js v1.6 проверьте в функции showLabel
строки 617–625 для соответствующих частей.
Возможным решением может быть дополнительная функция обратного вызова showErrors
, которая решает проблему с помощью грубой силы.
Что-то вроде
$("#send-mail").validate({
...
showErrors: function(errorMap, errorList) {
for (var i = 0; errorList[i]; i++) {
var element = this.errorList[i].element;
//solves the problem with brute force
//remove existing error label and thus force plugin to recreate it
//recreation == call to errorplacement function
this.errorsFor(element).remove();
}
this.defaultShowErrors();
}
...
});
Может быть, есть более чистое решение, но оно должно сработать и дать вам время для поиска лучшего решения.
Спасибо jitter ,
Я покопался и обнаружил ту же проблему.
Мне удалось заставить его работать, «взломав» функцию showLabel в jquery.validation.js. Это некрасиво, но работает.
Переопределение параметра функции showErrors избавит меня от необходимости изменять код плагина, поэтому я посмотрю.
Вот код, который я использовал для метода showLabel:
showLabel: function(element, message) {
// look for existing error message
var label = this.errorsFor( element );
// existing error exist?
if (label.length) {
// refresh error/success class
label.removeClass().addClass( this.settings.errorClass );
// check if we have a generated label, replace the message then
label.attr("generated");
// is message empty?
if(!message)
{
// add tick glyph
label.html("✔");
// wipe element title
$(element).attr('title', message)
}
else
{
// clear error html and add cross glyph
label.html("✘");
// update element title
$(element).attr('title', message)
}
// && label.html(message);
}
else {
// create label
label = $("<" + this.settings.errorElement + "/>")
.attr({"for": this.idOrName(element), generated: true})
.addClass(this.settings.errorClass)
.html(message || "");
if ( this.settings.wrapper ) {
// make sure the element is visible, even in IE
// actually showing the wrapped element is handled elsewhere
label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
}
if ( !this.labelContainer.append(label).length )
this.settings.errorPlacement
? this.settings.errorPlacement(label, $(element) )
: label.insertAfter(element);
}
if ( !message && this.settings.success ) {
label.text("");
typeof this.settings.success == "string"
? label.addClass( this.settings.success )
: this.settings.success( label );
}
this.toShow = this.toShow.add(label);
}