来自日期选择器输入字段的 WooCommerce 结帐 select 选项的时间循环

Time loop for WooCommerce checkout select option from date picker input field

输入字段一 - 交货日期附加了日期选择器。这填写客户要求的日期。此字段确定在其旁边的 select 字段中填充的交货时间选项。

但是选项基于一些规则

  1. 时间段是从上午 11 点到下午 4 点,间隔 30 分钟。
  2. 如果选择的日期=今天,派送开始时间=当前时间+一小时。
  3. 如果日期是未来,交货时间为上午 11 点到下午 4 点。 30 分钟间隔

我需要帮助根据所选日期的上述参数为 woocommerce 选项制作数组。谢谢

示例代码:首先,我使用日期选择器更新 select 日期上的 select 字段选项。使用下面的代码。

add_action( 'wp_footer', 'woocommerce_update_on_date_select', 21 );

function woocommerce_update_on_date_select() {
    if (is_checkout()) {
    ?>
    <script type="text/javascript">
        $(document).ready(function() {
          function updateCart() {
            var d = $("#billing_country").val(),
              e = $("#billing_state").val(),
              f = $("input#billing_postcode").val(),
              g = $("#billing_city").val(),
              h = $("input#billing_address_1").val(),
              i = $("input#billing_address_2").val(),
              j = d,
              k = e,
              l = f,
              m = g,
              n = h,
              o = i;
            $("#ship-to-different-address").find("input").is(":checked") && (j = $("#shipping_country").val(), k = $("#shipping_state").val(), l = $("input#shipping_postcode").val(), m = $("#shipping_city").val(), n = $("input#shipping_address_1").val(), o = $("input#shipping_address_2").val());
            var p = {
              security: wc_checkout_params.update_order_review_nonce,
              payment_method: $("#order_review").find('input[name="payment_method"]:checked').val(),
              country: d,
              state: e,
              postcode: f,
              city: g,
              address: h,
              address_2: i,
              s_country: j,
              s_state: k,
              s_postcode: l,
              s_city: m,
              s_address: n,
              s_address_2: o,
              post_data: $("form.checkout").serialize()
            };
            var c  = {update_shipping_method: !0};
            if (!1 !== c.update_shipping_method) {
              var q = {};
              $('select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]').each(function() {
                q[$(this).dat$("index")] = $(this).val()
              }), p.shipping_method = q
            }
            $.ajax({
              type: "POST",
              url: wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%", "update_order_review"),
              data: p,
              success: function(c) {
                var d = $('.woocommerce-checkout input[name="payment_method"]:checked').attr("id");
                if ("true" === c.reload) return void window.location.reload();
                $(".woocommerce-NoticeGroup-updateOrderReview").remove();
                var e = $("#terms").prop("checked");
                if (c && c.fragments && $.each(c.fragments, function(b, c) {
                    $(b).replaceWith(c)
                  }), e && $("#terms").prop("checked", !0), "failure" === c.result) {
                  var f = $("form.checkout");
                  $(".woocommerce-error, .woocommerce-message").remove(), c.messages ? f.prepend('<div class="woocommerce-NoticeGroup-updateOrderReview">' + c.messages + "</div>") : f.prepend(c), f.find(".input-text, select, input:checkbox").blur(), $("html, body").animate({
                    scrollTop: $("form.checkout").offset().top - 100
                  }, 1e3)
                }
              }
            });
          }

          $('#billing_delivery_date').attr('readonly', true);
          $('#billing_serving').on('change', function(){
              updateCart();
          });

          $( "#billing_delivery_date" ).on('change', function() {
            updateCart();
          });
      });
    </script>
    <?php
    }
}

然后使用从日期选择器中选择的日期,我尝试将数组发送到表单中的 select 字段。

add_filter( 'woocommerce_checkout_fields' , 'brown_remove_billing_postcode_checkout' );

        function brown_remove_billing_postcode_checkout( $fields ) {
            $error = '';

            if (isset($_POST['post_data'])) {
                parse_str( $_POST['post_data'], $post_data );
            } else {
                $post_data = $_POST;
            }

            $billing_delivery_date = $post_data['billing_delivery_date'];

            if ( $billing_delivery_date = !NULL ) { 

                $date = new DateTime();
                $date->setTimezone(new DateTimeZone('Africa/Kampala'));
                $order_day = $date->format('Y-m-d H:i:s');

                $date = new DateTime(date('Y-m-d', strtotime(str_replace('/' , '-', $billing_delivery_date))));

                //If the date picked is greater than the current date
                if (strtotime($order_day) > strtotime($date) {
                    //Make an array of values from 11am to 4pm to pass to $fields['billing']['billing_serving'] options array

                } elseif ($order_day == $date) {
                    //If the Make an array of values from 11am to 4pm to pass to $fields['billing']['billing_serving'] options array
                    //Get the current time + one hour. Append hour intervals from next top of the hour until 4pm.
                }

            }

            // Add New Fields
            $fields['billing']['billing_serving'] = array(
                'label'     => __('Delivery Time', 'woocommerce'),
                'placeholder'   => _x('Time for your delivery', 'placeholder', 'woocommerce'),
                'required'  => true,
                'class'     => array('form-row-last'),
                'clear'     => false,
                'autocomplete' => false,
                'type'        => 'select',
                'options'     => array(
                           //Generated array goes here.
                           '11am'    => __('11:00am', 'woocommerce' ),
                           '1130am'  => __('11:30am', 'woocommerce' ),
                           '12noon'  => __('12:00pm', 'woocommerce' ),
                           '1230pm'  => __('12:30pm', 'woocommerce' ),
                           '1pm'     => __('1:00pm', 'woocommerce' ),
                           '130pm'   => __('1:30pm', 'woocommerce' ),
                           '2pm'     => __('2:00pm', 'woocommerce' ),
                           '230pm'   => __('2:30pm', 'woocommerce' ),
                           '3pm'     => __('3:00pm', 'woocommerce' ),
                           '330pm'   => __('3:30pm', 'woocommerce' ),
                           '4pm'     => __('4:00pm', 'woocommerce' )
                    )
             );

            return $fields;

        }

由于缺少 交货日期 的代码,我已启用 jQuery-ui 日期选择器 (而您应该使用你自己的 CSS).

我没有使用您的 jQuery 代码,因为我的方法与 qui 不同,我对您的代码有点松懈。我的 PHP 代码也与 qui 不同。 select 字段 <options> 在 php 中几乎是空的,因为 javascript bui 动态加载它。

此处 php 代码正在传递给 Javascript/jQuery 一些数据:

  • 交货开始日期。
  • 对于 select 选项 key/value 对(可用时隙 + 默认时隙)。

这里 jQuery/Javascript 位于自定义结帐字段代码之后的同一个挂钩函数中…

“交货时间 select 字段中 <option> 标签的 html ui 由 jQuery 根据开始日期和当前时间。

您的所有要求ui都得到尊重:

  • 时间段从上午 11 点到下午 4 点,间隔 30 分钟。
  • 如果 selected 日期是今天,我们向时间段添加 +1 小时的偏移量
  • 如果select日期不是今天,我们会得到默认时间段(11 个可用)

现在你应该禁用你的相关代码来试试这个:

 // Enable available jQuery datepicker script in Wordpress
add_action( 'wp_enqueue_scripts', 'enabling_date_picker' );
function enabling_date_picker() {

    // Only on front-end and checkout page
    if( is_admin() || ! is_checkout() ) return;

    // Load available datepicker jQuery-ui plugin script
    wp_enqueue_script( 'jquery-ui-datepicker' );
}

// Add and display custom checkout fields + jQuery script
add_filter( 'woocommerce_checkout_fields' , 'brown_remove_billing_postcode_checkout' );
function brown_remove_billing_postcode_checkout( $fields ) {
    // Your Settings
    $start_hour = 11; // start time (in hours)
    $end_hour = 16; // end time (in hours)
    $offset = 1; // One hour before slot time (can be a float number like 1.5)
    date_default_timezone_set ('Africa/Kampala'); // The timezone

    // Initializing variables
    $hour = 3600; // 1 hour in seconds
    $day = $hour * 24; // 1 day in seconds
    $now = strtotime("now"); // Now time
    $real_now = $now + ($offset * $hour); // Now time + offset
    $today_date = date("Y-m-d"); // today date
    $tomorrow_date = date("Y-m-d", strtotime("+1 day")); // tomorow date
    $today_time = strtotime($today_date); // Today time at 00:00 in seconds
    $tomorrow_time = strtotime($tomorrow_date); // Tomorrow time at 00:00 in seconds
    $start_time = $today_time + ( $start_hour * $hour ); // Start datetime in seconds
    $end_time = $today_time + ( $end_hour * $hour ); // End datetime in seconds
    $today_slots = $default_slots = $option_days = array();

    // Add Delivery day field (with jquery-ui datepicker enabled)
    $fields['billing']['billing_delivery_day'] = array(
        'label'         => __('Delivery Day', 'woocommerce'),
        'placeholder'   => _x('Date for your delivery', 'placeholder', 'woocommerce'),
        'required'      => true,
        'id'            => 'datepicker', // Enable jQuery datepicker for this field
        'class'         => array('form-row-first'),
        'clear'         => false,
        'autocomplete'  => false,
        'type'          => 'text'
    );
   // Add Delivery hour slots
    $fields['billing']['billing_delivery_hour'] = array(
        'label'        => __('Delivery Time', 'woocommerce'),
        'required'     => true,
        'class'        => array('form-row-last'),
        'clear'        => false,
        'autocomplete' => false,
        'type'         => 'select',
        'options'      => array( '' => __('Select time for your delivery') ),
    );

    // Making the delivery hour slots <option> arrays for Javascript
    for($i = $start_time; $i <= $end_time; $i += 1800 ){ // 1800 seconds is half an hour
        $key     = date('H:i', $i);
        $value   = date('h:ia', $i);

        // Today available hour slots array
        if($real_now < $i)
            $today_slots[$key] = $value;

        // Default hour slots array
        $default_slots[$key] = $value;
    }

    // The correct start date and time (today or tomorow) for Javascript
    $date = $real_now < $end_time ? $today_date : $tomorrow_date;
    $dtime = $real_now < $end_time ? date("Y-m-d\TH:i:s", $today_time) : date("Y-m-d\TH:i:s", $tomorrow_time);

    ?>
    <script>
        jQuery(function($){
            var offsetDate = 15, // Number of days enabled in the datepicker (optional and disabled in the datepicker code)
                startingDate = new Date('<?php echo $dtime; ?>'), // Starting day (dynamic)
                endingDate = new Date('<?php echo $dtime; ?>'), // End date (calculated below)
                todaySlots = <?php echo json_encode($today_slots); ?>,
                defaultSlots = <?php echo json_encode($default_slots); ?>,
                sDay = 'input[name ="billing_delivery_day"]',
                sHour = 'select[name ="billing_delivery_hour"]',
                defaultOption = $(sHour+' > option').text(),
                todaySlotsLength = Object.keys(todaySlots).length;

            // ------ 1). Dates and Date picker ------ //

            // Set the default field start date
            $(sDay).val('<?php echo $date; ?>');
            $('#datepicker_field').addClass('woocommerce-validated');

            // Max date calculation (optional and diasabeld in the datepicker code)
            endingDate.setDate(startingDate.getDate()+offsetDate);

            // Jquery-ui datepicker
            $("#datepicker").datepicker({
                dateFormat: "yy-mm-dd",
                minDate: startingDate,
                // maxDate: endingDate, // optional, can be enabled.
                setDate: startingDate,
            });

            // ------ 2). HOUR slots select field (dynamic <option>) ------ //

            // Build the <option> html html in the select field dynamically
            function dynamic_select_options_buid( slotsType ){
                $.each( slotsType, function( index, value ){
                    $(sHour).append('<option value="'+index+'">'+value+'</option>');
                });
            }
            // Replace and Build the <option> html in the select field dynamically
            function dynamic_select_options_replace( slotsType ){
                $(sHour+' > option').remove();
                $(sHour).append('<option value="">'+defaultOption+'</option>');
                dynamic_select_options_buid( slotsType );
            }
            
            console.log(defaultOption);
            console.log(todaySlotsLength);
            if(todaySlotsLength != 0 && todaySlotsLength < 11 ){
                // Loaded at start
                dynamic_select_options_buid( todaySlots );

                // Live date selection event
                $(sDay).change( function(){
                    console.log('day changed: '+$(this).val());
                    if( $(this).val() != '<?php echo $date; ?>' )
                        dynamic_select_options_replace( defaultSlots );
                    else
                        dynamic_select_options_replace( todaySlots );
                })
            } else {
                dynamic_select_options_buid( defaultSlots );
            }
        });
    </script>
    <?
    return $fields;
}

代码进入您的活动子主题(或活动主题)的 function.php 文件。

已测试并有效。