Search code examples
jqueryjquery-validateqtip2

jQuery Validation plugin does not fire success despite "valid" class


I'm using the jQuery Validation plugin along with the qTip2 plugin to display the errors.

I've setup two jsFiddles to demonstrate a curious problem I'm having. The first two fields are "required", the third & fourth fields are "optional" while the third field is validating a phone number.

When I fill out the optional phone number field, I'm still validating the phone number even if it's not required. However, if the user puts in an invalid number (gets an error), changes their mind and backspaces the phone number field, the error message should go away.

It's working as expected here (Validation plugin with standard errors (no qTip2)):

jsFiddle #1: http://jsfiddle.net/avJ54/2/

The problem is that it does not work while using qTip2 to display the errors:

jsFiddle #2: http://jsfiddle.net/WKryu/3/

On the element, the error class is correctly removed and replaced with the valid class but apparently the success handler does not fire. However, qTip2 depends on the success handler to fire in order to destroy any error bubbles.

Two things will force the success handler to fire and clear out this error.

1) Hitting the submit button.

2) Filling out a "required" field and losing its focus.

So the issue is: I can't seem to get qTip2 to remove the error bubble immediately on optional fields when they're blanked out, similar to how it works in the first jsFiddle.

Since the success handler only seems to fire when losing focus of "required" fields, is there a way to get it to fire when losing focus of any field? This would solve the issue most easily.

Edit: I put an alert() on the success handler and it only fires when you lose focus of any field that is validated. The weird part is that despite my phone method, the success handler only fires when you lose focus after a valid phone number is entered. However, technically, when the field is blanked out and the default value is displayed, it's also a "valid" field, yet success does not fire. In other words, when blanking out the field and losing focus, the class immediately changes to .valid but the success handler never fires. This is what most perplexes me and for what I'm seeking an explanation.

Perhaps my assumption about the success handler not firing is wrong, but I cannot yet decipher what I need to do in order to get this all working properly.

A clue?: Simply removing the default field value gets it working...

jsFiddle #3: http://jsfiddle.net/BwNLs/

However, that's not really what I want (I need the default field values as part of my design). Clearly, toggling the default field values is not a problem in jsFiddle #1... it only becomes a problem when introducing qTip2.

It's some combination of using qTip2 along with the default field values causing all these headaches. Hopefully, one of you can see where I am blind.


Solution

  • Through much experimentation, here is what I've learned so far (besides desperately wishing there was more detailed documentation available):

    1) The success handler fires right after losing focus of a field that was just validated with a specific exception: I think it's a timing issue... the default value is put back at the same time the plugin is doing the validation.

    2) The success handler fires at the same exact instances in both jsFiddle cases 1 & 2 above. The difference is that the error messages in the first test case are toggled between display:none and display:inline internally by the plugin. However, in the second test case, the qTip message bubbles are toggled via the errorPlacement: and success: handlers.

    3) The valid and error classes are toggled identically in both cases. In the second test case, it seems that despite a class toggling from error to valid, it does not necessarily mean that success will fire. It seems that although the class is valid, having a default value put back into the field somehow prevents success from firing. Why?

    Workaround (temporary?):

    I added the onfocusout handler to .validate like this:

     onfocusout: function(element) {
         $(element).valid();
         $(element).filter('.valid').qtip('destroy');
     },
    

    http://jsfiddle.net/MNKMP/

    onfocusout is normally a boolean (as per the docs), so putting a function in there destroys the normal functionality when you lose focus. I had to invoke valid() on the first line to replace the normal onfocusout functionality that is lost. (what I don't understand is how the documentation fails to mention that you can replace a boolean with a function). (EDIT: I took a peak inside the plugin and despite the docs, onfocusout is not a boolean, it's a function. I noticed quite a few things in there either completely missing from, or opposed to, the official documentation) 1

    Then since I cannot rely on the success handler to fire when focus is lost, I've added a line that destroys the qTip bubble if the class says the field is valid.

    The only thing about my workaround is that it slightly changes the normal behavior. Normally, when you first load the page you can tab between the "required" fields without any error messages until you hit the submit button which then lights up all empty required fields. After installing my workaround, simply tabbing to & from an empty field lights up that one error message.

    I love the Validation plugin. I just wish there was a dependable way to manually duplicate any default functionality. It seems that every time I manually use a method, there are mysterious unexplained side effects to the other default behaviors.

    I'll expand upon this answer as my time permits.


    EDIT 2:

    1 Clarification on onkeyup:, onfocusout:, and possibly many of the other options: These options default to true ("on") according to the documentation, but they're really backed up by internal functions. In other words, you can set these options to false within your .validate() setup, but you cannot set them to true without breaking the plugin.