0

EDIT: see solution below from @motivast. With his basic setup you can then make whatever changes you'd like to specific auto-scroll actions and relocate whichever specific notices you want. My final solution also includes hooking a blank div within the coupon form and then targeting the coupon notices there, like this:

/* Add div to hook coupon notices to */
add_action ('woocommerce_cart_coupon' , 'coupon_notices_div' , 1 );
function coupon_notices_div() {
    echo "";
?>
<div class="cart-coupon-notices"></div>
<?php
}

With that in your custom plugin php file, you can then use .cart-coupon-notices instead of .cart-collaterals in @motivast's solution. This places the coupon notices immediately below the "apply coupon" button.


Original question:

I've found many examples of how to do this for the "added to cart" notice on products/shop pages, but the cart page seems to be altogether different. The notices I want to move more than any others are the coupon notices (i.e. "coupon applied successfully" etc.). Auto-scrolling the customers to the top of the page when they add a coupon is quite annoying for them.

The solution everyone talks about is that you need to just relocate wc_print_notices from the top of the cart page to somewhere else (I want it hooked to woocommerce_before_cart_totals), but no matter what I do the notices are still at the top of the page.

There are several variations of this question on stackexchange, none with any answers that work.

I've tried all the options listed here, but no luck.

I've tried playing with variations from here, also no luck.

I've tried the options from here, and... no luck.

Other variations of the same problem: here, here, a possible solution that works only with the storefront theme here.

Any help would be hugely appreciated!

EDIT: Two threads from elsewhere helping to solve this issue:

https://wordpress.org/support/topic/relocate-coupon-notices-on-cart-page/

https://www.facebook.com/groups/advanced.woocommerce/permalink/2141163449231396/

  • you would need to overwrite cart.min.js (there is also a non-minified version in wc included), since the element you are talking about is created there. look for the function show_notice – honk31 Jun 12 '18 at 15:35
  • Thanks @honk31 . I had a look at cart.js and I can see show_notice there. But it looks like that is just controlling when to trigger the notice, not where the notice will be displayed. Maybe I'm wrong about that though...? – Jon Fergus Jun 12 '18 at 17:07
  • the function show_notice takes two arguments ( html_element, $target ), the notice content and the jquery target. since no target is supplied, it will always use $( '.woocommerce-cart-form' ); as a fallback, so all you would need to change, is the $target, like in the answer of motivast, he passes a second argument in the ajax success argument. you can find it in the unminified version on line 452 – honk31 Jun 13 '18 at 7:44
0

Coupon notices are displayed by updating cart dynamically using JavaScript. Moving wc_print_notices function will not take effect because all logic is placed in the cart.js file. You have to deregister and dequeue WooCommerce cart.js file and add your own modified version.

/**
 * Deregister and dequeue WooCommerce cart.js file and add own modified version.
 */
function wpse_305939_replace_woocommerce_cart_script() {

    /**
     * Remove default woocommerce cart scripts.
     */
    wp_deregister_script( 'wc-cart' );
    wp_dequeue_script( 'wc-cart' );

    /**
     * Add own modify scripts.
     */
    wp_register_script( 'wc-cart', plugin_dir_url( __FILE__ ) . 'js/cart.js', array( 'jquery', 'woocommerce', 'wc-country-select', 'wc-address-i18n' ), WC_VERSION, true );

    if( is_cart() ) {
        wp_enqueue_script( 'wc-cart' );
    }
}

add_action( 'wp_enqueue_scripts', 'wpse_305939_replace_woocommerce_cart_script', 20 );

Copy original cart.js entirely to your custom cart.js and update two methods.

apply_coupon

/**
 * Apply Coupon code
 *
 * @param {JQuery Object} $form The cart form.
 */
apply_coupon: function( $form ) {
    block( $form );

    var cart = this;
    var $text_field = $( '#coupon_code' );
    var coupon_code = $text_field.val();

    var data = {
        security: wc_cart_params.apply_coupon_nonce,
        coupon_code: coupon_code
    };

    $.ajax( {
        type:     'POST',
        url:      get_url( 'apply_coupon' ),
        data:     data,
        dataType: 'html',
        success: function( response ) {
            $( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
            show_notice( response, $('.cart-collaterals') );
            $( document.body ).trigger( 'applied_coupon', [ coupon_code ] );
        },
        complete: function() {
            unblock( $form );
            $text_field.val( '' );
            cart.update_cart( true, false);
        }
    } );
}

and update_cart

/**
 * Update entire cart via ajax.
 */
update_cart: function( preserve_notices, scroll_to_notices ) {
    var $form = $( '.woocommerce-cart-form' );

    block( $form );
    block( $( 'div.cart_totals' ) );

    // Make call to actual form post URL.
    $.ajax( {
        type:     $form.attr( 'method' ),
        url:      $form.attr( 'action' ),
        data:     $form.serialize(),
        dataType: 'html',
        success:  function( response ) {
            update_wc_div( response, preserve_notices );
        },
        complete: function() {

            scroll_to_notices = typeof scroll_to_notices !== 'undefined' ? scroll_to_notices : true;

            unblock( $form );
            unblock( $( 'div.cart_totals' ) );

            if( scroll_to_notices ) {
                $.scroll_to_notices( $( '[role="alert"]' ) );
            }
        }
    } );
}

You can check what has been updated comparing these two methods with an original cart.js file (WooCommerce 3.4.2).

This solution works only for notice when a coupon is applied.

  • Thanks @motivast. That does the trick. Here's an update: I've created a custom plugin with your code, but with two adjustments: 1. I did the same for the remove_coupon_clicked function as you did for the apply_coupon function. 2. I changed .cart-collateral to .coupon, which locates the coupon notices directly above the coupon form. – Jon Fergus Jun 15 '18 at 13:47
  • Instead of .coupon, I've now added a new blank div within the coupon form and hooked the notices there. This works like a charm. – Jon Fergus Jun 16 '18 at 8:53

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.