5

I'm trying to show/hide some elements from my checkout page, based on the chosen shipping method. The page elements I'm trying to show/hide come from another plugin, so I tried to change the display properties for them. I've looked to many thread like:

Show or hide checkout fields based on shipping method in Woocommerce 3

But it's for checkout fields, and I'm not sure how to do it for page elements.

Then based on this answer thread Here's my code so far:

add_action( 'wp_footer', 'conditionally_hidding_order_delivery_date' );
function conditionally_hidding_order_delivery_date(){
    // Only on checkout page
    if( ! is_checkout() ) return;

    // HERE your shipping methods rate ID "Home delivery"
    $home_delivery = 'distance_rate_shipping';
    ?>
    <script>
        jQuery(function($){
            // Choosen shipping method selectors slug
            var shipMethod = 'input[name^="shipping_method"]',
                shipMethodChecked = shipMethod+':checked';

            // Function that shows or hide imput select fields
            function showHide( actionToDo='show', selector='' ){
                if( actionToDo == 'show' )
                    $(selector).show( 200, function(){
                        $(this).addClass("validate-required");
                    });
                else
                    $(selector).hide( 200, function(){
                        $(this).removeClass("validate-required");
                    });
                $(selector).removeClass("woocommerce-validated");
                $(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
            }

            // Initialising: Hide if choosen shipping method is "Home delivery"
            if( $(shipMethodChecked).val() != '<?php echo $home_delivery; ?>' ) {
                showHide('hide','#e_deliverydate_field' );
                showHide('hide','#time_slot_field' );
            }

            // Live event (When shipping method is changed)
            $( 'form.checkout' ).on( 'change', shipMethod, function() {
                if( $(shipMethodChecked).val() == '<?php echo $home_delivery; ?>' ) {
                        showHide('show','#e_deliverydate_field' );
                        showHide('show','#time_slot_field' );
                }
                else {
                        showHide('hide','#e_deliverydate_field' );
                        showHide('hide','#time_slot_field' );
                }
            });
        });
    </script>
    <?php
}

But it's not working completely (the initializing function is not working.)

Any help is very much appreciated.

Additional edit:

<p class="form-row form-row-wide validate-required" id="e_deliverydate_field" data-priority="" style="display: block;"><label for="e_deliverydate" class="">Date<abbr class="required" title="required">*</abbr></label><span class="woocommerce-input-wrapper"><input class="input-text hasDatepicker" name="e_deliverydate" id="e_deliverydate" placeholder="Choose a Date" value="" style="cursor:text !important;" type="text"></span></p>

My objective is to change the display properties for p element from block to none, and vice versa.

  • On what page this is intended to be used? … I suppose checkout on custom html structure. So It will be much more better if you include in your question, the generated html structure where you will like to make that work. Also please give use the exact location of this html elements. – LoicTheAztec Aug 08 '18 at 06:55
  • Hi Loic, I've looked at your other answer here: https://stackoverflow.com/questions/47738260/conditionally-hide-a-checkout-field-in-woocommerce-based-on-chosen-shipping and it's working partially for me. The initialize function on page load doesn't work. I'll add my code shortly. – Dicko Mas Soebekti Aug 08 '18 at 06:59
  • This is intended for checkout page, and probably also cart page. The html element I'm trying to hide is within
    . It's a

    element with id as I've written on my code.

    – Dicko Mas Soebekti Aug 08 '18 at 07:13
  • I have answered with a simplified code version… But you should add the necessary related generated html code in your question, as remember that: *"Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error **and the shortest code necessary to reproduce it in the question itself"**.* – LoicTheAztec Aug 08 '18 at 08:08
  • Noted, thanks for the reminder. Already edited the original question. – Dicko Mas Soebekti Aug 08 '18 at 08:10

1 Answers1

8

The needed code is something much more simple, than the one used in my other answers, but you need to be sure that the targeted chosen shipping method is 'distance_rate_shipping' as I can't test it.

For initialization problem, see the solution exposed at the end of my answer.

The simplified needed code:

// Embedded jQuery script
add_action( 'wp_footer', 'checkout_delivery_date_script' );
function checkout_delivery_date_script() {
    // Only checkout page
    if( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) return;
    ?>
    <script type="text/javascript">
    jQuery( function($){
        var a = 'input[name^="shipping_method"]', b = a+':checked',
            c = 'distance_rate_shipping',
            d = '#e_deliverydate_field,#time_slot_field';

        // Utility function that show or hide the delivery date
        function showHideDeliveryDate(){
            if( $(b).val() == c )
                $(d).show();
            else
                $(d).hide('fast');
            console.log('Chosen shipping method: '+$(b).val()); // <== Just for testing (to be removed)
        }

        // 1. On start
        showHideDeliveryDate();

        // 2. On live event "change" of chosen shipping method
        $('form.checkout').on('change', a, function(){
            showHideDeliveryDate();
        });
    });
    </script>
    <?php
}

Code goes in function.php file of your active child theme (or theme). It should work.


The initialization problem:

It's certainly because the plugin you are using that generates the delivery date output is delayed after initialization

The solution can be to add some delay on initialization execution.

So should try to replace this:

// 1. On start
showHideDeliveryDate();

By the following in my code (adjusting the execution delay to something higher or lower than 500):

// 1. On start
setTimeout(function(){
    showHideDeliveryDate();
}, 500);
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Hi Loic, thanks very much. I've tried it, and I've also use the setTimeout since the initialization not working, but I think the problem is not from your code, but from the other plugin. At first the elements were hidden, but then it showed up again. The plugin must've done something during the processing. As for your code, it's working as intended. I'll mark this as solved. Thanks. – Dicko Mas Soebekti Aug 08 '18 at 08:17
  • Definitely upvoted! Thanks for reminding me. So an update, I set the timeout to high value like 5000, and it works. Could be the other plugin loads so long or something, I'm not sure.. – Dicko Mas Soebekti Aug 08 '18 at 08:30
  • @DickoMasSoebekti Ok I have added to my answer, another answer after it. Try it please. I hope this will be the way. – LoicTheAztec Aug 08 '18 at 09:12
  • 1
    I've tried the alternative code, it seems it works the same as your original answer. I see what you did there with the CSS, good idea. But somehow, I think it performs the same. It's ok Loic, I've set the delay to 2000 now, I think it's safe enough, alhough sometimes it still misses the initialization, but most of the time it works perfectly. Thanks a lot! – Dicko Mas Soebekti Aug 08 '18 at 10:09