• Resolved therealgilles

    (@chamois_blanc)


    Hello,

    I took a look at the following script because my mobile menu cart menu item does not disappear when the cart is emptied through ajax:

    assets/js/wpmenucart-ajax-assist.js

    There is no way it is going to work when an item is removed from the cart and the cart becomes empty. Only the adding_to_cart action is bound.

Viewing 10 replies - 1 through 10 (of 10 total)
  • Thread Starter therealgilles

    (@chamois_blanc)

    Additionally the code below needs to be inside the bind call so that the state of the cart is re-evaluated properly:

    
                    if ( typeof window.Cookies !== 'undefined' ) { // WC3.0
                            items_in_cart = Cookies.get( 'woocommerce_items_in_cart' );
                    } else if ( typeof $.cookie !== 'undefined' && $.isFunction($.cookie) ){ // WC2.X
                            items_in_cart = $.cookie( 'woocommerce_items_in_cart' );
                    } else {
                            return; // no business here
                    }
    
                    if ( items_in_cart > 0 ) {
                            $('.empty-wpmenucart').removeClass('empty-wpmenucart');
                    } else if ( !(wpmenucart_ajax_assist.always_display) ) {
                            $('.wpmenucartli').addClass('empty-wpmenucart');
                            $('.wpmenucart-shortcode').addClass('empty-wpmenucart');
                    }
    
    Thread Starter therealgilles

    (@chamois_blanc)

    I believe the correct action to bind to is ‘updated_wc_div’.

    Mentioning that:

    $( document.body ).bind( <action>, function() {

    is deprecated, and should instead be written as:

    $( document.body ).on( <action>, function() {

    Plugin Contributor Ewout

    (@pomegranate)

    Hi @chamois_blanc!
    Thank you so much for contributing. The ajax assist script is actually specifically for assistence with server side caching, on non-cached sites it should work without this script too. That’s why this function is not bound to any trigger besides the add-to-cart, it’s only intended to be run once on page load to override cached CSS classes in the menu item. That’s also why there is no specific binding to the AJAX remove from cart action, as this would already trigger an update of the fragments.

    I think the issue you’re describing is resolved with the following script:

    
    jQuery( function( $ ) {
    	/* Cart Hiding */
    	if (wpmenucart_ajax_assist.shop_plugin == 'WooCommerce' ) {
    		// update on page load
    		wpmenucart_update_menu_classes();
    		// update when cart is updated
    		$( document.body ).on( 'adding_to_cart updated_wc_div', wpmenucart_update_menu_classes );
    	}
    
    	function wpmenucart_update_menu_classes() {
    		if ( typeof window.Cookies !== 'undefined' ) { // WC3.0
    			items_in_cart = Cookies.get( 'woocommerce_items_in_cart' );
    		} else if ( typeof $.cookie !== 'undefined' && $.isFunction($.cookie) ){ // WC2.X
    			items_in_cart = $.cookie( 'woocommerce_items_in_cart' );
    		} else {
    			return; // no business here
    		}
    
    		if ( items_in_cart > 0 ) {
    			$('.empty-wpmenucart').removeClass('empty-wpmenucart');
    		} else if ( !(wpmenucart_ajax_assist.always_display) ) {
    			$('.wpmenucartli').addClass('empty-wpmenucart');
    			$('.wpmenucart-shortcode').addClass('empty-wpmenucart');
    		}
    	}
    });
    

    Can you confirm this?

    Thanks!
    Ewout

    Thread Starter therealgilles

    (@chamois_blanc)

    Will do. Wouldn’t added_to_cart be better than adding_to_cart? adding_to_cart is used prior to modifying the cart content, while added_to_cart is used once the cart content is done. The latter is a better time to update the menu item.

    Thread Starter therealgilles

    (@chamois_blanc)

    A few other notes:

    The ajax assist script is actually specifically for assistence with server side caching, on non-cached sites it should work without this script too.

    What do you mean by ‘server-side caching’? Woocommerce uses ajax requests to update the cart content without having to reload the page. This is not server-side caching in my mind.

    That’s why this function is not bound to any trigger besides the add-to-cart, it’s only intended to be run once on page load to override cached CSS classes in the menu item.

    Not sure what you mean by ‘cached CSS classes’. The code updates the DOM to remove some of the classes and add other ones. I guess you could say the browser caches the CSS classes, but that’s not usually how people use the word.

    That’s also why there is no specific binding to the AJAX remove from cart action, as this would already trigger an update of the fragments.

    I am a bit confused by this statement. Updating the fragments does not necessarily reload the page and it won’t automatically update the menu item content either. That’s why you have assets/js/wpmenucart.js which triggers on listed button clicks.

    In my opinion, the file should have triggers on added_to_cart and updated_wc_div instead, and the code above should be integrated with it with the CSS classes updated appropriately. The button click specific code should then not be necessary anymore. This is for Woocommerce only obviously.

    Using added_to_cart ought to allow you to replace:

    setTimeout(function () { WPMenucart_Load_JS(); }, 1000);

    by just this:

    WPMenucart_Load_JS();

    as everything should be up-to-date when the event triggers.

    Caveats: not sure how it would fair with older versions of Woocommerce.

    Plugin Contributor Ewout

    (@pomegranate)

    What do you mean by ‘server-side caching’? Woocommerce uses ajax requests to update the cart content without having to reload the page. This is not server-side caching in my mind.

    By server side caching I mean varnish cache, W3 Total Cache, WP Rocket – anything that prerenders pages and serves that instead of dynamically generating them all the time. Indeed, WooCommerce uses AJAX to update the cart contents, and this works fine and does not suffer from server side caching. However, this only updates the actual cart contents and not it’s wrappers. WooCommerce faces a similar issue with their own mini-cart and have a similar solution.

    Not sure what you mean by ‘cached CSS classes’. The code updates the DOM to remove some of the classes and add other ones. I guess you could say the browser caches the CSS classes, but that’s not usually how people use the word.

    I am referring to the CSS classes in the li menu element (specifically, the class that defines whether it’s empty: empty-wpmenucart). Normally WP Menu Cart dynamically sets these, based on the content of the cart. But server side caching makes this static, which would produce unreliable results. Hence this ajax-assist script ??

    I am a bit confused by this statement. Updating the fragments does not necessarily reload the page and it won’t automatically update the menu item content either. That’s why you have assets/js/wpmenucart.js which triggers on listed button clicks.

    In my opinion, the file should have triggers on added_to_cart and updated_wc_div instead, and the code above should be integrated with it with the CSS classes updated appropriately. The button click specific code should then not be necessary anymore. This is for Woocommerce only obviously.

    Using added_to_cart ought to allow you to replace:

    
    setTimeout(function () { WPMenucart_Load_JS(); }, 1000);
    

    by just this:

    
    WPMenucart_Load_JS();
    

    as everything should be up-to-date when the event triggers.

    Actually, updating fragments does update the menucart automatically, as it has been added to the fragments data using woocommerce_add_to_cart_fragments: source.
    The additional script you are referring to is not used on default installations and only there for fallback purposes (primarily outside WooCommerce anyway (the plugin works with multiple shop plugins), since WooCommerce fragments work excellent most of the time also since most caching plugins have taken this into account).
    There is no need to reload the page after something has been added to the cart, we have AJAX to account for just the menu cart bit. The wpmenucart-ajax-assist.js script was only ran at the initial page load to prevent any cached empty-wpmenucart class from overriding the actual cart state.

    added_to_cart or adding_to_cart does not make a big difference anyway, it’s only to set or unset the empty-wpmenucart class in the item (the actual contents are updated by WooCommerce fragments when WC receives the ajax response). When something is added to the cart it can start removing the class regardless of the result. Semantically I agree, but I have decided to stick with the behavior WC has for the mini-cart to keep everything consistent.

    This is unrelated to the WPMenucart_Load_JS function that you are referring to which is only there for fallback/backup purposes and not used in WC unless there are issues with WooCommerce fragments (mostly a thing of the past). A delay like this wouldn’t be necessary for WooCommerce because it triggers events when it’s done, but some of the other shop plugins do not have such triggers so we rely on more basic solutions.

    Hope that clarifies things ??

    Should you have any follow up questions, do not hesitate to send an email to [email protected] (also since you appear to be using the pro version, you are entitled to priority support). Also, do note that some of what you may seeing could be both WooCommerce & Pro specific. Pro is a bit more advanced in this aspect!

    Have a fantastic weekend!
    Ewout

    Plugin Contributor Ewout

    (@pomegranate)

    A quick PS to avoid some confusion:
    The initial issue you posted here was an actual bug, but only in Pro, not in the free version (which does not have the empty-wpmenucart class at the top-level li item). Removing from cart via AJAX has only recently been introduced to WC and this hadn’t been taken into account yet.
    The cart would still update on the next page load, except if you had server side caching which is what the ajax-assist script would then fix when the page loaded – cart hidden again (if configured as such in the settings).

    Since the free version did not have that empty-wpmenucart class at the top-level li item, WC AJAX fragments would take care of the cart changes, including removal. (free only has the <a> element which would be updated by the fragments and include the class that would hide it, pro has a submenu <ul> next to it so we hide the entire top level item).

    Plugin Contributor Ewout

    (@pomegranate)

    Updates for both Pro and the free version were released today that address this issue. Thank you for contributing!

    Ewout

    Thread Starter therealgilles

    (@chamois_blanc)

    Thank you for the updates. I will try them out at some point, although I have already implemented my own workarounds.

    WooCommerce uses AJAX to update the cart contents, and this works fine and does not suffer from server side caching.

    It depends on how the server-side caching is done. Varnish, for instance, can cache everything, including ajax requests/responses.

    Semantically I agree, but I have decided to stick with the behavior WC has for the mini-cart to keep everything consistent.

    I am afraid adding_to_cart won’t work well when the cart is being emptied as the cart content hasn’t been updated yet at this point. The setTimeout delay may be masking / working around this “bug”.

    Plugin Contributor Ewout

    (@pomegranate)

    I am afraid adding_to_cart won’t work well when the cart is being emptied as the cart content hasn’t been updated yet at this point. The setTimeout delay may be masking / working around this “bug”.

    WooCommerce triggers the updated_wc_div (whats in a name) event when the cart is emptied (or updated otherwise) – this is also what I have bound for the ajax-assist script.

    Happy holidays!
    Ewout

Viewing 10 replies - 1 through 10 (of 10 total)
  • The topic ‘wpmenucart-ajax-assist.js script broken’ is closed to new replies.