var PopupEngineModule = PopupEngineModule || (function () { var POPUP_STORAGE_KEYS = { CONFIG: 'popup:config' }; var POPUP_STORAGE_TTL = { CONFIG_MS: 15 * 60 * 1000, AFTER_CLOSE_DELAY_MS: 2 * 1000, INITIAL_DELAY_MS: 2 * 1000 }; var POPUP_DISPLAY_OPTIONS = { OPEN_SITE: 1, AFTER_LOGIN: 2, AFTER_REGISTRATION: 3, BIRTHDAY: 4, VISIT_PAGE: 5, PLAYER_VERIFICATION: 6 }; var POPUP_URL_MATCH_TYPE = { EQUALS: 1, STARTS_WITH: 2, CONTAINS: 3 }; var state = { context: { playerId: 0, language: '', currencyCode: '', previewPopupId: 0, cookieDomain: '' }, queue: [], activePopup: null, playerPopupViews: [], eventsBound: false, timerId: null }; function init(args) { $.extend(state.context, args || {}); state.context.playerId = Number(state.context.playerId) || 0; state.context.language = getDocumentLanguage(); state.context.currencyCode = String(state.context.currencyCode || '').toUpperCase(); state.context.previewPopupId = Number(state.context.previewPopupId) || 0; state.context.cookieDomain = String(state.context.cookieDomain || ''); } function getDocumentLanguage() { var lang = String(document.documentElement.lang || '').toLowerCase(); if (!lang) { return ''; } return lang.split('-')[0]; } function parseDotNetDate(value) { if (!value) { return null; } if (typeof value === 'number') { return value; } if (value instanceof Date) { return value.getTime(); } if (typeof value === 'string') { var dotNetMatch = /\/Date\((\d+)\)\//.exec(value); if (dotNetMatch) { return Number(dotNetMatch[1]); } var parsed = new Date(value).getTime(); return Number.isNaN(parsed) ? null : parsed; } return null; } function normalizePopup(popup) { return $.extend({}, popup, { StartDateTs: parseDotNetDate(popup.StartDate), EndDateTs: parseDotNetDate(popup.EndDate) }); } function normalizePopups(popups) { return Array.isArray(popups) ? popups.map(normalizePopup) : []; } function normalizePlayerPopupViews(items) { if (!Array.isArray(items)) { return []; } return items.map(function (item) { return $.extend({}, item, { PopupId: Number(item.PopupId != null ? item.PopupId : item.Id), LastSeenDateTs: Number(item.LastSeenDateTs || 0) || parseDotNetDate(item.LastSeenDate) }); }); } function getCurrentPlayerId() { return state.context.playerId; } function isLoggedInPopupViewer() { return getCurrentPlayerId() > 0; } function getCurrentPopupViewerKey() { var playerId = getCurrentPlayerId(); return playerId > 0 ? 'player:' + playerId : 'guest'; } function getCurrentPath() { return normalizeUrlForPopupMatch( window.location.pathname + window.location.search ); } function getStoredPopupConfig() { var raw = localStorage.getItem(POPUP_STORAGE_KEYS.CONFIG); if (!raw) { return null; } try { var payload = JSON.parse(raw); if (!payload || !payload.expiresAt || Date.now() > payload.expiresAt) { localStorage.removeItem(POPUP_STORAGE_KEYS.CONFIG); return null; } return normalizePopups(Array.isArray(payload.data) ? payload.data : []); } catch (e) { localStorage.removeItem(POPUP_STORAGE_KEYS.CONFIG); return null; } } function savePopupConfig(popups) { var payload = { data: normalizePopups(popups), savedAt: Date.now(), expiresAt: Date.now() + POPUP_STORAGE_TTL.CONFIG_MS }; localStorage.setItem(POPUP_STORAGE_KEYS.CONFIG, JSON.stringify(payload)); } function removePopupFromStorage(popupId) { var storedPopups = getStoredPopupConfig() || []; var updatedPopups = storedPopups.filter(function (popup) { return popup.Id !== popupId; }); savePopupConfig(updatedPopups); } function getDismissStorageKey(popupId) { return 'popup:dismissed:' + getCurrentPopupViewerKey() + ':' + popupId; } function getLastShownStorageKey(popupId) { return 'popup:lastShownAt:' + getCurrentPopupViewerKey() + ':' + popupId; } function markPopupDismissedLocal(popupId) { localStorage.setItem(getDismissStorageKey(popupId), '1'); } function isPopupDismissedLocal(popupId) { return localStorage.getItem(getDismissStorageKey(popupId)) === '1'; } function markPopupShownLocal(popupId, time) { localStorage.setItem(getLastShownStorageKey(popupId), String(time || Date.now())); } function getPopupLastShownLocal(popupId) { var raw = localStorage.getItem(getLastShownStorageKey(popupId)); return raw ? Number(raw) : null; } function clearAllPopupConfigCache() { var keysToRemove = []; for (var i = 0; i < localStorage.length; i += 1) { var key = localStorage.key(i); if (key && key.indexOf(POPUP_STORAGE_KEYS.CONFIG) === 0) { keysToRemove.push(key); } } keysToRemove.forEach(function (key) { localStorage.removeItem(key); }); } function getPlayerPopupViewsCookieKey(playerId) { return 'popup_views_player_' + (Number(playerId) || 0); } function getPopupConfigResetCookieKey() { return 'popup_reset_config'; } function isBirthdayTriggerOn(playerId) { return getCookie('popup_birthday_player_' + (Number(playerId) || 0)) === '1'; } function isLoginTriggerOn(playerId) { return getCookie('popup_login_player_' + (Number(playerId) || 0)) === '1'; } function isRegistrationTriggerOn(playerId) { return getCookie('popup_registration_player_' + (Number(playerId) || 0)) === '1'; } function consumeLoginTrigger(playerId) { setCookie( 'popup_login_player_' + (Number(playerId) || 0), '0', 2, state.context.cookieDomain ); } function consumeRegistrationTrigger(playerId) { setCookie( 'popup_registration_player_' + (Number(playerId) || 0), '0', 2, state.context.cookieDomain ); } function shouldResetPopupConfig() { return getCookie(getPopupConfigResetCookieKey()) === '1'; } function consumePopupConfigReset() { if (!shouldResetPopupConfig()) { return; } clearAllPopupConfigCache(); setCookie( getPopupConfigResetCookieKey(), '0', 2, state.context.cookieDomain ); } function getPlayerPopupViewsFromCookie(playerId) { if (!(Number(playerId) > 0)) { return []; } var raw = getCookie(getPlayerPopupViewsCookieKey(playerId)); if (!raw || raw === 'null') { return []; } try { var parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : []; } catch (e) { return []; } } function savePlayerPopupViewsToCookie(playerId, views) { if (!(Number(playerId) > 0)) { return; } var normalized = (Array.isArray(views) ? views : []).map(function (item) { return { PopupId: Number(item.PopupId != null ? item.PopupId : item.Id), LastSeenDateTs: Number(item.LastSeenDateTs || Date.now()), IsDismissed: !!item.IsDismissed }; }); setCookie( getPlayerPopupViewsCookieKey(playerId), JSON.stringify(normalized), 2, state.context.cookieDomain ); } function loadPlayerPopupViewsFromCookie(playerId) { state.playerPopupViews = normalizePlayerPopupViews(getPlayerPopupViewsFromCookie(playerId)); } function getPlayerPopupViewById(popupId) { for (var i = 0; i < state.playerPopupViews.length; i += 1) { var item = state.playerPopupViews[i]; if (Number(item.PopupId != null ? item.PopupId : item.Id) === Number(popupId)) { return item; } } return null; } function getPopupLastShownCookie(popupId) { var item = getPlayerPopupViewById(popupId); return item ? item.LastSeenDateTs : null; } function isPopupDismissedCookie(popupId) { var item = getPlayerPopupViewById(popupId); return !!(item && item.IsDismissed); } function upsertPlayerPopupViewCookie(popupId, isDismissed) { var playerId = getCurrentPlayerId(); if (!(playerId > 0)) { return; } var rawViews = getPlayerPopupViewsFromCookie(playerId) || []; var now = Date.now(); var existingIndex = -1; for (var i = 0; i < rawViews.length; i += 1) { var item = rawViews[i]; if (Number(item.PopupId != null ? item.PopupId : item.Id) === Number(popupId)) { existingIndex = i; break; } } var updatedItem = { PopupId: Number(popupId), LastSeenDateTs: now, IsDismissed: !!isDismissed }; if (existingIndex >= 0) { rawViews[existingIndex] = $.extend({}, rawViews[existingIndex], updatedItem); } else { rawViews.push(updatedItem); } savePlayerPopupViewsToCookie(playerId, rawViews); state.playerPopupViews = normalizePlayerPopupViews(rawViews); } async function fetchBrandPopups() { var response = await fetch('/DynamicPopUp/BrandPopups', { method: 'GET', credentials: 'include' }); var result = null; try { result = await response.json(); } catch (e) { throw new Error('Failed to fetch brand popups'); } if (!result || !result.Success) { throw new Error((result && result.Message) || 'Failed to fetch brand popups'); } return Array.isArray(result.Data) ? result.Data : []; } async function loadPopupConfig() { var storedPopups = getStoredPopupConfig(); if (storedPopups !== null) { return storedPopups; } var popups = await fetchBrandPopups(); savePopupConfig(popups); return normalizePopups(popups); } async function fetchPopupContent(popupId) { var response = await fetch('/DynamicPopUp/PopupContent', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: new URLSearchParams({ id: popupId }).toString() }); var contentType = String(response.headers.get('content-type') || '').toLowerCase(); if (contentType.indexOf('application/json') >= 0) { try { await response.json(); } catch (e) { } return null; } var html = await response.text(); return html && html.trim() ? html : null; } async function savePopupSeenStatus(popupId, isDismissed) { var response = await fetch('/DynamicPopUp/SavePopupSeenStatus', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json; charset=UTF-8' }, body: JSON.stringify({ PopupId: popupId, IsDismissed: isDismissed }) }); var result = null; try { result = await response.json(); } catch (e) { return false; } return !!(result && result.Success); } function isLanguagePathSegment(segment) { segment = String(segment || '').toLowerCase(); if (!segment) { return false; } var currentLanguage = String(state.context.language || '').toLowerCase(); return segment === currentLanguage || segment.indexOf(currentLanguage + '-') === 0; } function normalizeUrlForPopupMatch(value) { if (!value) { return ''; } var url = String(value).toLowerCase().trim(); // If popup.Url is full URL, take only path + query if (/^[a-z][a-z0-9+.-]*:\/\//i.test(url)) { var parser = document.createElement('a'); parser.href = url; url = parser.pathname + parser.search; } if (url.charAt(0) !== '/') { url = '/' + url; } var queryIndex = url.indexOf('?'); var path = queryIndex >= 0 ? url.substring(0, queryIndex) : url; var query = queryIndex >= 0 ? url.substring(queryIndex) : ''; var parts = path.split('/'); // "/en/home" => ["", "en", "home"] if (parts.length > 2 && isLanguagePathSegment(parts[1])) { parts.splice(1, 1); // remove language path = parts.join('/') || '/'; } return path + query; } function matchesUrl(popup, currentUrl) { var popupUrl = popup.Url ? normalizeUrlForPopupMatch(popup.Url) : null; currentUrl = normalizeUrlForPopupMatch(currentUrl); if (!popupUrl) { return true; } switch (popup.UrlMatchType) { case POPUP_URL_MATCH_TYPE.EQUALS: return currentUrl === popupUrl; case POPUP_URL_MATCH_TYPE.STARTS_WITH: return currentUrl.indexOf(popupUrl) === 0; case POPUP_URL_MATCH_TYPE.CONTAINS: return currentUrl.indexOf(popupUrl) >= 0; default: return true; } } function matchesLanguage(popup) { if (!Array.isArray(popup.Languages) || popup.Languages.length === 0) { return true; } var currentLanguage = state.context.language; return popup.Languages.some(function (language) { return String(language).toLowerCase() === currentLanguage; }); } function matchesCurrency(popup) { if (!Array.isArray(popup.Currencies) || popup.Currencies.length === 0) { return true; } var currentCurrency = state.context.currencyCode; return popup.Currencies.some(function (currency) { return String(currency).toUpperCase() === currentCurrency; }); } function isPopupActive(popup) { var now = Date.now(); if (popup.StartDateTs && now < popup.StartDateTs) { return false; } if (popup.EndDateTs && now > popup.EndDateTs) { return false; } return true; } function getPopupCooldownMs(popup) { var hours = Number(popup.ReopenFrequency || 0); return hours > 0 ? hours * 60 * 60 * 1000 : 0; } function getPopupLastShownEffective(popupId) { return isLoggedInPopupViewer() ? getPopupLastShownCookie(popupId) : getPopupLastShownLocal(popupId); } function isPopupDismissedEffective(popupId) { return isLoggedInPopupViewer() ? isPopupDismissedCookie(popupId) : isPopupDismissedLocal(popupId); } function canShowPopupByFrequency(popup) { if ( popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.AFTER_REGISTRATION && isRegistrationTriggerOn(getCurrentPlayerId()) ) { return true; } if ( popup.ReopenFrequency === null || popup.ReopenFrequency === undefined || popup.ReopenFrequency === '' ) { return true; } var lastShownAt = getPopupLastShownEffective(popup.Id); var reopenFrequency = Number(popup.ReopenFrequency || 0); if (!lastShownAt) { return true; } if (reopenFrequency === 0) { return false; } return Date.now() - lastShownAt >= getPopupCooldownMs(popup); } function getInitialTriggers(popups) { var triggers = []; var currentUrl = getCurrentPath(); var playerId = getCurrentPlayerId(); var hasOpenSitePopup = popups.some(function (popup) { return popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.OPEN_SITE && isPopupActive(popup) && matchesLanguage(popup) && matchesCurrency(popup); }); var hasVisitPagePopup = popups.some(function (popup) { return popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.VISIT_PAGE && isPopupActive(popup) && matchesLanguage(popup) && matchesCurrency(popup) && matchesUrl(popup, currentUrl); }); var hasBirthdayPopup = isBirthdayTriggerOn(playerId) && popups.some(function (popup) { return popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.BIRTHDAY && isPopupActive(popup) && matchesLanguage(popup) && matchesCurrency(popup); }); var hasLoginPopup = isLoginTriggerOn(playerId) && popups.some(function (popup) { return popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.AFTER_LOGIN && isPopupActive(popup) && matchesLanguage(popup) && matchesCurrency(popup); }); var hasRegistrationPopup = isRegistrationTriggerOn(playerId) && popups.some(function (popup) { return popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.AFTER_REGISTRATION && isPopupActive(popup) && matchesLanguage(popup) && matchesCurrency(popup); }); if (hasOpenSitePopup) { triggers.push(POPUP_DISPLAY_OPTIONS.OPEN_SITE); } if (hasVisitPagePopup) { triggers.push(POPUP_DISPLAY_OPTIONS.VISIT_PAGE); } if (hasBirthdayPopup) { triggers.push(POPUP_DISPLAY_OPTIONS.BIRTHDAY); } if (hasLoginPopup) { triggers.push(POPUP_DISPLAY_OPTIONS.AFTER_LOGIN); } if (hasRegistrationPopup) { triggers.push(POPUP_DISPLAY_OPTIONS.AFTER_REGISTRATION); } return triggers; } function isPopupEligible(popup, triggers, currentUrl) { if (!popup) { return false; } if (!isPopupActive(popup)) { return false; } if (!matchesLanguage(popup) || !matchesCurrency(popup)) { return false; } if (triggers.indexOf(popup.DisplayOptions) < 0) { return false; } if ( popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.VISIT_PAGE && !matchesUrl(popup, currentUrl) ) { return false; } if (isPopupDismissedEffective(popup.Id)) { return false; } if (!canShowPopupByFrequency(popup)) { return false; } return true; } function buildQueue(popups, triggers) { if (!Array.isArray(popups) || !Array.isArray(triggers) || !triggers.length) { return []; } var currentUrl = getCurrentPath(); return popups.filter(function (popup) { return isPopupEligible(popup, triggers, currentUrl); }); } function ensurePopupContainer() { var container = document.getElementById('js_popup-container'); if (!container) { container = document.createElement('div'); container.id = 'js_popup-container'; document.body.appendChild(container); } return container; } function clearRenderedPopup() { var container = document.getElementById('js_popup-container'); if (!container) { return; } container.innerHTML = ''; } function consumePopupTriggerIfNeeded(popup) { if (!popup) { return; } if (popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.AFTER_LOGIN) { consumeLoginTrigger(getCurrentPlayerId()); } if (popup.DisplayOptions === POPUP_DISPLAY_OPTIONS.AFTER_REGISTRATION) { consumeRegistrationTrigger(getCurrentPlayerId()); } } function renderPopup(html, popup) { var container = ensurePopupContainer(); container.innerHTML = html; container.style.display = ''; delete container.dataset.pausedByBlockingUi; state.activePopup = popup; consumePopupTriggerIfNeeded(popup); bindPopupEvents(container, popup); } function bindPopupEvents(container, popup) { var closeButton = container.querySelector('.popup-close-btn'); var dismissCheckbox = container.querySelector('.popup-dismiss-checkbox'); if (!closeButton) { return; } closeButton.addEventListener('click', async function () { var isDismissChecked = dismissCheckbox ? dismissCheckbox.checked : false; await handlePopupClose(popup, isDismissChecked); }); } function isBlockingUiOpen() { var href = window.location.href.toLowerCase(); var hasBlockingUrl = href.indexOf('profile') >= 0 || href.indexOf('register') >= 0 || href.indexOf('logdialog') >= 0 || href.indexOf('/play/fun') >= 0 || href.indexOf('/play/real') >= 0; return document.body.classList.contains('ofh') || hasBlockingUrl; } function pauseActivePopupForBlockingUi() { var container = document.getElementById('popup-container'); if (!container || !state.activePopup) { return; } container.dataset.pausedByBlockingUi = '1'; container.style.display = 'none'; } function scheduleNextPopup(delay) { if (state.timerId) { clearTimeout(state.timerId); state.timerId = null; } state.timerId = setTimeout(function () { state.timerId = null; showNextPopupFromQueue(); }, delay); } async function showNextPopupFromQueue() { if (isBlockingUiOpen()) { pauseActivePopupForBlockingUi(); return; } while (state.queue.length) { var popup = state.queue.shift(); if (!popup) { continue; } if (!isPopupActive(popup)) { removePopupFromStorage(popup.Id); continue; } if (isPopupDismissedEffective(popup.Id)) { continue; } if (!canShowPopupByFrequency(popup)) { continue; } var content = await fetchPopupContent(popup.Id); if (!content) { continue; } renderPopup(content, popup); return; } } async function handlePopupClose(popup, isDismissChecked) { if (isLoggedInPopupViewer()) { upsertPlayerPopupViewCookie(popup.Id, isDismissChecked); try { await savePopupSeenStatus(popup.Id, isDismissChecked); } catch (e) { } } else { markPopupShownLocal(popup.Id); if (isDismissChecked) { markPopupDismissedLocal(popup.Id); } } clearRenderedPopup(); state.activePopup = null; scheduleNextPopup(POPUP_STORAGE_TTL.AFTER_CLOSE_DELAY_MS); } function bindGlobalUiEvents() { if (state.eventsBound) { return; } state.eventsBound = true; $(document).on('dialogclose', function () { setTimeout(async function () { if (isBlockingUiOpen()) { return; } var container = document.getElementById('popup-container'); if ( state.activePopup && container && container.dataset.pausedByBlockingUi === '1' ) { container.style.display = ''; delete container.dataset.pausedByBlockingUi; return; } if (!state.activePopup && Array.isArray(state.queue) && state.queue.length) { await showNextPopupFromQueue(); return; } await run(); }, 200); }); } async function run() { try { consumePopupConfigReset(); var popups = await loadPopupConfig(); if (isLoggedInPopupViewer()) { loadPlayerPopupViewsFromCookie(getCurrentPlayerId()); } else { state.playerPopupViews = []; } state.queue = buildQueue(popups, getInitialTriggers(popups)); bindGlobalUiEvents(); if (!state.queue.length) { return; } scheduleNextPopup(POPUP_STORAGE_TTL.INITIAL_DELAY_MS); } catch (e) { } } async function initPreview() { try { bindGlobalUiEvents(); var previewPopupId = Number(state.context.previewPopupId) || 0; if (previewPopupId <= 0) { return; } var content = await fetchPopupContent(previewPopupId); if (!content) { return; } var container = ensurePopupContainer(); container.innerHTML = content; container.style.display = ''; delete container.dataset.pausedByBlockingUi; state.activePopup = null; var closeButton = container.querySelector('.popup-close-btn'); if (closeButton) { closeButton.addEventListener('click', function () { clearRenderedPopup(); state.activePopup = null; }); } } catch (e) { } } return { init: init, run: run, initPreview: initPreview }; })();