const SELFBOOK_BASE_URL="https://sdk.selfbook.com",SELFBOOK_BASE_URL_V3="https://sdk-v3.selfbook.com",SELFBOOK_BASE_URL_LAYERS="%REACT_APP_SELFBOOK_BASE_URL_LAYERS%";let SELFBOOK_BACKEND_URL="https://api.selfbook.com/api/v2",SELFBOOK_BACKEND_URL_V3="https://api.selfbook.com/api/v3";const STATSIG_CLIENT_KEY="client-PV01TCjBc3a7zunh9brJUh2fIaLwbXaH7aQH2dFpSGW",STATSIG_EXPERIMENT="ddn",STATSIGN_SIGNAL_BOX_EXPERIMENT="ddn_signal_box";let SELFBOOK_APP_VERSION="v2",SELFBOOK_APP_BASE_URL=SELFBOOK_BASE_URL;const 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",IS_LANDING_PAGE_FLAG_ID="ddnLandingPage",BOOTSTRAP_ACTION="WIDGET/BOOTSTRAP",SELFBOOK_HOTEL_GROUP_INFO="selfbook_hotel_group_info",SELFBOOK_HOTEL_INFO="selfbook_hotel_info";window.selfbookStatsigClient=null;const 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"};let initialV35AvailabilityStartEndDates={},initialCalendarResponse=null;function setOverflowHidden(e){const t=e?"hidden":"";document.body.style.overflow=t,document.documentElement.style.overflow=t}function getStatsigValue(e,t){if(window.selfbookStatsigClient){const n=window.selfbookStatsigClient.getExperiment(e);return n&&n.value&&n.value[t]}return null}const SUPPORTED_LOCALES=["en","fr","pt","da","de","de-DE","es-MX","it","ja","ko","nl","ro","ru","sq","sv","vi","zh","zh-CN","zh-TW","es"];function parseLocaleFromUrl(){try{const{pathname:e}=new URL(window.location.href),t=e.split("/").filter(Boolean),n=t[0]?.toLowerCase();if(!n)return null;if(!/^[a-z]{2}(-[a-z]{2})?$/i.test(n))return null;const o=n.replace(/^([a-z]{2})(-[a-z]{2})?$/i,(e,t,n)=>n?`${t.toLowerCase()}-${n.slice(1).toUpperCase()}`:t.toLowerCase());return SUPPORTED_LOCALES.includes(o)?o:"en"}catch{return null}}function appendWidgetScript({src:e,callback:t,type:n="text/javascript"}){const o=document.createElement("script");o.type=n,o.src=e,document.body.appendChild(o),t&&"function"==typeof t&&(o.onload=function(){t()})}function initFloatingSearchbar({apiKey:e,hotelId:t}={}){appendWidgetScript({src:`${SELFBOOK_BASE_URL_V3}/widgets/floating-search-bar.js`,type:"module",callback:function(){const n=SELFBOOK_BACKEND_URL.replace(/\/v[123]/,"");window.renderWidget(null,{backendURL:n,hotelId:t,apiKey:e})}})}function initDDNSignalBox({signalPartner:e,apiKey:t,hotelId:n}={}){e&&"none"!==e&&appendWidgetScript({src:`${SELFBOOK_BASE_URL_V3}/widgets/ddn-signal-box.js`,callback:function(){const o=SELFBOOK_BACKEND_URL.replace(/\/v[123]/,"");window.renderSBSignalBox({backendURL:o,hotelId:n,apiKey:t,ddn_signal_partner:e,experiment:"ddn_signal_box",locale:parseLocaleFromUrl()})}})}function initWidgets({apiKey:e,hotelId:t,hotelData:n}){if(n?.enable_direct_distribution_network&&(n?.enable_paypal_partner&&n?.enable_paypal||n?.enable_perplexity_partner)){initDDNSignalBox({signalPartner:getStatsigValue("ddn_signal_box","ddn_signal_partner"),apiKey:e,hotelId:t})}}function initSDKBus(){const e={},t={};window.sb_sdkBus={emit(n,o){t[n]||(t[n]=[]),t[n].push(o),e[n]?.length&&e[n].forEach(e=>e(o))},on(t,n){e[t]||(e[t]=[]),e[t].push(n)},off(t,n){e[t]&&(e[t]=e[t].filter(e=>e!==n))},pull(e){const n=t[e]||[];return t[e]=[],n}}}function checkStatus(e){if(e.status>=200&&e.status<300)return e;const t=new Error(e.statusText);throw t.response=e,t}async function parseJSON(e){try{const t=await e.text();if(!t)return;return JSON.parse(t)}catch(e){console.error("parseJSON: err: ",e)}}function intervalWrapper(e,t){const n=setInterval(e,t);return function(){clearInterval(n)}}function getHotelBasicData(e){try{const t=getFromSessionStorage(SELFBOOK_HOTEL_GROUP_INFO).hotels?.filter(t=>t.id==e),n=t?.[0]||{};return getIsEnableV35(n)&&(n.app_version="v3",n.enable_v3_new_ui_version=!0),n}catch(e){return console.error("getHotelBasicData: err: ",e),{}}}function getFromSessionStorage(e){try{return JSON.parse(sessionStorage.getItem(e))}catch(e){return console.error("getFromSessionStorage: err: ",{e:e}),{}}}function getPersistedData(e){try{const t=JSON.parse(e.getItem("persist:root"));if(!t)return INITIAL_PERSISTED_DATA;const n=JSON.parse(t.booking||"{}"),o=JSON.parse(t.core||"{}"),a=JSON.parse(t?.router||"{}"),{expireTime:r}=o,s=(Date.now()-new Date(o.interactionTime))/1e3;return{isExpired:s>r,all:t,booking:n,core:o,router:a}}catch(e){return console.error("getPersistedData: err: ",e),INITIAL_PERSISTED_DATA}}function fillGuestsFields(e=[],t){const n=t.default_adult_occupancy?t.default_adult_occupancy:2;return e?.map(e=>e.type===GUEST_TYPE.ADULT?{type:GUEST_TYPE.ADULT,count:parseInt(e.count)||n}:e.type===GUEST_TYPE.CHILD&&parseInt(e.count)>0?{type:GUEST_TYPE.CHILD,count:parseInt(e.count),age:parseInt(e.age)||1,special_request:e.special_request||""}:e.type===GUEST_TYPE.INFANT&&parseInt(e.count)>0?{type:GUEST_TYPE.INFANT,count:parseInt(e.count)||1,age:parseInt(e.age)||1,special_request:e.special_request||""}:void 0).filter(Boolean)}function buildRoomsGuests(e,t){const n=t.default_adult_occupancy?t.default_adult_occupancy:2,o=()=>Math.random().toString(36).slice(2),a=["adult","child","childAges","room2Adult","room3Adult","room4Adult"].some(t=>!!e[t]);if(e.guests?.length&&!a)return Array.from({length:4},(t,a)=>{const r=0===a?"guests":`guestsRoom${a+1}`;if(!e[r])return null;const s=e[r]?.map(e=>{const t=e?.type===GUEST_TYPE.ADULT?e?.count||n:e?.count,a=e?.type===GUEST_TYPE.CHILD&&"number"==typeof e?.age;return{type:e?.type,count:Number(t),guest_details:a?[{key:o(),age:Number(e?.age)}]:void 0}});return{key:0===a?"room1":o(),data:s}}).filter(Boolean);const r=t=>Number(e[t]||0),[s,i,l,c]=["roomCount","adult","child","infants"].map(r);if(s>1&&!r("room2Adult")){const e=i||n,t=Math.floor(e/s);let a=e%s;return Array.from({length:s},(e,n)=>{const r=a>=n+1?1:0;return{key:0===n?"room1":o(),data:[{type:GUEST_TYPE.ADULT,count:t+r}]}})}const d=[];return Array.from({length:4}).forEach((t,a)=>{const s=a+1,u=0===a?i||n:r(`room${s}Adult`);if(u){const t=[{type:GUEST_TYPE.ADULT,count:u}],n=0===a?l:r(`room${s}Child`),i=e[0===a?"childAges":`room${s}ChildAges`];i?i.split(",").forEach(e=>{t.push({type:GUEST_TYPE.CHILD,count:1,guest_details:[{key:o(),age:Number(e)}]})}):n&&t.push({type:GUEST_TYPE.CHILD,count:n}),0===a&&c>0&&t.push({type:GUEST_TYPE.INFANT,count:c}),d.push({key:0===a?"room1":o(),data:t})}}),d}function buildRedirectSynxisLink(e,t){let n=`https://be.synxis.com/?hotel=${t.id}&theme=${t.synxis_theme}&config=${t.synxis_config}`;try{if(e){const{startDate:t,endDate:o,promoCode:a,groupCode:r,guests:s,iataNumber:i,couponCode:l,destinationId:c,nights:d,rate:u,hotelId:p,roomCategory:_}=e;d&&(n+=`&nights=${d}`),t&&(n+=`&arrive=${t}`),o&&(n+=`&depart=${o}`),a&&(n+=`&promo=${a}`),r&&(n+=`&group=${r}`),i&&(n+=`&iataNumber=${i}`),l&&(n+=`&couponCode=${l}`),u&&(n+=`&rate=${u}`),c&&(n+=`&destinationId=${c}`),Array.isArray(_)?n+=`&roomCategory=${_.map(e=>e).join(",")}`:_&&(n+=`&roomCategory=${_}`),s&&s.length>0?("adult"===s[0].type&&(n+=`&adult=${s[0].count}`),s[1]&&"child"===s[1].type&&(n+=`&child=${s[1].count}`)):n+="&adult=1"}}catch(e){console.error("buildRedirectSynxisLink: err: ",e)}return n}function selectShowWidgetButtonCopies(e){return e.core.showWidgetButtonCopies||{}}function selectRoute(e){return e?.router?.location?e.router.location.pathname:ROUTE_PATHS.app.editBooking}function isObjectEqual(e,t){return JSON.stringify(e)===JSON.stringify(t)}function isTemplateDomainMatch(e,t){return e?.booking_template_domain&&t?.target?.href?.includes(e.booking_template_domain)}function getElementById(e){return document?.getElementById(e)}function getIsEnableV35(e){return!!SELFBOOK_APP_VERSION.match(/^v3/i)||(e?.enable_v3_new_ui_version||!1)}function getIsLayers(e){return"layers"===e?.app_version||!!SELFBOOK_APP_VERSION.match(/^layers/i)}function runDirectApplication(){console.info("(!) selfbook: widget initialization started");let e,t,n,o=!1,a=!1,r=!1,s=!1,i=!1,l=!1,c=!1;function d(){try{const e=document.createElement("script");if(e.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;ee.destination_id?.toLowerCase()===o.destinationId.toLowerCase());e&&(o.hotelId=e.id)}else o.hotelId=o?.hotelId||a?.id;if(a?.enable_direct_distribution_network&&"signalBox"!==o.userStartingPoint&&(a?.enable_paypal_partner&&a?.enable_paypal||a?.enable_perplexity_partner)){const e=getStatsigValue("ddn_signal_box","ddn_signal_partner");if("paypal"===e){const t=function(){const e=g();if(e)return"authenticated"===e?.state?.step&&!!e?.state?.identifier}();l=c?{}:{partner:e,signalBoxUserVerified:!!t,paypalData:t?y():null,shouldExecuteRegularFlow:(!t||!a?.is_default_date_logic_enabled||"single"!==i?.structure)&&s}}}}setOverflowHidden(!0),window.toggleShowSBSignalBox?.(!1);const u=getElementById("selfbook_sdkwidget"),p=getElementById("selfbook_sdkwidget_wrapper");window.selfbookWidgetStore||(p.appendChild(function(){const e=document.createElement("div");return e.id="selfbook-loading",e.style.color="white",e.style.marginRight="-50%",e.style.position="absolute",e.style.top="50%",e.style.left="50%",e.style.fontFamily="sans-serif",e.style.transform="translate(-50%, -50%)",e.innerHTML='',e}()),p.style.zIndex=1e11,p.style.height="100%",p.style.background="v2"===SELFBOOK_APP_VERSION?"rgba(0, 0, 0, .74)":"rgba(39, 39, 39, 0.74)",setOverflowHidden(!0)),function(e){if(!0===r)return;n&&n.length>0&&n.forEach(e=>{if(e.includes(".js")){const t=document.createElement("script");t.type="text/javascript",t.src=`${SELFBOOK_APP_BASE_URL}/${e}`,document.body.appendChild(t)}});e?.enable_direct_distribution_network||d();r=!0}(a);const _=setInterval(()=>{if(window.selfbookWidgetStore){const n=getIsLayers(a),r={hotelInfo:{...!n&&{hotelIdAsArg:!!o.hotelId},...n&&{hotelResponse:getFromSessionStorage(SELFBOOK_HOTEL_INFO)},apiKey:o.apiKey||t,hotelId:o.hotelId||e},bookingData:{...o,...l},...!n&&{hotelGroupInfo:getFromSessionStorage(SELFBOOK_HOTEL_GROUP_INFO)},roomsGuests:o.roomsGuests||void 0,shouldExecuteRegularFlow:!1===l?.shouldExecuteRegularFlow?l?.shouldExecuteRegularFlow:s,userIP:o.userIP?.country_code?o.userIP:void 0,version:o.version,isDdnLandingPageSource:c};!function(){const e=document.getElementById("selfbook-loading");e&&getElementById("selfbook_sdkwidget_wrapper").removeChild(e)}(),clearInterval(_),window.selfbookWidgetStore.dispatch({type:BOOTSTRAP_ACTION,payload:r}),"none"===u.style.display&&(p.style.zIndex=1e11,p.style.height="100%",p.style.background="v2"===SELFBOOK_APP_VERSION?"rgba(0, 0, 0, .74)":"rgba(39, 39, 39, 0.74)",setOverflowHidden(!0)),setTimeout(()=>{u.style.display="block",u.setAttribute("class","slide-in")},20),setTimeout(()=>{const e=p.querySelector('[aria-modal="true"]');e&&e.focus()},250)}},100)}function _(){try{const{isExpired:e,core:t,booking:n}=getPersistedData(localStorage);if(e||!t?.hotel?.data?.id)return void function(){try{localStorage.removeItem("persist:root")}catch(e){console.error("removePersistedData: err",e)}}();const o=t.bootstrapArgs;f({...o,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:t.hotel.data.id})}catch(e){console.error("openPersistWidget: err",e)}}const m=async()=>await fetch(`${SELFBOOK_APP_BASE_URL}/asset-manifest.json`,{headers:{"content-type":"application/json"}}).then(e=>e.json()).then(e=>function(e){n=e.entrypoints}(e));function g(){try{return JSON.parse(localStorage.getItem("selfbook_ddn-signal-box_auth"))}catch(e){console.error("Unable to extract Signal box from local storage.")}}function y(){const e=g();if(e)return e?.state?.user?.paypal_data}async function f(n={}){try{if(o)return;n.currencyCode&&(n.currency=n.currencyCode,delete n.currencyCode);let a=n.shouldExecuteRegularFlow||!1;n.apiKey&&await k(n.apiKey,n.hotelId);const r=getHotelBasicData(n.hotelId||e);getIsLayers(r)&&await async function(e,t){try{l=!0;const n=await u({url:`${SELFBOOK_BACKEND_URL_V3}/hotels/${e}`,headers:{"content-type":"application/json","API-Key":t}});sessionStorage.setItem(SELFBOOK_HOTEL_INFO,JSON.stringify(n)),l=!1}catch(e){console.log(e)}}(n.hotelId||e,n.apiKey||t),console.log("args",n);const s=getIsEnableV35(r),c=getFromSessionStorage(SELFBOOK_HOTEL_GROUP_INFO),d="group"===c?.structure,_="single"===c?.structure,m=function(e,t=[]){if(!e||"object"!=typeof e||Array.isArray(e))return!1;for(const n in e){if(t.includes(n))continue;const o=e[n];if(null!=o&&!("string"==typeof o&&""===o.trim()||Array.isArray(o)&&0===o.length||"object"==typeof o&&!Array.isArray(o)&&0===Object.keys(o).length))return!0}return!1}(n,["version","selfbook","hotelId","destinationId"]);if(s&&!1!==n.shouldExecuteRegularFlow&&((/*!initialAPIsCallsExecuted && */_&&m||d&&!i)&&(a=!0),r?.is_default_date_logic_enabled?n.startDate&&n.endDate&&(_||d&&n.hotelId)&&(a=!0):a=!0),n.guests?n.guests=fillGuestsFields(n.guests,r):n.guests=[{type:GUEST_TYPE.ADULT,count:r.default_adult_occupancy?r.default_adult_occupancy:2}],r.redirect_to_synxis){const e=buildRedirectSynxisLink(n,r);return void window.open(e,"_blank").focus()}getIsEnableV35(r)&&(n.roomsGuests=buildRoomsGuests(n,r)),p(n,r,a),document.getElementsByTagName("html")[0].setAttribute("translate","no")}catch(e){console.error("bookNow: err: ",e)}}function h(){const e="\n #selfbook_sdkwidget {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0px;\n right: 0px;\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 ",t=document.createElement("style");t.textContent=e,document.head.append(t),function(e){const t=document.createElement("style");t.textContent=e,document.head.append(t)}(e)}function E(e){const t={startdate:"startDate",enddate:"endDate",rateplancode:"ratePlanCode",rate:"rate",roomid:"roomId",propertyid:"propertyId",destinationid:"destinationId",room:"room",room_count:"roomCount",adult:"adult",child:"child",child_ages:"childAges",infants:"infants",room2_adult:"room2Adult",room2_child:"room2Child",room2_child_ages:"room2ChildAges",room3_adult:"room3Adult",room3_child:"room3Child",room3_child_ages:"room3ChildAges",room4_adult:"room4Adult",room4_child:"room4Child",room4_child_ages:"room4ChildAges",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",include_inclusive_fees:"includeInclusiveFees",hotelid:"hotelId",version:"version",loyaltyuseremail:"loyaltyUserEmail",loyaltyeventname:"loyaltyEventname",loyaltysignupform:"loyaltySignupForm"};return Array.from(e.entries()).reduce((e,[n,o])=>({...e,[t[n.toLowerCase()]]:o}),{})}function S(){setTimeout(()=>{const t=setInterval(()=>{if(o||l)return;clearInterval(t);const n=E(new URLSearchParams(window.location.search));if("true"!==n.selfbook)return;const a=getHotelBasicData(n.hotel||n.hotelId||e),r=n.version?.toLowerCase?.();SELFBOOK_APP_VERSION=r||a?.app_version||"v2",w(n,a)},100)},500)}function w(e,t={}){const n=parseInt(t?.default_adult_occupancy)||2,o=[{type:"adult",count:e.adult||n},{type:"child",count:e.child||0},{type:"infants",count:e.infants||0}];f({...e,guests:o,groupCode:e.group,currency:e.currency||e.currencyCode,promoCode:e.promo||e.promocode,hotelId:e.hotel||e.hotelId||void 0,roomCategory:"string"==typeof e.roomCategory?e.roomCategory.split(",").map(e=>e.trim()):void 0})}async function b(){!function(){const e=document.createElement("div"),t=document.createElement("div");e.setAttribute("id","selfbook_sdkwidget"),e.style.display="none",t.setAttribute("id","selfbook_sdkwidget_wrapper"),t.style.background="rgba(0, 0, 0, 0)",t.style.position="fixed",t.style.top="0",t.style.right="0",t.style.width="100%",t.style.transition="background .5s ease-out",t.appendChild(e),document.body.appendChild(t)}(),await m(),function(){if(!0!==s){if(n&&n.length>0){const e=document.getElementsByTagName("head")[0];n.forEach(t=>{if(t.includes(".css")){const n=document.createElement("link");n.rel="stylesheet",n.type="text/css",n.media="all",n.href=`${SELFBOOK_APP_BASE_URL}/${t}`,e.appendChild(n)}})}s=!0}}(),_(),document?.querySelectorAll("a").forEach(t=>{t.addEventListener("click",t=>{try{"A"!==t.target.tagName&&"A"===t.target.parentNode?.tagName&&(t.target.href=t.target.parentNode.href);const n=t.target.href||"";if(-1===n.indexOf("?"))return;const o=E(new URLSearchParams(n.substring(n.indexOf("?")))),a=getHotelBasicData(o.hotelId||o.hotel||e);if(SELFBOOK_APP_VERSION=o.version?.toLowerCase?.()||a?.app_version||"v2",a?.mobile_display_only&&window.innerWidth>=768)return;(isTemplateDomainMatch(a,t)||"true"===o.selfbook)&&(t.preventDefault(),w(o,a))}catch(e){console.error("a-element: err: ",e)}})}),"complete"===document?.readyState?S():window?.addEventListener("load",S)}function O(e){return e.toISOString()}function I(){return new Promise(e=>{const t=document.createElement("script");t.src=`https://cdn.jsdelivr.net/npm/@statsig/js-client@3/build/statsig-js-client.min.js?apikey=${STATSIG_CLIENT_KEY}`,t.async=!0,t.onload=async()=>{await async function(){const e={userID:L()};let t=new window.Statsig.StatsigClient(STATSIG_CLIENT_KEY,e);await t.initializeAsync(),window.selfbookStatsigClient=t}(),e(t)},t.onerror=t=>{console.log("Failed to load Statsig script",t),e()},document.head.appendChild(t)})}function L(){const e="selfbook_statsig_anonymous_id";let t=localStorage.getItem(e);return t||(t=crypto.randomUUID?crypto.randomUUID():Math.random().toString(36).substring(2,15),localStorage.setItem(e,t)),t}async function k(n,r){try{o=!0;const s=r?`?id=${r}`:"",l=await u({url:`${SELFBOOK_BACKEND_URL}/hotels/info${s}`,headers:{"content-type":"application/json","API-Key":n}});sessionStorage.setItem(SELFBOOK_HOTEL_GROUP_INFO,JSON.stringify(l));const p={...l},_=getHotelBasicData(r);(function(e){const t=getFromSessionStorage(SELFBOOK_HOTEL_GROUP_INFO);return!("single"!==t?.structure||!e?.enable_direct_distribution_network&&!e?.enable_flex_cancellation)||!("group"!==t?.structure||!t?.hotels.some(e=>e.enable_direct_distribution_network||e.enable_flex_cancellation))||!("multiple_properties"!==t?.structure||!t?.hotels.some(e=>e.enable_direct_distribution_network||e.enable_flex_cancellation))})(_)&&await I(),d();const m=getIsLayers(_);!_?.enable_direct_distribution_network||m||c||initWidgets({apiKey:t,hotelId:e,hotelData:_}),m||initFloatingSearchbar({apiKey:t,hotelId:e});const g=E(new URLSearchParams(window.location.search));if(SELFBOOK_APP_VERSION=g.version?.toLowerCase?.()||_?.app_version||"v2",m?SELFBOOK_APP_BASE_URL=SELFBOOK_BASE_URL_LAYERS:SELFBOOK_APP_VERSION.match(/^v3/i)?(SELFBOOK_APP_BASE_URL=SELFBOOK_BASE_URL_V3,p.hotels=p?.hotels?.map(e=>({...e,enable_v3_new_ui_version:!0}))):SELFBOOK_APP_BASE_URL=SELFBOOK_BASE_URL,sessionStorage.setItem(SELFBOOK_HOTEL_GROUP_INFO,JSON.stringify(p)),!i&&getIsEnableV35(_)&&_?.is_default_date_logic_enabled&&"group"!==p?.structure)try{const t=await async function(t,n,o){try{const a=function(){const e=new Date,t=new Date(e.getFullYear(),e.getMonth(),1),n=new Date(e.getFullYear(),e.getMonth()+2,0);return{startDate:A(t),endDate:A(n)}}(),r={start_date:a.startDate,end_date:a.endDate,currency_code:o?.currency_code||"USD",guests:[{type:"adult",count:o?.default_adult_occupancy||2}]};window.sb_sdkBus.emit("sdk-calendar-status",{type:"loading",payload:r});const s=await u({url:`${"v2"===SELFBOOK_APP_VERSION?SELFBOOK_BACKEND_URL:SELFBOOK_BACKEND_URL.replace("v2","v3")}/hotels/${n||e}/calendar`,headers:{"content-type":"application/json","API-Key":t},data:JSON.stringify(r),method:"POST"});return initialCalendarResponse=s,window.sb_sdkBus.emit("sdk-calendar-status",{type:"success",payload:s}),s.data}catch(e){window.sb_sdkBus.emit("sdk-calendar-status",{type:"error",error:e.message}),console.log(e)}}(n,r,_),o=function(e){const t=new Date,n=t.getUTCFullYear(),o=t.getUTCMonth(),a=t.getUTCDate(),r=new Date(Date.UTC(n,o,a+14));let s=e.filter(e=>function(e){const[t,n,o]=e.split("-").map(Number);return new Date(Date.UTC(t,n-1,o))}(e.date)>r&&null!=e.price);0===s.length&&(s=e.filter(e=>null!=e.price));return 0===s.length?null:s.reduce((e,t)=>t.price`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`;const B=document?.getElementById("selfbook_jssdk");if(B){const n=new URL(B.getAttribute("src"));if(e=n.searchParams.get("hotelId"),t=n.searchParams.get("apiKey"),c="true"===n.searchParams.get("ddnLandingPage"),"?11howard"===window.location.search&&window.location.href.includes("staging")&&(e="66350",t="x9GTqyGB8Pboi5Tkk3fuQUrQ8qAecxzxNY0"),!t||!e)throw new Error("(!) selfbook: ApiKey and HotelId are required.");window.isSelfbookSDKActive=!0,initSDKBus(),k(t,e).then(e=>{getIsLayers(e)||h()})}window&&(window.sbApiLogger=function(n,o={},a){const r=`${"v2"===SELFBOOK_APP_VERSION?SELFBOOK_BACKEND_URL:SELFBOOK_BACKEND_URL.replace("v2","v3")}/hotels/${a||e}/events`;try{const e={generated_at:(new Date).toISOString(),event_source:"SDK",event_name:n,body:JSON.stringify(o)};fetch(r,{method:"POST",headers:{"Content-Type":"application/json","API-Key":t},body:JSON.stringify(e)})}catch(e){console.error("sbApiLogger error:",e)}},window.book=function(e,t,n,o,a,r,s,i,l,c,d="fr",u,p,_){f({startDate:e,endDate:t,guests:n,propertyId:o,currency:a,roomId:r,ratePlanCode:s,rate:i,promoCode:l,groupCode:c,locale:d,destinationId:p,hotelId:u,roomCategory:_})},window.bookNow=f,window.closeSelfbookWidget=function(){const e=getElementById("selfbook_sdkwidget"),t=getElementById("selfbook_sdkwidget_wrapper");setOverflowHidden(!1),e.setAttribute("class","slide-out"),t.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"}}),window.toggleShowSBSignalBox?.(!0),setTimeout(()=>{e.style.display="none",t.style.zIndex=-1e11},800)})}runDirectApplication(); /* eslint-disable no-undef */ /* ---------------------------------- // Integration for the Yotel Hotel Group https://www.yotel.com Chain Code: 17799 Mobile + Desktop ---------------------------------- */ /* Hotel's agency did integration with their date picker */ /* 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 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), 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); } // 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 compareDates(arrive, depart) { if (arrive && depart) { let arrivalDate = new Date(arrive); let departureDate = new Date(depart); arrivalDate.setHours(0, 0, 0, 0); departureDate.setHours(0, 0, 0, 0); if (arrivalDate > departureDate) { return false } return true; } return false; } 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); } } // 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]); } } } // Save a reference to the original bookNow() function const originalBookNow = bookNow; // Custom function that tracks bookNow() function sbBookNowTracker(myArgs) { if (myArgs && typeof myArgs === 'object') { let hasInvalidDates = !myArgs.startDate || !myArgs.endDate || myArgs.startDate.includes("NaN") || myArgs.endDate.includes("NaN"); if (hasInvalidDates) { console.log("Invalid dates detected:", myArgs); delete myArgs.startDate; delete myArgs.endDate; } // console.log('myArgs.startDate, myArgs.endDate',myArgs.startDate, myArgs.endDate, compareDates(myArgs.startDate, myArgs.endDate)); if (!compareDates(myArgs.startDate, myArgs.endDate)) { delete myArgs.startDate; delete myArgs.endDate; } if (myArgs.hotelId == '9194') { customAmsterdamTaxText(); customHideZeroTaxesAndFees(); } else if ( myArgs.hotelId == '8454' || myArgs.hotelId == '9694' || myArgs.hotelId == '31082' || myArgs.hotelId == '36681' || myArgs.hotelId == '10361') { customHideZeroTaxesAndFees(); customAmsterdamRemoveStyleTag(); } else if ( myArgs.hotelId == '76937' || myArgs.hotelId == '36425' || myArgs.hotelId == '64714' || myArgs.hotelId == '79147' || myArgs.hotelId == '77041' || myArgs.hotelId == '19828' || myArgs.hotelId == '8182' || myArgs.hotelId == '36424') { customRemoveHideZeroTaxesAndFees(); customAmsterdamRemoveStyleTag(); } else { customAmsterdamRemoveStyleTag(); customRemoveHideZeroTaxesAndFees(); } } else { console.log("no arguments, using default:", myArgs); } return myArgs; } // Override Selfbook's bookNow() function with new custom function // Override Selfbook's bookNow() function function newCustomBookNow(args) { let updatedArgs = sbBookNowTracker(args); return originalBookNow.call(this, updatedArgs); } // Assign override function to bookNow(); bookNow = newCustomBookNow; function findPricingModelTaxInfo() { const oldText = "Inc. fees, Excl. taxes"; let newText = "Inc. taxes & fees"; // room list screen if (document.querySelector('ul[data-testid="rooms-list"] li.sb-room-item span') && !document.querySelector('ul[data-testid="rooms-list"] li.sb-room-item span[data-sb-updated]')) { document.querySelectorAll('ul[data-testid="rooms-list"] li.sb-room-item span').forEach(elm => { document.querySelector('ul[data-testid="rooms-list"] li.sb-room-item span').setAttribute("data-sb-updated", "true"); if (elm.textContent === oldText) { elm.textContent = newText; } }) } // calendar if (document.querySelector('[data-testid="sb-cal-prices-msg"] span span') && !document.querySelector('[data-testid="sb-cal-prices-msg"] span span[data-sb-updated]')) { document.querySelector('[data-testid="sb-cal-prices-msg"] span span').setAttribute("data-sb-updated", "true"); document.querySelector('[data-testid="sb-cal-prices-msg"] span span').textContent = newText; } } function hideV2propertySelector() { if (!document.querySelector("#sb-yotel-v2")) { const customStyles = document.createElement("style"); customStyles.id = "sb-yotel-v2" customStyles.innerText = ` #sb-property-select { display: none !important; } [data-testid="properties-list"] li:nth-of-type(12) div div div div div { display: none !important; } `; document.head.appendChild(customStyles); } } function removeV2propertySelector() { if (document.querySelector("#sb-yotel-v2")) { document.querySelector("#sb-yotel-v2").remove(); } } setInterval(() => { if (typeof selfbookWidgetStore !== 'undefined' && selfbookWidgetStore?.getState()?.core?.hotel?.data?.id) { let hotelId = selfbookWidgetStore?.getState()?.core?.hotel?.data?.id; // console.log('hotelId', hotelId); if (hotelId === '36425' || hotelId === '36424') { findPricingModelTaxInfo(); } if (selfbookWidgetStore?.getState()?.core?.hotel?.data?.enable_v3_new_ui_version !== true) { hideV2propertySelector(); } if (selfbookWidgetStore?.getState()?.core?.hotel?.data?.enable_v3_new_ui_version === true) { removeV2propertySelector(); } } }, 1000); // 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('airside') == true || window.location.href.includes('london-stratford') == true || window.location.href.includes('park-city') == true || window.location.href.includes('geneva-lake') == true || window.location.href.includes('istanbul-airport-airside') == true || window.location.href.includes('tokyo-ginza') == 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 */ function 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 */ function 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 */ function 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 */ function formatDepartureDate(date) { if (!date) { return null; } return convertDate(date); }; function 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; }; function 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'; } }; function 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 function 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() */ function 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; 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=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') || /* Add code here */ 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(); e.stopImmediatePropagation(); // eslint-disable-next-line no-undef bookNow(finalParams); }); } } } } }; function closeHotelRoomModal() { if (document.querySelector('.yotel-modal-close')) { document.querySelector('.yotel-modal-close').click(); } } // Clone a CTA function RoomPagesButtonLinksCloner(bookNowButton) { if (bookNowButton !== null) { const link = bookNowButton.getAttribute('data-href').toLowerCase(); // https://www.yotel.com/?selfbook=true&locale=en&hotelId=32229&sbreplaced=true if (link.includes('be.synxis.com')) { if (link.includes('9194') || link.includes('76937') || link.includes('8454') || link.includes('9694') || link.includes('31082') || link.includes('36681') || link.includes('36425') || link.includes('64714') || link.includes('10361') || link.includes('8221') || link.includes('79147') || link.includes('77041') && isMobile() || link.includes('19828') || link.includes('8182') || link.includes('36424') ) { const bookNowButtonClone = bookNowButton.cloneNode(true); bookNowButton.parentNode.replaceChild(bookNowButtonClone, bookNowButton); bookNowButtonClone.addEventListener('click', (e) => { // eslint-disable-next-line no-undef e.preventDefault(); e.stopImmediatePropagation(); const parsedLink = parseURL(link); const finalParams = assignObjectVals(parsedLink[1]); bookNow(finalParams); closeHotelRoomModal(); }); } } } } function buttonsNotLinks() { if (document.querySelector(`button[data-href*='synxis']`)) { document.querySelectorAll(`button[data-href*='synxis']`).forEach(button => { if (!button.getAttribute('sb-updated')) { button.setAttribute('sb-updated', 'true'); RoomPagesButtonLinksCloner(button); } }); } } let sbHideMemberBanner = document.createElement("style"); sbHideMemberBanner.innerHTML = ` #sb-top-wrapper hr { display: none !important; } `; document.head.appendChild(sbHideMemberBanner); function changeHeaderCopy() { //Change from "Find the perfect room ..." to "Find a room ..." if (document.querySelector('[aria-label="BOOKING"] div[role="presentation"] + section div div:nth-child(2)') && document.querySelector('[aria-label="BOOKING"] div[role="presentation"] + section div div:nth-child(2)').textContent.includes("Find the perfect room")) { let target = document.querySelector('[aria-label="BOOKING"] div[role="presentation"] + section div div:nth-child(2)'); const textPart = target.childNodes[0].nodeValue.trim(); // "Find the perfect room" const spanPart = target.querySelector('span').outerHTML; // at YOTEL Boston Seaport // console.log(textPart); // → "Find the perfect room" // console.log(spanPart); // → at YOTEL Boston Seaport document.querySelector('[aria-label="BOOKING"] div[role="presentation"] + section div div:nth-child(2)').innerHTML = `Find a room ` + spanPart; } } function removeMemberBanner() { if (document.querySelector('[aria-label="BOOKING"] [alt="Sbid loyalty logo"]') && document.querySelector('[aria-label="BOOKING"] #sbid-create-account')) { document.querySelector('[aria-label="BOOKING"] [alt="Sbid loyalty logo"]').parentElement.remove(); } } setInterval(() => { changeHeaderCopy(); buttonsNotLinks(); linkReplacer(); removeMemberBanner(); }, 1000); let code = ''; const hotelInfo = { 'YOTEL Amsterdam': { hotelId: '9194', dataId: '236' }, 'YOTEL Amsterdam New': { hotelId: '9194', dataId: '7166' }, 'YOTEL Boston': { hotelId: '76937', dataId: '7171' }, 'YOTEL Boston New': { hotelId: '76937', dataId: '221' }, 'YOTEL Edinburgh': { hotelId: '8454', dataId: '7176' }, 'YOTEL Edinburgh New': { hotelId: '8454', dataId: '256' }, 'YOTEL Glasgow': { hotelId: '9694', dataId: '7186' }, 'YOTEL Glasgow New': { hotelId: '9694', dataId: '281' }, 'YOTEL London City': { hotelId: '31082', dataId: '7206' }, 'YOTEL London City New': { hotelId: '31082', dataId: '3651' }, 'YOTEL Manchester Deansgate': { hotelId: '36681', dataId: '7211' }, 'YOTEL Manchester Deansgate New': { hotelId: '36681', dataId: '4161' }, 'YOTEL Miami': { hotelId: '36425', dataId: '7121' }, 'YOTEL Miami New': { hotelId: '36425', dataId: '1991' }, 'YOTEL New York Times Square': { hotelId: '64714', dataId: '7216' }, 'YOTEL New York Times Square New': { hotelId: '64714', dataId: '106' }, 'YOTEL Porto': { hotelId: '10361', dataId: '7221' }, 'YOTEL Porto New': { hotelId: '10361', dataId: '4011' }, 'YOTEL San Francisco': { hotelId: '79147', dataId: '7226' }, 'YOTEL San Francisco New': { hotelId: '79147', dataId: '226' }, 'YOTEL Singapore': { hotelId: '77041', dataId: '7231' }, 'YOTEL Singapore New': { hotelId: '77041', dataId: '271' }, 'YOTEL Washington DC': { hotelId: '19828', dataId: '7246' }, 'YOTEL Washington DC New': { hotelId: '19828', dataId: '206' }, 'YOTELAIR Singapore Changi Airport': { hotelId: '8182', dataId: '7276' }, 'YOTELAIR Singapore Changi Airport New': { hotelId: '8182', dataId: '276' }, 'YOTEL Istanbul Airport (Landside)': { hotelId: '8221', dataId: '7196' }, 'YOTEL Istanbul Airport (Landside) New': { hotelId: '8221', dataId: '266' }, // 'YOTELAIR Istanbul Airport (Airside)': {hotelId: '8222', dataId: '7261'}, // 'YOTELAIR Istanbul Airport (Airside) New': {hotelId: '8222', dataId: '261'}, 'YOTELPAD Miami': { hotelId: '36424', dataId: '7291' }, 'YOTELPAD Miami New': { 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'); } } } 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(); const 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); } }); } } // customise the text and add a link for Yotel const EmailOptInText = { english: 'I\'d like to receive YOTEL marketing communications, including exclusive offers and the latest news.', french: 'J\'aimerais recevoir les communications marketing de YOTEL, notamment des offres exclusives et les dernières nouvelles.', german: 'Ich möchte Marketingmitteilungen von YOTEL erhalten, darunter exklusive Angebote und die neuesten Nachrichten.', dutch: 'Ik wil graag marketingcommunicatie van YOTEL ontvangen, inclusief exclusieve aanbiedingen en het laatste nieuws.', spanish: 'Me gustaría recibir comunicaciones de marketing de YOTEL, incluidas ofertas exclusivas y las últimas noticias.', portuguese: 'Gostaria de receber comunicações de marketing do YOTEL, incluindo ofertas exclusivas e as últimas novidades.', italian: 'Desidero ricevere comunicazioni di marketing di YOTEL, comprese offerte esclusive e le ultime novità.', }; function setEmailOptInTextByLocale() { const localeList = { 'fr-FR': EmailOptInText.french, 'fr-fr': EmailOptInText.french, 'fr': EmailOptInText.french, /* French */ 'de-DE': EmailOptInText.german, 'de-de': EmailOptInText.german, 'de': EmailOptInText.german, /* German */ 'nl': EmailOptInText.dutch, /* Dutch */ 'it-IT': EmailOptInText.italian, 'it-it': EmailOptInText.italian, 'it': EmailOptInText.italian, /* Italian */ 'es-ES': EmailOptInText.spanish, 'es-es': EmailOptInText.spanish, 'es': EmailOptInText.spanish, /* Spanish (Spain) */ 'es-MX': EmailOptInText.spanish, 'es-mx': EmailOptInText.spanish, /* Spanish (Mexico) */ 'pt-PT': EmailOptInText.portuguese, 'pt-pt': EmailOptInText.portuguese, 'pt': EmailOptInText.portuguese, /* Portuguese */ }; const locale = document.querySelector('#selfbook_sdkwidget [lang]').getAttribute('lang'); return localeList[locale] || localeList[document.documentElement.lang] || EmailOptInText.english; }; setInterval(() => { // Marketing opt-in box pre selected during the checkout process if (!document.querySelector('[data-testid="sb-checkbox"][for="email-me-special-offers"][data-sb-email-me-special-offers-override]') && document.querySelector('[data-testid="sb-checkbox"][for="i-accept-hotel-terms-checkbox"]') && document.querySelector('[data-testid="sb-checkbox"][for="email-me-special-offers"]')) { document.querySelector('[data-testid="sb-checkbox"][for="email-me-special-offers"]').setAttribute('data-sb-email-me-special-offers-override', 'true'); document.querySelector('#sb-screen label[for="email-me-special-offers"]:nth-child(2) span').innerHTML = setEmailOptInTextByLocale(); } // Marketing opt-in box pre selected for create account screen if (!document.querySelector('[data-testid="sb-checkbox"][for="sb-email-optin-checkbox"][data-sb-email-optin-checkbox-override]') && document.querySelector('[data-testid="sb-checkbox"][for="sb-policy-checkbox"]') && document.querySelector('[data-testid="sb-checkbox"][for="sb-email-optin-checkbox"]')) { document.querySelector('[data-testid="sb-checkbox"][for="sb-email-optin-checkbox"]').setAttribute('data-sb-email-optin-checkbox-override', 'true'); document.querySelector('#sb-screen label[for="sb-email-optin-checkbox"]:nth-child(2) span').innerHTML = setEmailOptInTextByLocale(); } if (typeof selfbookWidgetStore !== 'undefined') { const hotelId = selfbookWidgetStore?.getState()?.core?.hotel?.data?.id; if (customHotelText[parseInt(hotelId)]) { const selectors = customHotelText[parseInt(hotelId)]; selectors.forEach(({ selector, find, replace }) => updateText(selector, find, replace)); } } }, 1000); const style = document.createElement('style'); style.textContent = ` /* CSS Conflict. ACCESSIBLE ROOMS toggle hidden. Must be shown */ #selfbook-ada-rooms { opacity: 1 !important; } #widget-inner-wrapper [type=checkbox]:not(:checked), [type=checkbox]:checked { opacity: 1 !important; } #sb-rooms-filters-content__checkbox-filter { opacity: 1 !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; } #iprefer-rewards-wrapper { display: none !important; } [aria-label="BOEKING"] #sb-top-wrapper, [aria-label="BOOKING"] #sb-top-wrapper { margin-top: unset !important; } [data-testid="properties-list"] li button div div div { display: none !important; } `; document.head.appendChild(style); // Start of SSM-1175 // SSM-1175 - Text customization request: special request on summary page function 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); function isMobile() { console.log('isMobile() called'); return window.innerWidth < 768; } } })(); // Clone a room function roomCloner(selector, roomId, roomName, roomImage, roomDescription) { console.log(`${roomId}, ${roomName}, ${roomImage}`); const newRoom = selector; if (newRoom !== null) { const newRoomClone = newRoom.cloneNode(true); newRoomClone.setAttribute('data-roomid', roomId); newRoomClone.querySelector('h3').textContent = roomName; newRoomClone.querySelector('h3 + div div span:nth-child(1)').textContent = ''; newRoomClone.querySelector('h3 + div div span:nth-child(2)').textContent = ''; newRoomClone.querySelector('h3 + div > span').textContent = ''; if (newRoomClone.querySelector('img + div > div:nth-child(2)')) { newRoomClone.querySelector('img + div > div:nth-child(2)').innerHTML = roomDescription; newRoomClone.querySelector('img + div > div:nth-child(2)').classList.add('sb-custom-room-card-text'); newRoomClone.querySelector('[data-roomid="sb-int-room-item-1"] div svg[title="number-of-people"] ~ div:first-of-type').textContent = 'Max 1 Guest'; } else if (newRoomClone.querySelector('img + div + div > div:nth-child(2)')) { newRoomClone.querySelector('img + div + div > div:nth-child(2)').classList.add('sb-custom-room-card-text'); newRoomClone.querySelector('img + div + div > div:nth-child(2)').innerHTML = roomDescription; newRoomClone.querySelector('[data-roomid="sb-int-room-item-1"] div svg[title="number-of-people"] ~ div:first-of-type').textContent = 'Max 1 Guest'; } newRoomClone.querySelector('img').src = roomImage; const roomList = document.querySelector('ul[data-testid="rooms-list"]'); if (roomList) { roomList.appendChild(newRoomClone); newRoomClone.addEventListener('click', (e) => { e.preventDefault(); e.stopImmediatePropagation(); } ); } } } const customRoomList = [{ roomName: 'Family Cabin', roomImage: 'https://media.iceportal.com/134123/photos/68478419_M.jpg', roomId: 'sb-int-room-item-1', hotelId: '8454', hotelName: 'YOTEL Edinburgh', roomDescription: ` Ideal for families, with a queen-size bed, two bunk beds for the kids, Urban Jungle toiletries, and space-smart design that keeps everyone comfortable (and out of each other’s way).
Ready to book?
  1. Edit your booking above
  2. Select 2 adults and 2 children (under 12)
  3. Choose the family room from the available options
` }]; (() => { const customStyles = document.createElement('style'); customStyles.innerText = ` /* Calendar messaging styles */ #sb-cal-prices-msg div { display: none !important; } #sb-cal-prices-msg p { font-size: 14px !important; } #sb-cal-prices-msg a { color: #012993 !important; text-decoration: none !important; cursor: pointer !important; font-size: 14px !important; } .sb-custom-room-card-text { font-family: Montserrat !important; font-size: var(--sb-font-size-sm, 14px) !important; line-height: var(--sb-font-size-sm-line-height, 20px) !important; padding-top: 1em !important; padding-bottom: 1em !important; } .sb-custom-room-card-text ol li { font-family: Montserrat !important; margin-left: 25px !important; } .sb-custom-room-card-text + div { display: none !important; } [data-testid="sb-cal-prices-msg"] { font-size: 12px !important; margin--top: 10px !important; margin-bottom: 20px !important; } [data-testid="sb-cal-prices-msg"] a { color: #012993 !important; cursor: pointer !important; text-decoration: underline !important; text-underline-offset: 3px !important; font-weight: 500 !important; } `; document.head.appendChild(customStyles); } )(); // convert room availability message to html function roomAvailabilityMessage() { if (document.querySelector('[data-testid="sb-snackbar-children-wrapper"]')) { let calendarText = document.querySelector('[data-testid="sb-snackbar-children-wrapper"]').innerText; if (calendarText && calendarText.includes("href=")) { document.querySelector('[data-testid="sb-snackbar-children-wrapper"]').innerHTML = calendarText; } } } // convert calendar message to html function calendarMessageToHTML() { if (document.querySelector('[data-testid="sb-cal-prices-msg"]')) { const calendarText = document.querySelector('[data-testid="sb-cal-prices-msg"]').innerText; if (calendarText && calendarText.includes('href=')) { document.querySelector('[data-testid="sb-cal-prices-msg"]').innerHTML = calendarText; } } } setInterval(() => { roomAvailabilityMessage(); calendarMessageToHTML(); if (document.querySelector('ul[data-testid="rooms-list"] li') && !document.querySelector('ul[data-testid="rooms-list"] li[data-sb-updated-room]')) { document.querySelectorAll('ul[data-testid="rooms-list"] li').forEach((room, index) => { // console.log(room, index); room.setAttribute('data-sb-updated-room', true); const stateGuestCount = selfbookWidgetStore.getState().booking.bookingForm.guests[0].count; // console.log(stateGuestCount); if ((index === (document.querySelectorAll('ul[data-testid="rooms-list"] li').length - 1) && stateGuestCount > 0)) { const stateHotelId = selfbookWidgetStore.getState().core.hotel.data.id; customRoomList.filter((room) => room.hotelId === stateHotelId.toString()).forEach((item) => { // console.log(room); roomCloner(room, item.roomId, item.roomName, item.roomImage, item.roomDescription); } ); } } ); } }, 1000);