views:

561

answers:

4

Hi there - I'm using the jQuery Validation plugin (http://docs.jquery.com/Plugins/Validation) on a form I'm building. The form is made up of 6 fieldsets, each containing 3 text inputs for an email address, a first name and a last name. A simplified version of the markup is like so:

<form id="ref" action="submit.php" method="post">
    <fieldset id="ref_1">
        <input id="ref_1_email" type="text" />
        <input id="ref_1_fname" type="text" />
        <input id="ref_1_lname" type="text" />
    </fieldset>
    <fieldset id="ref_2">
        <input id="ref_2_email" type="text" />
        <input id="ref_2_fname" type="text" />
        <input id="ref_2_lname" type="text" />
    </fieldset>
    <fieldset id="ref_3">
        <input id="ref_3_email" type="text" />
        <input id="ref_3_fname" type="text" />
        <input id="ref_3_lname" type="text" />
    </fieldset>
</form>

and so forth, up to ref_6. However, the user does not necessarily need to complete every field - they may only choose to fill in the inputs inside fieldset#ref_1 and fieldset#ref_2, and leave the others blank. But if they enter, for example, an email for ref_1, a first and last name for ref_1 would be required also. So what I need to do is check all 3 inputs in a fieldset. If they are all blank, they can be ignored, however if one of the inputs is filled in, it's two neighbours must be completed also. All my attempts so far have been very cumbersome (watching for a change on each one and then evaluating to see if empty...), any help would be greatly, greatly appreciated.

Thanks

UPDATE

I found a post with a similar issue, with the suggested solution being:

    $('#emailToName2').keyup(function () {
    $('#emailToAddress2').toggleClass('required', $(this).val());
});

But that requires the above logic duplicated for each and every input, which seems like overkill to me. What would be a more dynamic approach?

Cheers!

A: 

You can specify an expression or callback when indicating that a field is required. The validation plugin will then evaluate the expression or callback before validating the field.

Here's an example:

$("#ref").validate({
  rules: {
    ref_1_email: {
      required: function(element) {
        return $("#ref_1_fname").val() || $("ref_1_lname").val();
      }
    }
  }
});
$("#ref_1_email").blur(function() {
  $("#ref_1_fname").valid();
  $("#ref_1_lname").valid();
});

There's probably some refactoring that you can do so that you don't have to repeat all of this for each field...

bdukes
Thanks for the suggestions so far. I'm trying to make this work, but it seems to apply a class of "valid" to the other 'related' fields, irrespective of whether they are blank or not. Any ideas?
AlvinRow
This example really just makes the email in the first section required if one of the other field in the first section has a value. You'll need to wire up similar rules for the other fields before the `blur` event handler will work properly...
bdukes
A: 

Not tried and neither properly written:

$("#ref input").keyup(function () {
 $(this).parents("fieldset").children("input").toggleClass("required", $(this).val());
});
ApoY2k
+2  A: 

You can write your own custom validation class that evaluates if the other either of the 2 inputs have been completed.

eg.

jQuery.validator.addMethod('MyOwnValidator', function(value, element) {
    var required = false;
    $(element).parent().children('input').each(function() {
       if($(this).val() && $(this).attr('id') != $(element).attr('id')){
           required = true;
       }
    });
    return !required;
});

This will evaluate if any of the sibling inputs have a value and if they do it makes the calling input required.

CeejeeB
This is almost there! The following is what I have for rules (I renamed the function checkSiblings): [code] $('#ref').validate( { rules : { ref_1_email : { required: function(element) { checkSiblings : true } }, ref_1_fname : { required: function(element) { checkSiblings : true } }, ref_1_lname : { required: function(element) { checkSiblings : true } } } }); [/code] But the only issue is that if I clear all the fields, it's still marking them as required, and therefore the form cannot be submitted. Any ideas? Thanks so much (to everyone!)
AlvinRow
A: 

You cant do it all in one loop, since you need to check siblings before toggling the class. You can, however, define a small loop function that can check and apply, but you will need to call it several times to maintain logic.

Try this:

var loop = function(target, fn) {
    var t = 0, fn = fn || function(){};
    $(target).siblings().andSelf().each(function(i, el) {
        t += $(el).val().length;
        fn(el);
    });
    return t;
}
$('fieldset input').each(function() {
    $(this).bind('blur', function(e) {
        if(loop(e.target)) {
            loop(e.target, function(el) {
                $(el).toggleClass('required', !$(el).val().length);
            })
        } else {
            loop(e.target, function(el) {
                $(el).removeClass('required');
            })
        }
    });
});
David