PageSourceSearch

https://currygardenip4.co.uk/assets/js/restaurant.js?1789043738

js currygardenip4.co.uk collected 2026-10-01 16:00:45 UTC 12,131 bytes, 397 lines download raw bytes

1!(function ($) {
2  "use strict";
3
4  var $dateInput = $("#date");
5
6  var dayKeysByIndex = ["sun", "mon", "tues", "wed", "thurs", "fri", "sat"];
7
8  // If dropdown for branch id doesnt exist it will use defaultbranch.
9  var getBranchId = function () {
10    var $branch = $('select[name="branch"]');
11    return $branch.length ? $branch.val() : defaultBranchId;
12  };
13
14  // Check if the selected date is closed
15  var isDateClosed = function (dateValue) {
16    if (typeof openingTimesByBranch === "undefined" || !dateValue) {
17      return false;
18    }
19
20    var branchId = getBranchId();
21
22    // No Branch selected, all dates disabled.
23    if (!branchId) {
24      return true;
25    }
26
27    var openingTimes = openingTimesByBranch[branchId] || {};
28    var selectedDate = new Date(dateValue + "T00:00:00");
29    var dayKey = dayKeysByIndex[selectedDate.getDay()];
30    var sessions = openingTimes[dayKey];
31    return !sessions || !sessions.length;
32  };
33
34  var $occasionSelect = $('select[name="occasion"]');
35  if ($occasionSelect.length) {
36    $occasionSelect.on("change", function() {
37      $occasionSelect.toggleClass("has-value", !!$occasionSelect.val());
38    });
39  }
40
41  $(".book-a-table .select select").each(function() {
42    var $select = $(this);
43    $select.on("mousedown", function() {
44      $select.addClass("is-open");
45    });
46    $select.on("blur change", function() {
47      $select.removeClass("is-open");
48    });
49  });
50
51  var fp = null;
52  var $branchSelect = $('select[name="branch"]');
53  if ($dateInput.length && typeof flatpickr !== "undefined") {
54    var $dateValidate = $dateInput.closest(".form-group").find(".validate");
55    var $dateFieldWrap = $dateInput.closest(".date-field-wrap");
56
57    // Flatpickr configuration properties and functions.
58    fp = flatpickr($dateInput[0], {
59      dateFormat: "Y-m-d",
60      altInput: true,
61      altFormat: "d/m/Y",
62      minDate: "today",
63      static: true,
64      disable: [
65        function (date) {
66          var value =
67            date.getFullYear() +
68            "-" +
69            String(date.getMonth() + 1).padStart(2, "0") +
70            "-" +
71            String(date.getDate()).padStart(2, "0");
72          return isDateClosed(value);
73        }
74      ],
75      onOpen: function (selectedDates, dateStr, instance) {
76        const inputToFocus = instance.altInput || instance.element;
77
78        // Flat picker is setting internally dateInput.focus(), Safari sees this as that this input has a focus and it should scroll
79        // to it, so scrollY = 0, during debugging, date clicked, flatpickr focus, input gets focu
79s, and safari scrolls to top.
80        // so we need to force a prevent scroll (so that safari focuses but doesn't scroll.)
81
82        const originalFocus = inputToFocus.focus;
83        inputToFocus.focus = function (options) {
84          options = options || {};
85          options.preventScroll = true;
86          originalFocus.call(this, options);
87        };
88
89        if (!getBranchId()) {
90          fp.close();
91          if ($branchSelect.length) {
92            $branchSelect[0].focus({ preventScroll: true });
93          }
94          return;
95        }
96        $dateFieldWrap.addClass("is-open");
97      },
98      onClose: function(){
99        $dateFieldWrap.removeClass("is-open");
100      },
101      onChange: function (selectedDates, dateStr) {
102        var closed = isDateClosed(dateStr);
103        $dateValidate.html(
104          closed ? "We are closed on this day, please pick another date" : ""
105        );
106      }
107    });
108
109    // If a branch dropdown exists, clear out any date that was picked before the branch changed.
110    if ($branchSelect.length) {
111      $branchSelect.on("change", function () {
112        fp.clear();
113        $dateValidate.html("");
114        fp.redraw();
115      });
116    }
117    // capture the pickers state before the click that opens it
118    // isn't mistaken for a re-click and immediately closes
119    var wasOpenOnPointerDown = false;
120    
121    var IfOpenOnPointerDown = function () {
122      wasOpenOnPointerDown = fp.isOpen;
123    };
124    var closeIfOpenOnReclick = function (e) {
125      if (!wasOpenOnPointerDown) {
126        return;
127      }
128      wasOpenOnPointerDown = false;
129      e.stopPropagation();
130      e.preventDefault();
131      fp.close();
132    };
133    [$dateInput[0], fp.altInput].forEach(function (el) {
134      if(el) {
135        el.addEventListener("mousedown", IfOpenOnPointerDown, true);
136        el.addEventListener("click", closeIfOpenOnReclick, true);
137      }
138    });
139
140
141    // Flatpickr's altInput sits between #date and .validate in the DOM, so  validate.js's i.next('.validate') never finds it for this field.
142    $dateInput.closest("form").on("submit", function () {
143      if (!$dateInput.val()) {
144        $dateValidate
145          .html($dateInput.attr("data-msg") || "Please select a date")
146          .show("blind");
147      }
148    });
149  }
150
151  /* 
152  If the user clicks the time field before picking a date, the select is disabled and
153  the date entry box is highlighted, if the date is also not selected the branch entry box is highlighted.
154  */
155  var $timeSelect = $("#time");
156  if ($dateInput.length && $timeSelect.length) {
157    $timeSelect.closest(".select").on("click", function () {
158      if (!$timeSelect.prop("disabled") || $dateInput.val()) {
159        return;
160      }
161      if ($branchSelect.length && !getBranchId()) {
162        $branchSelect[0].focus({ preventScroll: true});
163        return;
164      }
165      (fp.altInput || $dateInput[0]).focus({ preventScroll: true});
166      fp.close();
167    });
168  }
169
170  // Dropdowns will be populated with times relevant to each branch and date.
171  if (
172    $dateInput.length &&
173    $timeSelect.length &&
174    typeof openingTimesByBranch !== "undefined"
175  ) {
176    var buildTimeSlots = function () {
177      $timeSelect.empty();
178      $timeSelect.prop("disabled", true);
179      $timeSelect.removeClass("has-value");
180
181      var dateValue = $dateInput.val();
182      if (!dateValue) {
183        $timeSelect.append('<option value="" selected>Choose Time</option>');
184        return;
185      }
186
187      var branchId = getBranchId();
188      if (!branchId) {
189        $timeSelect.append(
190          '<option value="" selected>Select a branch first</option>',
191        );
192        return;
193      }
194      var openingTimes = openingTimesByBranch[branchId] || {};
195
196      var selectedDate = new Date(dateValue + "T00:00:00");
197      var dayKey = dayKeysByIndex[selectedDate.getDay()];
198      var sessions = openingTimes[dayKey];
199
200      // If there arent any sessions, then they're closed.
201      if (!sessions || !sessions.length) {
202        $timeSelect.append('<option value="" selected>Closed</option>');
203        return;
204      }
205
206      var now = new Date();
207      var isToday =
208        selectedDate.getFullYear() === now.getFullYear() &&
209        selectedDate.getMonth() === now.getMonth() &&
210        selectedDate.getDate() === now.getDate();
211
212      var slots = [];
213      sessions.forEach(function (session) {
214        var start = parseTimeToMinutes(session.opening_time_start);
215        var end = parseTimeToMinutes(session.opening_time_end);
216        if (start === null || end === null) {
217          return;
218        }
219        // Closing time at/before opening time means the session runs past midnight.
220        if (end <= start) {
221          end += 24 * 60;
222        }
223        var firstSlot = Math.ceil(start/15) * 15;
224        for (var minutes = firstSlot; minutes < end; minutes += 15) {
225          if (isToday && minutes <= now.getHours() * 60 + now.getMinutes()) {
226            continue;
227          }
228          slots.push(minutes);
229        }
230      });
231
232      if (!slots.length) {
233        $timeSelect.append(
234          '<option value="" selected>No times available</option>',
235        );
236        return;
237      }
238
239      // Time select is only available to click once Select date has been chosen.
240      $timeSelect.prop("disabled", false);
241      $timeSelect.append('<option value="" selected>Choose Time</option>');
242      slots.forEach(function (minutes) {
243        var value = formatMinutesAsTime(minutes % (24 * 60)); // Getting Time value
244        var label = formatMinutesAsDisplayTime(minutes % (24 * 60)); // Getting PM or AM
245        $timeSelect.append(
246          '<option value="' + value + '">' + label + "</option>",
247        );
248      });
249    };
250
251    // A function to get the total amount of time for comparision.
252    var parseTimeToMinutes = function (timeString) {
253      if (!timeString) {
254        return null;
255      }
256      var parts = timeString.split(":");
257      if (parts.length < 2) {
258        return null;
259      }
260      var hours = parseInt(parts[0], 10);
261      var mins = parseInt(parts[1], 10);
262      if (isNaN(hours) || isNaN(mins)) {
263        return null;
264      }
265      return hours * 60 + mins;
266    };
267
268    // Calculate total hours and remaining minutes.
269    var formatMinutesAsTime = function (minutes) {
270      var hours = Math.floor(minutes / 60);
271      var mins = minutes % 60;
272      return (
273        (hours < 10 ? "0" + hours : hours) +
274        ":" +
275        (mins < 10 ? "0" + mins : mins)
276      );
277    };
278
279    // Gets the Time in AM and PM to display to the user.
280    var formatMinutesAsDisplayTime = function (minutes) {
281      var hours = Math.floor(minutes / 60);
282      var mins = minutes % 60;
283      var period = hours < 12 ? "AM" : "PM";
284      var displayHours = hours % 12;
285      if (displayHours === 0) {
286        displayHours = 12;
287      }
288      return (
289        displayHours + ":" + (mins < 10 ? "0" + mins : mins) + " " + period
290      );
291    };
292
293    // Toggle the class for time, so when a branch or date is changed the time resets.
294    $timeSelect.on("change", function () {
295      $timeSelect.toggleClass("has-value", !!$timeSelect.val());
296    });
297
298    $dateInput.on("change", buildTimeSlots);
299    $('select[name="branch"]').on("change", buildTimeSlots);
300    buildTimeSlots();
301  }
302
303  var $guest_count = $("#stepper");
304
305  $guest_count.val(0);
306
307  function updateGuestCount(value) {
308    $guest_count.val(value || "");
309  }
310
311  function updateRemoveButton(value) {
312    const $button = $(".stepper-button.remove");
313    const $icon = $button.find("img");
314
315    if (value !== "" && parseInt(value, 10) > 0) {
316      $icon.attr("src", "/assets/icons/stepper/remove.svg");
317      $button.prop("disabled", false);
318    }
319    else {
320      $icon.attr("src", "/assets/icons/stepper/remove_disabled.svg");
321      $button.prop("disabled", true);
322    }
323  }
324
325
326  function updateAddButton(value) {
327    const $button = $(".stepper-button.add");
328    const $icon = $button.find("img");
329
330    if (value === "" || parseInt(value, 10) < 30) {
331      $icon.attr("src", "/assets/icons/stepper/add.svg");
332      $button.prop("disabled", false);
333    } else {
334      $icon.attr("src", "/assets/icons/stepper/add_disabled.svg");
335      $button.prop("disabled", true);
336    }
337  }
338
339  $(function () {
340    updateGuestCount(parseInt($guest_count.val() || 0));
341
342    updateRemoveButton($guest_count.val());
343    updateAddButton($guest_count.val());
344
345    $guest_count.on("input", function () {
346      const value = $(this).val();
347      updateRemoveButton(value);
348      updateAddButton(value);
349    });
350
351    $(".stepper-button").on("touchstart", function () {
352      $(this).addClass("is-active");
353    });
354
355    $(".stepper-button").on("touchend touchcancel", function() {
356      $(this).removeClass("is-active");
357    });
358
359    $(".stepper-button").click(function () {
360      let value = parseInt($guest_count.val() || 0, 10);
361      $('#stepper').focus()
362
363      if ($(this).hasClass("add")) {
364        value = Math.min(30, value + 1);
365      }
366      else if ($(this).hasClass("remove")) {
367        value = Math.max(0, value - 1);
368      }
369
370      updateGuestCount(value);
371      
372      $guest_count.trigger("input");
373
374      updateRemoveButton(value);
375      updateAddButton(value);
376    })
377  })
378
379
380  $dateInput.closest("form").on("form-reset-success", function () {
381    if (fp) {
382      fp.clear();
383    }
384
385    $(this).find(".form-group select").each(function () {
386      this.selectedIndex = 0;
387    }).removeClass("has-value");
388
389    if ($timeSelect.length) {
390      $timeSelect.prop("disabled", true);
391    }
392
393    updateGuestCount(0);
394    updateAddButton(0);
395    updateRemoveButton(0);
396  });
397})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.