callback for cart_update ?

jasonjason Member, Integration Developer, FoxyPal
in Bugs & Feature Requests edited April 2012
I was messing around with the postprocess callback.. and looking at the documentation (http://docs.foxycart.com/v/0.7.2/javascript) It mentions how you can update the minicart like:
fcc.events.cart.postprocess.add(function(){
		fcc.cart_update.call(fcc);
	});

However, it would be nice to be able to get a callback with the new json data like:
fcc.events.cart.postprocess.add(function(){
		fcc.cart_update.call(fcc, doMyCustomCartUpdate);
	});

function doMyCustomCartUpdate(data) {
  ... snip ...
}

Here's a quick stab at what I thought that might look like.
// CART UPDATING, JSON
FC.client.prototype.cart_update = function(callback) {
	var self = this;
	jQuery.getJSON('https://' + this.storedomain + '/cart.php?cart=get&output=json' + this.session_get() + '&callback=?', function(data) {
		FC.json = data;
		if ( ! self.session_initialized == true) {
			self.session_initialized = true;
			FC.session_id = data.session_id;
			self.session_set();
			self.session_get();
		}

		// "Minicart" Helpers
		(FC.json.product_count > 0) ? jQuery("#fc_minicart, .fc_minicart").show() : jQuery("#fc_minicart, .fc_minicart").css("display","none");
		// update values
		jQuery("#fc_quantity, .fc_quantity").html("" + FC.json.product_count);
		jQuery("#fc_total_price, .fc_total_price").html("" + self._currency_format(FC.json.total_price));
		// Execute the ready event on intial pageload, if it's defined
		if (self.events.cart.ready.counter == 0) {
			self.events.cart.ready.execute();
		}
                if (callback) {
                     callback(FC.json);
                }
	});
};
Comments
  • lukeluke FoxyCart Team
    Hey Jason, thanks for posting. The cart (currently) is not update able other than the quantity so mass updating the FC.json data wouldn't be possible. There's a lot of stuff going on "behind the scenes" when a product is added to the cart include quantity validations, category validations, line item discounts, category discounts, coupon discounts, etc.

    That being said, we are moving towards implementing Twig (and Swig) to do some really awesome cart / checkout stuff. Someone we both know (Kevin P) may be able to give you a demo of what he has so far. Pretty awesome stuff.

    We'll also be building out a REST API in the future which, eventually, may allow for full cart modifications like you're describing.

    In the meantime, please put in a request here: http://requests.foxycart.com/
  • jasonjason Member, Integration Developer, FoxyPal
    Hey Luke, I should have added a little more to my post. The last code snippet comes from foxycart.raw.js. I was trying to demonstrate how you could add a callback to your cart_update function. This would allow clients to know when the FC.json object has completed updating. I think this could be very handy and save the client an additional AJAX call to get the FC.json data. You're already getting it in cart_update, the client just doesn't know when the data is ready. It basically just involves adding these three lines near the bottom of the function (and the callback parameter):
    if (callback) {
                         callback(FC.json);
                    }
    
    I hope that makes more sense now.
  • lukeluke FoxyCart Team
    Ah, i see what you're saying. I'll have @brett take a look as he wrote that portion of code. I wasn't aware a callback was needed, but if it is, it should definitely be there.
  • RolfRolf Member
    Yes, @jason is right.. it should fire some event or invoke a callback with the fresh data just in case you want to do your own (dom) updates or something.

    However, I think it's also wise to always request the latest cart data whenever you are doing something, as the cart might be expired. If you rely on the local js object you might be using outdated data.
    So in my case for example I have a local shopping cart (for displaying the FC data) and whenever I open that one I do fresh jsonp request. I could implement some timer to only request new data after X minutes and then using the local FC object and use cart_update callback also to update the dom where I want, but it's not that big of a problem imho (the extra jsonp requests).




  • brettbrett FoxyCart Team
    @jason and @rolf, I think I might be missing you guys. I'll try to explain my take on it and if there are holes in the approach please let me know.
    This would allow clients to know when the FC.json object has completed updating. I think this could be very handy and save the client an additional AJAX call to get the FC.json data. You're already getting it in cart_update, the client just doesn't know when the data is ready.

    My thought here is that that's what the events are for (preprocess, process, postprocess). If fcc.cart_update() is _ever_ called, it's called within the context of the fcc.events. If you want to execute code whenever the cart is updated, add the function to the fcc.events. No?

    @Rolf, you mention "fresh data", but the very first thing that fcc.cart_update() does when it gets data is to update the FC.json object, so I'm having trouble thinking of a situation where the FC.json would be stale. FC.json will _always_ be the freshest available, unless you're manually making JSONP calls without using the fcc object. (The exception is if the customer is modifying the cart in two separate tabs, which I imagine would be uncommon but perhaps I'm wrong there?)

    On the one hand, I feel like perhaps adding a callback would be a good idea, but even if so I think I'd want to put it into an fcc.events.update or something, and in that case I'm not sure how it'd be different than what we already have? Are there situations you're running into where the existing events aren't giving you what you need? I'd love to know so we could improve what we're offering you :)
  • RolfRolf Member
    Well, I should dive into the code again really to check this...

    I have my own cart view (which could be an overview of the cart with links in a modal) and whenever I click a "view cart" link it does a JSONP call to get the (latest) cart data, and then build my cart table.
    the postprocess event runs fcc.cart_update.call(fcc); but I can not update my html (dom) at that moment because it runs FC.client.prototype.cart_update which does the jquery jsonp call which updates the mini cart stuff etc. At that moment (in the callback) I would like to be notified as well of the new data, correct? If I place my own function call in postprocess to update the (my) dom it has the old data because the jsonp from cart_update is (maybe) not finished yet because it's async.

    Or am I overlooking something?

    Also I was thinking of maybe FoxyCart is canceling the cart data after some period of time (I'm not sure it does or how long it takes), but if I would use the local stored FC.json I could be showing customers a populated cart, but when they go to the checkout they would get a message that their cart is actually empty/expired. Maybe this is far stretched, but that was the reason as well to just call for a fresh cart object every time someone views the cart (the extra call is just minor data so why not I thought).
  • jasonjason Member, Integration Developer, FoxyPal
    Hey @brett, thanks for hanging in here with me... there is one piece missing...
    you mention "fresh data", but the very first thing that fcc.cart_update() does when it gets data is to update the FC.json object, so I'm having trouble thinking of a situation where the FC.json would be stale.
    Yes, cart_update does make the call to update the FC.json object, but it does so asynchronously. Therefore, when you're in postprocess, right after cart_update is called, the data is still stale. That's why passing a callback function to cart_update would be convenient. So when cart_update finishes it's asynchronous call, you would get the fresh data. It saves me the trouble of making an additional call back to your server.. the only reason I have to make it is because I don't know when FC.json becomes ready after the call to cart_update.
  • RolfRolf Member
    yes, what I thought
  • brettbrett FoxyCart Team
    edited April 2012
    @Rolf and @jason, have you guys seen this?
    http://wiki.foxycart.com/v/0.7.2/javascript#pausing_and_resuming_event_execution
    That's new as of v0.7.2, but was added because of issues like these. If you're needing to make sure that you have the updated FC.json at a certain step, just pause and resume at an appropriate earlier step.

    Tbh, I'm really (really) happy to have this discussion. We're contemplating unifying the checkout javascript with the same FC.events functionality as in the foxycart.js, and if it needs improvement we definitely want to make that happen. The approach we had in v0.6.0 and prior was much simpler but also much less flexible, and this new approach has allowed us the flexibility (on our end) to do things like add a fully responsive JSONP-based cart (that's not done so it won't be in our upcoming release but probably the release after that) without needing to change the core foxycart.js.

    Prior to the addition of the pause/resume functionality, there were problems like you're pointing out, but I _think_ (or rather, _hope_) that that addresses them. We're trying to provide an event system that's extensible and flexible enough for _all_ of our users. There may be approaches to events that we haven't seen that are better, but I'd love to see whether what we have actually does meet your needs.

    EDIT: Sorry, I don't think I answered the question, but could you share (or whisper if it's private) a link to what you're doing? That might be easier for me to see. Thanks!

    EDIT 2: After talking with @fc_adam I think I better understand the underlying issue here, and we're working on ideas. Adam has some code to add the pause/resume to the cart_update() method, but I'm thinking it might make more sense to make an fcc.events.cart.update event, which would have as its first function the fcc.cart_update() with a pause then a resume when the JSON is returned. Thoughts?
  • jasonjason Member, Integration Developer, FoxyPal
    Re: EDIT 2. Yeah, I think that sounds in line with what I'm thinking. The main thing is just getting notified when the fresh JSON data is returned. Perhaps when Adam has his code ready I could take a look and give some feedback. Thanks!

    You asked about the code.. Here's what I'm doing right now:
    (function($) {
    	fcc.events.cart.postprocess = new FC.client.event();
    	fcc.events.cart.postprocess.add(function(e) {
    		fcc.cart_update.call(fcc);
    		$.getJSON('https://'+storedomain+'/cart?'+fcc.session_get()+'&output=json&callback=?', function(data) {
    			buildFullCart(data.products);
    		});
    	});
    })(jQuery);
    

    Where 'buildFullCart' is my own custom function that manipulates the page.
    Here's what I'd like to be able to do:
    (function($) {
    	fcc.events.cart.postprocess = new FC.client.event();
    	fcc.events.cart.postprocess.add(function(e) {
    		fcc.cart_update.call(fcc, function(data) {
    			buildFullCart(data.products);
    		});
    	});
    })(jQuery);
    

    However, if we add a new 'fcc.events.cart.update' this could look totally different, but accomplish the same goal.
  • fc_adamfc_adam FoxyCart Team
    @jason,

    Actually with the approach we're describing, it would look more like this:
    fcc.events.cart.postprocess = new FC.client.event();
    fcc.events.cart.postprocess.add(function(){
    	fcc.cart_update();
    	return "pause";
    });
    fcc.events.cart.postprocess.add(function(){
    	buildFullCart(FC.json.products);
    });
    

    It will be slightly different with a cart_update approach, but rather than assigning callbacks you'd simply add another function to the event queue and by using pause it runs after the called function calls resume on that event queue.
  • RolfRolf Member
    @fc_adam,

    With your example you would do a postprocess.resume() in the fcc.cart_update() method, if I understand correctly(?)

    I think this will work yes, it's basically using what you already have designed; the pause/resume part is describing our problem/request but at the moment cart_update doesn't use it internally which it should because it's using the async call.

    Let's try it?! :)
  • fc_adamfc_adam FoxyCart Team
    @Rolf,

    Yes that's right. You could give it a try right now by overwriting the cart_update function - give this a try: https://gist.github.com/a750a52ac8274226e056
  • RolfRolf Member
    @fc_adam, got caught up but this is on my list for tomorrow/coming days. I'll report back here.
  • jasonjason Member, Integration Developer, FoxyPal
    I just gave it a try and it works well for me. Thanks @fc_adam!
  • ocorralocorral Member
    Wow what perfect timing. I needed all of these questions answered and Adam's code works perfect. Thanks Adam!
Sign In or Register to comment.