https://summer-estate.com/wp-content/plugins/hostify-booking/public/res/inquiry-form-v2.js?ver=0.8.4
1/** 2 * JavaScript for handling the v2 inquiry form modal 3 * Implementing the v3 calendar (datepicker) functionality 4 */ 5jQuery(document).ready(function($) { 6 // console.log('inquiry-form-v2.js loaded (debug)'); 7 8 // Check if new inquiry form is enabled 9 if (typeof window.HFY_USE_NEW_INQUIRY_FORM === 'undefined' || !window.HFY_USE_NEW_INQUIRY_FORM) { 10 // console.log('New inquiry form is disabled, skipping V2 initialization'); 11 return; 12 } 13 14 // console.log('New inquiry form is enabled, initializing V2 modal'); 15 16 // Initialize the modal 17 function initInquiryModalV2() { 18 // Modal elements 19 const $modal = $('#hfy-direct-inquiry-modal-v2'); 20 const $form = $('#hfy-direct-inquiry-form-v2'); 21 const $modalClose = $modal.find('.hfy-modal-close, .hfy-modal-cancel'); 22 const $responseArea = $modal.find('.hfy-inquiry-response'); 23 24 // Calendar elements - check which type is being used 25 const isV3Calendar = typeof window.HFY_USE_V3_CALENDAR !== 'undefined' && window.HFY_USE_V3_CALENDAR; 26 27 let $datepickerInput, $startDateInput, $endDateInput; 28 29 if (isV3Calendar) { 30 // V3 Calendar (Datepicker) - Single input 31 $datepickerInput = $modal.find('#inquiry-hotel-datepicker'); 32 $startDateInput = $modal.find('input[name="start_date"]'); 33 $endDateInput = $modal.find('input[name="end_date"]'); 34 } else { 35 // V2 Calendar (Old Calendar) - Two separate inputs 36 $startDateInput = $modal.find('input[name="start_date"]'); 37 $endDateInput = $modal.find('input[name="end_date"]'); 38 // No datepicker input for V2 calendar 39 } 40 41 const $resetDateLink = $modal.find('.reset-date'); 42 43 // Guest elements 44 const $guestButtons = $modal.find('.hfy-guest-btn'); 45 const $guestCounts = $modal.find('.hfy-guest-count'); 46 const $guestInputs = $modal.find('input[name="adults"], input[name="children"], input[name="infants"]'); 47 const $maxGuests = $('#hfy-max-guests-v2'); 48 const $guestSummary = $('#hfy-guest-summary-v2'); 49 const $guestWarning = $('#hfy-guest-warning-v2'); 50 51 // Variable to store the inquiry datepicker instance 52 let inquiryDatepicker = null; 53 54 // Override the default click handler for the inquiry button 55 // Remove default handler by intercepting the event 56 $(document).off('click', '.direct-inquiry-modal-open'); 57 58 // Add our custom handler 59 $(document).on('click', '.direct-inquiry-modal-open', function(e){ 60 // console.log('V2 Inquiry modal open button clicked'); 61 e.preventDefault(); 62 e.stopPropagation(); 63 64 $modal.find('.thx').hide(); 65 $form.show(); // Keep showing form content if hidden on success 66 // Use the hfymodal function to show, assuming it handles blocker and body class 67 if ($.isFunction($.fn.hfymodal)) { 68 $modal.hfymodal('show'); 69 } else { 70 console.error('hfymodal function not found. Falling back to basic show.'); 71 $modal.show(); 72 $('body').addClass('hfy-modal-open'); // Fallback body class 73 } 74 75 // Delay calendar initialization to ensure modal and inputs are in DOM 76 setTimeout(function() { 77 // console.log('Calendar initialization check:', { 78 // isV3Calendar: isV3Calendar, 79 // datepickerInputExists: isV3Calendar ? ($datepickerInput && $datepickerInput.length > 0) : false, 80 // shouldInitDatepicker: isV3Calendar && $datepickerInput && $datepickerInput.length && $datepickerInput[0], 81 // shouldInitOldCalendar: !isV3Calendar 82 // }); 83 84 // Initialize datepicker only if V3 calendar is enabled 85 if (isV3Calendar && $datepickerInput && $datepickerInput.length && $datepickerInput[0]) { 86 initInquiryDatepicker(); 87 } else if (!isV3Calendar) { 88 // Initialize old calendar (V2) if V3 calendar is disabled
89 initInquiryOldCalendar(); 90 } 91 92 // Transfer dates from main booking form if they exist 93 const mainStartDate = $('.hfy-listing-booking-form input[name="start_date"]').val(); 94 const mainEndDate = $('.hfy-listing-booking-form input[name="end_date"]').val(); 95 96 // Also check URL parameters directly 97 const urlParams = new URLSearchParams(window.location.search); 98 const urlStartDate = urlParams.get('start_date'); 99 const urlEndDate = urlParams.get('end_date'); 100 101 // console.log('Checking for pre-selected dates from main booking form:', { 102 // mainStartDate: mainStartDate, 103 // mainEndDate: mainEndDate, 104 // urlStartDate: urlStartDate, 105 // urlEndDate: urlEndDate, 106 // isV3Calendar: isV3Calendar, 107 // currentUrl: window.location.href 108 // }); 109 110 // Use URL parameters if main booking form doesn't have dates 111 const effectiveStartDate = mainStartDate || urlStartDate; 112 const effectiveEndDate = mainEndDate || urlEndDate; 113 114 if (effectiveStartDate && effectiveEndDate) { 115 // console.log('Using effective dates for inquiry modal:', { 116 // effectiveStartDate: effectiveStartDate, 117 // effectiveEndDate: effectiveEndDate 118 // }); 119 120 // Set the hidden inputs in the modal 121 $startDateInput.val(effectiveStartDate); 122 $endDateInput.val(effectiveEndDate); 123 124 if (isV3Calendar) { 125 // Update the visible datepicker input in the modal 126 const dateValue = `${effectiveStartDate} - ${effectiveEndDate}`; 127 $datepickerInput.val(dateValue); 128 129 // Update the datepicker instance if initialized 130 if (inquiryDatepicker) { 131 inquiryDatepicker.close(); // Close if open 132 // Set the range in the datepicker instance 133 try { 134 inquiryDatepicker.setRange(effectiveStartDate, effectiveEndDate); 135 } catch (e) { 136 console.warn('Error setting range on inquiry datepicker:', e); 137 } 138 } 139 } else { 140 // For V2 calendar, update the visible calentim inputs 141 const $modalCalentimStart = $modal.find('input.calentim-start'); 142 const $modalCalentimEnd = $modal.find('input.calentim-end'); 143 144 // console.log('Updating V2 calendar inputs in modal:', { 145 // modalCalentimStartFound: $modalCalentimStart.length, 146 // modalCalentimEndFound: $modalCalentimEnd.length, 147 // startDate: effectiveStartDate, 148 // endDate: effectiveEndDate 149 // }); 150 151 if ($modalCalentimStart.length) { 152 $modalCalentimStart.val(effectiveStartDate); 153 // console.log('Updated modal calentim-start input:', effectiveStartDate); 154 } 155 if ($modalCalentimEnd.length) { 156 $modalCalentimEnd.val(effectiveEndDate); 157 // console.log('Updated modal calentim-end input:', effectiveEndDate); 158 } 159 } 160 161 // Calculate and update nights 162 updateNightsInput(effectiveStartDate, effectiveEndDate); 163 } else { 164 // Clear dates if main form has none selected 165 $startDateInput.val(''); 166 $endDateInput.val(''); 167 if (isV3Calendar) { 168 $datepickerInput.val(''); 169 if (inquiryDatepicker) { 170 inquiryDatepicker.clear(); 171 } 172 } else { 173 // For V2 calendar, clear the visible inputs 174 $modal.find('input[name="start_date"]').val(''); 175 $modal.find('input[name="end_date"]').val(''); 176 } 177 updateNightsInput(null, null); // Clear nights input 178 } 179 180 // Transfer guest counts if they exist 181 const adults = $('.listing-price .guests').val() || 1; 182 $('#hfy-inquiry-adults-v2').val(adults); 183 $('.hfy-guest-count[data-type="adults"]').text(adults); 184 updateGuestSummary(); 185 186 // Log for debugging 187 // console.log('Inquiry form modal opened, datepicker initialized:', inquiryDatepicker); 188 }, 100); // 100ms delay to ensure modal/input is in DOM 189 }); 190 191 // Close modal - Reverted to manual hide, but hide blocker instead of removing 192 $modalClose.on('click', function() { 193 // console.log('Close button clicked.'); // Add log 194 195 // Close datepicker if open 196 if (inquiryDatepicker) { 197 try { 198 inquiryDatepicker.close(); 199 } catch (e) { 200 console.warn('Error closing datepicker:', e); 201 } 202 } 203 204 $modal.hide(); // Hide the modal div itself 205 // Hide the blocker instead of removing it 206 $('.hfy-modal-blocker.current').hide(); 207 // It's possible hfymodal('show') adds/removes the 'current' class, 208 // or maybe we need to remove 'current' here? Let's try just hiding first. 209 210 $('body').removeClass('hfy-modal-open'); // Remove body class 211 212 // Reset visual state 213 $responseArea.hide().text(''); // Clear response area 214 $modal.removeClass('hfy-inquiry-success'); // Remove success class 215 $modal.find('.hfy-modal-header').show(); // Ensure header is visible 216 $form.show(); // Ensure form is visible for next open 217 $modal.find('.thx').hide(); // Hide thank you message 218 }); 219 220 // Initialize the v3 datepicker specifically for the inquiry form 221 function initInquiryDatepicker() { 222 // console.log('Initializing inquiry datepicker for V2 modal'); 223 // console.log('Datepicker input element:', $datepickerInput[0]); 224 // console.log('Datepicker input length:', $datepickerInput.length); 225 226 // Check if HotelDatepicker exists 227 if (typeof HotelDatepicker !== 'function') { 228 console.error('HotelDatepicker not found! Make sure datepicker.js is loaded.'); 229 return; 230 } 231 232 // Destroy existing instance if it exists 233 if (inquiryDatepicker) { 234 try { 235 inquiryDatepicker.destroy(); 236 } catch (e) { 237 console.warn('Error destroying existing datepicker:', e); 238 } 239 inquiryDatepicker = null; 240 } 241 242 // Process disabled dates from global variable - reusing from datepicker.js 243 var formattedDisabledDates = []; 244 if (typeof calendarDisabledDates !== 'undefined' && Array.isArray(calendarDisabledDates)) {
245 calendarDisabledDates.forEach(function(dateItem) { 246 if (typeof dateItem === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateItem)) { 247 formattedDisabledDates.push(dateItem); 248 } else if (dateItem instanceof Date) { 249 try { 250 formattedDisabledDates.push(fecha.format(dateItem, 'YYYY-MM-DD')); 251 } catch (e) { console.warn('Could not format Date object from calendarDisabledDates:', dateItem, e); } 252 } else if (typeof dateItem === 'object' && dateItem !== null && dateItem.start && dateItem.end && typeof dateItem.start === 'string' && typeof dateItem.end === 'string') { 253 try { 254 var rangeStartDate = fecha.parse(dateItem.start, 'YYYY-MM-DD'); 255 var rangeEndDate = fecha.parse(dateItem.end, 'YYYY-MM-DD'); 256 if (rangeStartDate && rangeEndDate && rangeStartDate <= rangeEndDate) { 257 var currentDate = new Date(rangeStartDate); 258 while (currentDate <= rangeEndDate) { 259 formattedDisabledDates.push(fecha.format(currentDate, 'YYYY-MM-DD')); 260 currentDate.setDate(currentDate.getDate() + 1); 261 } 262 } else { console.warn('Invalid date range object in calendarDisabledDates:', dateItem); } 263 } catch (e) { console.warn('Could not parse date range object from calendarDisabledDates:', dateItem, e); } 264 } else if (typeof dateItem === 'object' && dateItem !== null && typeof dateItem.format === 'function') { 265 try { 266 formattedDisabledDates.push(dateItem.format('YYYY-MM-DD')); 267 } catch (e) { console.warn('Could not format moment-like object from calendarDisabledDates:', dateItem, e); } 268 } else { console.warn('Ignoring invalid item in calendarDisabledDates:', dateItem); } 269 }); 270 } 271 272 // Get default minNights from global variable 273 var defaultMinNights = (typeof minNights !== 'undefined' && Number.isInteger(parseInt(minNights)) && parseInt(minNights) > 0) ? parseInt(minNights) : 1; 274 275 // Process disabled days of week from global variable (hfyArgs) 276 var disabledDaysOfWeek = (typeof hfyArgs !== 'undefined' && Array.isArray(hfyArgs.disabledWeekDays)) ? hfyArgs.disabledWeekDays : []; 277 278 // Process no check-in/check-out days of week from global variable (hfyArgs) 279 var noCheckInDaysOfWeek = (typeof hfyArgs !== 'undefined' && Array.isArray(hfyArgs.daysOfWeekDisabled)) ? hfyArgs.daysOfWeekDisabled : []; 280 var noCheckOutDaysOfWeek = (typeof hfyArgs !== 'undefined' && Array.isArray(hfyArgs.daysOfWeekDisabled)) ? hfyArgs.daysOfWeekDisabled : []; 281 282 // Process specific no check-in/check-out dates from global variables 283 var noCheckInDates = (typeof calendarOverInDays !== 'undefined' && Array.isArray(calendarOverInDays)) ? calendarOverInDays.filter(d => typeof d === 'string' && d !== '') : []; 284 var noCheckOutDates = (typeof calendarOverOutDays !== 'undefined' && Array.isArray(calendarOverOutDays)) ? calendarOverOutDays.filter(d => typeof d === 'string' && d !== '') : []; 285 286 // Get maxNights from global variable 287 var defaultMaxNights = (typeof maxNights !== 'undefined' && Number.isInteger(parseInt(maxNights)) && parseInt(maxNights) >= 0) ? parseInt(maxNights) : 0; 288 289 // Basic mobile check 290 var isMob = window.innerWidth <= 768; 291 292 // Define options for the datepicker 293 var options = { 294 showTopbar: false,
295 clearButton: false, 296 format: 'YYYY-MM-DD', 297 startOfWeek: 'monday', 298 minNights: defaultMinNights, 299 maxNights: defaultMaxNights, 300 selectForward: true, 301 autoClose: true, 302 moveBothMonths: true, 303 disabledDates: formattedDisabledDates, 304 enableCheckout: true, 305 disabledDaysOfWeek: disabledDaysOfWeek, 306 noCheckInDaysOfWeek: noCheckInDaysOfWeek, 307 noCheckOutDaysOfWeek: noCheckOutDaysOfWeek, 308 noCheckInDates: noCheckInDates, 309 noCheckOutDates: noCheckOutDates, 310 animationSpeed: '.3s', 311 calendarCustomStay: typeof calendarCustomStay !== 'undefined' ? calendarCustomStay : [], 312 313 // Mobile-specific options 314 mobileMonthsToShow: 6, 315 mobileMonthsToLoad: 24, 316 317 onDayClick: function(event, date) { 318 // This will handle the first date click 319 }, 320 onSelectRange: function() { 321 // This will handle when a range is selected 322 var dateValue = this.getValue(); // 'this' refers to the datepicker instance 323 if (!dateValue) return; 324 325 var dates = dateValue.split(' - '); 326 var startDateStr = dates[0]; 327 var endDateStr = dates.length > 1 ? dates[1] : null; 328 329 // Update hidden inputs for inquiry form 330 if (startDateStr) { 331 $startDateInput.val(startDateStr); 332 } 333 if (endDateStr) { 334 $endDateInput.val(endDateStr); 335 } 336 337 // Calculate and update nights input 338 updateNightsInput(startDateStr, endDateStr); 339 340 // Also update the main booking form fields to keep them in sync 341 var $mainStartDateInput = $('.hfy-listing-booking-form input[name="start_date"]'); 342 var $mainEndDateInput = $('.hfy-listing-booking-form input[name="end_date"]'); 343 var $mainDatepickerInput = $('.hfy-listing-booking-form #hotel-datepicker'); // Assuming main form also uses #hotel-datepicker 344 345 if ($mainStartDateInput.length) { 346 $mainStartDateInput.val(startDateStr); 347 } 348 if ($mainEndDateInput.length) { 349 $mainEndDateInput.val(endDateStr); 350 } 351 // Update the visible input in the main form as well 352 if ($mainDatepickerInput.length && startDateStr && endDateStr) { 353 $mainDatepickerInput.val(`${startDateStr} - ${endDateStr}`); 354 // Trigger change event if needed for other scripts listening on the main form 355 $mainDatepickerInput.trigger('change'); 356 } 357 358 // Update prices if the function exists 359 if (typeof window.doUpdatePriceBlock === 'function') { 360 window.doUpdatePriceBlock(); 361 } 362 }, 363 onOpenDatepicker: function() { 364 // Apply custom arrow logic for consecutive months every time the calendar opens 365 setTimeout(() => { 366 const datepickerElement = inquiryDatepicker.datepicker; 367 const nextButtons = datepickerElement.getElementsByClassName('datepicker__month-button--next'); 368 const prevButtons = datepickerElement.getElementsByClassName('datepicker__month-button--prev'); 369 370 // First, let the library apply its logic 371 if (inquiryDatepicker.disableNextPrevButtons) { 372 inquiryDatepicker.disableNextPrevButtons(); 373 } 374
375 // Then apply the custom logic for consecutive months 376 if (nextButtons.length >= 2 && prevButtons.length >= 2) { 377 // Hide left arrow of first month (except when we can go back) 378 const canGoBack = inquiryDatepicker.month1 && !inquiryDatepicker.isMonthOutOfRange(inquiryDatepicker.getPrevMonth(inquiryDatepicker.month1)); 379 if (!canGoBack) { 380 inquiryDatepicker.addClass(prevButtons[0], 'datepicker__month-button--disabled'); 381 prevButtons[0].setAttribute('aria-disabled', 'true'); 382 } 383 384 // Hide right arrow of first month (always, since we want both months to move together) 385 inquiryDatepicker.addClass(nextButtons[0], 'datepicker__month-button--disabled'); 386 nextButtons[0].setAttribute('aria-disabled', 'true'); 387 388 // Hide left arrow of second month (always, since we want both months to move together) 389 inquiryDatepicker.addClass(prevButtons[1], 'datepicker__month-button--disabled'); 390 prevButtons[1].setAttribute('aria-disabled', 'true'); 391 392 // Right arrow of second month - keep enabled if we can go forward 393 const canGoForward = inquiryDatepicker.month2 && !inquiryDatepicker.isMonthOutOfRange(inquiryDatepicker.getNextMonth(inquiryDatepicker.month2)); 394 if (canGoForward) { 395 inquiryDatepicker.removeClass(nextButtons[1], 'datepicker__month-button--disabled'); 396 nextButtons[1].setAttribute('aria-disabled', 'false'); 397 } 398 } 399 }, 50); 400 } 401 }; 402 403 // Initialize the datepicker on the modal's input 404 // console.log('Creating new HotelDatepicker instance for V2 modal'); 405 if (!$datepickerInput || !$datepickerInput.length || !$datepickerInput[0]) { 406 console.warn('Datepicker input not found. Skipping inquiry datepicker initialization.'); 407 return; 408 } 409 inquiryDatepicker = new HotelDatepicker($datepickerInput[0], options); 410 // console.log('HotelDatepicker instance created:', inquiryDatepicker); 411 412 // Add click and focus handlers to ensure datepicker opens 413 $datepickerInput.off('click.inquiryDatepicker focus.inquiryDatepicker').on('click.inquiryDatepicker focus.inquiryDatepicker', function(e) { 414 e.preventDefault(); 415 e.stopPropagation(); 416 // console.log('Inquiry datepicker input ' + e.type + 'ed, opening datepicker'); 417 // console.log('Datepicker instance available:', !!inquiryDatepicker); 418 if (inquiryDatepicker) { 419 // console.log('Attempting to open datepicker...'); 420 inquiryDatepicker.open(); 421 } else { 422 console.error('Datepicker instance is null!'); 423 } 424 }); 425 426 // console.log('Inquiry datepicker initialized successfully for V2 modal'); 427 } 428 429 // Initialize the old calendar (V2) for the inquiry form 430 function initInquiryOldCalendar() { 431 // console.log('Initializing old calendar (V2) for inquiry modal'); 432 433 // Check if calentim plugin is available 434 if (typeof $.fn.calentim !== 'function') { 435 console.error('Calentim plugin not found! Make sure calentim.js is loaded.'); 436 return; 437 } 438 439 // Check if moment.js is available 440 if (typeof moment !== 'function') { 441 console.error('Moment.js not found! Make sure moment.js is loaded.'); 442 return; 443 } 444 445 // Get the start and end date inputs by their calentim classes 446 const $startInput = $modal.find('input.calentim-start'); 447 const $endInput = $modal.find('input.calentim-end'); 448 449 // console.log('Found old calendar inputs:', { 450 // startInput: $startInput.length, 451 // endInput: $endInput.length, 452 // startInputElement: $startInput[0], 453 // endInputElement: $endInput[0] 454 // }); 455 456 if (!$startInput.length || !$endInput.length) { 457 console.error('Old calendar inputs not found in inquiry modal'); 458 return; 459 } 460 461 // Check if inputs have the correct classes 462 // console.log('Input classes:', { 463 // startClasses: $startInput.attr('class'), 464 // endClasses: $endInput.attr('class') 465 // }); 466 467 // Basic mobile check 468 const isMob = window.innerWidth <= 768; 469 const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); 470 471 // Get disabled dates from global variables 472 const calDisDates = (typeof calendarDisabledDates !== 'undefined' && Array.isArray(calendarDisabledDates)) ? calendarDisabledDates : []; 473 const minNightsValue = (typeof minNights !== 'undefined' && Number.isInteger(parseInt(minNights)) && parseInt(minNights) > 0) ? parseInt(minNights) : 1; 474 475 // Check global variables 476 // console.log('Global variables check:', { 477 // hfyStartOfWeek: typeof hfyStartOfWeek !== 'undefined' ? hfyStartOfWeek : 'undefined', 478 // hfySelectedLang: typeof hfySelectedLang !== 'undefined' ? hfySelectedLang : 'undefined', 479 // hfyDF: typeof hfyDF !== 'undefined' ? hfyDF : 'undefined', 480 // calDisDates: calDisDates.length, 481 // isMob: isMob, 482 // isIOS: isIOS 483 // }); 484 485 // Initialize start date calendar 486 // console.log('Initializing start date calendar with calentim...'); 487 $startInput.calentim({ 488 startOnMonday: typeof hfyStartOfWeek !== 'undefined' ? hfyStartOfWeek === 1 : false, 489 locale: typeof hfySelectedLang !== 'undefined' ? hfySelectedLang : 'en', 490 enableMonthSwitcher: false, 491 enableYearSwitcher: false, 492 showHeader: false, 493 showFooter: false, 494 showTimePickers: false, 495 calendarCount: isMob ? 24 : 2, 496 isMobile: isMob, 497 isIOS: isIOS, 498 format: typeof hfyDF !== 'undefined' ? hfyDF : 'L', 499 showOn: 'bottom', 500 arrowOn: 'center', 501 autoAlign: true, 502 oneCalendarWidth: 280, 503 continuous: true, 504 minDate: moment().startOf('day'), 505 disabledRanges: calDisDates, 506 autoCloseOnSelect: true, // Always auto-close on select 507 onaftershow: function(instance) { 508 // console.log('Inquiry start calendar shown'); 509 }, 510 onafterhide: function() { 511 // console.log('Inquiry start calendar hidden'); 512 }, 513 oninit: function(instance) { 514 // console.log('Inquiry start calendar initialized successfully'); 515 // console.log('Start calendar instance:', instance); 516 // Store reference for later use 517 window.inquiryCalentimStart = instance; 518 }, 519 onfirstselect: function(instance, start) { 520 // console.log('Inquiry start date selected:', start.format('YYYY-MM-DD'));
521 // Update hidden inputs 522 $startDateInput.val(start.format('YYYY-MM-DD')); 523 524 // Update main booking form start date 525 const $mainStartDateInput = $('.hfy-listing-booking-form input[name="start_date"]'); 526 if ($mainStartDateInput.length) { 527 $mainStartDateInput.val(start.format('YYYY-MM-DD')); 528 } 529 530 // Close this calendar 531 instance.hideDropdown(); 532 // Show end date calendar after a short delay 533 setTimeout(function() { 534 if (window.inquiryCalentimEnd) { 535 window.inquiryCalentimEnd.showDropdown(); 536 } 537 }, 100); 538 } 539 }); 540 541 // Initialize end date calendar 542 // console.log('Initializing end date calendar with calentim...'); 543 $endInput.calentim({ 544 startOnMonday: typeof hfyStartOfWeek !== 'undefined' ? hfyStartOfWeek === 1 : false, 545 locale: typeof hfySelectedLang !== 'undefined' ? hfySelectedLang : 'en', 546 enableMonthSwitcher: false, 547 enableYearSwitcher: false, 548 showHeader: false, 549 showFooter: false, 550 showTimePickers: false, 551 calendarCount: isMob ? 24 : 2, 552 isMobile: isMob, 553 isIOS: isIOS, 554 format: typeof hfyDF !== 'undefined' ? hfyDF : 'L', 555 showOn: 'bottom', 556 arrowOn: 'center', 557 autoAlign: true, 558 oneCalendarWidth: 280, 559 continuous: true, 560 minDate: moment().startOf('day'), 561 disabledRanges: calDisDates, 562 autoCloseOnSelect: true, // Always auto-close on select 563 onaftershow: function(instance) { 564 // console.log('Inquiry end calendar shown'); 565 }, 566 onafterhide: function() { 567 // console.log('Inquiry end calendar hidden'); 568 }, 569 oninit: function(instance) { 570 // console.log('Inquiry end calendar initialized successfully'); 571 // console.log('End calendar instance:', instance); 572 // Store reference for later use 573 window.inquiryCalentimEnd = instance; 574 }, 575 onfirstselect: function(instance, end) { 576 // console.log('Inquiry end date selected:', end.format('YYYY-MM-DD')); 577 // Update hidden inputs 578 $endDateInput.val(end.format('YYYY-MM-DD')); 579 580 // Close this calendar 581 instance.hideDropdown(); 582 583 // Calculate and update nights 584 const startDate = $startDateInput.val(); 585 if (startDate) { 586 updateNightsInput(startDate, end.format('YYYY-MM-DD')); 587 } 588 589 // Update main booking form 590 const $mainStartDateInput = $('.hfy-listing-booking-form input[name="start_date"]'); 591 const $mainEndDateInput = $('.hfy-listing-booking-form input[name="end_date"]'); 592 593 // For old calendar (V2), update the visible calentim inputs 594 const $mainCalentimStart = $('.hfy-listing-booking-form input.calentim-start'); 595 const $mainCalentimEnd = $('.hfy-listing-booking-form input.calentim-end'); 596 const $mainCalentimDates = $('.hfy-listing-booking-form input.calentim-dates'); 597 598 // For new calendar (V3), update the datepicker input 599 let $mainDatepickerInput = $('#hotel-datepicker'); // Try global selector first 600 if (!$mainDatepickerInput.length) { 601 $mainDatepickerInput = $('.hfy-listing-booking-form #hotel-datepicker'); 602 } 603 604 // console.log('Main booking form elements found:', { 605 // mainStartDateInput: $mainStartDateInput.length, 606 // mainEndDateInput: $mainEndDateInput.length, 607 // mainCalentimStart: $mainCalentimStart.length, 608 // mainCalentimEnd: $mainCalentimEnd.length, 609 // mainCalentimDates: $mainCalentimDates.length, 610 // mainDatepickerInput: $mainDatepickerInput.length, 611 // startDate: startDate, 612 // endDate: end.format('YYYY-MM-DD') 613 // }); 614 615 // Only update main form inputs if we're actually in the inquiry modal context 616 if ($mainStartDateInput.length && $('.direct-inquiry-modal').is(':visible')) { 617 $mainStartDateInput.val(startDate); 618 // console.log('Updated main start date input:', startDate); 619 } else if (!$('.direct-inquiry-modal').is(':visible')) { 620 // console.log('Skipping main form update - inquiry modal not visible'); 621 } else { 622 console.warn('Main start date input not found'); 623 } 624 625 if ($mainEndDateInput.length && $('.direct-inquiry-modal').is(':visible')) { 626 $mainEndDateInput.val(end.format('YYYY-MM-DD')); 627 // console.log('Updated main end date input:', end.format('YYYY-MM-DD')); 628 } else if (!$('.direct-inquiry-modal').is(':visible')) { 629 // console.log('Skipping main form update - inquiry modal not visible'); 630 } else { 631 console.warn('Main end date input not found'); 632 } 633 634 // Update the visible calentim inputs in main form (for old calendar) 635 // Only update if we're actually in the inquiry modal context 636 if ($mainCalentimStart.length && startDate && $('.direct-inquiry-modal').is(':visible')) { 637 $mainCalentimStart.val(startDate); 638 // console.log('Updated main calentim start input:', startDate); 639 } 640 641 if ($mainCalentimEnd.length && end.format('YYYY-MM-DD') && $('.direct-inquiry-modal').is(':visible')) { 642 $mainCalentimEnd.val(end.format('YYYY-MM-DD')); 643 // console.log('Updated main calentim end input:', end.format('YYYY-MM-DD')); 644 } 645 646 // Update the combined calentim-dates input 647 // Only update if we're actually in the inquiry modal context 648 // console.log('Inquiry form checking main calentim dates:', { 649 // hasMainCalentimDates: $mainCalentimDates.length > 0, 650 // hasStartDate: !!startDate, 651 // hasEndDate: !!end.format('YYYY-MM-DD'), 652 // modalVisible: $('.direct-inquiry-modal').is(':visible'), 653 // currentValue: $mainCalentimDates.val() 654 // }); 655 656 if ($mainCalentimDates.length && startDate && end.format('YYYY-MM-DD') && $('.direct-inquiry-modal').is(':visible')) { 657 const displayFormat = typeof hfyDF !== 'undefined' ? hfyDF : 'YYYY-MM-DD'; 658 const startMoment = moment(startDate, 'YYYY-MM-DD'); 659 const dateRange = `${startMoment.format(displayFormat)} - ${end.format(displayFormat)}`; 660 $mainCalentimDates.val(dateRange); 661 // console.log('Updated main calentim-dates input:', dateRange); 662 } 663 664 // Update the visible datepicker input in main form (for new calendar) 665 // Only update if we're actually in the inquiry modal context 666 if ($mainDatepickerInput.length && startDate && end.format('YYYY-MM-DD') && $('.direct-inquiry-modal').is(':visible')) { 667 const dateRange = `${startDate} - ${end.format('YYYY-MM-DD')}`; 668 $mainDatepickerInput.val(dateRange); 669 $mainDatepickerInput.trigger('change'); 670 // console.log('Updated main datepicker input:', dateRange); 671 } 672 673 // Update URL and prices by calling available functions 674 // console.log('Checking for submitForm function:', typeof submitForm); 675 // console.log('Checking for doUpdatePriceBlock function:', typeof window.doUpdatePriceBlock); 676 677 // Try to update URL manually first 678 try { 679 const startDateVal = $startDateInput.val(); 680 const endDateVal = end.format('YYYY-MM-DD'); 681 682 if (startDateVal && endDateVal) { 683 const href = new URL(window.location.href); 684 href.searchParams.set('start_date', startDateVal); 685 href.searchParams.set('end_date', endDateVal); 686 window.history.replaceState('', '', href.toString()); 687 // console.log('Updated URL manually:', href.toString()); 688 689 // Force browser to show the updated URL 690 setTimeout(function() { 691 window.history.replaceState('', '', href.toString()); 692 }, 100); 693 } 694 } catch (e) { 695 console.warn('Could not update URL manually:', e); 696 } 697 698 // Try to call available functions 699 if (typeof submitForm === 'function') {
700 // console.log('Calling submitForm()'); 701 submitForm(); 702 } else if (typeof window.doUpdatePriceBlock === 'function') { 703 // console.log('Calling doUpdatePriceBlock()'); 704 window.doUpdatePriceBlock(); 705 } else { 706 console.warn('No form submission method available'); 707 } 708 } 709 }); 710 711 // console.log('Old calendar (V2) initialized successfully for inquiry modal'); 712 } 713 714 // Reset Dates functionality 715 $resetDateLink.on('click', function(e) { 716 e.preventDefault(); 717 718 if (isV3Calendar) { 719 $datepickerInput.val(''); 720 if (inquiryDatepicker) { 721 inquiryDatepicker.clear(); 722 } 723 } else { 724 // For V2 calendar, clear the visible inputs and reset calentim instances 725 $modal.find('input[name="start_date"]').val(''); 726 $modal.find('input[name="end_date"]').val(''); 727 728 // Reset calentim instances if they exist 729 if (window.inquiryCalentimStart) { 730 window.inquiryCalentimStart.config.startDate = null; 731 window.inquiryCalentimStart.$elem.val(''); 732 } 733 if (window.inquiryCalentimEnd) { 734 window.inquiryCalentimEnd.config.endDate = null; 735 window.inquiryCalentimEnd.$elem.val(''); 736 } 737 } 738 739 $startDateInput.val(''); 740 $endDateInput.val(''); 741 updateNightsInput(null, null); // Clear nights input 742 743 // Optionally clear main form dates as well 744 var $mainStartDateInput = $('.hfy-listing-booking-form input[name="start_date"]'); 745 var $mainEndDateInput = $('.hfy-listing-booking-form input[name="end_date"]'); 746 var $mainDatepickerInput = $('.hfy-listing-booking-form #hotel-datepicker'); 747 $mainStartDateInput.val(''); 748 $mainEndDateInput.val(''); 749 if ($mainDatepickerInput.length) { 750 $mainDatepickerInput.val(''); 751 } 752 if (typeof window.doUpdatePriceBlock === 'function') { 753 window.doUpdatePriceBlock(); // Update price block after clearing dates 754 } 755 }); 756 757 // Function to calculate and update nights (Corrected) 758 function updateNightsInput(startDateStr, endDateStr) { 759 const $nightsInput = $('#hfy-inquiry-nights-v2'); 760 if (!$nightsInput.length) { 761 // console.log('Nights input (#hfy-inquiry-nights-v2) not found.'); 762 return; 763 } 764 765 // console.log('Attempting to update nights input. Start:', startDateStr, 'End:', endDateStr); 766 767 if (startDateStr && endDateStr && typeof moment === 'function') { // Ensure moment.js is available 768 try { 769 const startDate = moment(startDateStr, 'YYYY-MM-DD'); 770 const endDate = moment(endDateStr, 'YYYY-MM-DD'); 771 772 // Check if dates are valid moment objects and end date is strictly after start date 773 if (startDate.isValid() && endDate.isValid() && endDate.isAfter(startDate)) { 774 const nights = endDate.diff(startDate, 'days'); // Use moment's diff function 775 // console.log('Calculated nights:', nights); 776 $nightsInput.val(nights > 0 ? nights : 1); // Ensure nights is at least 1 777 } else { 778 if (!startDate.isValid()) console.warn('Start date is invalid:', startDateStr); 779 if (!endDate.isValid()) console.warn('End date is invalid:', endDateStr); 780 if (startDate.isValid() && endDate.isValid() && !endDate.isAfter(startDate)) console.warn('End date is not after start date.'); 781 // console.log('Invalid date range. Defaulting nights to 1.'); 782 $nightsInput.val(1); // Default to 1 if dates are invalid or same day 783 } 784 } catch (e) { 785 console.error('Error calculating nights with moment.js:', e); 786 $nightsInput.val(1); // Default on error 787 } 788 } else { 789 if (typeof moment !== 'function') { 790 console.warn('moment.js is not available for night calculation.'); 791 } 792 if (!startDateStr || !endDateStr) { 793 // console.log('Start or end date string is missing. Defaulting nights to 1.'); 794 } 795 $nightsInput.val(1); // Default to 1 if dates are cleared or moment is missing 796 } 797 } 798 799 // Guest counter functionality 800$guestButtons.on('click', function(e) { 801 e.preventDefault(); 802 803 const $btn = $(this); 804 const type = $btn.data('type'); // "adults" or "children" 805 const isPlus = $btn.hasClass('hfy-guest-btn-plus'); 806 const max = parseInt($maxGuests.val(), 10); 807 808 // Read current totals BEFORE we change anything: 809 const adults = parseInt($modal.find('.hfy-guest-count[data-type="adults"]').text(), 10); 810 const children = parseInt($modal.find('.hfy-guest-count[data-type="children"]').text(), 10); 811 const total = adults + children; 812 813 // **1) Prevent overshoot: bail out if weâre already at or above the max** 814 if (isPlus && total >= max) { 815 return; 816 } 817 818 // 2) Grab the single counter you actually want to inc/dec: 819 const $count = $modal.find(`.hfy-guest-count[data-type="${type}"]`); 820 const $input = $modal.find(`#hfy-inquiry-${type}-v2`);
821 let cnt = parseInt($count.text(), 10); 822 823 // 3) Increment or decrement (never let adults drop below 1, kids below 0): 824 if (isPlus) { 825 cnt++; 826 } else if (cnt > (type === 'adults' ? 1 : 0)) { 827 cnt--; 828 } 829 830 // 4) Write it back: 831 $count.text(cnt); 832 $input.val(cnt); 833 834 // 5) Disable the âââ if youâre already at the minimum: 835 $modal 836 .find(`.hfy-guest-btn-minus[data-type="${type}"]`) 837 .prop('disabled', (type === 'adults' && cnt === 1) || (type !== 'adults' && cnt === 0)); 838 839 // 6) Refresh summary & plus/minus state: 840 updateGuestSummary(); 841}); 842 843 // Summary + disabling of the â+â buttons 844function updateGuestSummary() { 845 const adults = parseInt($modal.find('.hfy-guest-count[data-type="adults"]').text(), 10); 846 const children = parseInt($modal.find('.hfy-guest-count[data-type="children"]').text(), 10); 847 const maxGuestsVal = parseInt($maxGuests.val(), 10); 848 const totalGuests = adults + children; 849 850 // Update the display 851 $guestSummary.text(`${totalGuests}/${maxGuestsVal} guests`); 852 853 if (totalGuests >= maxGuestsVal) { 854 // at max or over: show warning & disable all â+â 855 $guestWarning.show(); 856 $modal 857 .find('.hfy-guest-btn-plus[data-type="adults"], .hfy-guest-btn-plus[data-type="children"]') 858 .prop('disabled', true); 859 } else { 860 // under max: hide warning & re-enable relevant â+â 861 $guestWarning.hide(); 862 // Always enable adults '+' if under max 863 $modal.find('.hfy-guest-btn-plus[data-type="adults"]').prop('disabled', false); 864 865 // Only enable children '+' if under max AND children are allowed 866 const childrenAllowed = $modal.find('.space-y-3.border.rounded-md').data('children-allowed') === true; 867 if (childrenAllowed) { 868 $modal.find('.hfy-guest-btn-plus[data-type="children"]').prop('disabled', false); 869 } else { 870 $modal.find('.hfy-guest-btn-plus[data-type="children"]').prop('disabled', true); // Ensure it stays disabled 871 } 872 } 873} 874 875 // Form submission 876 $form.on('submit', function(e) { 877 e.preventDefault(); 878 879 // Show loading state 880 const $submitButton = $form.find('button[type="submit"]'); 881 $submitButton.prop('disabled', true).addClass('loading'); 882 883 // Check reCAPTCHA if it exists 884 const recaptchaVersion = window.hfyRecaptchaVersion || 'v2'; 885 886 if (recaptchaVersion === 'v2' && typeof grecaptcha !== 'undefined' && $('#g-recaptcha-error-v2').length && $('#g-recaptcha-error-v2').is(':visible')) { 887 const recaptchaResponse = grecaptcha.getResponse(); 888 if (recaptchaResponse.length === 0) { 889 $('#g-recaptcha-error-v2').html('<span style="color:red; display: block; margin-top: 10px;">Please verify you are not a robot.</span>'); 890 $submitButton.prop('disabled', false).removeClass('loading'); 891 return false; 892 } else { 893 $('#g-recaptcha-error-v2').html(''); 894 } 895 } else if (recaptchaVersion === 'v3' && typeof grecaptcha !== 'undefined') { 896 // For v3, we need to execute and get token 897 try { 898 grecaptcha.execute(window.hfyRecaptchaSiteKey, {action: 'inquiry_submit'}).then(function(token) { 899 if (!token) { 900 $('#g-recaptcha-error-v2').html('<span style="color:red; display: block; margin-top: 10px;">reCAPTCHA verification failed.</span>'); 901 $submitButton.prop('disabled', false).removeClass('loading'); 902 return false; 903 } 904 // Store token for AJAX request 905 window.hfyRecaptchaV3Token = token; 906 }).catch(function(error) { 907 console.error('reCAPTCHA v3 error:', error); 908 $('#g-recaptcha-error-v2').html('<span style="color:red; display: block; margin-top: 10px;">reCAPTCHA verification failed.</span>'); 909 $submitButton.prop('disabled', false).removeClass('loading'); 910 return false;
911 }); 912 } catch (error) { 913 console.error('reCAPTCHA v3 error:', error); 914 $('#g-recaptcha-error-v2').html('<span style="color:red; display: block; margin-top: 10px;">reCAPTCHA verification failed.</span>'); 915 $submitButton.prop('disabled', false).removeClass('loading'); 916 return false; 917 } 918 } 919 920 // Get form data 921 const formData = new FormData(this); 922 const formObject = {}; 923 924 // Map the form field names to what the AJAX processor expects 925 // Map form field names if necessary (adjust based on hfy_ajax_inquiry expectations) 926 // NOTE: Since we added start_date and end_date inputs directly, mapping might not be needed for them. 927 // Verify what 'hfy_ajax_inquiry' expects. Based on old form, it expects check_in/check_out. 928 const fieldMap = { 929 'firstName': 'first_name', 930 'lastName': 'last_name', 931 'start_date': 'check_in', // Map start_date to check_in 932 'end_date': 'check_out', // Map end_date to check_out 933 'comment': 'message', 934 'discountCode': 'discount_code' 935 // listingId, listingName, listingNickname, nights should be picked up directly by FormData 936 // Ensure 'action' and 'hfy_nonce' are included by FormData 937 }; 938 939 formData.forEach(function(value, key) { 940 const mappedKey = fieldMap[key] || key; 941 formObject[mappedKey] = value; 942 }); 943 944 // Ensure essential fields like listing_id are present 945 if (!formObject.listing_id) { 946 formObject.listing_id = $modal.find('input[name="listing_id"]').val(); 947 } 948 949 // Add listing name and nickname if not present (adjust selector if needed) 950 if (!formObject.listingName) { 951 formObject.listingName = $('.hfy-modal-title').text() || ''; 952 } 953 if (!formObject.listingNickname) { 954 formObject.listingNickname = $('.hfy-modal-title').text() || ''; 955 } 956 957 // Log the data being sent 958 // console.log('Submitting inquiry with data object:', formObject); 959 // console.log('Submitting inquiry with serialized data:', $.param(formObject)); 960 961 // Handle submission 962 $.ajax({ 963 url: hfyx.url, // Assuming hfyx.url is defined globally 964 type: 'POST', 965 data: { 966 action: 'inquiry', // Matches the old action 967 data: $.param(formObject), // Wrap the mapped data object, matching old structure 968 'g-recaptcha-response': (function() { 969 const recaptchaVersion = window.hfyRecaptchaVersion || 'v2'; 970 if (recaptchaVersion === 'v2' && typeof grecaptcha !== 'undefined' && $('#g-recaptcha-error-v2').is(':visible')) { 971 return grecaptcha.getResponse(); 972 } else if (recaptchaVersion === 'v3' && window.hfyRecaptchaV3Token) { 973 return window.hfyRecaptchaV3Token; 974 } 975 return ''; 976 })() 977 }, 978 dataType: 'json', // Expect JSON response from the server 979 success: function(response) { 980 // console.log('Inquiry AJAX Success Response:', response); // Log the full success response 981 $submitButton.prop('disabled', false).removeClass('loading'); 982 983 // Check the response structure carefully 984 if (response && response.success === true) { // Explicitly check for true 985 // console.log('Server indicated success. Applying success state.'); 986 // Add success class, hide form & header, show thank you message 987 $modal.addClass('hfy-inquiry-success'); // Add class to main modal 988 $form.hide(); 989 $modal.find('.hfy-modal-header').hide(); // Hide the header 990 $modal.find('.thx').show(); // Show the thank you container 991 $responseArea.hide().text('').removeClass('error success'); // Clear any previous messages 992 } else { 993 // Handle cases where success might be false, missing, or response is unexpected 994 $modal.removeClass('hfy-inquiry-success'); // Ensure success class is removed on failure 995 $modal.find('.hfy-modal-header').show(); // Ensure header is visible on failure 996 const errorMsg = (response && response.msg) ? response.msg : 'Inquiry submission failed. Please check your details and try again.'; 997 console.error('Inquiry failed (Server Response):', errorMsg, 'Full Response:', response); 998 $responseArea.text(errorMsg).removeClass('success').addClass('error').show(); 999 } 1000 }, 1001 error: function(xhr, status, error) { 1002 // Log detailed error information 1003 console.error('Inquiry AJAX Error:', { 1004 status: status, 1005 error: error, 1006 responseText: xhr.responseText, // Log server's raw response if available 1007 xhr: xhr 1008 }); 1009 $submitButton.prop('disabled', false).removeClass('loading'); 1010 $responseArea.text('A connection error occurred. Please check your internet connection and try again.').removeClass('success').addClass('error').show(); 1011 } 1012 }); 1013 }); 1014 1015 // Removed outside click handler for old container 1016 // Removed custom event listener 'direct-inquiry-modal-opened' 1017 } 1018 1019 // Initialize the modal when document is ready 1020 initInquiryModalV2(); 1021}); 1022 1023// --- Support for old inquiry form with new calendar (HotelDatepicker) --- 1024document.addEventListener('DOMContentLoaded', function() { 1025 // console.log('[Old Inquiry] Checking for old inquiry form elements...'); 1026 1027 // Check if new inquiry form is enabled - if so, skip old inquiry initialization 1028 if (typeof window.HFY_USE_NEW_INQUIRY_FORM !== 'undefined' && window.HFY_USE_NEW_INQUIRY_FORM) { 1029 // console.log('[Old Inquiry] New inquiry form is enabled, skipping old inquiry initialization'); 1030 return; 1031 } 1032 1033 // Check if V3 calendar is enabled - if not, skip new datepicker initialization for old form 1034 if (typeof window.HFY_USE_V3_CALENDAR === 'undefined' || !window.HFY_USE_V3_CALENDAR) { 1035 // console.log('[Old Inquiry] V3 calendar is disabled, skipping new datepicker initialization for old form'); 1036 return; 1037 } 1038 1039 // console.log('[Old Inquiry] V3 calendar is enabled, initializing new datepicker for old inquiry form'); 1040 1041 // Check if elements exist on page load 1042 var inquiryCheckinOnLoad = document.getElementById('inquiry_checkin'); 1043 var inquiryCheckoutOnLoad = document.getElementById('inquiry_checkout'); 1044 // console.log('[Old Inquiry] Elements on page load:', { 1045 // inquiryCheckin: !!inquiryCheckinOnLoad, 1046 // inquiryCheckout: !!inquiryCheckoutOnLoad, 1047 // inquiryCheckinParent: inquiryCheckinOnLoad ? inquiryCheckinOnLoad.parentNode : null, 1048 // inquiryCheckoutParent: inquiryCheckoutOnLoad ? inquiryCheckoutOnLoad.parentNode : null 1049 // }); 1050 1051 // Function to initialize old inquiry form datepicker 1052 function initOldInquiryDatepicker() { 1053 if (typeof HotelDatepicker !== 'function') { 1054 // console.log('[Old Inquiry] HotelDatepicker not available'); 1055 return; 1056 } 1057 1058 // Check for both possible structures 1059 var inquiryCheckin = document.getElementById('inquiry_checkin'); 1060 var inquiryCheckout = document.getElementById('inquiry_checkout'); 1061 var inquiryDatepicker = document.getElementById('inquiry-hotel-datepicker'); 1062 1063 // console.log('[Old Inquiry] Checking for elements:', { 1064 // inquiryCheckin: !!inquiryCheckin, 1065 // inquiryCheckout: !!inquiryCheckout, 1066 // inquiryDatepicker: !!inquiryDatepicker 1067 // }); 1068 1069 // Determine which structure is being used 1070 var isV3Calendar = !!inquiryDatepicker;
1071 var isOldStructure = !!(inquiryCheckin && inquiryCheckout); 1072 1073 // console.log('[Old Inquiry] Structure detected:', { 1074 // isV3Calendar: isV3Calendar, 1075 // isOldStructure: isOldStructure 1076 // }); 1077 1078 if (!isV3Calendar && !isOldStructure) { 1079 // console.log('[Old Inquiry] No date inputs found'); 1080 return; 1081 } 1082 1083 // console.log('[Old Inquiry] Found old inquiry form elements, initializing...'); 1084 1085 if (isV3Calendar) { 1086 // V3 Calendar structure - single input 1087 // console.log('[Old Inquiry] Using V3 Calendar structure'); 1088 1089 // Check if datepicker is already initialized 1090 if (inquiryDatepicker._hotelDatepicker) { 1091 // console.log('[Old Inquiry] Datepicker already initialized on V3 input'); 1092 return; 1093 } 1094 1095 // Define options for V3 structure 1096 var inquiryOptions = { 1097 showTopbar: false,
1098 clearButton: false, 1099 format: 'YYYY-MM-DD', 1100 startOfWeek: 'monday', 1101 minNights: (typeof minNights !== 'undefined' && Number.isInteger(parseInt(minNights)) && parseInt(minNights) > 0) ? parseInt(minNights) : 1, 1102 maxNights: (typeof maxNights !== 'undefined' && Number.isInteger(parseInt(maxNights)) && parseInt(maxNights) >= 0) ? parseInt(maxNights) : 0, 1103 selectForward: true, 1104 autoClose: true, 1105 moveBothMonths: true, 1106 disabledDates: (typeof formattedDisabledDates !== 'undefined') ? formattedDisabledDates : [], 1107 enableCheckout: true, 1108 disabledDaysOfWeek: (typeof disabledDaysOfWeek !== 'undefined') ? disabledDaysOfWeek : [], 1109 noCheckInDaysOfWeek: (typeof noCheckInDaysOfWeek !== 'undefined') ? noCheckInDaysOfWeek : [], 1110 noCheckOutDaysOfWeek: (typeof noCheckOutDaysOfWeek !== 'undefined') ? noCheckOutDaysOfWeek : [], 1111 noCheckInDates: (typeof noCheckInDates !== 'undefined') ? noCheckInDates : [], 1112 noCheckOutDates: (typeof noCheckOutDates !== 'undefined') ? noCheckOutDates : [], 1113 animationSpeed: '.3s', 1114 calendarCustomStay: (typeof calendarCustomStay !== 'undefined') ? calendarCustomStay : [], 1115 onSelectRange: function() { 1116 // console.log('[Old Inquiry V3] onSelectRange called!'); 1117 var dateValue = inquiryDatepicker.value; 1118 // console.log('[Old Inquiry V3] Date value:', dateValue); 1119 if (!dateValue) return; 1120 1121 var dates = dateValue.split(' - '); 1122 var start = dates[0] || ''; 1123 var end = dates[1] || ''; 1124 1125 // Update hidden inputs 1126 var $checkInInput = jQuery('input[name="check_in"]'); 1127 var $checkOutInput = jQuery('input[name="check_out"]'); 1128 if ($checkInInput.length) $checkInInput.val(start); 1129 if ($checkOutInput.length) $checkOutInput.val(end); 1130 1131 // Update main booking form 1132 var $mainStartDateInput = jQuery('.hfy-listing-booking-form input[name="start_date"]'); 1133 var $mainEndDateInput = jQuery('.hfy-listing-booking-form input[name="end_date"]'); 1134 var $mainDatepickerInput = jQuery('#hotel-datepicker'); 1135 1136 if ($mainStartDateInput.length) $mainStartDateInput.val(start); 1137 if ($mainEndDateInput.length) $mainEndDateInput.val(end); 1138 if ($mainDatepickerInput.length && start && end) { 1139 $mainDatepickerInput.val(`${start} - ${end}`); 1140 $mainDatepickerInput.trigger('change'); 1141 } 1142 1143 if (typeof window.doUpdatePriceBlock === 'function') { 1144 window.doUpdatePriceBlock(); 1145 } 1146 1147 // console.log('[Old Inquiry V3] Updated main booking form and called doUpdatePriceBlock'); 1148 } 1149 }; 1150 1151 // Initialize on the V3 input directly 1152 var oldInquiryDatepicker = new HotelDatepicker(inquiryDatepicker, inquiryOptions); 1153 inquiryDatepicker._hotelDatepicker = oldInquiryDatepicker; 1154 window.oldInquiryDatepicker = oldInquiryDatepicker; 1155 1156 // console.log('[Old Inquiry V3] Datepicker initialized on inquiry-hotel-datepicker'); 1157 1158 } else { 1159 // Old structure - two separate inputs 1160 // console.log('[Old Inquiry] Using old structure with two inputs'); 1161 1162 // Create a hidden input for the range picker if not already present 1163 let rangeInput = document.getElementById('inquiry-hotel-datepicker-old'); 1164 if (!rangeInput) { 1165 rangeInput = document.createElement('input'); 1166 rangeInput.type = 'text'; 1167 rangeInput.id = 'inquiry-hotel-datepicker-old'; 1168 rangeInput.style.display = 'none'; 1169 inquiryCheckin.parentNode.appendChild(rangeInput); 1170 // console.log('[Old Inquiry] Created hidden range input'); 1171 } 1172 1173 // Check if datepicker is already initialized 1174 if (rangeInput._hotelDatepicker) { 1175 // console.log('[Old Inquiry] Datepicker already initialized'); 1176 return; 1177 } 1178 1179 // Define options for old structure 1180 var inquiryOptions = { 1181 showTopbar: false,
1182 clearButton: false, 1183 format: 'YYYY-MM-DD', 1184 startOfWeek: 'monday', 1185 minNights: (typeof minNights !== 'undefined' && Number.isInteger(parseInt(minNights)) && parseInt(minNights) > 0) ? parseInt(minNights) : 1, 1186 maxNights: (typeof maxNights !== 'undefined' && Number.isInteger(parseInt(maxNights)) && parseInt(maxNights) >= 0) ? parseInt(maxNights) : 0, 1187 selectForward: true, 1188 autoClose: true, 1189 moveBothMonths: true, 1190 disabledDates: (typeof formattedDisabledDates !== 'undefined') ? formattedDisabledDates : [], 1191 enableCheckout: true, 1192 disabledDaysOfWeek: (typeof disabledDaysOfWeek !== 'undefined') ? disabledDaysOfWeek : [], 1193 noCheckInDaysOfWeek: (typeof noCheckInDaysOfWeek !== 'undefined') ? noCheckInDaysOfWeek : [], 1194 noCheckOutDaysOfWeek: (typeof noCheckOutDaysOfWeek !== 'undefined') ? noCheckOutDaysOfWeek : [], 1195 noCheckInDates: (typeof noCheckInDates !== 'undefined') ? noCheckInDates : [], 1196 noCheckOutDates: (typeof noCheckOutDates !== 'undefined') ? noCheckOutDates : [], 1197 animationSpeed: '.3s', 1198 calendarCustomStay: (typeof calendarCustomStay !== 'undefined') ? calendarCustomStay : [], 1199 onSelectRange: function() { 1200 // console.log('[Old Inquiry] onSelectRange called!'); 1201 // When a range is selected, update the visible check_in and check_out fields 1202 var dateValue = rangeInput.value; 1203 // console.log('[Old Inquiry] Date value from range input:', dateValue); 1204 if (!dateValue) { 1205 // console.log('[Old Inquiry] No date value, returning'); 1206 return; 1207 } 1208 var dates = dateValue.split(' - '); 1209 var start = dates[0] || ''; 1210 var end = dates[1] || ''; 1211 if (inquiryCheckin) inquiryCheckin.value = start; 1212 if (inquiryCheckout) inquiryCheckout.value = end; 1213 // console.log('[Old Inquiry] Picked:', start, end); 1214 1215 // --- Use the same proven logic from new form --- 1216 // Update hidden inputs for inquiry form (if they exist) 1217 var $startDateInput = jQuery('input[name="start_date"]'); 1218 var $endDateInput = jQuery('input[name="end_date"]'); 1219 if (start) { 1220 $startDateInput.val(start); 1221 } 1222 if (end) { 1223 $endDateInput.val(end); 1224 } 1225 1226 // Also update the main booking form fields to keep them in sync 1227 var $mainStartDateInput = jQuery('.hfy-listing-booking-form input[name="start_date"]'); 1228 var $mainEndDateInput = jQuery('.hfy-listing-booking-form input[name="end_date"]'); 1229 var $mainDatepickerInput = jQuery('#hotel-datepicker'); // Direct ID selector 1230 1231 // console.log('[Old Inquiry] Found main form elements:', { 1232 // mainStartDateInput: $mainStartDateInput.length, 1233 // mainEndDateInput: $mainEndDateInput.length, 1234 // mainDatepickerInput: $mainDatepickerInput.length 1235 // }); 1236 1237 if ($mainStartDateInput.length) { 1238 $mainStartDateInput.val(start); 1239 } 1240 if ($mainEndDateInput.length) { 1241 $mainEndDateInput.val(end); 1242 } 1243 // Update the visible input in the main form as well 1244 if ($mainDatepickerInput.length && start && end) { 1245 $mainDatepickerInput.val(`${start} - ${end}`); 1246 // Trigger change event if needed for other scripts listening on the main form 1247 $mainDatepickerInput.trigger('change'); 1248 // console.log('[Old Inquiry] Updated hotel-datepicker:', $mainDatepickerInput.val()); 1249 } 1250 1251 // Update prices if the function exists 1252 if (typeof window.doUpdatePriceBlock === 'function') { 1253 window.doUpdatePriceBlock(); 1254 // console.log('[Old Inquiry] Called doUpdatePriceBlock'); 1255 } 1256 1257 // console.log('[Old Inquiry] Updated main booking form and called doUpdatePriceBlock'); 1258 } 1259 }; 1260 1261 // Initialize the datepicker on the hidden range input 1262 var oldInquiryDatepicker = new HotelDatepicker(rangeInput, inquiryOptions); 1263 rangeInput._hotelDatepicker = oldInquiryDatepicker; // Store reference 1264 window.oldInquiryDatepicker = oldInquiryDatepicker; // Store globally 1265 // console.log('[Old Inquiry] Datepicker initialized:', oldInquiryDatepicker); 1266 1267 // When user clicks either check_in or check_out, open the datepicker 1268 inquiryCheckin.addEventListener('focus', function() { 1269 // console.log('[Old Inquiry] inquiry_checkin focused, opening datepicker'); 1270 oldInquiryDatepicker.open(); 1271 }); 1272 inquiryCheckout.addEventListener('focus', function() { 1273 // console.log('[Old Inquiry] inquiry_checkout focused, opening datepicker'); 1274 oldInquiryDatepicker.open(); 1275 }); 1276 } 1277 1278 // console.log('[Old Inquiry] Old inquiry form initialization complete'); 1279 } 1280 1281 // Remove immediate initialization 1282 // initOldInquiryDatepicker(); 1283 1284 // Listen for the hfymodal OPEN event (this is the proper way) 1285 jQuery(document).ready(function($) { 1286 $('.direct-inquiry-modal').on($.hfymodal.OPEN, function(event, modal) { 1287 // console.log('[Old Inquiry] hfymodal OPEN event fired, initializing...'); 1288 1289 // Check if new inquiry form is enabled - if so, skip old inquiry initialization 1290 if (typeof window.HFY_USE_NEW_INQUIRY_FORM !== 'undefined' && window.HFY_USE_NEW_INQUIRY_FORM) { 1291 // console.log('[Old Inquiry] New inquiry form is enabled, skipping old inquiry initialization'); 1292 return; 1293 } 1294 1295 // Check if this is the V2 modal - if so, skip old inquiry initialization 1296 if ($(this).find('#hfy-direct-inquiry-form-v2').length > 0) { 1297 // console.log('[Old Inquiry] V2 modal detected, skipping old inquiry initialization'); 1298 return; 1299 } 1300 1301 setTimeout(function() { 1302 initOldInquiryDatepicker(); 1303 }, 200); // Same delay as the existing code 1304 }); 1305 }); 1306 1307 // Also listen for the modal open event (backup) 1308 document.addEventListener('direct-inquiry-modal-opened', function() { 1309 // console.log('[Old Inquiry] Modal opened event received, checking for elements...'); 1310 1311 // Check if new inquiry form is enabled - if so, skip old inquiry initialization 1312 if (typeof window.HFY_USE_NEW_INQUIRY_FORM !== 'undefined' && window.HFY_USE_NEW_INQUIRY_FORM) { 1313 // console.log('[Old Inquiry] New inquiry form is enabled, skipping old inquiry initialization'); 1314 return; 1315 } 1316 1317 // Check if this is the V2 modal - if so, skip old inquiry initialization 1318 if (document.querySelector('#hfy-direct-inquiry-form-v2')) { 1319 // console.log('[Old Inquiry] V2 modal detected in backup event, skipping old inquiry initialization'); 1320 return; 1321 } 1322 1323 setTimeout(function() { 1324 initOldInquiryDatepicker(); 1325 }, 150); 1326 }); 1327}); 1328 1329// --- Global sync: Booking form to old inquiry form (outside DOMContentLoaded) --- 1330function syncBookingFormToOldInquiry() { 1331 var mainDateInput = document.getElementById('hotel-datepicker'); 1332 if (mainDateInput && mainDateInput.value) { 1333 var value = mainDateInput.value; 1334 var dates = value.split(' - '); 1335 var start = dates[0] || ''; 1336 var end = dates[1] || ''; 1337 1338 // Target the old inquiry form specifically 1339 var inquiryCheckin = document.querySelector('.direct-inquiry-modal #inquiry_checkin'); 1340 var inquiryCheckout = document.querySelector('.direct-inquiry-modal #inquiry_checkout'); 1341 var inquiryDatepicker = document.querySelector('.direct-inquiry-modal #inquiry-hotel-datepicker'); 1342 var rangeInput = document.getElementById('inquiry-hotel-datepicker-old'); 1343 1344 // console.log('[Global Sync] Found elements:', { 1345 // inquiryCheckin: !!inquiryCheckin, 1346 // inquiryCheckout: !!inquiryCheckout, 1347 // inquiryDatepicker: !!inquiryDatepicker, 1348 // rangeInput: !!rangeInput, 1349 // start: start, 1350 // end: end 1351 // }); 1352 1353 if (inquiryCheckin) { 1354 inquiryCheckin.value = start;
1355 // console.log('[Global Sync] Updated inquiry_checkin:', start); 1356 } 1357 if (inquiryCheckout) { 1358 inquiryCheckout.value = end; 1359 // console.log('[Global Sync] Updated inquiry_checkout:', end); 1360 } 1361 if (inquiryDatepicker) { 1362 inquiryDatepicker.value = value; 1363 // console.log('[Global Sync] Updated inquiry-hotel-datepicker:', value); 1364 } 1365 if (rangeInput) { 1366 rangeInput.value = value; 1367 // Try to update the datepicker instance if it exists 1368 if (window.oldInquiryDatepicker) { 1369 window.oldInquiryDatepicker.setRange(start, end); 1370 // console.log('[Global Sync] Updated datepicker range:', start, end); 1371 } 1372 } 1373 // console.log('[Global Sync] Booking form updated old inquiry form:', start, end); 1374 } else { 1375 // console.log('[Global Sync] No main date input or value found'); 1376 } 1377} 1378 1379// --- Listen for booking form changes globally --- 1380document.addEventListener('DOMContentLoaded', function() { 1381 // Listen for changes on the main booking form 1382 var mainDateInput = document.getElementById('hotel-datepicker'); 1383 if (mainDateInput) { 1384 mainDateInput.addEventListener('change', syncBookingFormToOldInquiry); 1385 mainDateInput.addEventListener('input', syncBookingFormToOldInquiry); 1386 } 1387 1388 // Also listen for the datepicker's afterClose event 1389 if (mainDateInput) { 1390 mainDateInput.addEventListener('afterClose', function() { 1391 setTimeout(syncBookingFormToOldInquiry, 100); // Small delay to ensure value is updated 1392 }); 1393 } 1394 1395 // Store the old inquiry datepicker globally for access 1396 if (typeof HotelDatepicker === 'function' && document.getElementById('inquiry-hotel-datepicker-old')) { 1397 var rangeInput = document.getElementById('inquiry-hotel-datepicker-old'); 1398 if (rangeInput && rangeInput._hotelDatepicker) { 1399 window.oldInquiryDatepicker = rangeInput._hotelDatepicker; 1400 } 1401 } 1402}); 1403 1404// --- Ensure HotelDatepicker is initialized for old inquiry modal input when modal opens (with debug logging and event delegation) --- 1405// This section is now handled by the main modal initialization above 1406 1407// --- Fallback: Only initialize HotelDatepicker on focus for old inquiry form, not new modal --- 1408document.addEventListener('focusin', function(e) { 1409 if (e.target && e.target.id === 'inquiry-hotel-datepicker') { 1410 var input = e.target; 1411 1412 // Check if new inquiry form is enabled - if so, skip fallback initialization 1413 if (typeof window.HFY_USE_NEW_INQUIRY_FORM !== 'undefined' && window.HFY_USE_NEW_INQUIRY_FORM) { 1414 console.log('[Fallback] New inquiry form is enabled, skipping fallback initialization'); 1415 return; 1416 } 1417 1418 // Check if V3 calendar is disabled - if so, skip new datepicker initialization 1419 if (typeof window.HFY_USE_V3_CALENDAR === 'undefined' || !window.HFY_USE_V3_CALENDAR) { 1420 console.log('[Fallback] V3 calendar is disabled, skipping new datepicker initialization'); 1421 return; 1422 } 1423 1424 // Skip fallback if inside the new inquiry modal - let the new modal handle it 1425 if (input.closest('#hfy-direct-inquiry-form-v2') || input.closest('.hfy-modal-body')) { 1426 console.log('[Fallback] Skipping focusin handler for V2 modal input'); 1427 return; 1428 } 1429 // For old inquiry forms, use the existing logic below 1430 var latest = window.hfyMainBookingDates || { start: '', end: '', value: '' }; 1431 if (typeof HotelDatepicker === 'function' && !input._hotelDatepicker) { 1432 var inquiryOptions = { 1433 showTopbar: false,
1434 clearButton: false, 1435 format: 'YYYY-MM-DD', 1436 startOfWeek: 'monday', 1437 minNights: (typeof minNights !== 'undefined' && Number.isInteger(parseInt(minNights)) && parseInt(minNights) > 0) ? parseInt(minNights) : 1, 1438 maxNights: (typeof maxNights !== 'undefined' && Number.isInteger(parseInt(maxNights)) && parseInt(maxNights) >= 0) ? parseInt(maxNights) : 0, 1439 selectForward: true, 1440 autoClose: true, 1441 moveBothMonths: true, 1442 disabledDates: (typeof formattedDisabledDates !== 'undefined') ? formattedDisabledDates : [], 1443 enableCheckout: true, 1444 disabledDaysOfWeek: (typeof disabledDaysOfWeek !== 'undefined') ? disabledDaysOfWeek : [], 1445 noCheckInDaysOfWeek: (typeof noCheckInDaysOfWeek !== 'undefined') ? noCheckInDaysOfWeek : [], 1446 noCheckOutDaysOfWeek: (typeof noCheckOutDaysOfWeek !== 'undefined') ? noCheckOutDaysOfWeek : [], 1447 noCheckInDates: (typeof noCheckInDates !== 'undefined') ? noCheckInDates : [], 1448 noCheckOutDates: (typeof noCheckOutDates !== 'undefined') ? noCheckOutDates : [], 1449 animationSpeed: '.3s', 1450 calendarCustomStay: (typeof calendarCustomStay !== 'undefined') ? calendarCustomStay : [], 1451 onSelectRange: function() {} 1452 }; 1453 var inquiryDatepicker = new HotelDatepicker(input, inquiryOptions); 1454 input._hotelDatepicker = inquiryDatepicker; 1455 input.removeAttribute('readonly'); 1456 // Always set value and range to latest main booking form dates 1457 if (latest.value) { 1458 input.value = latest.value; 1459 inquiryDatepicker.setRange(latest.start, latest.end); 1460 console.log('Fallback: Set value and setRange to', latest.start, latest.end); 1461 } 1462 inquiryDatepicker.open(); 1463 console.log('Fallback: HotelDatepicker initialized and opened on focus'); 1464 } else if (input._hotelDatepicker && latest.value) { 1465 // If already initialized, always sync value and range 1466 input.value = latest.value; 1467 input._hotelDatepicker.setRange(latest.start, latest.end); 1468 console.log('Fallback: Already initialized, set value and setRange to', latest.start, latest.end); 1469 } 1470 } 1471}); 1472 1473// --- Store last selected main booking form dates globally --- 1474window.hfyMainBookingDates = { start: '', end: '', value: '' }; 1475document.addEventListener('DOMContentLoaded', function() { 1476 var mainDateInput = document.getElementById('hotel-datepicker'); 1477 if (mainDateInput) { 1478 mainDateInput.addEventListener('change', function() { 1479 var value = mainDateInput.value; 1480 if (!value) return; 1481 var dates = value.split(' - '); 1482 var start = dates[0] || ''; 1483 var end = dates[1] || ''; 1484 window.hfyMainBookingDates = { start: start, end: end, value: value }; 1485 1486 // Update old inquiry form (two fields) - new modal handles its own updates 1487 var oldCheckin = document.getElementById('inquiry_checkin'); 1488 var oldCheckout = document.getElementById('inquiry_checkout'); 1489 if (oldCheckin && oldCheckout) { 1490 oldCheckin.value = start; 1491 oldCheckout.value = end; 1492 } 1493 1494 // console.log('Main booking form dates updated:', window.hfyMainBookingDates); 1495 }); 1496 } 1497}); 1498 1499// --- When the inquiry modal is opened, sync dates from main booking form (with forced events and debug) --- 1500// This is now handled by the main modal initialization above
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.