Deregister core cart/checkout scripts and styles when rendering the blocks (https://github.com/woocommerce/woocommerce-blocks/pull/2842)
* Deregister core cart/checkout scripts and styles when rendering the blocks * Fix regression: redirect to full cart when adding a product from empty cart * Make it so it scrolls to the top * Update assets/js/base/utils/legacy-events.js Co-authored-by: Darren Ethier <darren@roughsmootheng.in> * Add check for jQuery availability * Listen to removed from cart event too * Remove unnecessary useEffect dependency * Remove jQuery event subscriptions on component unmount * Fix tests Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
This commit is contained in:
parent
d894fed1df
commit
8bfb95c808
|
@ -16,6 +16,7 @@ module.exports = {
|
|||
context: true,
|
||||
jestPuppeteer: true,
|
||||
fetchMock: true,
|
||||
jQuery: 'readonly',
|
||||
},
|
||||
plugins: [ 'jest', 'woocommerce' ],
|
||||
rules: {
|
||||
|
|
|
@ -1,19 +1,63 @@
|
|||
const Event = window.Event || null;
|
||||
|
||||
/**
|
||||
* Wrapper function to dispatch an event so it's compatible with IE11.
|
||||
*
|
||||
* @param {string} name Name of the event to dispatch.
|
||||
* @param {boolean} bubbles Whether the event bubbles.
|
||||
* @param {boolean} cancelable Whether the event is cancelable.
|
||||
*/
|
||||
const dispatchEvent = ( name, bubbles = false, cancelable = false ) => {
|
||||
// In IE, Event is an object and can't be instantiated with `new Event()`.
|
||||
if ( typeof Event === 'function' ) {
|
||||
const event = new Event( name, {
|
||||
bubbles,
|
||||
cancelable,
|
||||
} );
|
||||
document.body.dispatchEvent( event );
|
||||
} else {
|
||||
const event = document.createEvent( 'Event' );
|
||||
event.initEvent( name, bubbles, cancelable );
|
||||
document.body.dispatchEvent( event );
|
||||
}
|
||||
};
|
||||
|
||||
// This is a hack to trigger cart updates till we migrate to block based cart
|
||||
// that relies on the store, see
|
||||
// https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/1247
|
||||
export const triggerFragmentRefresh = () => {
|
||||
// In IE, Event is an object and can't be instantiated with `new Event()`.
|
||||
if ( typeof Event === 'function' ) {
|
||||
const event = new Event( 'wc_fragment_refresh', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
} );
|
||||
document.body.dispatchEvent( event );
|
||||
} else {
|
||||
const event = document.createEvent( 'Event' );
|
||||
event.initEvent( 'wc_fragment_refresh', true, true );
|
||||
document.body.dispatchEvent( event );
|
||||
}
|
||||
dispatchEvent( 'wc_fragment_refresh', true, true );
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that listens to a jQuery event and dispatches a native JS event.
|
||||
* Useful to convert WC Core events into events that can be read by blocks.
|
||||
*
|
||||
* @param {string} jQueryEventName Name of the jQuery event to listen to.
|
||||
* @param {string} nativeEventName Name of the native event to dispatch.
|
||||
* @param {boolean} bubbles Whether the event bubbles.
|
||||
* @param {boolean} cancelable Whether the event is cancelable.
|
||||
*
|
||||
* @returns {Function} Function to remove the jQuery event handler. Ideally it
|
||||
* should be used when the component is unmounted.
|
||||
*/
|
||||
export const translateJQueryEventToNative = (
|
||||
jQueryEventName,
|
||||
nativeEventName,
|
||||
bubbles = false,
|
||||
cancelable = false
|
||||
) => {
|
||||
// @ts-ignore -- jQuery is window global
|
||||
if ( typeof jQuery !== 'function' ) {
|
||||
return () => void null;
|
||||
}
|
||||
|
||||
const eventDispatcher = () => {
|
||||
dispatchEvent( nativeEventName, bubbles, cancelable );
|
||||
};
|
||||
|
||||
// @ts-ignore -- jQuery is window global
|
||||
jQuery( document ).on( jQueryEventName, eventDispatcher );
|
||||
// @ts-ignore -- jQuery is window global
|
||||
return () => jQuery( document ).off( jQueryEventName, eventDispatcher );
|
||||
};
|
||||
|
|
|
@ -1,22 +1,66 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
|
||||
import { dispatch } from '@wordpress/data';
|
||||
import { useStoreCart } from '@woocommerce/base-hooks';
|
||||
import { RawHTML } from '@wordpress/element';
|
||||
import { useEffect, RawHTML } from '@wordpress/element';
|
||||
import LoadingMask from '@woocommerce/base-components/loading-mask';
|
||||
import {
|
||||
ValidationContextProvider,
|
||||
CartProvider,
|
||||
} from '@woocommerce/base-context';
|
||||
import { translateJQueryEventToNative } from '@woocommerce/base-utils';
|
||||
import withScrollToTop from '@woocommerce/base-hocs/with-scroll-to-top';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import FullCart from './full-cart';
|
||||
|
||||
const Block = ( { emptyCart, attributes } ) => {
|
||||
const Block = ( { emptyCart, attributes, scrollToTop } ) => {
|
||||
const { cartItems, cartIsLoading } = useStoreCart();
|
||||
|
||||
useEffect( () => {
|
||||
const invalidateCartData = () => {
|
||||
dispatch( storeKey ).invalidateResolutionForStore();
|
||||
scrollToTop();
|
||||
};
|
||||
|
||||
// Make it so we can read jQuery events triggered by WC Core elements.
|
||||
const removeJQueryAddedToCartEvent = translateJQueryEventToNative(
|
||||
'added_to_cart',
|
||||
'wc-blocks_added_to_cart'
|
||||
);
|
||||
const removeJQueryRemovedFromCartEvent = translateJQueryEventToNative(
|
||||
'removed_from_cart',
|
||||
'wc-blocks_removed_from_cart'
|
||||
);
|
||||
|
||||
document.body.addEventListener(
|
||||
'wc-blocks_added_to_cart',
|
||||
invalidateCartData
|
||||
);
|
||||
document.body.addEventListener(
|
||||
'wc-blocks_removed_from_cart',
|
||||
invalidateCartData
|
||||
);
|
||||
|
||||
return () => {
|
||||
removeJQueryAddedToCartEvent();
|
||||
removeJQueryRemovedFromCartEvent();
|
||||
|
||||
document.body.removeEventListener(
|
||||
'wc-blocks_added_to_cart',
|
||||
invalidateCartData
|
||||
);
|
||||
document.body.removeEventListener(
|
||||
'wc-blocks_removed_from_cart',
|
||||
invalidateCartData
|
||||
);
|
||||
};
|
||||
}, [ scrollToTop ] );
|
||||
|
||||
return (
|
||||
<>
|
||||
{ ! cartIsLoading && cartItems.length === 0 ? (
|
||||
|
@ -34,4 +78,4 @@ const Block = ( { emptyCart, attributes } ) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default Block;
|
||||
export default withScrollToTop( Block );
|
||||
|
|
|
@ -63,6 +63,12 @@ class Cart extends AbstractBlock {
|
|||
}
|
||||
);
|
||||
|
||||
// Deregister core cart scripts and styles.
|
||||
wp_deregister_script( 'wc-cart' );
|
||||
wp_deregister_script( 'wc-password-strength-meter' );
|
||||
wp_deregister_script( 'selectWoo' );
|
||||
wp_deregister_style( 'select2' );
|
||||
|
||||
return $this->inject_html_data_attributes( $content . $this->get_skeleton(), $block_attributes );
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,12 @@ class Checkout extends AbstractBlock {
|
|||
$this->enqueue_assets( $block_attributes );
|
||||
do_action( 'woocommerce_blocks_enqueue_checkout_block_scripts_after' );
|
||||
|
||||
// Deregister core checkout scripts and styles.
|
||||
wp_deregister_script( 'wc-checkout' );
|
||||
wp_deregister_script( 'wc-password-strength-meter' );
|
||||
wp_deregister_script( 'selectWoo' );
|
||||
wp_deregister_style( 'select2' );
|
||||
|
||||
return $this->inject_html_data_attributes( $content . $this->get_skeleton(), $block_attributes );
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,11 @@ global.wcSettings = {
|
|||
},
|
||||
};
|
||||
|
||||
global.jQuery = () => ( {
|
||||
on: () => void null,
|
||||
off: () => void null,
|
||||
} );
|
||||
|
||||
const wordPressPackages = [
|
||||
'blocks',
|
||||
'components',
|
||||
|
|
Loading…
Reference in New Issue