admin管理员组文章数量:1303498
I am having a really strange problem with Jquery validate that only occurs in Chrome. The validation on this page seems to be firing both the Highlight and the Unhighlight functions in the .validate() function so if I dont fill out the form it cycles through each element and applies the "invalid" class in the highlight function but then for some reason it goes through and immediately applies the code in unhighlight and I cant work out why?
JS
$(document).ready(function () {
//Validation for form fields on Payment form
/*This adds a method to test whether value is equal to placeholder, and if it is, don't consider it filled out. This is necessary to circumvent IE placeholder plugin*/
jQuery.validator.addMethod("notEqual", function (value, element, param) {
return this.optional(element) || value != param;
}, "Required.");
$('#payment-form').validate({
onfocusout: function (element) {
$(element).valid();
},
rules: {
"data[Payment][card_holder]": { required: true, minlength: 2 },
"data[Payment][card_number]": { required: true, creditcard: true },
"data[User][first_name]": { required: true, notEqual: "First Name" },
"data[User][last_name]": { required: true, notEqual: "Last Name" },
"data[UserDetail][pany]": { required: true },
"data[UserDetail][job_title]": { required: true },
"data[UserDetail][telephone]": { required: true },
"data[User][email]": {
required: true,
email: true,
remote: {
url: "/usermgmt/users/email_exists",
type: "post"
}
},
"data[User][password]": { required: true },
"data[Address][billing_line_1]": { required: true },
"data[Address][billing_line_2]": { required: true },
"data[Address][billing_state]": { required: true },
"data[Address][billing_postcode]": { required: true },
credit_exp_month: { required: true, notEqual: "MM", number: true, max: 12, minlength: 2, maxlength: 2 },
credit_exp_year: { required: true, notEqual: "YYYY", number: true, minlength: 2, maxlength: 4 },
"data[Payment][cvv]": { required: true, number: true, minlength: 3, maxlength: 4 },
},
errorClass: 'error',
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass);
validateIcon(element);
},
highlight: function (element, errorClass, validClass) {
$(element).addClass(errorClass).removeClass(validClass);
validateIcon(element);
}
});
function validateIcon(element) {
$(element).siblings('span.validate_icon').remove();
if ($(element).hasClass('error')) {
alert("error");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon invalid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-exclamation"></i></span></span>');
} else if ($(element).hasClass('valid')) {
alert("valid");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon valid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-ok"></i></span></span>');
}
}
});
PHP Code that handles the email exists:
public function email_exists() {
$this->autoRender = false;
if($this->request->is('post')) {
$this->RequestHandler->respondAs('json');
if(!$this->User->findByEmail($this->request->data['User']['email'])) {
echo json_encode(true);
} else {
echo json_encode(false);
}
}
}
I have also tried simply echo "true"; and echo 1; I have tried everything suggested in the ments below but regardless - the problem exists.
I am having a really strange problem with Jquery validate that only occurs in Chrome. The validation on this page seems to be firing both the Highlight and the Unhighlight functions in the .validate() function so if I dont fill out the form it cycles through each element and applies the "invalid" class in the highlight function but then for some reason it goes through and immediately applies the code in unhighlight and I cant work out why?
JS
$(document).ready(function () {
//Validation for form fields on Payment form
/*This adds a method to test whether value is equal to placeholder, and if it is, don't consider it filled out. This is necessary to circumvent IE placeholder plugin*/
jQuery.validator.addMethod("notEqual", function (value, element, param) {
return this.optional(element) || value != param;
}, "Required.");
$('#payment-form').validate({
onfocusout: function (element) {
$(element).valid();
},
rules: {
"data[Payment][card_holder]": { required: true, minlength: 2 },
"data[Payment][card_number]": { required: true, creditcard: true },
"data[User][first_name]": { required: true, notEqual: "First Name" },
"data[User][last_name]": { required: true, notEqual: "Last Name" },
"data[UserDetail][pany]": { required: true },
"data[UserDetail][job_title]": { required: true },
"data[UserDetail][telephone]": { required: true },
"data[User][email]": {
required: true,
email: true,
remote: {
url: "/usermgmt/users/email_exists",
type: "post"
}
},
"data[User][password]": { required: true },
"data[Address][billing_line_1]": { required: true },
"data[Address][billing_line_2]": { required: true },
"data[Address][billing_state]": { required: true },
"data[Address][billing_postcode]": { required: true },
credit_exp_month: { required: true, notEqual: "MM", number: true, max: 12, minlength: 2, maxlength: 2 },
credit_exp_year: { required: true, notEqual: "YYYY", number: true, minlength: 2, maxlength: 4 },
"data[Payment][cvv]": { required: true, number: true, minlength: 3, maxlength: 4 },
},
errorClass: 'error',
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass);
validateIcon(element);
},
highlight: function (element, errorClass, validClass) {
$(element).addClass(errorClass).removeClass(validClass);
validateIcon(element);
}
});
function validateIcon(element) {
$(element).siblings('span.validate_icon').remove();
if ($(element).hasClass('error')) {
alert("error");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon invalid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-exclamation"></i></span></span>');
} else if ($(element).hasClass('valid')) {
alert("valid");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon valid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-ok"></i></span></span>');
}
}
});
PHP Code that handles the email exists:
public function email_exists() {
$this->autoRender = false;
if($this->request->is('post')) {
$this->RequestHandler->respondAs('json');
if(!$this->User->findByEmail($this->request->data['User']['email'])) {
echo json_encode(true);
} else {
echo json_encode(false);
}
}
}
I have also tried simply echo "true"; and echo 1; I have tried everything suggested in the ments below but regardless - the problem exists.
Share Improve this question edited Apr 22, 2014 at 9:47 the1dv asked Apr 7, 2014 at 4:38 the1dvthe1dv 9318 silver badges15 bronze badges 2- From what I can gather it is to do with this part: $(element).removeClass(errorClass).addClass(validClass); Would the removal of a class in jQuery cause a focusout event? if so this would cause revalidation of the form? – the1dv Commented Apr 7, 2014 at 5:51
- And actually this only seems to occur on Chrome on Linux - I havent been able to replicate this on BrowserStack! – the1dv Commented Apr 7, 2014 at 6:09
2 Answers
Reset to default 7I had the exact same problem, and by seeing your code I might say that you have the same cause, but let's break it down.
Checking
First, let's check that my ment is relevant, and I can actually help you. Comment the remote param on your email validation set up:
"data[User][email]": {
required: true,
email: true
},
Is your problem fixed? Great, keep reading (feel free to skip to the fix section).
The problem
1. When the plugin validates, it creates a list of errors, stored into an array called "errorList".
2. Have you ever used the showErrors functionality? It's there to show all the errors, but also to target-show errors. If you want to show specific errors, or to show errors that are out of the limits of the plugin (ej.: a 60s timeout has expired), you can use that method.
3. When showing specific errors, what that method does is to add the specified error(s) to the errorList.
4. The problem is that before adding new errors that list is cleared up (I didn't write the code, but it seems that it's done in order to keep that list nice and clean, and not having two different errors of the same input).
5. Now, when the email is checked remotely we are in the same situation of a timeout. So it uses the showErrors functionality, and that means that the form is validated when click, and some seconds later (with the PHP response), the email error is shown, but clearing up the errorList. That's what is happening.
The fix
If you are not going to do explicit use of showErrors, truth is that you can ment the line where the errorList is cleared up:
showErrors: function( errors ) { if ( errors ) { // add items to error list and map $.extend( this.errorMap, errors ); //this.errorList = []; for ( var name in errors ) { ...
If you are going to do an explicit use of that method, you can try this version instead. Doesn't clear the error list, but checks that you're not adding the same error twice:
showErrors: function( errors ) { if ( errors ) { // add items to error list and map $.extend( this.errorMap, errors ); for ( var name in errors ) { var tempElem = this.findByName(name)[0]; this.errorList = jQuery.grep(this.errorList, function( error, i ) { return error.element != tempElem; }); this.errorList.push({ message: errors[name], element: tempElem }); }
Let me know if worked or you have any problem.
This code of yours can be a problem...
onfocusout: function (element) {
$(element).valid();
},
You cannot put the .valid()
method inside of the .validate()
method without causing some serious issues.
This is the default onfocusout
function from the plugin...
onfocusout: function( element, event ) {
if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
this.element(element);
}
}
What's the purpose of your custom onfocusout
function? Generally, it's not needed since the onfocusout
trigger is already built into the functionality. One constructs their own onfocusout
function only to over-ride the built-in default. So if you want the default onfocusout
behavior, just remove the onfocusout
option entirely.
If you really want to emulate something like in your code, it would need to look like this...
onfocusout: function(element, event) {
this.element(element);
}
Quote OP Comment:
"as I said im not really sure what good it would do you: (I cant get it to format here..)"
$this->RequestHandler->respondAs('json');
if(!$this->User->findByEmail($this->request->data['User']['email'])) {
return json_encode(true);
} else {
return json_encode(false);
}
It does a lot of good to show any code that could be affecting the problem, especially any code that's wrong. This could have been solved two days ago.
return
is for returning to the PHP function that called this one. In other words, return
will do nothing here since there is no PHP function to return to. On the other hand, echo
will output from PHP... and that's what you need for jQuery Validate remote
...
if (....) {
echo true;
} else {
echo false;
}
PHP return
versus PHP echo
Also see: https://stackoverflow./a/21313309/594235
本文标签: javascriptJQuery Validate is firing both Highlight and Unhighlight in ChromeStack Overflow
版权声明:本文标题:javascript - JQuery Validate is firing both Highlight and Unhighlight in Chrome - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741722901a2394491.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论