const SELFBOOK_BASE_URL="https://sdk.selfbook.com",SELFBOOK_BACKEND_URL="https://api.selfbook.com/api/v2",SELFBOOK_SCRIPT_ID="selfbook_jssdk",SELFBOOK_HOTEL_ID_PROP="hotelId",SELFBOOK_API_KEY_PROP="apiKey",SELFBOOK_WIDGET_ELEMENT_ID="selfbook_sdkwidget",SELFBOOK_WIDGET_WRAPPER_ELEMENT_ID="selfbook_sdkwidget_wrapper",SELFBOOK_WIDGET_LOADING_ELEMENT="selfbook-loading",SELFBOOK_WIDGET_RESUME="selfbook-sdkwidget-resume",SELFBOOK_WIDGET_RESUME_TEXT="selfbook-sdkwidget-resume-text",BOOTSTRAP_ACTION="WIDGET/BOOTSTRAP",SELFBOOK_HOTEL_GROUP_INFO="selfbook_hotel_group_info",BLACK_SQUARE_THEME_HOTELS=["6739"],THE_LINE_HOTELS=["68711","71661","2427"],COMPLETE_BOOKING_BTN_CLICK="Complete your reservation button click",ROUTE_PATHS={app:{confirmation:"/confirmation",wallet:"/wallet",account:"/account",settings:"/settings",reservations:"/reservations",reservationDetail:"/reservation-detail",editBooking:"/edit-booking",bookingConfirmed:"/booking-confirmed"}},INITIAL_PERSISTED_DATA={isExpired:!0,all:null,booking:null,core:null,router:null},GUEST_TYPE={ADULT:"adult",CHILD:"child",INFANT:"infants"};function checkStatus(t){if(t.status>=200&&t.status<300)return t;const e=new Error(t.statusText);throw e.response=t,e}async function parseJSON(t){try{const e=await t.text();if(!e)return;return JSON.parse(e)}catch(t){console.error("parseJSON: err: ",t)}}function intervalWrapper(t,e){const n=setInterval(t,e);return function(){clearInterval(n)}}function getHotelBasicData(t,e){try{const n=getFromLocalStorage(t,SELFBOOK_HOTEL_GROUP_INFO).hotels?.filter((t=>t.id==e));return n?.[0]||{}}catch(t){return console.error("getHotelBasicData: err: ",t),{}}}function getFromLocalStorage(t,e){try{return JSON.parse(t.getItem(e))}catch(t){return console.error("getFromLocalStorage: err: ",{e:t}),{}}}function getPersistedData(t){try{const e=JSON.parse(t.getItem("persist:root"));if(!e)return INITIAL_PERSISTED_DATA;const n=JSON.parse(e.booking||"{}"),o=JSON.parse(e.core||"{}"),r=JSON.parse(e?.router||"{}"),{expireTime:a}=o,i=(Date.now()-new Date(o.interactionTime))/1e3;return{isExpired:i>a,all:e,booking:n,core:o,router:r}}catch(t){return console.error("getPersistedData: err: ",t),INITIAL_PERSISTED_DATA}}function fillGuestsFields(t=[],e){const n=e.default_adult_occupancy?e.default_adult_occupancy:2;return t.map((t=>t.type===GUEST_TYPE.ADULT?{type:GUEST_TYPE.ADULT,count:parseInt(t.count)||n}:t.type===GUEST_TYPE.CHILD&&parseInt(t.count)>0?{type:GUEST_TYPE.CHILD,count:parseInt(t.count),age:parseInt(t.age)||1,special_request:t.special_request||""}:t.type===GUEST_TYPE.INFANT&&parseInt(t.count)>0?{type:GUEST_TYPE.INFANT,count:parseInt(t.count)||1,age:parseInt(t.age)||1,special_request:t.special_request||""}:void 0)).filter(Boolean)}function buildRedirectSynxisLink(t,e){let n=`https://be.synxis.com/?hotel=${e.id}&theme=${e.synxis_theme}&config=${e.synxis_config}`;try{if(t){const{startDate:e,endDate:o,promoCode:r,groupCode:a,guests:i,iataNumber:s,couponCode:l,destinationId:d,nights:c,rate:p,hotelId:u,roomCategory:m}=t;c&&(n+=`&nights=${c}`),e&&(n+=`&arrive=${e}`),o&&(n+=`&depart=${o}`),r&&(n+=`&promo=${r}`),a&&(n+=`&group=${a}`),s&&(n+=`&iataNumber=${s}`),l&&(n+=`&couponCode=${l}`),p&&(n+=`&rate=${p}`),d&&(n+=`&destinationId=${d}`),Array.isArray(m)?n+=`&roomCategory=${m.map((t=>t)).join(",")}`:m&&(n+=`&roomCategory=${m}`),i&&i.length>0?("adult"===i[0].type&&(n+=`&adult=${i[0].count}`),i[1]&&"child"===i[1].type&&(n+=`&child=${i[1].count}`)):n+="&adult=1"}}catch(t){console.error("buildRedirectSynxisLink: err: ",t)}return n}function selectShowWidgetButtonCopies(t){return t.core.showWidgetButtonCopies||{}}function selectRoute(t){return t?.router?.location?t.router.location.pathname:ROUTE_PATHS.app.editBooking}function isObjectEqual(t,e){return JSON.stringify(t)===JSON.stringify(e)}function isTemplateDomainMatch(t,e){return t?.booking_template_domain&&e?.target?.href?.includes(t.booking_template_domain)}function getElementById(t){return document?.getElementById(t)}function runDirectApplication(){console.info("(!) selfbook: widget initialization started");let t,e,n,o,r,a=!1,i=!1,s=!1,l=!1;function d({url:t,method:e,data:n,headers:o,callback:r}){fetch(t,{method:e,body:n,headers:o}).then(checkStatus).then(parseJSON).then(r).catch((t=>{console.debug("requestWrapper: Request failed",t)}))}function c(){try{const t=n||{},e=o||ROUTE_PATHS.app.editBooking;n=selectShowWidgetButtonCopies(window.selfbookWidgetStore.getState()),o=selectRoute(window.selfbookWidgetStore.getState());const r=getElementById(SELFBOOK_WIDGET_RESUME_TEXT);let a=t.COMPLETE_BOOKING;isObjectEqual(t,n)&&o===e||(a=o===ROUTE_PATHS.app.reservations?n.VIEW_RESERVATIONS:o===ROUTE_PATHS.app.confirmation||o===ROUTE_PATHS.app.reservationDetail?n.VIEW_RESERVATION:o===ROUTE_PATHS.app.account?n.VIEW_ACCOUNT:o===ROUTE_PATHS.app.wallet?n.VIEW_WALLET:o===ROUTE_PATHS.app.bookingConfirmed?n.RETURN_BOOKING:n.COMPLETE_BOOKING,r&&(r.innerHTML=a))}catch(t){console.error("handleStoreChange: err: ",t)}}function p(){return THE_LINE_HOTELS.includes(t)?"Lydian BT":"Main"}function u(e){const n=e?.colors||{},o=`\n position: fixed;\n overflow: hidden;\n cursor: pointer;\n display: flex;\n justify-content: space-evenly;\n align-items: center;\n width: 217px;\n height: 46px;\n box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.1);\n right: 30px;\n z-index: 100000000000;\n bottom: 40px;\n font-family: ${p()}!important;\n font-size: 14px;\n line-height: 142%;\n letter-spacing: 0.02em;\n text-transform: capitalize!important;\n border: none;\n transform: translateX(300px);\n `,r="\n background: #343A40;\n color: #FFFFFF;\n ",a=`\n ${r}\n border-radius: 23px;\n `,i=`\n background: ${n.primary_color||n.primary};\n color: ${n.secondary_color||n.secondary}!important;\n `;return s=e?.id||t,BLACK_SQUARE_THEME_HOTELS.includes(s)?`${o}${r}`:n.primary_color&&n.secondary_color||n.primary&&n.secondary?`${o}${i}`:`${o}${a}`;var s}function m(t){const e=document.createElement("style");e.textContent=t,document.head.append(e)}function f(n,o){if(!r)return;m(`#${SELFBOOK_WIDGET_RESUME} {\n ${u(o)}\n }`),document.body.style.overflow="hidden";const a=getElementById("selfbook_sdkwidget"),i=getElementById("selfbook_sdkwidget_wrapper"),l=getElementById(SELFBOOK_WIDGET_RESUME),d=l?l.getAttribute("class"):null;d&&d.includes("dismiss-btn")&&(l.removeAttribute("class"),l.setAttribute("class","dismiss-btn-slide-out")),window.selfbookWidgetStore||(i.appendChild(function(){const t=document.createElement("div");return t.id="selfbook-loading",t.style.color="white",t.style.marginRight="-50%",t.style.position="absolute",t.style.top="50%",t.style.left="50%",t.style.fontFamily="sans-serif",t.style.transform="translate(-50%, -50%)",t.innerHTML='',t}()),i.style.zIndex=1e11,i.style.height="100%",i.style.background="rgba(0, 0, 0, .74)",document.body.style.overflow="hidden"),function(){if(!0===s)return;r&&r.length>0&&r.forEach((t=>{if(t.includes(".js")){const e=document.createElement("script");e.type="text/javascript",e.src=`${SELFBOOK_BASE_URL}/${t}`,document.body.appendChild(e)}}));(function(){try{const t=document.createElement("script");t.innerHTML='\n !function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","identify","reset","group","track","ready","alias","debug","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e{if(window.selfbookWidgetStore){window.selfbookWidgetStore.subscribe(c);!function(){const t=document.getElementById("selfbook-loading");t&&getElementById("selfbook_sdkwidget_wrapper").removeChild(t)}(),clearInterval(p),window.selfbookWidgetStore.dispatch({type:BOOTSTRAP_ACTION,payload:{hotelInfo:{apiKey:n.apiKey||e,hotelId:n.hotelId||t},bookingData:n,hotelGroupInfo:getFromLocalStorage(localStorage,SELFBOOK_HOTEL_GROUP_INFO)}}),"none"===a.style.display&&(i.style.zIndex=1e11,i.style.height="100%",i.style.background="rgba(0, 0, 0, .4)",document.body.style.overflow="hidden"),setTimeout((()=>{a.style.display="block",a.setAttribute("class","slide-in")}),20),setTimeout((()=>{const t=i.querySelector('[aria-modal="true"]');t&&t.focus()}),250),function(){const t=getElementById("selfbook_sdkwidget"),e=getElementById("selfbook_sdkwidget_wrapper"),n=getElementById(SELFBOOK_WIDGET_RESUME);n.addEventListener("click",(o=>{try{if(n){const o=n?n.getAttribute("class"):null;o&&o.includes("dismiss-btn")&&(n.removeAttribute("class"),n.setAttribute("class","dismiss-btn-slide-out")),document.body.style.overflow="hidden",e.style.zIndex=1e11,e.style.height="100%",e.style.background="rgba(0, 0, 0, .5)",t.style.display="block",t.setAttribute("class","slide-in"),window.selfbookWidgetStore.dispatch({type:"ANALYTICS/TRACK_EVENT",payload:{eventType:COMPLETE_BOOKING_BTN_CLICK,eventPayload:null}}),setTimeout((()=>{const t=e.querySelector('[aria-modal="true"]');t&&t.focus()}),500)}}catch(t){console.error("handleWidgetCloseListeneres: err: ",t)}}))}()}}),100)}function y(){try{const{isExpired:t,core:e,booking:n}=getPersistedData(localStorage),o=!!e?.hotel?.data?.feature_flags?.persist_state;if(t||!e?.hotel?.data?.id||!o)return void function(){try{localStorage.removeItem("persist:root")}catch(t){console.error("removePersistedData: err",t)}}();const r=e.bootstrapArgs;E({...r,startDate:n.bookingForm.start_date.slice(0,10),endDate:n.bookingForm.end_date?.slice(0,10)||null,guests:n.bookingForm.guests,propertyId:n.bookingForm.property_id,persistActive:!0,hotelId:e.hotel.data.id})}catch(t){console.error("openPersistWidget: err",t)}}const g=async()=>await fetch(`${SELFBOOK_BASE_URL}/asset-manifest.json`,{headers:{"content-type":"application/json"}}).then((t=>t.json())).then((t=>function(t){r=t.entrypoints}(t)));function E(e={}){try{e.apiKey&&w(e.apiKey,e.hotelId);const n=getHotelBasicData(localStorage,e.hotelId||t);if(e.guests?e.guests=fillGuestsFields(e.guests,n):e.guests=[{type:GUEST_TYPE.ADULT,count:n.default_adult_occupancy?n.default_adult_occupancy:2}],console.log(e),n.redirect_to_synxis){const t=buildRedirectSynxisLink(e,n);return void window.open(t,"_blank").focus()}f(e,n),document.getElementsByTagName("html")[0].setAttribute("translate","no")}catch(t){console.error("bookNow: err: ",t)}}function h(t){const e={startdate:"startDate",enddate:"endDate",rateplancode:"ratePlanCode",rate:"rate",roomid:"roomId",propertyid:"propertyId",destinationid:"destinationId",room:"room",adult:"adult",child:"child",infants:"infants",currency:"currency",group:"group",locale:"locale",hotel:"hotel",promo:"promo",promocode:"promocode",selfbook:"selfbook",iatanumber:"iataNumber",couponcode:"couponCode",nights:"nights",reservationid:"reservationId",lastname:"lastName",search:"search",sbsearch:"sbsearch",threeDsContinueId:"three_ds_continue_id",status:"status",roomcategory:"roomCategory",properties:"properties",source:"source"};return Array.from(t.entries()).reduce(((t,[n,o])=>({...t,[e[n.toLowerCase()]]:o})),{})}function _(){setTimeout((()=>{const e=setInterval((()=>{if(a)return;clearInterval(e);const n=h(new URLSearchParams(window.location.search));"true"===n.selfbook&&b(n,getHotelBasicData(localStorage,n.hotel||t))}),100)}),500)}function b(t,e={}){const n=parseInt(e?.default_adult_occupancy)||2,o=[{type:"adult",count:t.adult||n},{type:"child",count:t.child||0},{type:"infants",count:t.infants||0}];E({...t,guests:o,groupCode:t.group,promoCode:t.promo||t.promocode,hotelId:t.hotel||void 0,roomCategory:"string"==typeof t.roomCategory?t.roomCategory.split(",").map((t=>t.trim())):void 0})}async function k(){!function(){const t=document.createElement("div"),e=document.createElement("div"),n=document.createElement("button"),o=document.createElement("span"),r=document.createElement("img");n.id=SELFBOOK_WIDGET_RESUME,n.style.cursor="pointer",r.src="https://sdk.selfbook.com/assets/resume-icon-black.png",r.alt="Resume booking",r.width="16",r.height="16",o.innerHTML="Complete your booking",o.id=SELFBOOK_WIDGET_RESUME_TEXT,n.appendChild(o),n.appendChild(r),t.setAttribute("id","selfbook_sdkwidget"),t.style.display="none",e.setAttribute("id","selfbook_sdkwidget_wrapper"),e.style.background="rgba(0, 0, 0, 0)",e.style.position="fixed",e.style.top="0",e.style.right="0",e.style.width="100%",e.style.transition="background .5s ease-out",e.appendChild(t),document.body.appendChild(e),document.body.appendChild(n)}(),await g(),function(){if(!0!==l){if(r&&r.length>0){const t=document.getElementsByTagName("head")[0];r.forEach((e=>{if(e.includes(".css")){const n=document.createElement("link");n.rel="stylesheet",n.type="text/css",n.media="all",n.href=`${SELFBOOK_BASE_URL}/${e}`,t.appendChild(n)}}))}l=!0}}(),y(),document?.querySelectorAll("a").forEach((e=>{e.addEventListener("click",(e=>{try{"A"!==e.target.tagName&&"A"===e.target.parentNode?.tagName&&(e.target.href=e.target.parentNode.href);const n=e.target.href||"";if(-1===n.indexOf("?"))return;const o=h(new URLSearchParams(n.substring(n.indexOf("?")))),r=getHotelBasicData(localStorage,o.hotel||t);if(r?.mobile_display_only&&window.innerWidth>=768)return;(isTemplateDomainMatch(r,e)||"true"===o.selfbook)&&(e.preventDefault(),b(o,r))}catch(t){console.error("a-element: err: ",t)}}))})),"complete"===document?.readyState?_():window?.addEventListener("load",_)}function w(t,e){a=!0;d({url:`${SELFBOOK_BACKEND_URL}/hotels/info${e?`?id=${e}`:""}`,headers:{"content-type":"application/json","API-Key":t},callback(t){localStorage.setItem(SELFBOOK_HOTEL_GROUP_INFO,JSON.stringify(t)),i||k(),i=!0,a=!1}})}const S=document?.getElementById("selfbook_jssdk");if(S){const n=new URL(S.getAttribute("src"));if(t=n.searchParams.get("hotelId"),e=n.searchParams.get("apiKey"),!e||!t)throw new Error("(!) selfbook: ApiKey and HotelId are required.");window.isSelfbookSDKActive=!0,w(e,t),intervalWrapper((()=>{w(e,t)}),3e5),function(){const t=`\n #selfbook_sdkwidget {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0px;\n right: 0px;\n }\n\n #${SELFBOOK_WIDGET_RESUME} {\n ${u()}\n }\n\n #${SELFBOOK_WIDGET_RESUME_TEXT} {\n display: block!important;\n font-family: ${p()}!important;\n font-size: 14px!important;\n font-weight: 400!important;\n color: #ffffff!important;\n }\n\n .dismiss-btn-slide-in {\n -webkit-transition: 500ms;\n -moz-transition: 500ms;\n transition: 500ms;\n transform: translateX(0)!important\n }\n\n .dismiss-btn-slide-out {\n -webkit-transition: 500ms;\n -moz-transition: 500ms;\n transition: 500ms;\n transform: translateX(300px)!important\n }\n\n .dismiss-btn-slide-out span {\n display: none;\n }\n\n .payment-summary-wrapper {\n overflow: scroll!important;\n -ms-overflow-style: none!important;\n scrollbar-width: none!important;\n }\n .payment-summary-wrapper::-webkit-scrollbar {\n display: none!important;\n }\n\n .dismiss-btn-resize-in {\n width: 46px!important;\n height: 46px!important;\n transition: 500ms;\n right: 30px!important;\n }\n\n .dismiss-btn-resize-in span {\n display: none;\n }\n\n .dismiss-btn-resize-in:hover {\n width: 217px!important;\n height: 46px!important;\n transition: all 300ms linear;\n cursor: pointer;\n }\n\n .dismiss-btn-resize-in:hover span {\n display: inline;\n height: 20px!important;\n overflow: hidden;\n }\n\n .dismiss-btn-resize-out {\n width: 46px!important;\n height: 46px!important;\n transition: 500ms;\n right: -100px!important;\n }\n\n .slide-in {\n transform: translateX(100%);\n -webkit-transform: translateX(100%);\n animation: slide-in 0.8s forwards !important;\n -webkit-animation: slide-in 0.8s forwards !important;\n z-index: 1000000000000;\n }\n\n .slide-out {\n transform: translateX(100%);\n -webkit-transform: translateX(100%);\n animation: slide-out 1s forwards !important;\n -webkit-animation: slide-out 1s forwards !important;\n z-index: -1000000000000;\n }\n\n @media screen and (max-width:495px) {\n .slide-in {\n transform: translateY(100%);\n -webkit-transform: translateY(100%);\n animation: slide-up 0.8s forwards !important;\n -webkit-animation: slide-up 0.8s forwards !important;\n z-index: 1000000000000;\n }\n .slide-out {\n transform: translateY(100%);\n -webkit-transform: translateY(100%);\n animation: slide-down 0.5s forwards !important;\n -webkit-animation: slide-down 1s forwards !important;\n z-index: -1000000000000;\n }\n }\n\n @keyframes slide-in {\n 100% {\n transform: translateX(0%);\n }\n }\n\n @-webkit-keyframes slide-in {\n 100% {\n -webkit-transform: translateX(0%);\n }\n }\n\n @keyframes slide-up {\n 100% {\n transform: translateY(0%);\n }\n }\n\n @-webkit-keyframes slide-up {\n 100% {\n -webkit-transform: translateY(0%);\n }\n }\n\n @keyframes slide-out {\n 0% {\n transform: translateX(0%);\n }\n 100% {\n transform: translateX(100%);\n }\n }\n\n @-webkit-keyframes slide-out {\n 0% {\n -webkit-transform: translateX(0%);\n }\n 100% {\n -webkit-transform: translateX(100%);\n }\n }\n\n @keyframes slide-down {\n 0% {\n transform: translateY(0%);\n }\n 100% {\n transform: translateY(100%);\n }\n }\n\n @-webkit-keyframes slide-down {\n 0% {\n -webkit-transform: translateY(0%);\n }\n 100% {\n -webkit-transform: translateY(100%);\n }\n }\n `,e=document.createElement("style");e.textContent=t,document.head.append(e),m(t)}()}window&&(window.sbApiLogger=function(n){try{d({url:`${SELFBOOK_BACKEND_URL}/hotels/${t}/events`,method:"POST",headers:{"content-type":"application/json","API-Key":e},data:JSON.stringify({generated_at:(new Date).toISOString(),event_source:"SDK",body:n})})}catch(t){console.log(t)}},window.book=function(t,e,n,o,r,a,i,s,l,d,c="fr",p,u,m){E({startDate:t,endDate:e,guests:n,propertyId:o,currency:r,roomId:a,ratePlanCode:i,rate:s,promoCode:l,groupCode:d,locale:c,destinationId:u,hotelId:p,roomCategory:m})},window.bookNow=E,window.closeSelfbookWidget=function(){const t=getElementById("selfbook_sdkwidget"),e=getElementById("selfbook_sdkwidget_wrapper"),n=getElementById(SELFBOOK_WIDGET_RESUME);document.body.style.overflow="initial",t.setAttribute("class","slide-out"),e.style.background="rgba(0, 0, 0, 0)",window.selfbookWidgetStore.dispatch({type:"WIDGET/SELFBOOK_WIDGET_CLOSED"}),window.selfbookWidgetStore.dispatch({type:"ANALYTICS/TRACK_EVENT",payload:{eventType:"widget closed"}}),setTimeout((()=>{t.style.display="none",e.style.zIndex=-1e11;const o=getFromLocalStorage(localStorage,SELFBOOK_HOTEL_GROUP_INFO);o&&(o.maintenance_mode||(n.setAttribute("class","dismiss-btn-slide-in"),n.focus()))}),800)})}runDirectApplication(); /* eslint-disable no-undef */ /* ---------------------------------- // Integration for the Yotel Hotel Group https://www.yotel.com Chain Code: 17799 Mobile + Desktop ---------------------------------- */ // Client requested that Selfbook should not run on certain pages (() => { if (window.location.href.includes('/user/account') == true || window.location.href.includes('non-stop-rewards-with-jetblue') == true || window.location.href.includes('/jetblue') == true || window.location.href.includes('hotels/yotel-new-york-times-square') == true || window.location.href.includes('landside') == true || window.location.href.includes('airside') == true ) { console.log( '%cSkip page', 'background: orange; color: white;', ); return; } else { console.log( '%cCustom script has been initialized', 'background: green; color: white;', ); /* Compares an input date vs todays date. If date is in the past will select todays date. This is to prevent stale synxis link from resulting in no availability */ // Hiding Edit Button to prevent user from seeing hotel list since not all hotels are live atm /* Compares an input date vs todays date. If date is in the past will select todays date. This is to prevent stale synxis link from resulting in no availability */ const verifyFutureDate = (date) => { const inputDate = new Date(date).toISOString().split('T')[0]; const today = new Date().toISOString().split('T')[0]; if (inputDate > today) { return inputDate; } return ''; }; /* Checks the format of the inputted date and puts it in the correct order format (YYYY-MM-DD), for example 25/10/2023 is converted to 2023-10-25 */ const convertDate = (date) => { let newDate = ''; const d = new Date(date); let month = '' + (d.getMonth() + 1); let day = '' + d.getDate(); const year = d.getFullYear(); if (month.length < 2) { month = '0' + month; } if (day.length < 2) { day = '0' + day; } newDate = [year, month, day].join('-'); return newDate; }; /* Trims the arrival date to ISO format for SB Widget */ const formatArrivalDate = (date) => { if (!date) { return null; } return convertDate(date); }; /* Trims the departure date to ISO format for SB Widget, can also take an optional parameter to modify the minimum stay */ const formatDepartureDate = (date) => { if (!date) { return null; } return convertDate(date); }; const pruneObjectKeys = (object) => { const pruneObject = object; Object.keys(pruneObject).forEach((key) => { if (key === 'guests') { if (pruneObject[key][0] !== null && pruneObject[key][0].count > 0) { const adultCount = pruneObject[key][0].count; pruneObject.adult = adultCount; if ( pruneObject[key][1] !== null && pruneObject[key][1].count > 0) { const childCount = pruneObject[key][1].count; pruneObject.child = childCount; } return delete pruneObject.guests; } if ( pruneObject[key] !== null && pruneObject[key][1].count !== null) { const childCount = pruneObject[key][1].count; pruneObject.child = childCount; delete pruneObject.guests; } delete pruneObject[key]; } if (!pruneObject[key]) { delete pruneObject[key]; } return pruneObject; }); return pruneObject; }; const localeSelector = () => { const urlPath = window.location.pathname; if (urlPath.includes('/de')) { return 'de'; } else if (urlPath.includes('/fr')) { return 'fr'; } else if (urlPath.includes('/tr')) { return 'tr'; } else if (urlPath.includes('/pt-pt')) { return 'pt-PT'; } else if (urlPath.includes('/es')) { return 'es'; } else if (urlPath.includes('/ru')) { return 'ru'; } else { return 'en'; } }; const assignObjectVals = (param) => { const {arrive, startdate, depart, enddate, adult, child, locale, hotel, hotelid, ...urlData} = param; const guests = [ { type: 'adult', count: (!adult ? null : parseInt(adult, 10)), }, { type: 'child', count: (!child ? null : parseInt(child, 10)), }, ]; const bookNowParams = { startDate: arrive ? arrive : startdate, endDate: depart ? depart : enddate, guests, propertyId: urlData.propertyId, currencyCode: urlData.currency, roomId: urlData.room, ratePlanCode: urlData.rate, promoCode: urlData.promo, groupCode: urlData.group, locale: (locale ? null : localeSelector()), hotelId: hotel ? hotel : hotelid, }; return pruneObjectKeys(bookNowParams); }; // Create a function that parses the URL and returns an object with the params const parseURL = (url) => { const params = {}; const urlInput = url.toLowerCase().split('?'); const urlParams = urlInput[1].split('&'); for (let i = 0; i < urlParams.length; i++) { const param = urlParams[i].split('='); params[param[0]] = param[1]; } const searchParams = decodeURIComponent( new URLSearchParams(assignObjectVals(params)), ); searchParams.toString(); // eslint-disable-next-line max-len const domain = `https://${window.location.hostname}?selfbook=true&${searchParams}`; return [domain, params]; }; /* this finds all tags and checks that thier hrefs contain a parameter then runs a loop that replaces that href and adds an event listener for the bookNow() */ const linkReplacer = () => { const allSynxisLinks = document.querySelectorAll(`a[href*='synxis'],a[href*='selfbook=true']`); const sbTrueLinks = document.querySelectorAll(`a[href*='selfbook=true']`); if (allSynxisLinks.length >= 1) { // const linkArray = Array.from(allSynxisLinks); // const result = linkArray.filter((link) => !link.href.includes('be.synxis.com') && !(link.href.includes('selfbook=true') && link.href.includes('sbreplaced=true'))); // allSynxisLinks = result; if (window.location.href.includes('/user/account') || window.location.href.includes('non-stop-rewards-with-jetblue') || window.location.href.includes('/jetblue') || window.location.href.includes('/en/hotels/yotel-new-york-times-square') ) { return; } else { for (let i = 0; i < allSynxisLinks.length; i++) { const atag = allSynxisLinks[i]; const link = allSynxisLinks[i].href.toLowerCase(); // https://www.yotel.com/?selfbook=true&locale=en&hotelId=32229&sbreplaced=true if (link.includes('be.synxis.com') || (link.includes('selfbook=true') && !link.includes('sbreplaced=true'))) { if (link.includes('hotel=9194') || link.includes('hotel=76937') || link.includes('hotel=8454') || link.includes('hotel=9694') || link.includes('hotel=31082') || link.includes('hotel=38140') || link.includes('hotel=36681') || link.includes('hotel=36425') || link.includes('hotel=64714') || link.includes('hotel=10361') || link.includes('hotel=79147') || link.includes('hotel=77041') && isMobile() || link.includes('hotel=19828') || link.includes('hotel=8182') || link.includes('hotel=36424') ) { const parsedLink = parseURL(link); const finalParams = assignObjectVals(parsedLink[1]); atag.href = parseURL(link)[0]; atag.href = atag.href + '&sbreplaced=true'; // console.log(atag.href); // atag.href = '#'; atag.addEventListener('click', (e) => { e.preventDefault(); // eslint-disable-next-line no-undef if (link.includes('=9194')) { customAmsterdamTaxText(); customHideZeroTaxesAndFees(); } else if (link.includes('=8454') || link.includes('=9694') || link.includes('=31082') || link.includes('=38140') || link.includes('=36681') || link.includes('=10361')) { customHideZeroTaxesAndFees(); customAmsterdamRemoveStyleTag(); } else if (link.includes('=76937') || link.includes('=36425') || link.includes('=64714') || link.includes('=79147') || link.includes('=19828') || link.includes('=8182') || link.includes('=36424')) { customRemoveHideZeroTaxesAndFees(); customAmsterdamRemoveStyleTag(); } else { customAmsterdamRemoveStyleTag(); customRemoveHideZeroTaxesAndFees(); } bookNow(finalParams); }); } } } } } }; // linkReplacer('synxis.com', false); function formatDate(date) { let d = new Date(date); if (!date) { d = new Date(); } let month = '' + (d.getMonth() + 1); let day = '' + d.getDate(); const year = d.getFullYear(); if (month.length < 2) { month = '0' + month; } if (day.length < 2) { day = '0' + day; } return [year, month, day].join('-'); } // English, French, German, Spanish function getDayAbbreviation(dayName) { const dayMapping = { 'mon': 'Mon', 'lun': 'Mon', 'tue': 'Tue', 'die': 'Tue', 'mar': 'Tue', 'wed': 'Wed', 'mer': 'Wed', 'mit': 'Wed', 'mie': 'Wed', 'mié': 'Wed', 'thu': 'Thu', 'jeu': 'Thu', 'jue': 'Thu', 'don': 'Thu', 'fri': 'Fri', 'ven': 'Fri', 'vie': 'Fri', 'fre': 'Fri', 'sat': 'Sat', 'sáb': 'Sat', 'sab': 'Sat', 'sam': 'Sat', 'sun': 'Sun', 'dim': 'Sun', 'son': 'Sun', 'dom': 'Sun' }; const lowerDayName = dayName.toLowerCase(); const trimmedDay = lowerDayName.slice(0, 3); return dayMapping[trimmedDay] || ""; } function getMonthNumber(monthAbbr) { const monthMapping = { 'jan': 'Jan', 'ene': 'Jan', 'feb': 'Feb', 'fév': 'Feb', 'fev': 'Feb', 'mar': 'Mar', 'mär': 'Mar', 'apr': 'Apr', 'avr': 'Apr', 'abr': 'Apr', 'may': 'May', 'mai': 'May', 'jun': 'Jun', 'jui': 'Jun', 'jun': 'Jun', 'jul': 'Jul', 'aug': 'Aug', 'aoû': 'Aug', 'aou': 'Aug', 'ago': 'Aug', 'sep': 'Sep', 'oct': 'Oct', 'okt': 'Oct', 'nov': 'Nov', 'dec': 'Dec', 'déc': 'Dec', 'dez': 'Dec', 'dic': 'Dec' }; const lowerMonthAbbr = monthAbbr.toLowerCase(); const trimmedMonth = lowerMonthAbbr.slice(0, 3); return monthMapping[trimmedMonth] || ""; } let code = ''; const hotelInfo = { 'YOTEL Amsterdam': { hotelId: '9194', dataId: '236' }, 'YOTEL Boston': { hotelId: '76937', dataId: '221' }, 'YOTEL Edinburgh': { hotelId: '8454', dataId: '256' }, 'YOTEL Glasgow': { hotelId: '9694', dataId: '281' }, 'YOTEL London City': { hotelId: '31082', dataId: '3651' }, 'YOTEL London Shoreditch': { hotelId: '38140', dataId: '4721' }, 'YOTEL Manchester Deansgate': { hotelId: '36681', dataId: '4161' }, 'YOTEL Miami': { hotelId: '36425', dataId: '1991' }, 'YOTEL New York Times Square': { hotelId: '64714', dataId: '106' }, 'YOTEL Porto': { hotelId: '10361', dataId: '4011' }, 'YOTEL San Francisco': { hotelId: '79147', dataId: '226' }, 'YOTEL Singapore': { hotelId: '77041', dataId: '271' }, 'YOTEL Washington DC': { hotelId: '19828', dataId: '206' }, 'YOTELAIR Singapore Changi Airport': { hotelId: '8182', dataId: '276' }, // 'YOTELAIR Istanbul Airport (Airside)': {hotelId: '8222', dataId: '261'}, 'YOTELPAD Miami': { hotelId: '36424', dataId: '1996' }, }; // linkReplacer('synxis.com', false); linkReplacer(); function returnHotelIdfromDataId(dataId) { for (const key in hotelInfo) { if (hotelInfo[key].dataId === dataId) { return hotelInfo[key].hotelId; } } } function returnHotelIdfromHotelSelector(hotelName) { // console.log('1st step'); if (hotelName) { // console.log('2nd step'); for (const key in hotelInfo) { if (key === hotelName || hotelName.includes(key)) { // console.log('3rd step'); return hotelInfo[key].hotelId; } else if (hotelInfo[hotelName]) { console.log('else if', hotelInfo[hotelName]); return hotelInfo[hotelName].hotelId; } else console.log('not found'); } } } // Desktop Hotel Picker let arrivalYear = new Date().getFullYear(); let departureYear = ''; let hotelSelector = ''; let hotelElement = ''; let selectedArrivalDate = ''; let selectedDepartureDate = ''; if (window.innerWidth >= 768) { console.log('desktop'); function getCodes() { console.log('getCodes'); const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // console.log('mutation', mutation); }); observer.observe(document.querySelector('.yot-location-search-container') || document, { subtree: true, childList: true, attributes: true, }); const modal = document.querySelector('.yot-location-search__gr-selector__rate-title'); const corpRate = document.getElementById('yls-corpo-rate'); const groupRate = document.getElementById('yls-group-rate'); const promoRate = document.getElementById('yls-promo-rate'); // const locationSearchPopup = document.querySelector('.yot-location-search__segment__popup'); let hotelIdVal = ''; if (modal) { if (corpRate.value !== '') { code = { promoCode: corpRate.value }; } if (groupRate.value !== '') { code = {groupCode: groupRate.value}; } if (promoRate.value !== '') { code = {promoCode: promoRate.value}; } } const selectedArrivalDateFirst = document.querySelector('.react-datepicker__day--selected'); const selectedDepartureDateFirst = document.querySelectorAll('.react-datepicker__day--in-selecting-range'); function findLastDateNode(queryEl) { const nodes = queryEl; if (nodes.length > 0) { const result = nodes[nodes.length - 1].getAttribute('aria-label').slice(-4); return result; } } selectedArrivalDate = document.querySelector('.react-datepicker__day--range-start'); selectedDepartureDate = document.querySelectorAll('.react-datepicker__day--range-end'); if (selectedArrivalDate !== null) { arrivalYear = selectedArrivalDate.getAttribute('aria-label').slice(-4); } if (selectedArrivalDateFirst !== null) { arrivalYear = selectedArrivalDateFirst.getAttribute('aria-label').slice(-4); } if (selectedDepartureDate !== null && selectedDepartureDate.length > 0) { departureYear = findLastDateNode(selectedDepartureDate); } if (selectedDepartureDateFirst !== null && selectedDepartureDateFirst.length > 0) { departureYear = findLastDateNode(selectedDepartureDateFirst); } // this was causing an issue where some hotels that are not currently on SB were triggering SB // if (!locationSearchPopup) { hotelSelector = document.querySelector('div.yot-location-search__container > div.yot-location-search__location-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)'); if (hotelSelector !== null) { // console.log('hotelSelector', hotelSelector); const searchBtn = document.querySelector('div.yot-location-search__container > button'); const hotelSelectorText = hotelSelector.innerHTML; hotelElement = hotelSelectorText; hotelIdVal = returnHotelIdfromHotelSelector(hotelElement); if (((hotelIdVal === undefined || hotelIdVal === '' || hotelIdVal === null) && searchBtn !== null) || (hotelIdVal === '77041' && !isMobile())) { searchBtn.removeEventListener('click', customDatePicker); } } // } const submitBtn = document.querySelector('.yot-location-search button.yotel-btn'); if (submitBtn !== null) { submitBtn.addEventListener('click', () => { observer.disconnect(); }); } }); console.log('after observer'); hotelDropDown = document.querySelector('.yot-location-search__location-selector.yot-location-search__segment'); hotelSelector = document.querySelector('div.yot-location-search__container > div.yot-location-search__location-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)'); const dateSelector = document.querySelector('.yot-location-search__date-picker.yot-location-search__segment '); const guestAndRoomSelector = document.querySelector('.yot-location-search__gr-selector.yot-location-search__segment '); if (hotelDropDown) { // console.log('hotelDropDown', hotelDropDown); hotelDropDown.addEventListener('click', () => { console.log('hotelDropDown Event Listener Added'); observer.observe(document.querySelector('.yot-location-search-container') || document, { subtree: true, childList: true, attributes: true, }); let hotelSelectorText = ''; if (hotelSelector !== '' && hotelSelectorText !== '' || hotelSelector !== null && hotelSelectorText !== null) { hotelSelectorText = hotelSelector.innerHTML; } hotelElement = hotelSelectorText; hotelIdVal = returnHotelIdfromHotelSelector(hotelElement); if (hotelIdVal !== null || hotelIdVal !== undefined || hotelIdVal !== '') { const searchBtn = document.querySelector('div.yot-location-search__container > button'); searchBtn.addEventListener('click', customDatePicker); } }); } if (dateSelector) { dateSelector.addEventListener('click', () => { observer.observe(document.querySelector('.yot-location-search-container') || document, { subtree: true, childList: true, attributes: true, }); }); } if (guestAndRoomSelector) { guestAndRoomSelector.addEventListener('click', () => { observer.observe(document.querySelector('.yot-location-search-container') || document, { subtree: true, childList: true, attributes: true, }); }); } } getCodes(); function customDatePicker(e) { e.preventDefault(); e.stopPropagation(); let hotel = ''; const searchBtn = document.querySelector('div.yot-location-search__container > button'); let arrivalDate = ''; let departureDate = ''; let guestCount = ''; // let roomCount = ''; let arrivalMonthDay = ''; let departureMonthDay = ''; let year = new Date().getFullYear(); let hotelIdVal = ''; const locationDataAttribute = document.querySelector('[data-location-id]'); let hotelElement = ''; if (locationDataAttribute !== null) { hotelElement = locationDataAttribute.getAttribute('data-location-id'); hotelIdVal = returnHotelIdfromDataId(hotelElement); } hotelSelector = document.querySelector('div.yot-location-search__container > div.yot-location-search__location-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)'); let hotelSelectorText = ''; if (hotelSelector !== null) { hotelSelectorText = hotelSelector.innerHTML; hotelElement = hotelSelectorText; hotelIdVal = returnHotelIdfromHotelSelector(hotelElement); } hotel = hotelIdVal; if (hotel == '77041' && !isMobile()) { console.log('singapore and not mobile'); return; } if (hotel == '9194') { customAmsterdamTaxText(); customHideZeroTaxesAndFees(); } else if (hotel == '8454' || hotel == '9694' || hotel == '31082' || hotel == '38140' || hotel == '36681' || hotel == '10361') { customHideZeroTaxesAndFees(); customAmsterdamRemoveStyleTag(); } else if (hotel == '76937' || hotel == '36425' || hotel == '64714' || hotel == '79147' || hotel == '19828' || hotel == '8182' || hotel == '36424') { customAmsterdamRemoveStyleTag(); customRemoveHideZeroTaxesAndFees(); } let textArrivalDate = document.querySelector('div.yot-location-search__container > div.yot-location-search__date-picker.yot-location-search__segment > div:nth-child(1) > div:nth-child(2) > p:nth-child(2)')?.innerHTML; let textDepartureDate = document.querySelector('div.yot-location-search__container > div.yot-location-search__date-picker.yot-location-search__segment > div:nth-child(2) > div:nth-child(2) > p:nth-child(2)')?.innerHTML; if (textArrivalDate === 'Add date' || textDepartureDate === 'Add date') { textArrivalDate = ''; textDepartureDate = ''; // console.log(`arrivalDate === 'Add date' || departureDate === 'Add date'`) } else if (textArrivalDate !== textDepartureDate) { let [a_dayOfWeek, a_dayOfMonth, a_monthOfYear] = textArrivalDate.split(" "); let arrivalMonthDay_eng = getDayAbbreviation(a_dayOfWeek) + ", " + a_dayOfMonth + " " + getMonthNumber(a_monthOfYear); // this format => 'Thurs, 20 Jun' let ar_year = returnCorrectYear(arrivalMonthDay_eng); const arr = new Date(arrivalMonthDay_eng + ' ' + ar_year); let [d_dayOfWeek, d_dayOfMonth, d_monthOfYear] = textDepartureDate.split(" "); let departureMonthDay_eng = getDayAbbreviation(d_dayOfWeek) + ", " + d_dayOfMonth + " " + getMonthNumber(d_monthOfYear); // this format => 'Thurs, 20 Jun' let de_year = returnCorrectYear(departureMonthDay_eng); const dep = new Date(departureMonthDay_eng + ' ' + de_year); arrivalDate = arr; departureDate = dep; // console.log(`(arrivalDate !== departureDate`) } else { // console.log(`final else`) } guestCount = document.querySelector('div.yot-location-search__container > div.yot-location-search__gr-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)').innerHTML.split(' ')[0]; roomCount = document.querySelector('div.yot-location-search__container > div.yot-location-search__gr-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)').innerHTML.split(' ')[2]; console.log('arrivalYear => ', arrivalYear); if (hotel === undefined || hotel === '' || hotel === null) { searchBtn.removeEventListener('click', customDatePicker); } const finalArrivalDate = formatDate(arrivalDate); let finalDepartureDate = formatDate(departureDate); if (departureMonthDay === 'Add date') { finalDepartureDate = ''; } console.log('arrivalMonthDay => ', arrivalMonthDay, 'arrivalDate => ', arrivalDate); console.log('departureMonthDay => ', departureMonthDay, 'departureDate => ', departureDate); console.log('finalArrivalDate => ', finalArrivalDate, 'finalDepartureDate => ', finalDepartureDate); // check if finalArrivalDate is nan // if (isNaN(finalArrivalDate)) { // finalArrivalDate = ''; // } // // check if finalDepartureDate is nan // if (isNaN(finalDepartureDate)) { // finalDepartureDate = ''; // } const params = { hotelId: hotel, startDate: finalArrivalDate, endDate: finalDepartureDate, guests: [ { type: 'adult', count: guestCount, }, ], locale: localeSelector(), ...code, }; bookNow(params); } const searchBtn = document.querySelector('div.yot-location-search__container > button'); const bottomCTA2 = document.querySelector('.yotel-btn[wbo-id="3"]'); const currentUrl = window.location.href; if (searchBtn) { if (currentUrl.includes('yotel-amsterdam')) { customAmsterdamTaxText(); searchBtn.addEventListener('click', customDatePicker); if (bottomCTA2) { bottomCTA2.addEventListener('click', customDatePicker); } } else if ( currentUrl.includes('glasgow') || currentUrl.includes('london-city') || currentUrl.includes('edinburgh') || // currentUrl.includes('istanbul-airport') || currentUrl.includes('london-shoreditch') || currentUrl.includes('manchester') || currentUrl.includes('porto') ) { searchBtn.addEventListener('click', customDatePicker); customAmsterdamRemoveStyleTag(); customHideZeroTaxesAndFees(); if (bottomCTA2) { bottomCTA2.addEventListener('click', customDatePicker); customAmsterdamRemoveStyleTag(); } } else if ( currentUrl.includes('boston') || currentUrl.includes('miami') || currentUrl.includes('new-york') || currentUrl.includes('san-francisco') || currentUrl.includes('singapore') && isMobile()|| currentUrl.includes('washington-dc') || currentUrl.includes('singapore-changi') || currentUrl.includes('yotelpad-miami') ) { searchBtn.addEventListener('click', customDatePicker); customAmsterdamRemoveStyleTag(); customRemoveHideZeroTaxesAndFees(); if (bottomCTA2) { bottomCTA2.addEventListener('click', customDatePicker); customAmsterdamRemoveStyleTag(); } } else if (currentUrl.endsWith('yotel.com/en')) { if (bottomCTA2) { bottomCTA2.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); bookNow(); }); } } } } function closeHotelModal() { if (document.querySelector('.yot-location-search__overlay.is-active')) { document.querySelector('.yot-location-search__overlay.is-active .yotel-form button').click(); } } function returnCorrectYear(date) { let [oldDay, splitDate] = date.split(", "); let [day, month] = splitDate.split(' '); let newDateMonth = new Date(`${month} ${day}, ${new Date().getFullYear()}`).getMonth(); let currentMonth = new Date().getMonth(); if (newDateMonth < currentMonth) { return new Date().getFullYear() + 1; } return new Date().getFullYear(); } // Mobile Hotel Picker function mobileHotelPicker() { const locationSearchContainer = document.querySelector('.yot-location-search'); const dataPromoCode = document.querySelector('[data-promo-code-promo]')?.getAttribute('data-promo-code-promo'); // const year = new Date().getFullYear(); const guestCount = document.querySelector('div.yot-location-search__container > div.yot-location-search__gr-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)')?.innerHTML.split(' ')[0]; // roomCount = document.querySelector('div.yot-location-search__container > div.yot-location-search__gr-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)').innerHTML.split(' ')[2]; function hasNestedValue(obj, value) { for (const key in obj) { if (obj.hasOwnProperty(key)) { if (obj[key] === value) return true; if (typeof obj[key] === 'object') { if (hasNestedValue(obj[key], value)) return true; } } } return false; } const locationDataAttribute = document.querySelector('[data-location-id]'); let locationDataId = ''; if (locationDataAttribute !== null) { locationDataId = locationDataAttribute.getAttribute('data-location-id'); } const hotelSearchBtn = document.querySelector('.yot-location-search button.yotel-btn'); // eslint-disable-next-line max-len if (hotelSearchBtn && locationDataId && hasNestedValue(hotelInfo, locationDataId)) { const checkHotelID = returnHotelIdfromDataId(locationDataId); if (checkHotelID == '77041' && !isMobile()) { console.log('singapore and not mobile'); return; } hotelSearchBtn.addEventListener('click', (e) => { console.log('hotelSearchBtn click'); e.preventDefault(); e.stopPropagation(); const hotel_id = returnHotelIdfromDataId(locationDataId); if (hotel_id == '9194') { customAmsterdamTaxText(); customHideZeroTaxesAndFees(); } else if (hotel_id == '8454' || hotel_id == '9694' || hotel_id == '31082' || hotel_id == '38140' || hotel_id == '36681' || hotel_id == '10361') { customHideZeroTaxesAndFees(); customAmsterdamRemoveStyleTag(); } else if (hotel_id == '76937' || hotel_id == '36425' || hotel_id == '64714' || hotel_id == '79147' || hotel_id == '19828' || hotel_id == '8182' || hotel_id == '36424') { customAmsterdamRemoveStyleTag(); customRemoveHideZeroTaxesAndFees(); } let tempGuestCount = document.querySelector('div.yot-location-search__container > div.yot-location-search__gr-selector.yot-location-search__segment > div:nth-child(2) > p:nth-child(2)')?.innerHTML.split(' ')[0]; let arrivalDate = document.querySelector('div.yot-location-search__container > div.yot-location-search__date-picker.yot-location-search__segment > div:nth-child(1) > div:nth-child(2) > p:nth-child(2)')?.innerHTML; let departureDate = document.querySelector('div.yot-location-search__container > div.yot-location-search__date-picker.yot-location-search__segment > div:nth-child(2) > div:nth-child(2) > p:nth-child(2)')?.innerHTML; if (arrivalDate === 'Add date' || departureDate === 'Add date') { arrivalDate = ''; departureDate = ''; // console.log(`arrivalDate === 'Add date' || departureDate === 'Add date'`) } else if (arrivalDate !== departureDate) { let year = returnCorrectYear(arrivalDate); const arr = new Date(arrivalDate + ' ' + year); const dep = new Date(departureDate + ' ' + year); arrivalDate = formatDate(arr); departureDate = formatDate(dep); // console.log(`(arrivalDate !== departureDate`) } else { // console.log(`final else`) } // console.log('2: finalArrivalDate => ', document.querySelector('div.yot-location-search__container > div.yot-location-search__date-picker.yot-location-search__segment > div:nth-child(1) > div:nth-child(2) > p:nth-child(2)')?.innerHTML); // console.log('2: finalDepartureDate => ', document.querySelector('div.yot-location-search__container > div.yot-location-search__date-picker.yot-location-search__segment > div:nth-child(2) > div:nth-child(2) > p:nth-child(2)')?.innerHTML); const params = { hotelId: locationDataId, startDate: arrivalDate, endDate: departureDate, guests: [ { type: 'adult', count: tempGuestCount, }, ], hotelId: hotel_id, promoCode: dataPromoCode ? dataPromoCode : '', locale: localeSelector(), ...code, }; bookNow(params); }); } const observer = new MutationObserver(() => { function afterClickEvents(e) { e.preventDefault(); e.stopPropagation(); observer.disconnect(); } closeBtn = document.querySelector('body > div.dialog-off-canvas-main-canvas > div.layout-container > main > div > article > header > div.yot-location-search-container > div > div > div > section > div.yot-location-search__overlay.is-active > div.yot-location-search__step.yot-location-search__location-selector > div > div > div > button'); if (closeBtn) { closeBtn.addEventListener('click', () => { observer.observe(locationSearchContainer, { childList: true, subtree: true, }); }); } const locationSearchDiv = document.querySelector('.yot-location-search__overlay.is-active'); if (locationSearchDiv !== null) { const hotelNameArray = Object.keys(hotelInfo); const listHotels = Array.from(document.querySelectorAll('.yot-location-search__location-selector__list li')); // filter the results to only show hotels that match the hotelInfo object const filteredHotels = listHotels.filter((hotelx) => { for (let i = 0; i < hotelNameArray.length; i++) { if (hotelx.innerHTML.includes(hotelNameArray[i])) { return true; } } }); filteredHotels.forEach((hotel) => { hotel.addEventListener('click', (e) => { afterClickEvents(e); const localeCode = localeSelector(); customAmsterdamRemoveStyleTag(); customRemoveHideZeroTaxesAndFees(); const hotelText = hotel.innerText; if (hotelText.includes('YOTEL Amsterdam')) { bookNow({hotelId: '9194', locale: localeCode}); closeHotelModal(); customAmsterdamTaxText(); customHideZeroTaxesAndFees(); } else if (hotelText.includes('YOTEL Boston')) { bookNow({hotelId: '76937', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL Edinburgh')) { customHideZeroTaxesAndFees(); bookNow({hotelId: '8454', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL Glasgow')) { customHideZeroTaxesAndFees(); bookNow({hotelId: '9694', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL London City')) { customHideZeroTaxesAndFees(); bookNow({hotelId: '31082', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL London Shoreditch')) { customHideZeroTaxesAndFees(); bookNow({hotelId: '38140', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL Manchester Deansgate')) { customHideZeroTaxesAndFees(); bookNow({hotelId: '36681', locale: localeCode}); closeHotelModal(); } else if (hotel.innerText.includes('YOTEL Miami')) { bookNow({hotelId: '36425', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL New York Times Square')) { bookNow({hotelId: '64714', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL Porto')) { customHideZeroTaxesAndFees(); bookNow({hotelId: '10361', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL San Francisco')) { bookNow({hotelId: '79147', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL Singapore') && isMobile()) { console.log('singapore test'); bookNow({hotelId: '77041', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTEL Washington DC')) { bookNow({hotelId: '19828', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTELAIR Singapore Changi Airport')) { bookNow({hotelId: '8182', locale: localeCode}); closeHotelModal(); } else if (hotelText.includes('YOTELPAD Miami')) { bookNow({hotelId: '36424', locale: localeCode}); closeHotelModal(); } else { return; } }); }); } }); setInterval(() => { if (locationSearchContainer !== null) { observer.observe(locationSearchContainer, { childList: true, subtree: true, }); } }, 1000); if (locationSearchContainer !== null) { observer.observe(locationSearchContainer, { childList: true, subtree: true, }); } } mobileHotelPicker(); function promoCTA() { const ctaBtn = document.getElementById('ug-exit-CTA'); if (ctaBtn) { const closeBtn = document.querySelector('#ug-exit-popup > div > div > div.ug-exit-popup-close.ug-popup-close'); if (closeBtn) { closeBtn.click(); ctaBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); closeBtn.click(); bookNow(); }); } } } promoCTA(); // Search for style tag with the text "Including VAT and excluding 6.29% city tax and € 3 per person per night." function customAmsterdamRemoveStyleTag() { console.log('customAmsterdamRemoveStyleTag() called'); if (document.querySelector("#sb-amsterdam-tax")) { document.querySelector("#sb-amsterdam-tax").remove(); } } function customAmsterdamTaxText() { console.log('customAmsterdamTaxText() called'); if (!document.querySelector("#sb-amsterdam-tax")) { const s = document.createElement('style'); s.id = "sb-amsterdam-tax"; s.textContent = ` /* Jira SSM-1152 */ ul > li.sb-room-item > button > div > div[class^="css-"] > div > span { display: none !important; } `; document.head.appendChild(s); } } let customHotelText = { 9194: [ { selector: '#selfbook_sdkwidget [lang="en"] #sb-modalcontent > div > div > div[class^="css-"] > div > p', find: "Tax & Fees Included.", replace: "Including VAT and excluding 12.5% city tax. " }, { selector: '#selfbook_sdkwidget [lang="nl"] #sb-modalcontent > div > div > div[class^="css-"] > div > p', find: "Belastingen & kosten inbegrepen.", replace: "Inclusief BTW en exclusief 12,5% toeristenbelasting. " }, ], }; function replaceText(element, find, replace) { // console.log('replaceText',element, find, replace); let text = element.textContent; text = text.replace(find, replace); element.innerText = text; } function updateText(selector, find, replace) { if (document.querySelectorAll(selector).length > 0) { document.querySelectorAll(selector).forEach(element => { if (element.textContent.includes(find) && !element.hasAttribute('data-sb-updated')) { // console.log('updateText',selector, find, replace); element.setAttribute('data-sb-updated', 'true'); replaceText(element, find, replace); } }); } } setInterval(() => { if (typeof selfbookWidgetStore !== 'undefined') { let hotelId = selfbookWidgetStore?.getState()?.core?.hotel?.data?.id; if (customHotelText[parseInt(hotelId)]) { let selectors = customHotelText[parseInt(hotelId)]; selectors.forEach(({ selector, find, replace }) => updateText(selector, find, replace)); } } }, 1000); /* SSM-1177 - YOTEL - Hide 'Taxes & Fees $0' line for hotels on Incl VAT customHideZeroTaxesAndFees(); customRemoveHideZeroTaxesAndFees(); // #sb-summary-taxes-fees See list below for the properties that need this update: - YOTEL Amsterdam - 9194 - YOTEL Edinburgh - 8454 - YOTEL Glasgow - 9694 - YOTELAir Istanbul Airport (Airside) - 8222 - YOTEL Istanbul Airport (Landside) - 8221 - YOTEL London City - 31082 - YOTEL London Shoreditch - 38140 - YOTEL Manchester Deansgate - 36681 - YOTEL Porto - 10361 */ /* 9194 (Amsterdam) = includes vat 8454 (Edinburgh), 9694 (Glasgow), 8222 (Istanbul Airport (Airside)), 8221 (Istanbul Airport (Landside)), 31082 (London City), 38140 (London Shoreditch), 36681 (Manchester Deansgate), 10361 (Porto) = $0 taxes 76937 (Boston), 36425 (Miami), 64714 (NY Times Sq), 79147 (SF), 19828 (DC), 8182 (Singapore Changi Airport), 36424 (Yotel PAD Miami) = else */ function customHideZeroTaxesAndFees() { console.log('customHideTaxesAndFees() called'); const s = document.createElement('style'); s.textContent = ` /* Jira SSM-1177 */ #sb-summary-taxes-fees { display: none !important; } `; document.head.appendChild(s); } // if #sb-summary-taxes-fees display: none, then remove the style tag function customRemoveHideZeroTaxesAndFees() { console.log('customRemoveHideTaxesAndFees() called'); const styleTags = document.getElementsByTagName('style'); for (let i = 0; i < styleTags.length; i++) { if (styleTags[i].innerHTML.includes('#sb-summary-taxes-fees')) { // remove the style tag styleTags[i].parentNode.removeChild(styleTags[i]); } } } const style = document.createElement('style'); style.textContent = ` /* CSS Conflict. ACCESSIBLE ROOMS toggle hidden. Must be shown */ #selfbook-ada-rooms { opacity: 1 !important; } #sb-property-select { display: none !important; } [data-testid="properties-list"] li:nth-of-type(12) div div div div div { display: none !important; } @media screen and (max-width: 768px) { #selfbook-sdkwidget-resume { bottom: 65px !important; right: 0px !important; border-radius: 0px !important; } } // ADA checkbox appears hidden in room filters [type=checkbox]:not(:checked), [type=checkbox]:checked, #selfbook_sdkwidget [type=checkbox]:not(:checked), #selfbook_sdkwidget [type=checkbox]:checked, #sb-rooms-filters-content__checkbox-filter { position: static !important; opacity: 1 !important; pointer-events: auto !important; } `; document.head.appendChild(style); // Start of SSM-1175 // SSM-1175 - Text customization request: special request on summary page const specialRequestText = () => { const urlPath = window.location.pathname; if (urlPath.includes('/de')) { return 'Fügen Sie eine Sonderanfrage oder eine Anfrage zur Barrierefreiheit hinzu'; } else if (urlPath.includes('/fr')) { return 'Ajouter une demande spéciale ou une demande d\'accessibilité'; } else if (urlPath.includes('/tr')) { return 'Özel İstek veya Erişilebilirlik İhtiyaçları İsteği Ekle'; } else if (urlPath.includes('/pt-pt')) { return 'Adicionar solicitação especial ou solicitação de necessidades de acessibilidade'; } else if (urlPath.includes('/es')) { return 'Agregar solicitud especial o solicitud de necesidades de accesibilidad'; } else if (urlPath.includes('/ru')) { return 'Добавить специальный запрос или запрос о потребностях в специальных возможностях'; } else { return 'Add Special Request or Accessibility Needs Request'; } }; const ssm1175_style = document.createElement('style'); ssm1175_style.textContent = ` textarea#special-request + label { visibility: hidden !important; } textarea#special-request + label:before{ visibility: visible !important; content: "${specialRequestText()}" !important; } `; document.head.appendChild(ssm1175_style); // End of SSM-1175 document.addEventListener('click', function(e) { if ( e.target && e.target.nodeName == 'BUTTON' && e.target.getAttribute('aria-label') == 'Close' || (e.target.parentElement && e.target.parentElement.parentElement && e.target.parentElement.parentElement.nodeName == 'BUTTON' && e.target.parentElement.parentElement.getAttribute('aria-label') == 'Close') || (e.target.parentElement && e.target.parentElement.nodeName == 'BUTTON' && e.target.parentElement.getAttribute('aria-label') == 'Close') ) { removeOverlayBackground(); } }); function removeOverlayBackground() { let counter = 0; const overlayInt = setInterval(function() { counter++; if (counter >= 3) { document.querySelector('#selfbook_sdkwidget_wrapper').style = 'background: rgba(0, 0, 0, 0); position: fixed; top: 0px; right: 0px; width: 100%; transition: background 0.5s ease-out 0s;'; clearInterval(overlayInt); } }, 500); } function isMobile() { console.log('isMobile() called'); return window.innerWidth < 768; } // https://bugsnagerrorreportingapi.docs.apiary.io/# const API_KEY_BUGSNAG = '6cb771be223c608f92775d1516dce6e2'; const CLIENT_URL = window.location.href; async function sendErrorToBugsnag(error, func, sb_int_queue) { const apiKey = API_KEY_BUGSNAG; const apiUrl = 'https://notify.bugsnag.com'; const payload = { apiKey: apiKey, notifier: { name: 'Custom Notifier', version: '1.0', url: CLIENT_URL, }, events: [ { payloadVersion: '5', exceptions: [ { errorClass: 'SbIntegration', message: `${error.name ? error.name : ''}. Message: ${error.message}.`, stacktrace: [ { file: CLIENT_URL, method: ' (' + func + ' Error) ', code: { 1: `${error.name ? error.name : ''}. Message: ${error.message}.`, 2: 'Browser: ' + navigator.userAgent, 3: 'Language: ' + navigator.language, }, }, ], }, ], severity: 'error', context: CLIENT_URL, app: { releaseStage: sb_int_queue ? sb_int_queue : '', }, }, ], }; const headers = new Headers({ 'Content-Type': 'application/json', 'Bugsnag-Api-Key': apiKey, 'Bugsnag-Payload-Version': '5', 'Bugsnag-Sent-At': new Date().toISOString(), }); const requestOptions = { method: 'POST', headers: headers, body: JSON.stringify(payload), }; try { const response = await fetch(apiUrl, requestOptions); if (response.ok) { console.log('Error report sent successfully'); } else { console.error('Failed to send error report'); } } catch (error) { console.error('Error sending error report:', error); } }; function handleError(error, func, sb_int) { console.error(`${func} error occurred:`, error); sendErrorToBugsnag(error, func, sb_int); // Forward the error to Bugsnag reporting }; // Global error capture window.onerror = (message, source, lineno, colno, error) => { // Returning true prevents the default browser error handling if (message && !message?.toString().toLowerCase().includes('resizeobserver') && !source?.toString().toLowerCase().includes('guestbook') && !source?.toString().toLowerCase().includes('yotel')) { const customError = { name: message?.toString().split(' ')[0], message: ` message: ${message}. source: ${source}. lineno: ${lineno}. colno: ${colno}. error: ${error}.`, }; if ( source && ( source.toString().includes('react') || source.toString().includes('saga.js') || source.toString().includes('breadcrumbs') || source.toString().includes('affirm.js') ) ) { handleError(customError, 'selfbook-crash', 'sb_integrations'); return true; } else if ( source && source.toString().includes('selfbook') && !source.toString().includes('selfbook=true') ) { handleError(customError, 'window.onerror'); return true; } } }; } })();