| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- /* global wc_cart_params */
- jQuery( function( $ ) {
- // wc_cart_params is required to continue, ensure the object exists
- if ( typeof wc_cart_params === 'undefined' ) {
- return false;
- }
- // Utility functions for the file.
- /**
- * Gets a url for a given AJAX endpoint.
- *
- * @param {String} endpoint The AJAX Endpoint
- * @return {String} The URL to use for the request
- */
- var get_url = function( endpoint ) {
- return wc_cart_params.wc_ajax_url.toString().replace(
- '%%endpoint%%',
- endpoint
- );
- };
- /**
- * Check if a node is blocked for processing.
- *
- * @param {JQuery Object} $node
- * @return {bool} True if the DOM Element is UI Blocked, false if not.
- */
- var is_blocked = function( $node ) {
- return $node.is( '.processing' ) || $node.parents( '.processing' ).length;
- };
- /**
- * Block a node visually for processing.
- *
- * @param {JQuery Object} $node
- */
- var block = function( $node ) {
- if ( ! is_blocked( $node ) ) {
- $node.addClass( 'processing' ).block( {
- message: null,
- overlayCSS: {
- background: '#fff',
- opacity: 0.6
- }
- } );
- }
- };
- /**
- * Unblock a node after processing is complete.
- *
- * @param {JQuery Object} $node
- */
- var unblock = function( $node ) {
- $node.removeClass( 'processing' ).unblock();
- };
- /**
- * Update the .woocommerce div with a string of html.
- *
- * @param {String} html_str The HTML string with which to replace the div.
- * @param {bool} preserve_notices Should notices be kept? False by default.
- */
- var update_wc_div = function( html_str, preserve_notices ) {
- var $html = $.parseHTML( html_str );
- var $new_form = $( '.woocommerce-cart-form', $html );
- var $new_totals = $( '.cart_totals', $html );
- var $notices = $( '.woocommerce-error, .woocommerce-message, .woocommerce-info', $html );
- // No form, cannot do this.
- if ( $( '.woocommerce-cart-form' ).length === 0 ) {
- window.location.href = window.location.href;
- return;
- }
- // Remove errors
- if ( ! preserve_notices ) {
- $( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
- }
- if ( $new_form.length === 0 ) {
- // If the checkout is also displayed on this page, trigger reload instead.
- if ( $( '.woocommerce-checkout' ).length ) {
- window.location.href = window.location.href;
- return;
- }
- // No items to display now! Replace all cart content.
- var $cart_html = $( '.cart-empty', $html ).closest( '.woocommerce' );
- $( '.woocommerce-cart-form__contents' ).closest( '.woocommerce' ).replaceWith( $cart_html );
- // Display errors
- if ( $notices.length > 0 ) {
- show_notice( $notices, $( '.cart-empty' ).closest( '.woocommerce' ) );
- }
- } else {
- // If the checkout is also displayed on this page, trigger update event.
- if ( $( '.woocommerce-checkout' ).length ) {
- $( document.body ).trigger( 'update_checkout' );
- }
- $( '.woocommerce-cart-form' ).replaceWith( $new_form );
- $( '.woocommerce-cart-form' ).find( ':input[name="update_cart"]' ).prop( 'disabled', true );
- if ( $notices.length > 0 ) {
- show_notice( $notices );
- }
- update_cart_totals_div( $new_totals );
- }
- $( document.body ).trigger( 'updated_wc_div' );
- };
- /**
- * Update the .cart_totals div with a string of html.
- *
- * @param {String} html_str The HTML string with which to replace the div.
- */
- var update_cart_totals_div = function( html_str ) {
- $( '.cart_totals' ).replaceWith( html_str );
- $( document.body ).trigger( 'updated_cart_totals' );
- };
- /**
- * Clear previous notices and shows new one above form.
- *
- * @param {Object} The Notice HTML Element in string or object form.
- */
- var show_notice = function( html_element, $target ) {
- if ( ! $target ) {
- $target = $( '.woocommerce-cart-form' );
- }
- $target.before( html_element );
- };
- /**
- * Object to handle AJAX calls for cart shipping changes.
- */
- var cart_shipping = {
- /**
- * Initialize event handlers and UI state.
- */
- init: function( cart ) {
- this.cart = cart;
- this.toggle_shipping = this.toggle_shipping.bind( this );
- this.shipping_method_selected = this.shipping_method_selected.bind( this );
- this.shipping_calculator_submit = this.shipping_calculator_submit.bind( this );
- $( document ).on(
- 'click',
- '.shipping-calculator-button',
- this.toggle_shipping
- );
- $( document ).on(
- 'change',
- 'select.shipping_method, :input[name^=shipping_method]',
- this.shipping_method_selected
- );
- $( document ).on(
- 'submit',
- 'form.woocommerce-shipping-calculator',
- this.shipping_calculator_submit
- );
- $( '.shipping-calculator-form' ).hide();
- },
- /**
- * Toggle Shipping Calculator panel
- */
- toggle_shipping: function() {
- $( '.shipping-calculator-form' ).slideToggle( 'slow' );
- $( document.body ).trigger( 'country_to_state_changed' ); // Trigger select2 to load.
- return false;
- },
- /**
- * Handles when a shipping method is selected.
- */
- shipping_method_selected: function() {
- var shipping_methods = {};
- $( 'select.shipping_method, :input[name^=shipping_method][type=radio]:checked, :input[name^=shipping_method][type=hidden]' ).each( function() {
- shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
- } );
- block( $( 'div.cart_totals' ) );
- var data = {
- security: wc_cart_params.update_shipping_method_nonce,
- shipping_method: shipping_methods
- };
- $.ajax( {
- type: 'post',
- url: get_url( 'update_shipping_method' ),
- data: data,
- dataType: 'html',
- success: function( response ) {
- update_cart_totals_div( response );
- },
- complete: function() {
- unblock( $( 'div.cart_totals' ) );
- $( document.body ).trigger( 'updated_shipping_method' );
- }
- } );
- },
- /**
- * Handles a shipping calculator form submit.
- *
- * @param {Object} evt The JQuery event.
- */
- shipping_calculator_submit: function( evt ) {
- evt.preventDefault();
- var $form = $( evt.currentTarget );
- block( $( 'div.cart_totals' ) );
- block( $form );
- // Provide the submit button value because wc-form-handler expects it.
- $( '<input />' ).attr( 'type', 'hidden' )
- .attr( 'name', 'calc_shipping' )
- .attr( 'value', 'x' )
- .appendTo( $form );
- // 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 );
- },
- complete: function() {
- unblock( $form );
- unblock( $( 'div.cart_totals' ) );
- }
- } );
- }
- };
- /**
- * Object to handle cart UI.
- */
- var cart = {
- /**
- * Initialize cart UI events.
- */
- init: function() {
- this.update_cart_totals = this.update_cart_totals.bind( this );
- this.input_keypress = this.input_keypress.bind( this );
- this.cart_submit = this.cart_submit.bind( this );
- this.submit_click = this.submit_click.bind( this );
- this.apply_coupon = this.apply_coupon.bind( this );
- this.remove_coupon_clicked = this.remove_coupon_clicked.bind( this );
- this.quantity_update = this.quantity_update.bind( this );
- this.item_remove_clicked = this.item_remove_clicked.bind( this );
- this.item_restore_clicked = this.item_restore_clicked.bind( this );
- this.update_cart = this.update_cart.bind( this );
- $( document ).on(
- 'wc_update_cart',
- function() { cart.update_cart.apply( cart, [].slice.call( arguments, 1 ) ); } );
- $( document ).on(
- 'click',
- '.woocommerce-cart-form :input[type=submit]',
- this.submit_click );
- $( document ).on(
- 'keypress',
- '.woocommerce-cart-form :input[type=number]',
- this.input_keypress );
- $( document ).on(
- 'submit',
- '.woocommerce-cart-form',
- this.cart_submit );
- $( document ).on(
- 'click',
- 'a.woocommerce-remove-coupon',
- this.remove_coupon_clicked );
- $( document ).on(
- 'click',
- '.woocommerce-cart-form .product-remove > a',
- this.item_remove_clicked );
- $( document ).on(
- 'click',
- '.woocommerce-cart .restore-item',
- this.item_restore_clicked );
- $( document ).on(
- 'change input',
- '.woocommerce-cart-form .cart_item :input',
- this.input_changed );
- $( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', true );
- },
- /**
- * After an input is changed, enable the update cart button.
- */
- input_changed: function() {
- $( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', false );
- },
- /**
- * Update entire cart via ajax.
- */
- update_cart: function( preserve_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() {
- unblock( $form );
- unblock( $( 'div.cart_totals' ) );
- $.scroll_to_notices( $( '[role="alert"]' ) );
- }
- } );
- },
- /**
- * Update the cart after something has changed.
- */
- update_cart_totals: function() {
- block( $( 'div.cart_totals' ) );
- $.ajax( {
- url: get_url( 'get_cart_totals' ),
- dataType: 'html',
- success: function( response ) {
- update_cart_totals_div( response );
- },
- complete: function() {
- unblock( $( 'div.cart_totals' ) );
- }
- } );
- },
- /**
- * Handle the <ENTER> key for quantity fields.
- *
- * @param {Object} evt The JQuery event
- *
- * For IE, if you hit enter on a quantity field, it makes the
- * document.activeElement the first submit button it finds.
- * For us, that is the Apply Coupon button. This is required
- * to catch the event before that happens.
- */
- input_keypress: function( evt ) {
- // Catch the enter key and don't let it submit the form.
- if ( 13 === evt.keyCode ) {
- var $form = $( evt.currentTarget ).parents( 'form' );
- try {
- // If there are no validation errors, handle the submit.
- if ( $form[0].checkValidity() ) {
- evt.preventDefault();
- this.cart_submit( evt );
- }
- } catch( err ) {
- evt.preventDefault();
- this.cart_submit( evt );
- }
- }
- },
- /**
- * Handle cart form submit and route to correct logic.
- *
- * @param {Object} evt The JQuery event
- */
- cart_submit: function( evt ) {
- var $submit = $( document.activeElement ),
- $clicked = $( ':input[type=submit][clicked=true]' ),
- $form = $( evt.currentTarget );
- // For submit events, currentTarget is form.
- // For keypress events, currentTarget is input.
- if ( ! $form.is( 'form' ) ) {
- $form = $( evt.currentTarget ).parents( 'form' );
- }
- if ( 0 === $form.find( '.woocommerce-cart-form__contents' ).length ) {
- return;
- }
- if ( is_blocked( $form ) ) {
- return false;
- }
- if ( $clicked.is( ':input[name="update_cart"]' ) || $submit.is( 'input.qty' ) ) {
- evt.preventDefault();
- this.quantity_update( $form );
- } else if ( $clicked.is( ':input[name="apply_coupon"]' ) || $submit.is( '#coupon_code' ) ) {
- evt.preventDefault();
- this.apply_coupon( $form );
- }
- },
- /**
- * Special handling to identify which submit button was clicked.
- *
- * @param {Object} evt The JQuery event
- */
- submit_click: function( evt ) {
- $( ':input[type=submit]', $( evt.target ).parents( 'form' ) ).removeAttr( 'clicked' );
- $( evt.target ).attr( 'clicked', 'true' );
- },
- /**
- * 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 );
- $( document.body ).trigger( 'applied_coupon', [ coupon_code ] );
- },
- complete: function() {
- unblock( $form );
- $text_field.val( '' );
- cart.update_cart( true );
- }
- } );
- },
- /**
- * Handle when a remove coupon link is clicked.
- *
- * @param {Object} evt The JQuery event
- */
- remove_coupon_clicked: function( evt ) {
- evt.preventDefault();
- var cart = this;
- var $wrapper = $( evt.currentTarget ).closest( '.cart_totals' );
- var coupon = $( evt.currentTarget ).attr( 'data-coupon' );
- block( $wrapper );
- var data = {
- security: wc_cart_params.remove_coupon_nonce,
- coupon: coupon
- };
- $.ajax( {
- type: 'POST',
- url: get_url( 'remove_coupon' ),
- data: data,
- dataType: 'html',
- success: function( response ) {
- $( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
- show_notice( response );
- $( document.body ).trigger( 'removed_coupon', [ coupon ] );
- unblock( $wrapper );
- },
- complete: function() {
- cart.update_cart( true );
- }
- } );
- },
- /**
- * Handle a cart Quantity Update
- *
- * @param {JQuery Object} $form The cart form.
- */
- quantity_update: function( $form ) {
- block( $form );
- block( $( 'div.cart_totals' ) );
- // Provide the submit button value because wc-form-handler expects it.
- $( '<input />' ).attr( 'type', 'hidden' )
- .attr( 'name', 'update_cart' )
- .attr( 'value', 'Update Cart' )
- .appendTo( $form );
- // 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 );
- },
- complete: function() {
- unblock( $form );
- unblock( $( 'div.cart_totals' ) );
- $.scroll_to_notices( $( '[role="alert"]' ) );
- }
- } );
- },
- /**
- * Handle when a remove item link is clicked.
- *
- * @param {Object} evt The JQuery event
- */
- item_remove_clicked: function( evt ) {
- evt.preventDefault();
- var $a = $( evt.currentTarget );
- var $form = $a.parents( 'form' );
- block( $form );
- block( $( 'div.cart_totals' ) );
- $.ajax( {
- type: 'GET',
- url: $a.attr( 'href' ),
- dataType: 'html',
- success: function( response ) {
- update_wc_div( response );
- },
- complete: function() {
- unblock( $form );
- unblock( $( 'div.cart_totals' ) );
- $.scroll_to_notices( $( '[role="alert"]' ) );
- }
- } );
- },
- /**
- * Handle when a restore item link is clicked.
- *
- * @param {Object} evt The JQuery event
- */
- item_restore_clicked: function( evt ) {
- evt.preventDefault();
- var $a = $( evt.currentTarget );
- var $form = $( 'form.woocommerce-cart-form' );
- block( $form );
- block( $( 'div.cart_totals' ) );
- $.ajax( {
- type: 'GET',
- url: $a.attr( 'href' ),
- dataType: 'html',
- success: function( response ) {
- update_wc_div( response );
- },
- complete: function() {
- unblock( $form );
- unblock( $( 'div.cart_totals' ) );
- }
- } );
- }
- };
- cart_shipping.init( cart );
- cart.init();
- } );
|