2

Since the CartThrob guys seem to have vanished from the face of this earth, I hope somebody here has the knowledge to help me out with this problem:

I am using AJAX to update the totals on a single page checkout page.

When entering an invalid discount code in the input for the ‘add_coupon_form’ and then entering a valid code after that, the discount value returns as ‘undefined’. Also, apart from the XID code, none of the other CT debugging info displays in the console.

If entering a valid discount code straight away (without entering an invalid one on first try), the code is applied and totals are updated as expected.

The form code in my template:

{exp:cartthrob:coupon_info}     
    {if no_results}
      {exp:cartthrob:add_coupon_form return="shopping-bag/payment" id="coupon"}
        <label class="show" for="coupon_code">Have a discount code? Enter it here:</label>
        <input type="text" name="coupon_code" id="coupon_code" class="coupon_code" value="" placeholder="Discount code" />
        <button type="submit" class="apply btn classy">Apply Discount</button>
      {/exp:cartthrob:add_coupon_form}
    {/if}

    {exp:cartthrob:add_coupon_form return="shopping-bag/payment" id="coupon"}
      <label class="show" for="coupon_code">Discount code used:</label>
      <input type="text" name="coupon_code" id="coupon_code" class="coupon_code" value="{coupon_code}" disabled />
      <a href="{path='shopping-bag/remove-coupon'}" class="remove btn classy">Remove discount code</a>
    {/exp:cartthrob:add_coupon_form}
{/exp:cartthrob:coupon_info} 

The AJAX code:

// AJAX functions
            // if set to true, ajax form will be shown, and all json data will be printed to the console log
            var ct_debug = true;

            function update_cart(data, statusText, xhr, $form) {
                if (data.success) {
                    $('input[name=XID]').val(data.XID);
                    $('.payment-total .subtotal .col2').html( data.cart_subtotal );
                    $('.payment-total .discount .col2').html( '- ' + data.cart_discount );
                    $('.payment-total .shipping .col2').html( data.cart_shipping );
                    $('.payment-total .total .col2').html( data.cart_total );

                    if (data.cart_discount && data.cart_discount != '$0.00') {
                        $('.payment-total .discount').removeClass('hidden');
                        $('form#coupon label').html('Discount code used:');
                        $('form#coupon input').attr('disabled', 'true');
                        $('form#coupon button.apply').addClass('hidden');
                        if ( $('form#coupon .remove').length == '0' ) {
                            $('form#coupon').append('<a href="{path=\\'shopping-bag/remove-coupon\\'}" class="remove btn classy">Remove discount code</a>')
                        }
                        $('form#coupon .invalid').addClass('hidden');
                    }
                }
                if (!data.success) {
                    // invalid discount code added
                    if ( $('form#coupon .invalid').length == '0' ) {
                        $('form#coupon').append('<p class="invalid"><small>The code you entered is invalid.</small></p>');
                    }
                    $('.shopping-bag.payment').find('form#coupon input.coupon_code').val(''); 
                }
                // if debugging is turned on, all data will be output to the js console log
                if (ct_debug)
                {
                    $.each(data, function(index, item){
                      console.log(index + ": " +item);
                    });  
                    $.each(data.errors, function(index, item){
                      console.log(index + ": " +item);
                    });
                }
                return true; 
            }

            var cart_form_options = {
                success: update_cart,
                dataType: 'json'
            }

           // discount code entered
            $('.shopping-bag.payment').find('form#coupon button').click(function(){
                var form = $('form#coupon'); 
                $(form).ajaxForm(cart_form_options);
                $(form).submit(); 
            }); 

I am only just getting to grips with AJAX, so maybe I made a mistake there that I can't see.

I've also posted this in the CartThrob forums, but as I've said, the team hasn't been answering any posts for over a month, and aren't replying to emails or tweets.

  • A good rule of thumb when debugging AJAX, is to disable the secure form submission option in the security setting. Get it working without that on, and then enable and test again. I don't think this is the root of your problem, but it's worth mentioning. – Justin Kimbrell Jan 11 '13 at 4:32
  • Thank you Justin. Whilst switching 'Secure Mode' off did at least process all the other form data when a valid code was added after an invalid one, but the discount itself still isn't being registered unless I submit the form a third time, so there's still an issue there... – Katrin Jan 14 '13 at 11:32
  • Quote:Since the CartThrob guys seem to have vanished from the face of this earth, /quote this is not my experience. One can book time for support or presales requests from their site link. Worked very well for me. – Hansl Jan 9 '14 at 18:02
1

It could be that your update to the XID isn't specific to the form you're updating. Do you have an update cart form on the page as well? This line:

$('input[name=XID]').val(data.XID);

Will look for ALL fields on a page with the name set to XID. You need to set that in the scope of the form you're updating, like so:

$form.find('input[name=XID]').val(data.XID);

Notice $form is passed as one of the attributes to your success function of ajaxForm. You should do that for all your calls to the form fields.

Regarding some of your jquery, you could improve performance by chaining (See: http://api.jquery.com/end/). E.g, instead of:

$('.payment-total .subtotal .col2').html( data.cart_subtotal );
$('.payment-total .discount .col2').html( '- ' + data.cart_discount );
$('.payment-total .shipping .col2').html( data.cart_shipping );
$('.payment-total .total .col2').html( data.cart_total );

You should really do:

$form
    .find('.payment-total')
        .find('.subtotal .col2')
            .html( data.cart_subtotal )
        .end()
        .find('.discount .col2')
            .html( '- ' + data.cart_discount )
        .end()
        .find('.shipping .col2')
            .html( data.cart_shipping )
        .end()
        .find('.total .col2')
        .html( data.cart_total );

That saves jquery having to start traversing the DOM for each line and is a good practice.

| improve this answer | |
  • Thank you for your helpful answer, Will. I've added $form as an attribute, but unfortunately that didn't solve the problem - I still have to submit the form containing the correct coupon code twice before it's being fully executed. LOVING the end() function! Thank you for introducing me to it and reminding me to pull my finger out and majorly spruce up my JS and jQuery knowledge... – Katrin Jan 29 '13 at 21:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.