Description
I have the following form:
<form>
<p>
<label for="cname">Name</label>
<input id="cname" name="name" />
</p>
<p><input type="submit" value="Create" /></p>
</form>
<table id="log" cellpadding="2" cellspacing="0" border="1"></table>
<script>
function onError(error, inputElement) {
var logMsg = $("<tr><th>onError</th><td></td></tr>");
logMsg.find("td").html(error.clone());
$("#log").append(logMsg);
}
function onErrors(form, validator) {
var logMsg = $("<tr><th>onErrors</th><td></td></tr>"),
logTd = logMsg.find("td");
$.each(validator.errorList, function () {
logTd.append("<div>" + this.message + "</div>");
});
$("#log").append(logMsg);
}
function onSuccess(error) {
var logMsg = $("<tr><th>onSuccess</th><td></td></tr>");
logMsg.find("td").html(error.clone());
$("#log").append(logMsg);
}
$(function() {
$("form").validate({
errorPlacement: onError,
invalidHandler: onErrors,
success: onSuccess
});
$("#cname").rules("add", {"maxlength": 25});
});
</script>
When I run this form and type more than 25 characters into the box, then tab away, I get a call to onError as I'd expected. If I then delete characters one at a time until I have less than 25, I get calls to onError and onSuccess as I expect (which tells me to clear the error message).
Refresh the page and start over. Again, type more than 25 characters into the box and tab away, and see the call to onError. This time, highlight the entire block of text and hit the delete key. Instead of seeing the calls to onError and onSuccess as I'd expect, I see no calls at all.
Stepping into check() function, it would appear that the logic for dependency mismatch is causing my problem. jQuery Validate keeps two lists: errorList and successList. Inside of check(), if you have not failed validator, but your last validator returns "dependency-mismatch" (a common scenario when you are validated but not required), then the element ends up in neither errorList nor successList. At the end of check(), you can see that dependencyMismatch being true short-circuits putting the otherwise valid element into successList.
I can work around this bug by adding a dummy validator (which always returns true) and making sure that validator is last in my list:
$.validator.addMethod("__dummy", function (value, element, params) {
return true;
});
$(function() {
$("form").validate({
errorPlacement: onError,
invalidHandler: onErrors,
success: onSuccess
});
$("#cname").rules("add", {"maxlength": 25, "__dummy": true});
});
Note that the dummy validator has to come last in the list, since we need to ensure that the dependencyMismatch flag ends up false instead of true.