Плагин JQuery Validation: вызывать функцию errorPlacement, когда onfocusout, keyup и click
Я использую плагин проверки 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"
});
Ответы
Ответ 1
Ваша проблема в том, что плагин только вызывает функцию errorPlacement
один раз для каждого проверяемого элемента. Namly, когда сначала создается метка ошибки для элемента. После этого плагин просто повторно использует уже существующую метку и просто заменяет html внутри (или скрывает метку ошибки, если этот элемент теперь действителен). Вот почему ваш крест удаляется и отображается фактическое сообщение об ошибке.
Просто убедитесь, что поток плагина понятен.
- элемент (еще нет errorlabel)
Элемент
- получает подтверждение в какой-то момент
- плагин создает метку ошибки и вызывает
errorPlacement
функцию
- элемент "cross" (сообщение об ошибке в заголовке)
- Элемент получает фокус, и вы что-то меняете.
- плагин обновляет элемент
- Видит, что метка ошибки уже создана (и помещена)
- плагин просто вызывает
label.html(message)
вместо удаления старой метки и чтения ее
Итак, вы видите, что ваша проблема - это своего рода оптимизация, которую плагин делает для сохранения ненужных вставок/удалений меток ошибок. Это тоже имеет смысл.
Вы можете проверить, что я сказал, посмотрев код validation-plugin-source
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();
}
...
});
Возможно, для этого есть более чистое решение, но это должно сделать это и дать вам время для изучения лучшего решения.
Ответ 2
Спасибо дрожание,
Я сделал кое-какие операции и нашел ту же проблему.
Мне удалось заставить его работать, "взломав" функцию 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);
}