Dec 09
FoxyCart: Replacing A Cart Item
//Find the id of the existing registration in the cart, if it does exist
$.each(fc_json.products, function(key, product) {
if(product.name=="Registration") {
// Do the remove request, with parameter quantity=0
$.ajax({
async: false,
type: "GET",
url: "https://mydomain.foxycart.com/cart?output=json&cart=update&id="+product.id+"&quantity=0&callback=?" + fc_AddSession(),
dataType: 'json'
});
}
});
// Add the new one
add_item();
}
function add_item() {
//Get the form data
var submitted_data = $("#signup").serialize();
//Do the add request
$.ajax({
type: "GET",
url: "https://mydomain.foxycart.com/cart?"+submitted_data+"&callback=?" + fc_AddSession(),
dataType: 'json'
});
}
This javascript/jQuery code gets the contents of your cart (which is in the variable fc_json, made available by foxycart_includes.js), removes any item whose name matches a certain string, and then adds your new item. It looks so obvious now, but it took a while for me to get it.
I’m working on a shopping cart at the moment, and it’s my first day with FoxyCart, which is a really nice solution for a common but pretty badly-catered-for requirement (ie. online shopping carts and checkouts). I wanted to just plug and play: just set up a few templates for the cart, checkout and email receipt, and go with that, because FoxyCart is pretty nice without too much customization. But things are rarely so simple. The website will be selling not only products in a shop, but registrations to an event. Yep, that’s still easy, but a registration can be for multiple attendees, and the registrant needs to fill in the same information about each of them as he did for himself, and some of that information determines the price.
So the registrant’s gone through the whole process of filling in the forms for each attendee, and they get to their registration summary page, and there’s a list of the names of the attendees with the cost for each one (which depends on what information was supplied, what boxes were ticked), and a grand total at the bottom. This is all before they get to the shopping cart. It’s true that when adding to the FoxyCart cart you can supply it with options and corresponding prices, and this would have been good for allowing for the selection of multiple attendees; but it wouldn’t have allowed for the entry of all the attendee-specific details and their corresponding prices.
A Problem
So they hit “Add to cart” and then “Checkout” and everything’s great – if that’s the only thing they do. But what if, after adding the registration to the cart, they go back and change the details for an attendee, thereby changing the price? First of all I set the quantity_max parameter to 1 to prevent them adding it twice. But if what you’re adding has a different price, it’s treated as a different item. If they click to update the cart with a registration that comes to a different price from the one they previously added, the amended registration is added as a new product, so that they now have two in the cart.
It seems odd that FoxyCart gets stuck on this, and I thought there must be some parameter I could use, but I couldn’t find it. The solution had to be to either somehow update the price of the item in the cart, or remove any registration in the cart before adding the amended one. I ended up using the latter. To do it requires JSON AJAX requests, which you can do in jQuery with $.getJSON or $.ajax. Anyway, I quickly arrived at the essential logic on which the above code is based. But I couldn’t get it to work.
I was led first of all to use the fc_PreProcess() function. From reading the documentation it seemed that I should define a function called fc_PreProcess, put all the code inside that, and then the included FoxyCart javascript file would find my function definition and execute it prior to adding anything to the cart. Sounds perfect, I thought.
Here’s how it didn’t work. You add a registration to the cart, close the cart, amend your registration so that it now has a new price, and then add to the cart again (although as far as the user is concerned they are updating the cart), at which point the new one should be substituted for the old. And at first it seemed to work: only one registration item in the cart, and with the new price too! I cheered at the time, until I clicked “checkout” to find that the item had just fallen out. And doing it all again I saw that in the cart itself the item would disappear if you refreshed it.
What seemed to be happening was that even though the item was displayed in the cart, it had since disappeared. The item was being removed after it was added; more precisely: a new one was added, making a total of two items; the cart was displayed; and then my code found and removed both items. I’m still not quite sure how this happened, but blame may lie in the asynchronous nature of the JSON calls, mixed use of http and https, sessions, or in my lack of sleep.
A Solution
So what you see above is the hand-made solution. The “add to cart” or “update cart” button on my registration summary page doesn’t submit the form, it just executes the function add_pre_process(), which looks for an existing registration and removes any it finds; and then adds the new one. There is a separate “View cart” button.
Ideally I would have liked to use the success callback of the ajax request in add_item(), but it doesn’t fire.
So, the problem seems to be solved, but not properly solved. The question now is do I spend time investigating what the problem was and delve deep into the workings of FoxyCart, or move on to the next stage, which is the shop. Well, I’ve got two websites going live in the first week of January, so it’s no contest. Onwards!
Hi Alistair. Definitely an interesting issue. I’d like to get to the bottom of it, as it sounds like perhaps your JSONP calls were being executed one too many times. If you or others that might be interested in further discussion we have it here:
http://forum.foxycart.com/comments.php?DiscussionID=2304