1/** 2 * HomeRunner Toolkit â Advance Notice Blocking (frontend) 3 * 4 * Patches the booking widget calendar utility and the explorer range 5 * calendar plugin so dates inside the advance-notice window are treated 6 * as unavailable with a clear tooltip. 7 * 8 * Config (window.hrtkAdvanceNotice): 9 * - hours number Hours of advance notice required. 10 * - days number hours / 24, rounded up. 11 * - tooltip string Pre-formatted tooltip text (already has %d filled in). 12 */ 13/* global jQuery */ 14(function () { 15 'use strict'; 16 17 var cfg = window.hrtkAdvanceNotice || { hours: 0, days: 0, tooltip: '' }; 18 if (!cfg.hours || cfg.hours <= 0) return; 19 20 var noticeMs = cfg.hours * 60 * 60 * 1000; 21 22 // Server-computed earliest bookable check-in date (Y-m-d, site timezone). 23 // Comparing calendar dates against this fixed boundary is deterministic for 24 // every visitor; the old browser-clock math was off by up to a day for 25 // guests in a different timezone than the property. 26 var minCheckinMs = null; 27 if (cfg.minCheckin) { 28 // Parse as a date-only value at UTC midnight, then compare against the 29 // candidate date also normalised to UTC midnight, so neither side 30 // depends on the browser timezone. 31 var parts = String(cfg.minCheckin).split('-'); 32 if (parts.length === 3) { 33 minCheckinMs = Date.UTC(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10)); 34 } 35 } 36 37 // Normalise a date (Date or string) to UTC midnight ms for day-granular 38 // comparison, independent of the browser timezone. 39 function dayStartUtcMs(date) { 40 if (!date) return NaN; 41 var d = (date instanceof Date) ? date : new Date(date); 42 if (isNaN(d.getTime())) return NaN; 43 // Use the date's UTC components: calendar dates from the host arrive as 44 // "YYYY-MM-DD" which JS parses as UTC midnight already. 45 return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()); 46 } 47 48 function isInsideWindow(date) { 49 if (!date) return false; 50 51 if (minCheckinMs !== null) { 52 var dayMs = dayStartUtcMs(date); 53 if (isNaN(dayMs)) return false; 54 return dayMs < minCheckinMs; 55 } 56 57 // Fallback (no server boundary available): legacy browser-clock math. 58 var d = (date instanceof Date) ? date : new Date(date); 59 if (isNaN(d.getTime())) return false; 60 var diff = d.getTime() - Date.now(); 61 return diff < noticeMs; 62 } 63 64 // Layer 1 â booking widget calendar utility. 65 function patchCalendarUtils() { 66 // The host declares `class HomeLocalCalendarUtils {â¦}` at top-level in 67 // calendar-utils.js with no window.X assignment â so it's a lexical 68 // global binding, NOT a property of window. Bare-name access works 69 // across classic scripts; `window.HomeLocalCalendarUtils` is undefined. 70 if (typeof HomeLocalCalendarUtils !== 'function' || !HomeLocalCalendarUtils.prototype) { 71 return false; 72 } 73 if (HomeLocalCalendarUtils.prototype.__hrtkAnbPatched) return true; 74 75 var orig = HomeLocalCalendarUtils.prototype._calculateCanCheckin; 76 HomeLocalCalendarUtils.prototype._calculateCanCheckin = function (date) { 77 if (isInsideWindow(date)) { 78 return { status: false, message: cfg.tooltip }; 79 } 80 if (typeof orig === 'function') { 81 return orig.apply(this, arguments); 82 } 83 return { status: true }; 84 }; 85 HomeLocalCalendarUtils.prototype.__hrtkAnbPatched = true; 86 return true; 87 } 88 89 // Layer 2 â explorer range calendar jQuery plugin. 90 function patchRangeCalendar() { 91 if (!window.jQuery || !jQuery.fn || !jQuery.fn.homelocalRangeCalendar) return false; 92 if (jQuery.fn.homelocalRangeCalendar.__hrtkAnbPatched) return true; 93 94 var origPlugin = jQuery.fn.homelocalRangeCalendar; 95 jQuery.fn.homelocalRangeCalendar = function () { 96 var ret = origPlugin.apply(this, arguments); 97 this.each(function () { 98 var inst = jQuery(this).data('homelocalRangeCalendar'); 99 if (!inst || inst.__hrtkAnbPatched) return; 100 inst.__hrtkAnbPatched = true; 101 102 if (typeof inst.isUnavailable === 'function') { 103 var origUnavail = inst.isUnavailable.bind(inst); 104 inst.isUnavailable = function (date) { 105 return isInsideWindow(date) || origUnavail(date); 106 }; 107 } 108 if (typeof inst.canCheckin === 'function') { 109 var origCanCheckin = inst.canCheckin.bind(inst); 110 inst.canCheckin = function (date) { 111 if (isInsideWindow(date)) { 112 return { status: false, message: cfg.tooltip }; 113 } 114 return origCanCheckin(date); 115 }; 116 } 117 }); 118 return ret; 119 }; 120 jQuery.fn.homelocalRangeCalendar.__hrtkAnbPatched = true; 121 return true; 122 } 123 124 // Try immediately, then retry briefly while the host scripts finish loading. 125 function attemptPatch() { 126 var calendarOk = patchCalendarUtils();
127 var rangeOk = patchRangeCalendar(); 128 return calendarOk && rangeOk; 129 } 130 131 if (attemptPatch()) return; 132 133 var attempts = 0; 134 var iv = setInterval(function () { 135 attempts++; 136 if (attemptPatch() || attempts > 60) { 137 clearInterval(iv); 138 } 139 }, 150); 140})();
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.