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}`),u&&(n+=`&hotel=${u}`),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",search:"search",sbsearch:"sbsearch",threeDsContinueId:"three_ds_continue_id",status:"status",roomcategory:"roomCategory",properties:"properties"};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();
/*
Mira Hong Kong
www.themirahotel.com/hong-kong/en/?selfbook-staging
Hotel code: 28926
*/
// Standard Integration Code Goes Here
console.log(
'%cCustom script has been initialized',
'background: green; color: white;',
);
function setLocale(lang) {
if (lang == '' || lang == undefined || lang == null) {
return 'en-US';
} else if (lang) {
return lang;
}
// Check if simple chinese
else if (window.location.href.includes('/sc/')) {
return 'zh-CN';
}
// Check for traditional chinese
else if (window.location.href.includes('/tc/')) {
return 'zh-TW';
}
// default to english
else {
return 'en-US';
}
}
function bookByUrl() {
let localeFromUrl = '';
if (window.location.href.includes('/sc/')) {
localeFromUrl = 'zh-CN';
}
// Check for traditional chinese
else if (window.location.href.includes('/tc/')) {
localeFromUrl = 'zh-TW';
}
// default to english
else {
localeFromUrl = 'en-US';
}
bookNow({
locale: localeFromUrl,
});
}
let replacedLinks = 0;
/*
Checks the format of the inputted date and puts it in the correct order format (YYYY-MM-DD)
*/
function convertDate(date) {
const inputDate = new Date(date);
const year = inputDate.getFullYear();
const month = (inputDate.getMonth() + 1).toString().padStart(2, '0');
const day = inputDate.getDate().toString().padStart(2, '0');
return [year, month, day].join('-');
};
/*
Validates date format is 'YYYY-MM-DD'
*/
function checkDateIsISOformat(inputString) {
const regexPattern = /^\d{4}-\d{2}-\d{2}$/;
return regexPattern.test(inputString);
}
/*
Verifies these date formats: 'DD MONTH YYYY', 'YYYY-MM-DD', 'YYYY/MM/DD', 'MM/DD/YYYY'
*/
function verifyFutureDate(date) {
if (date) {
if (checkDateIsISOformat(date)) {
const inputDate = new Date(date);
const today = new Date();
today.setHours(0, 0, 0, 0);
if (inputDate > today) {
const formattedDate = inputDate.toISOString().split('T')[0];
return formattedDate;
}
} else {
const inputDate = new Date(date);
const today = new Date();
today.setHours(0, 0, 0, 0);
if (inputDate > today) {
return convertDate(inputDate);
}
}
}
return '';
}
/* This function filters the initial parameters and returns the ones that
are null of undefined, it also flattens the array / object within guests */
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;
}
}
if (
pruneObject[key] !== null && pruneObject[key][1].count !== null) {
const childCount = pruneObject[key][1].count;
pruneObject.child = childCount;
} else {
delete pruneObject[key];
}
}
if (!pruneObject[key]) {
// console.log(pruneObject[key]);
delete pruneObject[key];
}
return pruneObject;
});
return pruneObject;
};
/* Fix for Currency Case Bug */
const upperCaseCurrency = (currency) => {
if (!currency) {
return null;
}
const currencyCode = currency.toUpperCase();
return currencyCode;
};
/* This function defines the bookNow() Object and assigns the values
after running it through pruneObjectKeys(). */
const assignObjectVals = (param) => {
const urlData = param;
const bookNowParams = {
startDate: verifyFutureDate(urlData.arrive),
endDate: verifyFutureDate(urlData.depart),
guests: [
{
type: 'adult',
count: (!urlData.adult ? null : parseInt(urlData.adult, 10)),
},
{
type: 'child',
count: (!urlData.child ? null : parseInt(urlData.child, 10)),
},
],
propertyId: urlData.propertyId,
currency: upperCaseCurrency(urlData.currency),
roomId: urlData.room,
ratePlanCode: urlData.rate,
promoCode: urlData.promo,
groupCode: urlData.group,
locale: setLocale(urlData.locale),
hotelId: urlData.hotel,
iataNumber: urlData.agencyid,
};
// console.log('assignObjectVals urlData.child', urlData.child);
return pruneObjectKeys(bookNowParams);
};
// Create a function that parses the URL and returns an object with the params
const parseURL = (url) => {
const params = {};
let urlInput = url.replace(/%20/g, '');
urlInput = urlInput.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)),
).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']`);
// const allSynxisLinks = document.querySelectorAll(`a[href*='reservations'], a[href*='synxis']`);
for (let i = 0; i < allSynxisLinks.length; i++) {
allSynxisLinks[i].removeAttribute('target');
const atag = allSynxisLinks[i];
const link = allSynxisLinks[i].href;
if (!link.includes('signin')) {
const parsedLink = parseURL(link);
const finalParams = assignObjectVals(parsedLink[1]);
atag.href = parseURL(link)[0];
// console.log('parseURL(link)[0]', parseURL(link)[0]);
// console.log('finalParams', finalParams)
// atag.href = '#';
atag.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
bookNow(finalParams);
});
replacedLinks += 1;
}
}
};
linkReplacer();
console.log('Replaced Links', replacedLinks);
if (document.querySelector('#booking-widget-form')) {
document.querySelector('#booking-widget-form').addEventListener('submit', (e) => {
// Desktop hero form
e.preventDefault();
const obj = {};
obj.arrive = document.querySelector('#booking-widget-arrive').value;
obj.depart = document.querySelector('#booking-widget-depart').value;
obj.adult = document.querySelector('#mira_booking_widget_adult_num').value;
if (document.querySelector('#booking-widget-form > div.booking-widget-top > div:nth-child(4) > ul > li.same-as-selected')) {
const childText = document.querySelector('#booking-widget-form > div.booking-widget-top > div:nth-child(4) > ul > li.same-as-selected').textContent;
obj.child = childText.split(' ')[0];
} else {
obj.child = '';
}
if (document.querySelector('#booking-widget-form > div.booking-widget-top > div:nth-child(5) > ul > li.same-as-selected')) {
const roomsText = document.querySelector('#booking-widget-form > div.booking-widget-top > div:nth-child(5) > ul > li.same-as-selected').textContent;
obj.rooms = roomsText.split(' ')[0];
} else {
obj.rooms = '';
}
obj.promo = document.querySelector('#booking-widget-form > div.booking-widget-bottom > div.booking-widget-promo-code > input').value;
obj.agencyid = document.querySelector('#booking-widget-form > div.booking-widget-bottom > div.booking-widget-corporate-code > input').value;
bookNow(assignObjectVals(obj));
});
}
// Popup/Dynamic CTAs with offers
const clickEventListenerAdded = false; // Variable to track whether the event listener is added
setInterval(() => {
if (document.querySelectorAll('a.ug-link, #ug-buttons-group-0 > a')) {
const links = document.querySelectorAll('a.ug-link, #ug-buttons-group-0 > a');
links.forEach((elem) => {
if (elem.getAttribute('href')) {
const hlink = elem.getAttribute('href').toLowerCase();
if (hlink.includes('synxis')) {
linkReplacer();
}
}
});
}
}, 1000);
document.addEventListener('click', function(e) {
if (
e.target &&
e.target.nodeName == 'BUTTON' &&
e.target.getAttribute('aria-label') == 'Close' ||
e.target.parentElement.parentElement?.nodeName == 'BUTTON' &&
e.target.parentElement.parentElement?.getAttribute('aria-label') == 'Close' ||
e.target.parentElement.nodeName == 'BUTTON' &&
e.target.parentElement.getAttribute('aria-label') == 'Close'
) {
removeOverFlowHidden();
}
});
function removeOverFlowHidden() {
let counter = 0;
const iScroll = setInterval(function() {
counter++;
if (document.body.style.overflow == '') {
console.log(`Took ${counter} loops to remove overflow hidden`);
clearInterval(iScroll);
} else {
document.body.style = 'position: static;';
}
}, 500);
}
function cloneElem(selector) {
// Get the element
const elem = document.querySelector(selector);
// Create a copy of it
const clone = elem.cloneNode(true);
// Update the ID and add a class
clone.setAttribute('onclick', 'event.preventDefault();event.stopImmediatePropagation();event.stopPropagation();bookByUrl();');
// Inject it into the DOM
elem.after(clone);
elem.remove();
}
// Top nav CTA
cloneElem('body > div.inner-bkg > header > div.header-button-group > button.desktop-header-button.book-room-menu-toggle.remove-button-style');
// Top nav CTA responsive
cloneElem('#mobile-book-button-container > div > button.mobile-book-room-menu-toggle.remove-button-style');
// remove date-picker
function removeDatePicker() {
let counter = 0;
const intVar = setInterval(function() {
counter++;
if (document.querySelector('#book-room-menu-container')) {
document.querySelector('#book-room-menu-container').remove();
clearInterval(intVar);
}
}, 500);
}
removeDatePicker();
// Check availability CTAs, desktop and mobile
document.querySelectorAll('div.wp-block-mira-button-block').forEach((el) => {
el.addEventListener('click', (e) => {
if (e.target.href) {
if (e.target.href.includes('tel:+') || e.target.href.indexOf('synxis') < 0) {
return;
} else if (e.target.href.includes('synxis')) {
e.preventDefault();
e.target.removeAttribute('target');
const hlink = e.target.href.toString().toLowerCase();
const parsedLink = parseURL(hlink);
bookNow(assignObjectVals(parsedLink[1]));
}
}
});
});
// Custom text added to rate descriptions about cancellation steps
const customStyle = document.createElement('style');
// Simplified Chinese
if (window.location.href.includes('/sc/')) {
customStyle.textContent = `
#sb-modalcontent > div > div > div:last-child p:after {
visibility: visible !important;
content: "。如果需要修改预订,请取消现有预订并完成新预订。" !important;
}`;
}
// Traditional Chinese
else if (window.location.href.includes('/tc/')) {
customStyle.textContent = `
#sb-modalcontent > div > div > div:last-child p:after {
visibility: visible !important;
content: "。如果需要修改預訂,請取消現有預訂並完成新預訂。" !important;
}`;
}
// default to English
else {
// window.location.href.includes("/en/")
customStyle.textContent = `
#sb-modalcontent > div > div > div:last-child p:after {
visibility: visible !important;
content: ". If modifications are needed on the reservation, please cancel existing reservation and complete new booking." !important;
}`;
}
document.head.appendChild(customStyle);
const closeResumeBookingCTA_Style = document.createElement('style');
closeResumeBookingCTA_Style.textContent = `
/* Close 'Complete your booking' CTA */
#selfbook-sdkwidget-resume {
overflow: visible !important;
z-index: 10000000000 !important;
}
button#selfbook-sdkwidget-resume:focus {
outline:0 !important;
}
.sb-close-cta {
padding: 5px 7px 3px 7px;
margin-top: -65px !important;
margin-right: -25px;
color: white;
font-size: 20px;
font-weight: bolder;
z-index: 100000000000 !important;
background-color: #766E63;
border-radius: 50%;
}
.sb-close-cta:hover {
color: #766E63;
background-color: white;
}
/* Hyperlink in Room and Rate description */
#room-detail-description li a, #sb-modalcontent li a {
color: #56246F !important;
cursor: pointer !important;
text-decoration: underline !important;
font-weight: bold !important;
}
/* Hotel alerts border-top */
.sb-rate-item > div > div > div:nth-child(5) {
border-top: 1px solid #766E63 !important;
}
/* Remove border on SVG for hotel alerts */
#sb-vendor-messages svg#icon {
stroke: transparent;
stroke-width: 0px;
}
/* Center SVG for hotel alerts */
#sb-vendor-messages > div > div:nth-child(1) {
padding-top: 3px !important;
}
/* added border on modal for changing lang/currency */
#sb-modalcontent {
border-top: 1px solid #766E63 !important;
}
/* border top for hamburger menu inside Direct */
div[aria-label="Selfbook Main Menu"] ul {
border-top: 1px solid #CED4DA !important;
}
/* Hide bed type in room list page */
div[aria-label="Select room"] svg[title="bed"] + div, div[aria-label="Select room"] svg[title="bed"],
div[aria-label="选择房间"] svg[title="bed"] + div, div[aria-label="选择房间"] svg[title="bed"],
div[aria-label="選擇房型"] svg[title="bed"] + div, div[aria-label="選擇房型"] svg[title="bed"]
{
visibility: hidden !important;
}
label[for="i-accept-hotel-terms-checkbox"] a {
color: #56246F !important;
}
/* Hide hotel alert short desc */
[data-testid="sb-vendor-message-short"] {
display: none !important;
}
`;
document.head.appendChild(closeResumeBookingCTA_Style);
function findSBresumeBtn() {
const sbCloseBtn = document.createElement('span');
sbCloseBtn.textContent = '✕';
sbCloseBtn.className = 'sb-close-cta';
let counter = 0;
const intVar = setInterval(function() {
counter++;
if (document.querySelector('#selfbook-sdkwidget-resume')) {
document.querySelector('#selfbook-sdkwidget-resume').appendChild(sbCloseBtn);
document.querySelector('.sb-close-cta').addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// .dismiss-btn-slide-out -> slide-out
// .dismiss-btn-slide-in -> slide-in
document.querySelector('#selfbook-sdkwidget-resume').classList.toggle('dismiss-btn-slide-out');
});
clearInterval(intVar);
}
}, 500);
}
findSBresumeBtn();
function inputErrorAlert(input) {
const customInputAlert = 'border: 1px solid red !important;background-color: #FCEAEA !important;';
if (input) {
if (input.value == null || input.value == '') {
if (input.parentElement.parentElement.getAttribute('data-testid') === 'sb-input-container') {
input.parentElement.parentElement.style = customInputAlert;
} else {
input.style = customInputAlert;
}
} else {
if (input.parentElement.parentElement.getAttribute('data-testid') === 'sb-input-container') {
input.parentElement.parentElement.style = '';
} else {
input.style = '';
}
}
}
}
const miraHotelAlertsSC = {
/* Simple Chinese */
["Direct Booking Benefits"]: {
engTitle: "Direct Booking Benefits",
engSubheading: "Exclusive Benefit of Booking Direct",
title: "官网预订独家礼遇",
subtitle: "直接预订的独家优惠",
description: "官网独家,凡於官网预订房间,均可免费享用迷你酒吧饮品,迷你酒吧将会每日补充一次。"
},
["Temp Swimming Pool Closure"]: {
engTitle: "Temp Swimming Pool Closure",
title: "關於游泳池",
engSubheading: "Pool Closure",
subtitle: "官網預訂獨家禮遇",
description: "我们的游泳池从2023年7月24日起,每天下午6至7时暂停开放,直至另行通知。"
},
}
const miraHotelAlertsTC = {
/* Traditional Chinese */
["Direct Booking Benefits"]: {
engTitle: "Direct Booking Benefits",
engSubheading: "Exclusive Benefit of Booking Direct",
title: "官網預訂獨家禮遇",
subtitle: "直接預訂的獨家優惠",
description: "官網獨家,凡於官網預訂房間,均可免費享用迷你酒吧飲品,迷你酒吧將會每日補充一次。"
},
["Temp Swimming Pool Closure"]: {
engTitle: "Temp Swimming Pool Closure",
title: "關於游泳池",
engSubheading: "Pool Closure",
subtitle: "官網預訂獨家禮遇",
description: "我們的游泳池從2023年7月24日起,每天下午6至7時暫停開放,直至另行通知。"
}
}
setInterval(() => {
if (document.querySelector('#selfbook_sdkwidget [lang]')?.getAttribute('lang') == 'zh-CN') {
// Simplified Chinese translation
document.querySelectorAll('#sb-vendor-messages > div').forEach((alert) => {
if (!alert.querySelector('[data-testid="sb-vendor-message-name"][data-sb-int-update="true"]') && alert.querySelector('[data-testid="sb-vendor-message-name"]')) {
let title = alert.querySelector('[data-testid="sb-vendor-message-name"]');
let subtitle = alert.querySelector('[data-testid="sb-vendor-message-short"]');
let description = alert.querySelector('[data-testid="sb-vendor-message-long"]');
let tempTitle = miraHotelAlertsSC[title?.textContent.trim()]?.title;
let tempSubtitle = miraHotelAlertsSC[title?.textContent.trim()]?.subtitle;
let tempDescription = miraHotelAlertsSC[title?.textContent.trim()]?.description;
alert.querySelector('[data-testid="sb-vendor-message-name"]').innerText = tempTitle;
if (alert.querySelector('[data-testid="sb-vendor-message-short"]')) {
alert.querySelector('[data-testid="sb-vendor-message-short"]').innerText = tempSubtitle;
}
if (alert.querySelector('[data-testid="sb-vendor-message-long"]')) {
alert.querySelector('[data-testid="sb-vendor-message-long"]').innerText = tempDescription;
}
alert.querySelector('[data-testid="sb-vendor-message-name"]').setAttribute("data-sb-int-update", "true")
// console.log(tempTitle, tempSubtitle, tempDescription);
}
})
}
else if (document.querySelector('#selfbook_sdkwidget [lang]')?.getAttribute('lang') == 'zh-TW') {
// Traditional Chinese translation
document.querySelectorAll('#sb-vendor-messages > div').forEach((alert) => {
if (!alert.querySelector('[data-testid="sb-vendor-message-name"][data-sb-int-update="true"]') && alert.querySelector('[data-testid="sb-vendor-message-name"]')) {
let title = alert.querySelector('[data-testid="sb-vendor-message-name"]');
let subtitle = alert.querySelector('[data-testid="sb-vendor-message-short"]');
let description = alert.querySelector('[data-testid="sb-vendor-message-long"]');
let tempTitle = miraHotelAlertsTC[title?.textContent.trim()]?.title;
let tempSubtitle = miraHotelAlertsTC[title?.textContent.trim()]?.subtitle;
let tempDescription = miraHotelAlertsTC[title?.textContent.trim()]?.description;
alert.querySelector('[data-testid="sb-vendor-message-name"]').innerText = tempTitle;
if (alert.querySelector('[data-testid="sb-vendor-message-short"]')) {
alert.querySelector('[data-testid="sb-vendor-message-short"]').innerText = tempSubtitle;
}
if (alert.querySelector('[data-testid="sb-vendor-message-long"]')) {
alert.querySelector('[data-testid="sb-vendor-message-long"]').innerText = tempDescription;
}
alert.querySelector('[data-testid="sb-vendor-message-name"]').setAttribute("data-sb-int-update", "true")
// console.log(tempTitle, tempSubtitle, tempDescription);
}
})
}
if (document.querySelector('button#sb-pay')) {
if (document.querySelector('button#sb-pay').getAttribute('data-sb-form-check')) {
// No actions
// console.log("[data-sb-form-check] exists")
} else {
console.log('Event Listener [data-sb-form-check] added');
document.querySelector('button#sb-pay').setAttribute('data-sb-form-check', true);
document.querySelector('button#sb-pay').addEventListener('click', (e) => {
console.log('button#sb-pay clicked');
// #firstname
const billingFN = document.querySelector('input#firstname');
const billingLN = document.querySelector('input#lastname');
const billingAddress = document.querySelector('input#address-line1');
const billingState = document.querySelector('input#address-level1');
const billingCity = document.querySelector('input#address-level2');
const billingZipCode = document.querySelector('input#postal-code');
const billingEmail = document.querySelector('input#Email');
inputErrorAlert(billingFN);
inputErrorAlert(billingLN);
inputErrorAlert(billingAddress);
inputErrorAlert(billingState);
inputErrorAlert(billingCity);
inputErrorAlert(billingZipCode);
inputErrorAlert(billingEmail);
if (
billingAddress.value == '' ||
billingState.value == '' ||
billingCity.value == '' ||
billingZipCode.value == '' ||
billingFN.value == '' ||
billingLN.value == '' ||
billingEmail.value == ''
) {
e.preventDefault();
e.stopImmediatePropagation();
e.stopPropagation();
} else {
console.log(
'%cForm validation successful',
'background: green; color: white;',
);
}
});
}
}
if (document.querySelector('label[for="i-accept-hotel-terms-checkbox"] a') !== null) {
const t_an_c_English = 'https://www.themirahotel.com/hong-kong/en/terms-conditions/';
const t_an_c_TraditionalChinese = 'https://www.themirahotel.com/hong-kong/tc/terms-conditions/';
const t_an_c_SimplifiedChinese = 'https://www.themirahotel.com/hong-kong/sc/terms-conditions/';
const opt_in_English = 'Yes, I understand and agree to the use of my personal data in direct marketing.';
const opt_in_TraditionalChinese = '是的,本人明白並同意使用我的個人資料作直接促銷。';
const opt_in_SimplifiedChinese = '是的,本人明白并同意使用我的个人资料作直接促销。';
if (document.querySelector('div[lang="zh-TW"]') !== null &&
document.querySelector('label[for="i-accept-hotel-terms-checkbox"] a') !== null) {
document.querySelector('label[for="i-accept-hotel-terms-checkbox"] a').href = t_an_c_TraditionalChinese;
document.querySelector('span label[for="email-me-special-offers"] span').innerHTML = opt_in_TraditionalChinese;
} else if (document.querySelector('div[lang="zh-CN"]') !== null &&
document.querySelector('label[for="i-accept-hotel-terms-checkbox"] a') !== null) {
document.querySelector('label[for="i-accept-hotel-terms-checkbox"] a').href = t_an_c_SimplifiedChinese;
document.querySelector('span label[for="email-me-special-offers"] span').innerHTML = opt_in_SimplifiedChinese;
} else {
document.querySelector('label[for="i-accept-hotel-terms-checkbox"] a').href = t_an_c_English;
document.querySelector('span label[for="email-me-special-offers"] span').innerHTML = opt_in_English;
}
}
}, 1000);
/*
Standalone bugsnag API
*/
// 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: `${JSON.stringify(error)}.`,
stacktrace: [
{
file: CLIENT_URL,
method: " (" + func + " Error) ",
code: {
1: `${JSON.stringify(error)}`,
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
};
// https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator
function getBrowserName(userAgent) {
// The order matters here, and this may report false positives for unlisted browsers.
if (userAgent.includes("Firefox")) {
// "Mozilla/5.0 (X11; Linux i686; rv:104.0) Gecko/20100101 Firefox/104.0"
return "Mozilla Firefox";
} else if (userAgent.includes("SamsungBrowser")) {
// "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.4 Chrome/67.0.3396.87 Mobile Safari/537.36"
return "Samsung Internet";
} else if (userAgent.includes("Opera") || userAgent.includes("OPR")) {
// "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_5_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36 OPR/90.0.4480.54"
return "Opera";
} else if (userAgent.includes("Edge")) {
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"
return "Microsoft Edge (Legacy)";
} else if (userAgent.includes("Edg")) {
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36 Edg/104.0.1293.70"
return "Microsoft Edge (Chromium)";
} else if (userAgent.includes("Chrome")) {
// "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
return "Google Chrome or Chromium";
} else if (userAgent.includes("Safari")) {
// "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Mobile/15E148 Safari/604.1"
return "Apple Safari";
} else {
return "unknown";
}
}
function checkIfObj(message) {
let st = "";
// Check if message is an instance of ErrorEvent or object. ErrorEvent may not stringify.
if (message) {
if (typeof message === 'object' || message instanceof ErrorEvent) {
message._getBrowserName = getBrowserName(navigator.userAgent);
Object.keys(message).forEach(function (key) {
st += " " + key + ", Value: " + message[key] + ". "
});
} else {
message += getBrowserName(navigator.userAgent);
st = message
}
}
return st;
}
// 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') && !message?.toString().toLowerCase().includes('script error.')
&& !source?.toString().toLowerCase().includes('guestbook')) {
let customError = {
name: checkIfObj(message),
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, 'selfbook script window.onerror');
return true;
}
}
};