0

Within my application, I would like to only show a link to the the user's cart only if there are products in it.

I was going to use javascript to check the cookie I can see getting set. commerce_cookie

The problem I'm having is how to read that cookie. I realize its encrypted & I'm not accessing the cookie correctly. That's why I'm unable to get and check for any orders. Is there a better way to check the cart dynamically in this way?

I am trying to read it like this:

var cart = getCookie('commerce_cookie');

console.log(cart);  // false

// check if there are any products in the cart
if (cart) {
   // show the cart icon
} else {
    // hide the cart icon
}

function getCookie(cookie) {
    if ($.cookie(name)) {
        returnJSON.parse($.cookie(name));
    }
}

I have read through this thread about LJ Cookies, but I'm still not confident I'm looking for the cookie correctly:

{{ craft.lj_cookies.get( 'commerce_cookie' ) }}

SOLUTION

What I was tying to do was hide the cart icon and only show it (along with item quantity) only if there were items in the cart.

To do this, you'll need a plugin to listen for the onBeforeAddToCart event.

MyPlugin.php

// Listen for items getting added to the cart.
craft()->on('commerce_cart.onBeforeAddToCart', function (Event $event) {
    $cart = craft()->commerce_cart->getCart();
    // set expire & other params as needed
    $cookie = new HttpCookie('totalQty', $cart->totalQty);
    craft()->request->getCookies()->add($cookie->name, $cookie);
});

Then I've got an ajax request that will check if that cookie exists.

jquery

var data = {
    'CSRF': $('input[name="CSRF"]').val()
};

$.ajax({
    'type': 'post',
    'contentType': 'application/x-www-form-urlencoded; charset=UTF-8',
    'cache': false,
    'data': data,
    'url': '/actions/myplugin/checkCookie',
    'dataType': 'json',
    'timeout': 50000
}).done(function (response) {
    // handle response
}).fail(function (error) {
   // Total fail.
});

That routes to a controller method within my plugin:

MyPlugin.php

if (craft()->request->isAjaxRequest()) {
    return $this->returnJson(craft()->request->getCookie('totalQty'));
}

Here is how I am then handling/updating the UI with the results of that ajax request. I am summarizing my code here, there is more logic than I am listing - just trying to keep the size of this thread below the level of "book".

I am using velocity for my transitions.

jquery

 ...
 var qty = (result.value + 1);  // value is zero-based array so +1

  $('#icon').velocity('fadeIn', {
      'duration': 300,
      'display': 'inline-block',
      'complete': function () {
          $('<div/>', {
              'id': 'cartQty',
              'text': qty
          }).appendTo($('#icon'))
              .velocity('transition.bounceIn', {
                  'duration': 300,
                  'easing': 'easeInOutSine'
              });
          }
      });

I wasn't able to find an event that listened for the Empty Cart event, so I had to get creative here.

I listen for the "Empty Cart" form submit via jQuery. From there I make another ajax request to my plugin:

jQuery

$('#emptyCartForm').submit(function (event) {
     deleteCookie(); // calls an ajax method (below)
});


$.ajax({
    'type': 'post',
    'contentType': 'application/x-www-form-urlencoded; charset=UTF-8',
    'cache': false,
    'data': data,
    'url': '/actions/myplugin/deleteCookie',
    'dataType': 'json',
    'timeout': 50000
}).done(function (response) {
    // handle response
}).fail(function (error) {
   // Total fail.
});

That request makes a call to a controller method within my plugin:

MyPlugin.php

 if (craft()->request->isAjaxRequest()) {
     craft()->request->deleteCookie('totalQty');
     return $this->returnJson(['status' => 'success']);
}

I'm happy to edit or please feel free to edit if there is any way I can improve this technique.

1 Answer 1

2

The cookie that Craft Commerce uses for cart/session management is set using Craft's craft()->userSession->saveCookie, which hard-codes cookie's httpOnly flag, meaning it can't be accessed by JavaScript.

If you want to pull of what you're trying to do, you'll need to use something like the LJ Cookies or Cookies plugin to add and ready your own cookie according to your business logic.

1
  • 1
    Thanks Brad! I've updated my question with what I came up with in case someone stumbles across this question.
    – Damon
    Feb 4, 2016 at 20:42

Your Answer

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

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