PageSourceSearch

https://www.jaresortshotels.com/Mvc/Views/ReservationForm/homereservationform.js?v=639118038393525295

js jaresortshotels.com collected 2026-10-02 07:41:57 UTC 45,250 bytes, 1,043 lines download raw bytes

1/// watches for changes in the class of an element
2class ClassWatcher {
3
4    constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) {
5        this.targetNode = targetNode
6        this.classToWatch = classToWatch
7        this.classAddedCallback = classAddedCallback
8        this.classRemovedCallback = classRemovedCallback
9        this.observer = null
10        this.lastClassState = targetNode.classList.contains(this.classToWatch)
11
12        this.init()
13    }
14
15    init() {
16        this.observer = new MutationObserver(this.mutationCallback)
17        this.observe()
18    }
19
20    observe() {
21        this.observer.observe(this.targetNode, { attributes: true })
22    }
23
24    disconnect() {
25        this.observer.disconnect()
26    }
27
28    mutationCallback = mutationsList => {
29        for (let mutation of mutationsList) {
30            if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
31                let currentClassState = mutation.target.classList.contains(this.classToWatch)
32                if (this.lastClassState !== currentClassState) {
33                    this.lastClassState = currentClassState
34                    if (currentClassState) {
35                        this.classAddedCallback()
36                    }
37                    else {
38                        this.classRemovedCallback()
39                    }
40                }
41            }
42        }
43    }
44}
45
46
47// Booking Modal & Widget Month&Day
48
49/// all labels used here are defined in the .cshtml file due to translations
50
51/// booking vars
52var _jabook_hotelname = _jabook_allHotelsId; /// global var
53var _jabook_hotelid = "";
54var _jabook_start_date = "";
55var _jabook_end_date = "";
56var _jabook_adult_count = 2;
57var _jabook_child_count = 0;
58var _jabook_no_of_rooms = 1;
59
60document.addEventListener("DOMContentLoaded", function () {
61
62    const hotelPopup = document.querySelector('.hotel-popup');
63    const hotelMobilePopup = document.querySelector('.mobile-hotel-selector');
64    const hotelMobilePopupClose = hotelMobilePopup.querySelector('.close-mobile-popup');
65    const hotelSelector = document.querySelector('.hotel-selector');
66    const widget = document.querySelector('.reservation-search');
67    const widgetUI = document.querySelector('.widget-container');
68    const hotelListItems = document.querySelectorAll('.hotel_list_item');
69    const datePopup = document.querySelector('.date-popup');
70    const dateSelector = document.querySelector('.date-selector');
71    const dateMobilePopup = document.querySelector('.mobile-date-selector');
72    const dateMobilePopupClose = dateMobilePopup.querySelector('.close-mobile-popup');
73    const selectedDatebutton = dateMobilePopup.querySelector('.select-date-button');
74    const paxPopup = document.querySelector('.pax-popup');
75    const paxMobilePopup = document.querySelector('.mobile-guest-selector');
76    const paxSelector = document.querySelector('.guest-selector');
77    const guestRooms = document.querySelector('.pax-popup .rooms');
78    const addRoom = document.querySelectorAll('.addroom');
79    const paxMobilePopupClose = paxMobilePopup.querySelector('.close-mobile-popup');
80    const guestClearBtn = paxMobilePopup.querySelector('.guest-clear-btn');
81    const mobileGuestRooms = paxMobilePopup.querySelector('.mobile-guest-selector .rooms');
82    const findrooms = document.querySelectorAll('.findrooms');
83    const stayCalendar = document.querySelectorAll('.stayCalendar');
84    const PromocodeInput = document.querySelectorAll('.promocode_input_widget');
85    var mobileBookingwidget = document.querySelector('.mobile-bookingwidget-selector');
86    var hotelwidget = document.querySelector('.hotel-selection');
87    var datewidget = document.querySelector('.date-selection');
88    var guestwidget = document.querySelector('.guest-selection');
89    var codewidget = document.querySelector('.code-input-selection');
90    var isMobile = window.innerWidth < 1199 ? true : false;
91    var isTab = window.innerWidth < 699 ? true : false;
92
93    var code_type = "";
94    var code_value = "";
95    var selected_codetype = "";
96    var selected_codevalue = "";
97
98    var rate_plan_code = "";
99    var prices = {};
100    var status = {};
101    var minlength = {};
102    let displayedMonths = new Set();
103    var offset = 120;
104    let currentDate = new Date(moment().utcOffset(offset).format("YYYY/MM/DD"));
105    let automaticallySelectedHotel = false;
106
107    function checkResolution() {
108        isMobile = window.innerWidth < 1199 ? true : false;
109        isTab = window.innerWidth < 699 ? true : false;
110        if (_jabook_start_date == "" && _jabook_end_date == "") {
111            if (isMobile)
112                document.querySelector('.selected-date').textContent = checkinmobile_text;
113            else
114                document.querySelector('.selected-date').textContent = checkin_text;
115        }
116    }
117
118    // Run on page load
119    checkResolution();
120
121    // This will return the current date adjusted for the UTC offset
122    // Listen to the window resize event and update isMobile
123    //window.addEventListener('resize', checkResolution);
124    let date_picker_elements = document.querySelectorAll('.home-reservation-search .datepicker');
125
126    let datepickers = Array.from(date_picker_elements).map(date_picker_element => {
127        return new easepick.create({
128            element: date_picker_element,
129            css: [
130                'https://cdn.jsdelivr.net/npm/@easepick/[email protected]/dist/index.css',
131                '/Mvc/Views/ReservationForm/theme-easepick.css'
132            ],
133            inline: true,
134            alwaysOpen: true,
135            calendars: 2,
136            grid: isTab ? 1 : 2,
137            format: 'DD MMM YYYY',
138            plugins: ['RangePlugin', 'LockPlugin'],
139            RangePlugin: {
140                tooltip: false,
141                locale: {
142                    one: "night",
143                    other: "nights",
144                },
145            },
146            lang: 'en',
147            LockPlugin: {
148                minDate: currentDate,
149                maxDate: moment().add(1, 'year').toDate(),
150            },
151            setup(picker) {
152                // Set initial dates if present
153                // if (_jabook_start_date && _jabook_end_date) {
154                //
155                // }
156                picker.on("select", (e) => {
157
158                    let start, end;
159                    if (e.detail.date) {
160                        start = e.detail.date.toLocaleDateString("en-US", { day: "2-digit", month: "2-digit", year: "numeric" });
161                        end = e.detail.date.toLocaleDateString("en-US", { day: "2-digit", month: "2-digit", year: "numeric" });
162                    } else {
163                        start = e.detail.start.toLocaleDateString("en-US", { day: "2-digit", month: "2-digit", year: "numeric" });
164                        end = e.detail.end.toLocaleDateString("en-US", { day: "2-digit", month: "2-digit", year: "numeric" });
165                    }
166
167                    // Convert start and end to Moment objects for formatting
168                    let startMoment = moment(start, 'MM/DD/YYYY');
169                    let endMoment = moment(end, 'MM/DD/YYYY');
170
171                    datepickers.forEach(p => {
172                        p.setStartDate(startMoment.toDate()); // Set the start date
173                        p.setEndDate(endMoment.toDate());     // Set the end date
174                    });
175                    
176                    document.querySelector('.selected-date').textContent =
177                        `${startMoment.format('DD/MM/YYYY')} - ${endMoment ? endMoment.format('DD/MM/YYYY') : 'Check Out'}`;
178                    document.querySelector('.selected-date').classList.add('visible-date');
179                    document.querySelectorAll('.mobile-popup-wrapper .date-selector-title-text').forEach(selectedDate => {
180                        selectedDate.textContent =
181                            `${startMoment.format('DD/MM/YYYY')} - ${endMoment ? endMoment.format('DD/MM/YYYY') : 'Check Out'}`;
182                    })
183                    _jabook_start_date = startMoment.format('YYYY-MM-DD');
184                    _jabook_end_date = endMoment.format('YYYY-MM-DD');
185                    const nightDifference = endMoment.diff(startMoment, 'days'); // Calculate the difference in nights
186                    var var_night = nightDifference > 1 ? nightsVar : nightVar;
187                    document.querySelectorAll('.night_var_widget').forEach(nightcount => {
188                        nightcount.classList.remove('d-none');
189                        nightcount.innerText = nightDifference + var_night;
190                    });
191                    document.querySelector('.date-clear-btn').classList.remove('d-none');
192                    checkDateValidity(_jabook_start_date, _jabook_end_date);
193
194                });
195                picker.on('view', (evt) => {
196
197                    if (dateSelector.classList.contains('errorbox'))
198                        dateSelector.classList.remove('errorbox');
199
200                    if (_jabook_start_date && _jabook_end_date) {
201                        var difference_in_days = moment(_jabook_end_date).diff(moment(_jabook_start_date), 'days');
202                        if (_jabook_start_date === _jabook_end_date && status[_jabook_start_date] === "Only-Check-out") {
203                            showCalendarError(checkin_unavail);
204                        } else if (_jabook_start_date === _jabook_end_date) {
205                            showCalendarError(calendar_minerror);
206                        } else if (status[_jabook_end_date] === "Only-Check-in") {
207                            showCalendarError(checkout_unavail);
208                        } else if (status[_jabook_start_date] === "Only-Check-out") {
209                            showCalendarError(checkin_unavail);
210                        } else if (difference_in_days < minlength[_jabook_start_date]) {
211                            showCalendarError(minLength_error_message + " " + minlength[_jabook_start_date] + " " + nights_stay_var);
212                        }
213                    }
214                });
215            },
216        });
217    });
218
219    // Hotel Popup functions
220    window.addEventListener('scroll', function () {
221        var scrollThreshold = 200;
222        if (isMobile) {
223            scrollThreshold = 20;
224            if (window.scrollY) {
225                widget.classList.add('active-scroll', 'fixed-scroll');
226            } else {
227                widget.classList.remove('active-scroll', 'fixed-scroll');
228            }
229
230        }
231    });
232
233    window.addEventListener('scroll', function () {
234        if (window.scrollY > 0 && window.scrollX > 0)
235            hotelPopup.classList.add('d-none');
236
237        const scrollThreshold = window.innerHeight;
238        if (!isMobile) {
239            const scrollThreshold = widget.getBoundingClientRect().top;
240            if (scrollThreshold <= 0 && window.scrollY > window.innerHeight * 0.8) {
241                widget.classList.add('fixed-scroll', 'active-scroll');
242                const topPosition = widgetUI.getBoundingClientRect().bottom;
243                hotelPopup.style.top = topPosition + 2 + 'px';
244                hotelPopup.style.position = 'fixed';
245
246                if ($('.reservation-in').css("display") != "none") {
247                    $("header").removeClass("non-sticky");
248                }
249                else {
250                    $("header").addClass("non-sticky");
251                }
252                ///  make the header non-fixed
253               
254            } else {
255                widget.classList.remove('fixed-scroll', 'active-scroll');
256                hotelPopup.style.position = 'absolute';
257                hotelPopup.style.top = 'unset';
258
259                $("header").removeClass("non-sticky");
260            }
261        }
262    });
263
264    // CHILD AGE DROPDOWNS
265    //$("#childrenSelect").on("change", function () {
266    //    const count = parseInt($(this).val(), 10);
267    //    const $container = $("#childAgeList");
268
269    //    $container.empty(); // reset
270
271    //    for (let i = 0; i < count; i++) {
272    //        // Build <li> with child age dropdown
273    //        const $li = $(`
274    //        <li>
275    //            <div class="children-age">
276    //                <select class="child-age-select">
277    //                    <option value="">Age</option>
278    //                </select>
279    //            </div>
280    //        </li>
281    //    `);
282
283    //        // Append age options 0–11
284    //        for (let age = 0; age < 12; age++) {
285    //            $li.find("select").append(
286    //                $("<option>", { value: age, text: age })
287    //            );
288    //        }
289
290    //        $container.append($li);
291    //    }
292    //});
293
294    hotelListItems.forEach(item => {
295
296        // check if item has a role=button and only then add the click event
297        if ($(item).attr("role") !== "button") {
298            return;
299        }
300
301        item.addEventListener('click', function () {
302            let hotelId = item.getAttribute('data-id');
303            hotelSelector.setAttribute('data-id', hotelId);
304            hotelPopup.classList.add('d-none');
305            hotelSelector.querySelector('.selected-hotel').textContent = item.textContent;
306            hotelMobilePopup.querySelector('.hotel-selector-title-text').textContent = item.textContent;
307            document.querySelector('.mobile-bookingwidget-selector .hotel-selector-title-text').textContent = item.textContent;
308            _jabook_hotelname = item.textContent.trim();
309
310            _jabook_hotelid = hotelId;
311
312            currentDate = new Date(moment().format("YYYY/MM/DD"));
313
314            initaiatecalendar();
315            if (isMobile) {
316                if (automaticallySelectedHotel) {
317                    /// do not open the date popup if the hotel is automatically selected
318                    /// because of the url that we are on
319                    automaticallySelectedHotel = false;
320                    return;
321                }
322                hotelMobilePopup.classList.add('d-none');
323                dateMobilePopup.classList.remove('d-none');
324            }
325            if (_jabook_hotelid == 'all')
326                datepickers.forEach(picker => {
327                    picker.renderAll();
328                });
329        });
330    });
331
332    function dNoneClassAdded() {
333        $("header").css("z-index", 801);
334    }
335
336    function dNoneClassRemoved() {
337        $("header").css("z-index", 788);
338    }
339
340    // watch for a specific class change
341    let classWatcherHotel = new ClassWatcher(hotelPopup, 'd-none', dNoneClassAdded, dNoneClassRemoved);
342    let classWatcherDate = new ClassWatcher(datePopup, 'd-none', dNoneClassAdded, dNoneClassRemoved);
343
344
345    hotelSelector.addEventListener('click', function () {
346
347        if (isMobile)
348            hotelMobilePopup.classList.toggle('d-none')
349        else {
350            hotelPopup.classList.toggle('d-none');
351
352            if (window.scrollY < window.innerHeight * 0.8) {
353                window.scrollTo(0, 0);
354            } else {
355                if (widget.classList.contains('active-scroll')) {
356                    const topPosition = widgetUI.getBoundingClientRect().bottom;
357                    hotelPopup.style.top = topPosition + 2 + 'px';
358                    hotelPopup.style.position = 'fixed';
359                } else {
360                    hotelPopup.style.position = 'absolute';
361                    hotelPopup.style.top = 'unset';
362                }
363            }
364        }
365    });
366
367
368    $('.hotel_list_item').click(function () {
369        $('.individualHotels_Dropdown-Menu.show').removeClass('show')
370        $('.allHotels_Dropdown-Menu.show').removeClass('show')
371    });
372
373
374    $('#hotel_dropdown .modal-content .hotel-mobile-dropdown .dropdown-menu .dropdown-item').click(function () {
375        $('#navbarContent .hoteldropdown .hotel-dropdown-mobile  span').text($(this).text());
376        $('#hotel_dropdown .modal-content .hotel-mobile-dropdown .dropdown-toggle span').text($(this).text());
377        $('#hotel_dropdown').modal('hide');
378    });
379
380    document.addEventListener('click', function (event) {
381        if (!hotelPopup.contains(event.target) && !hotelSelector.contains(event.target)) {
382            hotelPopup.classList.add('d-none');
383        }
384    });
385    hotelMobilePopupClose.addEventListener('click', function (event) {
386        hotelMobilePopup.classList.add('d-none');
387    });
388
389    function initaiatecalendar() {
390        prices = {};
391        status = {};
392        minlength = {};
393        // clear the displayed months
394        displayedMonths = new Set();
395        stayCalendar.forEach(calenar => {
396            if (!calenar.classList.contains('d-none'))
397                calenar.classList.add('d-none');
398        });
399        generateFirstMonthData();
400    }
401
402    function generateFirstMonthData() {
403        var pricestext = document.querySelector('.prices-text');
404        var pricestextmobile = document.querySelector('.currency-text');
405        if (_jabook_hotelid != null && _jabook_hotelid != "all" && _jabook_hotelid != "") {
406            const from_date = moment(currentDate).format('YYYY-MM-DD');
407            const to_date = moment(currentDate).endOf('month').format("YYYY-MM-DD");
408
409        } else {
410            if (!pricestext.classList.contains('d-none'))
411                document.querySelector('.prices-text').classList.add('d-none');
412            if (!pricestextmobile.classList.contains('d-none'))
413                pricestextmobile.classList.add('d-none');
414        }
415    }
416
417    dateSelector.addEventListener('click', function () {
418        var dpopup = $(".date-popup");
419        if (isMobile) {
420            dateMobilePopup.classList.toggle('d-none');
421            datepickers.forEach(picker => {
422                picker.renderAll();
423            });
424        }
425        else {
426            datePopup.classList.toggle('d-none');
427            if (window.scrollY < window.innerHeight * 0.8) {
428                window.scrollTo(0, 0);
429            }
430            if (!dpopup.hasClass("d-none")) {
431                $("header").css("z-index", 788);
432            }
433            else {
434                $("header").css("z-index", 801);
435            }
436
437        }
438    });
439    document.addEventListener('click', function (event) {
440        if (!datePopup.contains(event.target) && !dateSelector.contains(event.target)) {
441            datePopup.classList.add('d-none');
442        }
443
444    });
445    dateMobilePopupClose.addEventListener('click', function (event) {
446        dateMobilePopup.classList.add('d-none');
447    });
448
449    $(document).on("click", ".hotel-popup-header .nav-item:first button.active", function () {
450
451        /// if the user clicks on the All Hotels tab, we clear the selected hotel
452        _jabook_hotelname = _jabook_allHotelsId;
453        hotelSelector.querySelector('.selected-hotel').textContent = all_hotels_var;
454    });
455
456    function checkDateValidity(start, end) {
457        var difference_in_days = moment(end).diff(moment(start), 'days');
458        if (start === end && status[start] === "Only-Check-out") {
459            showCalendarError(checkin_unavail);
460        } else if (start === end) {
461            showCalendarError(calendar_minerror);
462        } else if (status[end] === "Only-Check-in") {
463            showCalendarError(checkout_unavail);
464        } else if (status[start] === "Only-Check-out") {
465            showCalendarError(checkin_unavail);
466        } else if (difference_in_days < minlength[start]) {
467            showCalendarError(minLength_error_message + " " + minlength[start] + " " + nights_stay_var);
468        } else {
469            hideCalendarError();
470        }
471    }
472
473    function showCalendarError(message) {
474        stayCalendar.forEach(calenar => {
475            calenar.classList.remove('d-none');
476            calenar.innerHTML = `
477    <div class="calendar-error-msg mb-0" role="alert">
478      <p>
479      <i class="fal fa-exclamation-triangle px-1"></i>
480      <span class="error-message">${message}</span>
481      </p>
482    </div>`;
483        });
484        findrooms.forEach(findRoom => {
485            findRoom.classList.add('disabled');
486            findRoom.setAttribute('disabled', 'disabled');
487        });
488        dateSelector.classList.add('errorbox');
489        selectedDatebutton.classList.add('d-none');
490        // selectedDatebutton.setAttribute('disabled', 'disabled');
491    }
492
493    function hideCalendarError() {
494        stayCalendar.forEach(calenar => {
495            calenar.classList.add('d-none');
496        });
497        findrooms.forEach(findRoom => {
498            findRoom.classList.remove('disabled');
499            findRoom.removeAttribute('disabled');
500        });
501        selectedDatebutton.classList.remove('d-none');
502        document.querySelector('.date-popup').classList.add('d-none');
503        if (dateSelector.classList.contains('errorbox'))
504            dateSelector.classList.remove('errorbox');
505    }
506    function clearDatePicker() {
507        datepickers.forEach(picker => {
508            picker.clear(); // Clear the selected date
509        });
510        // Reset the displayed date text
511        if (isMobile)
512            document.querySelector('.selected-date').textContent = checkinmobile_text;
513        else
514            document.querySelector('.selected-date').textContent = checkin_text;
515        document.querySelector('.selected-date').classList.remove('visible-date');
516        document.querySelectorAll('.mobile-popup-wrapper .date-selector-title-text').forEach(selectedDate => {
517            selectedDate.textContent = checkin_text;
518        })
519        document.querySelectorAll('.night_var_widget').forEach(nightcount => {
520            nightcount.classList.add('d-none');
521        });
522        document.querySelector('.date-clear-btn').classList.add('d-none');
523
524        _jabook_start_date = "";
525        _jabook_end_date = "";
526        stayCalendar.forEach(calenar => {
527            if (!calenar.classList.contains('d-none'))
528                calenar.classList.add('d-none');
529        });
530        selectedDatebutton.classList.add('d-none');
531    }
532
533    document.querySelector('.date-clear-btn').addEventListener('click', function () {
534        clearDatePicker();
535    });
536
537    selectedDatebutton.addEventListener('click', function () {
538        dateMobilePopup.classList.add('d-none');
539        mobileBookingwidget.classList.remove('d-none');
540    });
541
542    // Pax Popup functions
543    paxSelector.addEventListener('click', function () {
544        if (isMobile)
545            paxMobilePopup.classList.toggle('d-none');
546        else {
547            paxPopup.classList.toggle('d-none');
548            if (window.scrollY < window.innerHeight * 0.8) {
549                window.scrollTo(0, 0);
550            }
551        }
552    });
553
554    document.addEventListener('click', function (event) {
555        if (!paxPopup.contains(event.target) && !paxSelector.contains(event.target) && !event.target.closest('.btn-remove-room')) {
556            paxPopup.classList.add('d-none');
557        }
558    });
559    paxMobilePopupClose.addEventListener('click', function () {
560        paxMobilePopup.classList.add('d-none');
561    });
562
563    addRoom.forEach(addRoombtn => {
564        addRoombtn.addEventListener('click', function () {
565            if (window.scrollY < window.innerHeight * 0.8) {
566                window.scrollTo(0, 0);
567            }
568            if (_jabook_no_of_rooms == 1) {
569                [guestRooms, mobileGuestRooms].forEach(container => {
570                    const dropdownDiv = container.querySelector('.room:first-child .room-header');
571                    dropdownDiv.classList.remove('d-none');
572                    dropdownDiv.classList.add('d-flex');
573                });
574            }
575
576            if (_jabook_no_of_rooms < 9) {
577                const newRoomNumber = _jabook_no_of_rooms + 1;
578                addnewroom(newRoomNumber);
579                addnewroomMobile(newRoomNumber);
580                if (addRoombtn.classList.contains('desktop'))
581                    updatechildadultcount('desktop');
582                else
583                    updatechildadultcount('mobile');
584
585                // Scroll to the bottom of the room lists
586                [guestRooms, mobileGuestRooms].forEach(container => {
587                    container.scrollTo({
588                        top: paxPopup.scrollHeight,
589                        behavior: 'smooth'
590                    });
591                });
592                paxPopup.scrollTop = paxPopup.scrollHeight;
593                paxMobilePopup.querySelector('.overflow-wrapper').scrollTop = paxMobilePopup.querySelector('.overflow-wrapper').scrollHeight;
594            }
595
596            if (_jabook_no_of_rooms == 8) {
597                addRoom.forEach(addRoombtn => {
598                    addRoombtn.parentElement.classList.add('d-none');
599                });
600            }
601            _jabook_no_of_rooms++;
602        });
603    });
604
605    function addnewroom(newRoomNumber) {
606        const newRoom = document.createElement('div');
607        newRoom.classList.add('room');
608        newRoom.setAttribute('data-room', newRoomNumber);
609
610        newRoom.innerHTML = `
611        <div class="room-header d-flex align-items-center mt-3">
612          <div class="room-title">${room_var} ${newRoomNumber}</div>
613          <span class="btn-remove-room" aria-label="Remove room">
614            <i class="fa fa-trash trash_widget"></i>
615          </span>
616        </div>
617        <div class="guest-counter d-flex justify-content-between align-items-center py-1 my-3">
618          <label class="guest-label mb-0">${adult_text} (12+)</label>
619          <div class="counter-box d-flex align-items-center">
620            <span class="btn_counter ag-minus disabled" data-action="minus">
621              <i class="fa fa-minus-circle"></i>
622            </span>
623            <span class="adult-counter count b4">1</span>
624            <span class="btn_counter ag-plus" data-action="plus">
625              <i class="fa fa-plus-circle"></i>
626            </span>
627          </div>
628        </div>
629        <div class="guest-counter d-flex justify-content-between align-items-center py-1 my-3">
630          <label class="guest-label mb-0">${children_text} (4-11)</label>
631          <div class="counter-box d-flex align-items-center">
632            <span class="btn_counter cg-minus disabled" data-action="minus">
633              <i class="fa fa-minus-circle"></i>
634            </span>
635            <span class="child-counter count b4">0</span>
636            <span class="btn_counter cg-plus" data-action="plus">
637              <i class="fa fa-plus-circle"></i>
638            </span>
639          </div>
640        </div>
641      `;
642
643        guestRooms.appendChild(newRoom);
644    }
645    function addnewroomMobile(newRoomNumber) {
646        const newRoom = document.createElement('div');
647        newRoom.classList.add('room', 'mb-2', 'bg-grey', 'rounded-8px', 'py-2');
648        newRoom.setAttribute('data-room', newRoomNumber);
649
650        newRoom.innerHTML = `
651        <div class="px-4 room-header align-items-center d-flex mt-2">
652                    <div class="room-title">${room_var} ${newRoomNumber}</div>
653                    <span class="btn-remove-room" aria-label="Remove room">
654                      <i class="fa fa-trash trash_widget"></i>
655                    </span>
656                  </div>
657                  <div class="d-flex justify-content-between align-items-center">
658                    <div class="guest-counter w-100 py-1">
659                      <label class="guest-label mb-2 px-4">${adult_text} (12+)</label>
660                      <div class="counter-box d-flex align-items-center justify-content-between px-4">
661                        <span class="btn_counter ag-minus disabled" data-action="minus">
662                          <i class="fa fa-minus-circle"></i>
663                        </span>
664                        <span class="adult-counter count b4">1</span>
665                        <span class="btn_counter ag-plus" data-action="plus">
666                          <i class="fa fa-plus-circle"></i>
667                        </span>
668                      </div>
669                    </div>
670                    <div style="background: #25282D29; width: 1px; height: 48px;"></div>
671                    <div class="guest-counter w-100 py-1">
672                      <label class="guest-label mb-2 px-4">${children_text} (4-11)</label>
673                      <div class="counter-box d-flex align-items-center justify-content-between px-4">
674                        <span class="btn_counter cg-minus disabled" data-action="minus">
675                          <i class="fa fa-minus-circle"></i>
676                        </span>
677                        <span class="child-counter count b4">0</span>
678                        <span class="btn_counter cg-plus" data-action="plus">
679                          <i class="fa fa-plus-circle"></i>
680                        </span>
681                      </div>
682                    </div>
683                  </div>
684      `;
685
686        mobileGuestRooms.appendChild(newRoom);
687    }
688
689    function updatechildadultcount(resolution) {
690        let adult_counters;
691        let child_counters;
692        if (resolution == 'desktop') {
693            adult_counters = guestRooms.querySelectorAll('.adult-counter');
694            child_counters = guestRooms.querySelectorAll('.child-counter');
695        }
696        else {
697            adult_counters = mobileGuestRooms.querySelectorAll('.adult-counter');
698            child_counters = mobileGuestRooms.querySelectorAll('.child-counter');
699        }
700        let adult_totalcount = 0;
701        let child_totalcount = 0;
702
703        adult_counters.forEach(function (item) {
704            adult_totalcount += parseInt(item.innerText);
705        });
706        child_counters.forEach(function (item) {
707            child_totalcount += parseInt(item.innerText);
708        });
709
710        _jabook_adult_count = adult_totalcount;
711        _jabook_child_count = child_totalcount;
712        paxSelector.querySelector('.selected-guest').textContent = `${adult_totalcount} ${adult_text}, ${child_totalcount} ${child_text}`;
713        document.querySelectorAll('.guest-selected-title-text').forEach(guest => {
714            guest.textContent = `${adult_totalcount} ${adult_text}, ${child_totalcount} ${child_text}`;
715        });
716
717    }
718
719    // Desktop
720    guestRooms.addEventListener('click', function (event) {
721        const target = event.target;
722        // find the data-room attribute value
723        cuurentroomnumber = target.closest('.room').getAttribute('data-room');
724        const counterBox = target.closest('.counter-box');
725        const mobileRoom = mobileGuestRooms.querySelector(`.room[data-room="${cuurentroomnumber}"]`);
726
727
728        if (counterBox) {
729            const counter = counterBox.querySelector('.count');
730            const isAdult = counter.classList.contains('adult-counter');
731            const isPlus = target.closest('[data-action="plus"]');
732            const isMinus = target.closest('[data-action="minus"]');
733
734            if (isAdult)
735                mobileCounter = mobileRoom.querySelector('.counter-box .adult-counter');
736            else
737                mobileCounter = mobileRoom.querySelector('.counter-box .child-counter');
738
739            const mobileMinBtn = mobileCounter.closest('.counter-box').querySelector('[data-action="minus"]');
740            const mobilePlusBtn = mobileCounter.closest('.counter-box').querySelector('[data-action="plus"]');
741
742            if (isPlus || isMinus) {
743                let count = parseInt(counter.innerText);
744                const minBtn = counterBox.querySelector('[data-action="minus"]');
745                const plusBtn = counterBox.querySelector('[data-action="plus"]');
746
747                if (isPlus) {
748                    count++;
749                    counter.innerText = count;
750                    minBtn.classList.remove('disabled');
751                    mobileCounter.innerText = count;
752                    mobileMinBtn.classList.remove('disabled');
753                    if (count == 10) {
754                        plusBtn.classList.add('disabled');
755                        mobilePlusBtn.classList.add('disabled');
756                    }
757                } else if (isMinus && count > (isAdult ? 1 : 0)) {
758                    count--;
759                    counter.innerText = count;
760                    mobileCounter.innerText = count;
761                    if (count === (isAdult ? 1 : 0)) {
762                        minBtn.classList.add('disabled');
763                        mobileMinBtn.classList.add('disabled');
764                    }
765                    if (count < 10) {
766                        if (plusBtn.classList.contains('disabled'))
767                            plusBtn.classList.remove('disabled');
768                        if (mobilePlusBtn.classList.contains('disabled'))
769                            mobilePlusBtn.classList.remove('disabled');
770                    }
771
772
773                }
774
775                updatechildadultcount('desktop');
776            }
777        }
778
779        if (target.closest('.btn-remove-room')) {
780            event.stopPropagation(); // Add this line to prevent event bubbling
781            const room = target.closest('.room');
782            const mobileroom = mobileGuestRooms.querySelector(`.room[data-room="${cuurentroomnumber}"]`); //
783            if (mobileroom && room && guestRooms.children.length > 1) {
784                room.remove();
785                mobileroom.remove(); // Remove the room
786                updatechildadultcount('desktop');
787                _jabook_no_of_rooms--;
788                addRoom.forEach(addRoombtn => {
789                    if (addRoombtn.parentElement.classList.contains('d-none'))
790                        addRoombtn.parentElement.classList.remove('d-none');
791                });
792
793                renumberroom();
794            }
795        }
796    });
797    // Mobile
798    mobileGuestRooms.addEventListener('click', function (event) {
799        const target = event.target;
800        cuurentroomnumber = target.closest('.room').getAttribute('data-room');
801        const counterBox = target.closest('.counter-box');
802        const desktopRoom = guestRooms.querySelector(`.room[data-room="${cuurentroomnumber}"]`);
803
804        if (counterBox) {
805            const counter = counterBox.querySelector('.count');
806            const isAdult = counter.classList.contains('adult-counter');
807            const isPlus = target.closest('[data-action="plus"]');
808            const isMinus = target.closest('[data-action="minus"]');
809            let desktopCounter;
810            if (isAdult)
811                desktopCounter = desktopRoom.querySelector('.counter-box .adult-counter');
812            else
813                desktopCounter = desktopRoom.querySelector('.counter-box .child-counter');
814
815            const desktopMinBtn = desktopCounter.closest('.counter-box').querySelector('[data-action="minus"]');
816
817            const desktopPlusBtn = desktopCounter.closest('.counter-box').querySelector('[data-action="plus"]');
818            if (isPlus || isMinus) {
819                let count = parseInt(counter.innerText);
820                const minBtn = counterBox.querySelector('[data-action="minus"]');
821                const plusBtn = counterBox.querySelector('[data-action="plus"]');
822
823                if (isPlus) {
824                    count++;
825                    counter.innerText = count;
826                    minBtn.classList.remove('disabled');
827                    desktopCounter.innerText = count;
828                    desktopMinBtn.classList.remove('disabled');
829                    if (count == 10) {
830                        plusBtn.classList.add('disabled');
831                        desktopPlusBtn.classList.add('disabled');
832                    }
833                } else if (isMinus && count > (isAdult ? 1 : 0)) {
834                    count--;
835                    counter.innerText = count;
836                    desktopCounter.innerText = count;
837                    if (count === (isAdult ? 1 : 0)) {
838                        minBtn.classList.add('disabled');
839                        desktopMinBtn.classList.add('disabled');
840                    }
841                    if (count < 10) {
842                        if (plusBtn.classList.contains('disabled'))
843                            plusBtn.classList.remove('disabled');
844                        if (desktopPlusBtn.classList.contains('disabled'))
845                            desktopPlusBtn.classList.remove('disabled');
846                    }
847                }
848
849                updatechildadultcount('mobile'); // Update the total count for desktop
850            }
851        }
852
853        if (target.closest('.btn-remove-room')) {
854            event.stopPropagation(); // Prevent event bubbling
855            const room = target.closest('.room');
856            const desktoproom = guestRooms.querySelector(`.room[data-room="${cuurentroomnumber}"]`); //
857            if (desktoproom && room && mobileGuestRooms.children.length > 1) {
858                room.remove();
859                desktoproom.remove(); // Remove the room
860                updatechildadultcount('mobile'); // Update the total count for desktop
861                _jabook_no_of_rooms--;
862                addRoom.forEach(addRoombtn => {
863                    if (addRoombtn.parentElement.classList.contains('d-none'))
864                        addRoombtn.parentElement.classList.remove('d-none');
865                });
866                renumberroom();
867            }
868        }
869    });
870    function renumberroom() {
871        // Renumber the rooms for both desktop and mobile
872        [guestRooms, mobileGuestRooms].forEach(container => {
873            const rooms = container.querySelectorAll('.room');
874            rooms.forEach((room, index) => {
875                const roomNumber = index + 1;
876                room.setAttribute('data-room', roomNumber);
877                room.querySelector('.room-title').textContent = `${room_var} ${roomNumber}`;
878            });
879            // If only one room is left, add 'd-none' to the room-header
880            if (rooms.length === 1) {
881                const firstRoomHeader = rooms[0].querySelector('.room-header');
882                firstRoomHeader.classList.add('d-none');
883                firstRoomHeader.classList.remove('d-flex');
884            }
885        });
886    }
887    guestClearBtn.addEventListener('click', function (event) {
888        clearpaxdata();
889    });
890    function clearpaxdata() {
891        // Clear all rooms except the first one
892        _jabook_no_of_rooms = 1;
893        [guestRooms, mobileGuestRooms].forEach(container => {
894            const rooms = container.querySelectorAll('.room');
895
896            // Remove all rooms except the first
897            for (let i = 1; i < rooms.length; i++) {
898                if (rooms.length > 1) {
899                    rooms[i].remove();
900                }
901            }
902            // Set the first room to have 1 adult and 0 children
903            const firstRoom = rooms[0];
904            const firstRoomHeader = rooms[0].querySelector('.room-header');
905            firstRoomHeader.classList.add('d-none');
906            firstRoomHeader.classList.remove('d-flex');
907            firstRoom.querySelector('.adult-counter').innerText = '1';
908            const adultCounterMinusBtn = firstRoom.querySelector('.adult-counter').closest('.counter-box').querySelector('[data-action="minus"]');
909            if (adultCounterMinusBtn) {
910                adultCounterMinusBtn.classList.add('disabled');
911            }
912            firstRoom.querySelector('.child-counter').innerText = '0';
913            const childCounterMinusBtn = firstRoom.querySelector('.child-counter').closest('.counter-box').querySelector('[data-action="minus"]');
914            if (childCounterMinusBtn) {
915                childCounterMinusBtn.classList.add('disabled');
916            }
917            updatechildadultcount('mobile');
918        });
919        addRoom.forEach(addRoombtn => {
920            if (addRoombtn.parentElement.classList.contains('d-none'))
921                addRoombtn.parentElement.classList.remove('d-none');
922        });
923    }
924
925    document.querySelector('.mobile-guest-selector-done').addEventListener('click', function () {
926        paxMobilePopup.classList.add('d-none');
927        mobileBookingwidget.classList.remove('d-none');
928    });
929    document.querySelector('.backtoguestwidget').addEventListener('click', function () {
930        paxMobilePopup.classList.add('d-none');
931        mobileBookingwidget.classList.remove('d-none');
932    });
933
934
935    // Mobile Booking Widget
936    hotelwidget.addEventListener('click', function () {
937        mobileBookingwidget.classList.add('d-none');
938        hotelMobilePopup.classList.remove('d-none');
939    });
940    datewidget.addEventListener('click', function () {
941        mobileBookingwidget.classList.add('d-none');
942        dateMobilePopup.classList.remove('d-none');
943    });
944    guestwidget.addEventListener('click', function () {
945        mobileBookingwidget.classList.add('d-none');
946        paxMobilePopup.classList.remove('d-none');
947    });
948
949    mobileBookingwidget.querySelector('.close-mobile-popup').addEventListener('click', function () {
950        mobileBookingwidget.classList.add('d-none');
951    });
952    mobileBookingwidget.querySelector('.widget-clear-btn').addEventListener('click', function () {
953        // clear hotels
954        if (!mobileBookingwidget.querySelector('.hotel-selection').classList.contains('disabled')) {
955            _jabook_hotelid = "all";
956            _jabook_hotelname = _jabook_allHotelsId;
957            hotelSelector.querySelector('.selected-hotel').textContent = all_hotels_var;
958            hotelMobilePopup.querySelector('.hotel-selector-title-text').textContent = all_hotels_var;
959            document.querySelector('.mobile-bookingwidget-selector .hotel-selector-title-text').textContent = all_hotels_var;
960        }
961    });
962    const popupWrapper = document.querySelector('.mobile-popup-wrapper');
963
964    // Function to check if any immediate child div inside `mobile-popup-wrapper` is visible
965    function checkPopupVisibility() {
966        let isPopupVisible = false;
967        popupWrapper.querySelectorAll(':scope > div').forEach(div => {
968            if (!div.classList.contains('d-none')) {
969                isPopupVisible = true;
970            }
971        });
972        document.body.style.overflow = isPopupVisible ? 'hidden' : '';
973    }
974    const observer = new MutationObserver(checkPopupVisibility);
975    popupWrapper.querySelectorAll(':scope > div').forEach(div => {
976        observer.observe(div, { attributes: true, attributeFilter: ['class'] });
977    });
978
979    checkPopupVisibility();
980
981    /// preselect the hotel based on the url
982    if ($(".hotel_list_item.hotel-selected").length > 0) {
983        automaticallySelectedHotel = true;
984
985        $(".hotel_list_item.hotel-selected").trigger("click");
986    }    
987});
988
989
990
991/// triggered by the book now button on desktop and mobile
992/// similar to ghadashboard, populate the top right form fields and use that logic
993function homePageSearchBookNow() {
994
995    showHideValidation();
996
997    if (!_jabook_hotelname) {
998        return;
999    }
1000
1001    /// hotel
1002    var selectedHotelValue = _jabook_hotelname == _jabook_allHotelsId ? 
1003        _jabook_hotelname : $(".be-property").find("option:contains('" + _jabook_hotelname + "')").val();
1004    $(".be-property").val(selectedHotelValue).trigger("change");
1005
1006    /// dates
1007    $(".reservation-inner .txt-checkin").val(_jabook_start_date);
1008    /// manually update the siblings
1009    var mDate = new moment(_jabook_start_date);
1010    var dateString = mDate.format("[<em>]Do MMMM YYYY[</em><small>]dddd[</small>]");
1011    $(".date-checkin").find(".date-display").html(dateString);
1012
1013    $(".reservation-inner .txt-checkout").val(_jabook_end_date);
1014    mDate = new moment(_jabook_end_date);
1015    dateString = mDate.format("[<em>]Do MMMM YYYY[</em><small>]dddd[</small>]");
1016    $(".date-checkout").find(".date-display").html(dateString);
1017
1018    // rooms
1019    $(".room-count").val(_jabook_no_of_rooms);
1020
1021    // adults
1022    $(".adults-count").val(_jabook_adult_count).trigger("change");
1023
1024    // children and infants
1025    var children = _jabook_child_count;
1026    $(".child-count").val(children).trigger("change");
1027    
1028    // promo
1029    $(".reservation-inner .txt-promo").val($("#txtPromoCode").val() || $('#txtPromoCodeMobile').val());
1030
1031    $("#btnReservationBookNow").click();
1032}
1033
1034function showHideValidation() {
1035
1036    /// hotel
1037    if (!_jabook_hotelname) {
1038        $(".hotel-selector").addClass("invalid");
1039    }
1040    else {
1041        $(".hotel-selector").removeClass("invalid");
1042    }
1043}

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.