2

Like I stated on the title, I would like to add multiple function .rules() to my script. When I tried this:

$("#braintree-payment-form").validate({});



    $("#month").rules('add', {
        required: true,
        regex: "(0[123456789]|10|11|12)",
        messages : {
            required: "Expiration date is required.",
            regex: "Invalid expiration date."
        }
    });
    $("#year").rules('add', {
        required: true,
        regex: "([0-9][0-9])",
        messages : {
            required: "Expiration date is required.",
            regex: "Invalid expiration date."
        }
    });


    $("#cardNum").rules('add', {
        required: true,
        regex: "(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})",
        messages : {
            required: "Credit card number is required.",
            regex: "Invalid credit card number"
        }
    });

Only the last .rules() applied, and also it applied to the first input element rather than corresponding id one.

Thanks in advance :)

Here is the form that I am currently using:

<form action="#" method="POST" id="braintree-payment-form">
    <p>
      <label>Card Number</label>
      <input type="text" size="20" autocomplete="off" name='number' id='number' data-encrypted-name="number"/>
    </p>
    <p>
      <label>CVV</label>
      <input type="text" size="4" autocomplete="off" name='cvv' data-encrypted-name="cvv" id='cvv'/>
    </p>
    <p>
      <label>Expiration (MM/YYYY)</label>
      <input type="text" size="2" data-encrypted-name="month" id="month" name = 'month' /> / <input type="text" size="4" data-encrypted-name="year" id="year" name='year' />
    </p>
    <input type="submit" id="submit" name='braintree'/>
  </form>
3
  • Working fine for me: jsfiddle.net/hc2Bj/1 Show the HTML of your form so we can help you figure this out. Commented Jul 3, 2013 at 23:00
  • I noticed you are targeting #cardNum in your jQuery, yet I do not see id="cardNum" anywhere in your HTML. Commented Jul 4, 2013 at 15:28
  • I cannot reproduce your issue. Commented Jul 4, 2013 at 15:44

4 Answers 4

2

Just a guess, since I cannot reproduce your problem from the limited code you've posted, but I'd say you forgot to include a name attribute on each input element. The jQuery Validate plugin requires a unique name on every input.

See the "Markup recommendations" section on the General Guidelines page:

"The name attribute is 'required' for input elements, the validation plugin doesn't work without it. Usually name and id attributes should have the same value."

<form id="braintree-payment-form">  
     <input type="text" name="month" id="month" data-encrypted-name="month" />
     <input type="text" name="year" id="year" data-encrypted-name="year" />
     <input type="text" name="cardNum" id="cardNum" data-encrypted-name="cardNum" />
     <input type="submit" />
</form> 

Otherwise, your code is working fine: http://jsfiddle.net/hc2Bj/2/

EDIT after OP posted HTML:

I also noticed you are targeting #cardNum in your jQuery, yet I do not see id="cardNum" anywhere in your posted HTML.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the reply, the thing is in order to make Braintree's own JavaScript to run I have to put 'data-encrypted-name' attribute and this breaks the code some how.
@user2533002, I've added the data-encrypted-name attribute and it's still working fine: jsfiddle.net/hc2Bj/2 ~ You're going to have to construct a demo to show how it's broken.
@Sparky I have this same issue. Per Braintree, the name attribute must be completely replaced by data-encrypted-name. So basically, the name attribute must be completely removed from the field, and jquery validate doesn't seem to work in this situation. It seems any rules defined by .rules("add") "accumulate". In other words, the final field that I call .rules("add") for takes on all the rules of the previous .rules("add") calls. Hope this makes sense.
Yeah, I've got exactly this issue and I can't get it to work at all - the inability of using name attributes seems to mess with the plugins head. pastebin.com/nBAAH11R - it seems to throw the same error messages on all the unique fields. Not really sure how to get around this and would love some client side validation before sending data to braintree.
0

I have successfully been able to use the jQuery validator plugin with braintree.js. The first thing I had to do was download braintree.js to my local instead of the hosted version. I then edited the file where:

element.removeAttribute("name");

was located. I simply commented it out thus:

/*element.removeAttribute("name");*/

It's in the last line of the file.

I also put braintree's initialization before the validation script

var braintree = Braintree.create("<%=SESSION("ENCRYPTIONKEY")%>");
braintree.onSubmitEncryptForm('donation-form', null);

As you can see, I am integrating some server-side code for the encryption key, and I do not call any function after it does it's thing with the form.

I use a regular submit button which triggers both the validator and braintree.js. Braintree creates the new hidden inputs with the same name as the fields. jQuery validator validates normally as it only looks at the first instance of the input name. Then in the submitHandler method of jQuery validator I do the removal of the name attribute, but creating a new "name" attribute called "xname". This is because if braintree returns errors on their end, we have to allow the user to resubmit the form. I'll get to how that will work next.

submitHandler: function(form) {
// braintree has duplicated our fields as hidden encrypted.
// now change the name attribute from each field so it won't be submitted

$("input[data-encrypted-name]").each(function(){
$this = $(this);
var thisname = $this.attr("name");
$this.attr("xname",thisname);
$this.removeAttr("name");
}).promise().done(function(){ 
ajaxpost();             });                     

} // end submitHandler

The ajaxpost call is an $.ajax function which posts to a PHP file. This is a trick part, as I get the response from Braintree and create my own JSON with a "result" key. If the result is not "success" also, it will be either "error" or "invalid".

In the case of either "error" or "invalid" i then call a function which reinstates the original name of the fields.

    var reinstate = function(){
    // if the form has already been submitted, but braintree returns errors,
    // we have to reinstate the original field names.

    $("input[xname]").each(function(){
        $this = $(this);
        var thisxname = $this.attr("xname");
        $this.attr("name",thisxname);
        $this.removeAttr("xname");
    });
}

Now the user can try again. Hope this helps. I know this explaination is pretty hairy considering all the ajax and server side processing solutions I implemented.

tl;dr You have to stop braintree from removing the name attributes and then do it yourself right before submission.

1 Comment

I think this is not a good idea, my form validation works even without the name attributes.
0

Hi all I solve this way

$('#purchase_form').validate({
        rules: {
            name: {
                required: true
            },
            number: {
                required: true,
                minlength: 13,
                maxlength: 19
            },
            month: {
                required: true,
                regex: "(0[123456789]|10|11|12)"
            },
            year: {
                required: true,
                regex: "([0-9][0-9])"
            },
            cvv: {
                required: true,
                minlength: 3,
                maxlength: 4
            },
        },
        submitHandler: function (form) {
            $('#purchase_form').hide();
            $('#processing').show();

            braintree.encryptForm($(form));

            $.ajax({
                type: "POST",
                url: base_url+'items/purchase_direct',
                data: $(form).serialize(),
                dataType: "json",
                success: function (response) {
                    if(response.status == 'error')
                    {
                        $('#number_direct').attr('name','number');
                        $('#cvv_direct').attr('name','cvv');
                    }
                    else
                    {
                        $('#purchase_form').hide();
                        $('#processing').hide();
                        $('#purchaseconfirm').show();

                    }
                }
            });
            return false;
        }
    });

add the braintree.encryptForm($(form)); inside the submitHandler.. that makes the braintree removed there the input name. in the case it fails again I will add the input name again.

Don't forget to remove braintree.onSubmitEncryptForm('braintree-payment-form', optionalCallback);

sorry for my english..

Comments

0

There is a way to extend the validator object to add multiple rules. See the documentation here.

var newRules = {name: {required: true}, email: {required: true} }; //your object of new rules

$.validator.addClassRules(newRules);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.