Search code examples
javascripthtmljqueryfrontenddhtml

Pure JavaScript Datepicker displays calendar only once to never do it again in a Shopify cart page


To achieve greater performance with our Shopify store, we decided to minimize use of jQuery across the site. In cartpage, I added a pure JavaScript datepicker that sometimes displays the calendar just once and never afterwards. I ensured only one version of jQuery loads in the theme, thinking multiple instances from other Shopify apps might be causing this issue. But even with a single jQuery instance being loaded now in the theme, the issue still persists. I don't see any console errors. Please add a product to the cart and go to the cart page to see this issue by clicking the date picker. Below is the link to the preview theme.

Following is the datepicker code for pickaday plugin.

<div class="cart-attribute__field">
  <p>
    <label for="ship_date">Ordering early? Pick a future ship date here:</label>
    <input id="ship_date" type="text" name="attributes[ship_date]" value="{{ cart.attributes.ship_date }}" />
  </p>
</div>
<p class="shipping-text">If you are placing an order with <b>a future ship date</b> that <u>also</u> includes multiple addresses please email <a href="mailto:[email protected]" target="_blank">[email protected]</a> upon placing your order to confirm your preferred ship date.</p>
<!-- Added 11162020 -->
<p class="shipping-text">Please note that specifying a date above ensures your gift is packaged and shipped on that date. <b>This is not a delivery date.</b> As we work with third party shipping agencies, your delivery date is subject to the specific carrier selected as well as your shipping destination. Please find our estimated shipping transit times for all regions of the US <strong><a href="https://packedwithpurpose.gifts/shipping-returns/" target="_blank" style="text-decoration: underline;">here</a></strong>.</p>

<script type="text/javascript">
(function() {
  var disabledDays = ["2022-12-23","2022-12-24","2022-12-25","2022-12-30","2022-12-31","2023-1-1"];
  var minDate = new Date();
  var maxDate = new Date();
  maxDate.setDate((maxDate.getDate()) + 60);
  minDaysToShip = 2;        // Default minimum days
  if (minDate.getDay() == 5) {
    // Friday. Set min day to Tuesday. 4 days from now.
  minDaysToShip = 4;
  } else if (minDate.getDay() == 6) {
    // Saturday. Set min day to Tuesday. 3 days from now.
    minDaysToShip = 3;
  }
  minDate.setDate(minDate.getDate() + minDaysToShip);
  var picker = new Pikaday(
  {
      field: document.getElementById('ship_date'),
      format: 'MM/DD/YYYY',
      disableWeekends: 'true',
      toString(date, format) {
        // you should do formatting based on the passed format,
        // but we will just return 'D/M/YYYY' for simplicity
        const day = ("0" + date.getDate()).slice(-2);
        // Get two digit month ("0" + (this.getMonth() + 1)).slice(-2)
        const month = ("0" + (date.getMonth() + 1)).slice(-2);
        const year = date.getFullYear();
        return `${month}/${day}/${year}`;
      },
      parse(dateString, format) {
        // dateString is the result of `toString` method
        const parts = dateString.split('/');
        const day = parseInt(parts[0], 10);
        const month = parseInt(parts[1], 10) - 1;
        const year = parseInt(parts[2], 10);
        return new Date(year, month, day);
      },
      firstDay: 0,
      minDate: minDate,
      maxDate: maxDate,
      disableDayFn: function(inputDate) {
        // Disable national holidays
        var formattedDate = inputDate.getFullYear() + '-' + (inputDate.getMonth() + 1) + '-' + inputDate.getDate();
        return ((disabledDays.indexOf(formattedDate) == -1) ? false : true);
      }
  });
})();
</script>

Solution

  • This was fixed by replacing (function() with window.addEventListener("load", function()