const isDebugMode = window.location.search.includes('debug=true');
let debugLogContainer = null;
let debugLogCounter = 0;
const cookieDomain = '.' + getMainDomain(window.location.href);
firebaseDebugLog(true, 'cookieDomain-' + cookieDomain);
let refreshInterval;
let logoutInProgress = false;
let pendingCred = null;
document.addEventListener('DOMContentLoaded', function () {
// Create debug overlay if debug mode is enabled
if (isDebugMode) {
createDebugOverlay();
}
//Safe to expose as they are identification values not auth keys
const firebaseConfig = {
apiKey: "AIzaSyA6qrL3tY40YlRkSK4XTS7zijAJ4n15MNU",
authDomain: "sso.consequence.net",
projectId: "consequence-25a8e",
storageBucket: "consequence-25a8e.appspot.com",
messagingSenderId: "993189234631",
appId: "1:993189234631:web:4d0a240cc0ab799b65fbe2",
measurementId: "G-V7CZFS1TQG"
};
firebase.initializeApp(firebaseConfig);
// Check for native Facebook OAuth callback first (Option 5)
handleFacebookOAuthCallback().then(handled => {
if (handled) {
firebaseDebugLog(true, 'Facebook OAuth callback handled, skipping Firebase redirect check');
return;
}
// If not a Facebook OAuth callback, check for Firebase redirect result
return firebase.auth().getRedirectResult();
}).then(async (result) => {
if (!result) return; // Already handled by Facebook OAuth callback
if (!result || !result.user) return;
const user = result.user;
const idToken = await user.getIdToken();
const response = await login(user, idToken);
if (response && response.success) {
window.location.reload();
} else {
console.log("WP login failed after redirect");
}
})
.catch((e) => {
console.log("getRedirectResult error:", e.code, e.message, e);
});
var googleLoginBtn = document.getElementById('googleLoginBtn');
var facebookLoginBtn = document.getElementById('facebook-login');
var twitterLoginBtn = document.getElementById('twitter-login');
var appleLoginBtn = document.getElementById('apple-login');
var logoutBtn = document.getElementById('logoutBtn');
if (googleLoginBtn) {
googleLoginBtn.addEventListener('click', function () {
var provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
prompt: 'select_account'
});
handleSignInWithProvider(provider, 'google');
});
}
// Facebook Authentication
if (facebookLoginBtn) {
facebookLoginBtn.addEventListener('click', function () {
var provider = new firebase.auth.FacebookAuthProvider();
// provider.setCustomParameters({
// auth_type: 'reauthenticate'
// });
handleSignInWithProvider(provider, 'facebook');
});
}
// Twitter Authentication
if (twitterLoginBtn) {
twitterLoginBtn.addEventListener('click', function () {
var provider = new firebase.auth.TwitterAuthProvider();
provider.setCustomParameters({
'force_login': 'true' // Forces the user to reauthenticate
});
handleSignInWithProvider(provider, 'twitter');
});
}
// Apple Authentication
if (appleLoginBtn) {
appleLoginBtn.addEventListener('click', function () {
var provider = new firebase.auth.OAuthProvider('apple.com');
handleSignInWithProvider(provider, 'apple');
});
}
if (logoutBtn) {
logoutBtn.addEventListener('click', function () {
logout();
});
}
firebase.auth().onAuthStateChanged((user) => {
firebaseDebugLog(true, '---Start onAuthStateChanged---');
if (logoutInProgress == true) return;
// Don't logout if Facebook OAuth is in progress (Option 5 only)
if (localStorage.getItem('fb_oauth_processing') === 'true') {
firebaseDebugLog(true, 'Facebook OAuth in progress, skipping auth state check');
firebaseDebugLog(true, '---End onAuthStateChanged---');
return;
}
if (user) {
syncGeoToLambda(user.email);
firebaseDebugLog(true, 'User signed in:' + user);
// regenerateIdToken(user);
// Start the refresh process
if (checkCookieExists()) {
firebaseDebugLog(true, 'CookieExists');
startTokenRefresh(user);
}
else {
firebaseDebugLog(true, 'No CookieExists');
firebaseDebugLog(true, 'No sessioncookie found, logout');
localStorage.setItem('localLogout', 2); //1=local, 2=auto
logout();
}
} else {
firebaseDebugLog(true, 'No user signed in');
clearInterval(refreshInterval); // Clear the interval on sign-out
firebaseDebugLog(true, 'On authstatechange check cookie');
// checkSessionCookie();
}
firebaseDebugLog(true, '---End onAuthStateChanged---');
});
async function handleSignInWithProvider(provider, pname) {
firebaseDebugLog(true, '---Start handleSignInWithProvider');
const loader = document.getElementById('loginSpinner');
try {
localStorage.setItem('loggedInLocally', 'true');
logoutInProgress = true;
// Option 5: Use native Facebook OAuth for mobile devices ONLY
// This includes: mobile regular browsers AND mobile in-app browsers
// Desktop in-app browsers will use standard popup flow
// This bypasses Firebase's /__/auth/ handler which is blocked by nginx
if (pname === 'facebook' && isMobileDevice()) {
firebaseDebugLog(true, 'Using custom Facebook OAuth (Option 5) for mobile device');
await handleFacebookNativeAuth();
return;
}
if (isInAppBrowser()) {
await firebase.auth().signInWithRedirect(provider);
return;
}
const result = await firebase.auth().signInWithPopup(provider);
loader.style.display = 'flex';
document.getElementById('socialLogin').style.display = 'none';
document.querySelector('.sfba-close').style.display = 'none';
const user = result.user;
firebaseDebugLog(true, 'handleSignInWithProvider-' + user);
const idToken = await user.getIdToken();
firebaseDebugLog(true, 'ID Token:-' + idToken);
const response = await login(user, idToken);
if (!response || !response.success) {
// Handle unsuccessful login
localStorage.removeItem('loggedInLocally');
document.getElementById('socialLogin').style.display = 'block';
document.querySelector('.sfba-close').style.display = 'block';
loader.style.display = 'none';
throw new Error('Failed to authenticate.');
}
logoutInProgress = false;
window.location.reload(); // Reload the page on successful login
} catch (error) {
logoutInProgress = false;
firebaseDebugLog(true, 'Error during Firebase authentication:' + error.message);
localStorage.removeItem('loggedInLocally'); // Ensure localStorage is cleaned up
handleLoginError(error);
}
firebaseDebugLog(true, '---End handleSignInWithProvider');
}
function login(user, idToken) {
firebaseDebugLog(true, '---Start Login');
return new Promise((resolve, reject) => {
jQuery.ajax({
url: firebaseAuthAjax.ajax_url,
method: 'POST',
data: {
action: 'firebase_login',
nonce: firebaseAuthAjax.nonce,
email: user.email,
display_name: user.displayName,
provider_id: user.providerData[0].uid,
provider_name: user.providerData[0].providerId,
idToken: idToken,
firebase_uid: user.uid
},
success: function (response) {
firebaseDebugLog(true, 'login success response:-' + response);
setCookie('ssosession', idToken, 24, cookieDomain);
syncGeoToLambda(user.email);
resolve(response);
firebaseDebugLog(true, '---End Login');
},
error: function (error) {
firebaseDebugLog(true, 'Error logging in:-' + error);
reject(error);
}
});
});
}
async function handleLoginError(error) {
if (error.code === 'auth/account-exists-with-different-credential') {
jQuery('.temp-preferences').show();
jQuery('.temp-preferences .sfba-before-login').show();
jQuery(".socialLogin").hide();
var email = error.email;
// Store credential in memory - cannot reliably serialize Firebase credentials to JSON
pendingCred = error.credential;
try {
var methods = await firebase.auth().fetchSignInMethodsForEmail(email);
if (methods.length > 0) {
localStorage.setItem('existingProvider', methods[0]);
jQuery(".sfba-mask").removeClass("sfba-active");
jQuery(".sfba-link-mask").addClass('sfba-active');
handleLinkModel(methods[0]);
}
} catch (fetchError) {
firebaseDebugLog(true, 'Error fetching sign-in methods: ' + fetchError.message);
}
}
else if (error.code === 'auth/popup-blocked' || error.code === 'auth/popup-closed-by-user') {
firebaseDebugLog(true, 'Popup blocked or closed by user');
// Note: Cannot redirect here as we don't have provider context
}
else {
firebaseDebugLog(true, error.message);
jQuery('.temp-preferences').hide();
jQuery('.temp-preferences .sfba-before-login').hide();
jQuery(".socialLogin").show();
localStorage.removeItem('Firebaseuserstorage');
}
}
function handleLinkModel(provider) {
// Hide all link buttons first, then show only the relevant one
jQuery(".sfba-social-btn-link").hide();
if (provider == 'google.com') {
jQuery("#socialLoginLink .link-message .provider-name").html("Google");
jQuery(".sfba-social-btn-link.sfba-login-with-google-btn").show();
}
else if (provider == 'facebook.com') {
jQuery("#socialLoginLink .link-message .provider-name").html("Facebook");
jQuery(".sfba-social-btn-link.sfba-login-with-facebook-btn").show();
}
else if (provider == 'apple.com') {
jQuery("#socialLoginLink .link-message .provider-name").html("Apple");
jQuery(".sfba-social-btn-link.sfba-login-with-apple-btn").show();
}
else {
firebaseDebugLog(true, 'Provider doesnt exist: ' + provider);
}
}
function getAuthProvider(providerId) {
switch (providerId) {
case firebase.auth.GoogleAuthProvider.PROVIDER_ID:
return new firebase.auth.GoogleAuthProvider();
case firebase.auth.FacebookAuthProvider.PROVIDER_ID:
return new firebase.auth.FacebookAuthProvider();
case 'apple.com':
return new firebase.auth.OAuthProvider('apple.com');
default:
throw new Error('No provider found for the given provider ID.');
}
}
// Modal for SSO Social media buttons and Add ARtist/Tags
jQuery(".sfba-show").on("click", function () {
var errorElement = document.getElementById("errorMessage");
if (errorElement) {
errorElement.innerHTML = '';
}
jQuery(".sfba-mask").addClass("sfba-active");
});
// Close popup
jQuery(".sfba-close").on("click", function () {
jQuery(".sfba-mask").removeClass("sfba-active");
});
// Close popup
jQuery(".sfba-link-close").on("click", function () {
jQuery(".sfba-link-mask").removeClass("sfba-active");
});
jQuery(".sfba-show-pref").on("click", function () {
jQuery(".sfba-mask-pref").addClass("sfba-active");
});
jQuery(".sfba-close-pref").on("click", function () {
jQuery(".sfba-mask-pref").removeClass("sfba-active");
});
jQuery('.tab-nav span').on('click', function () {
if (jQuery(this).text() == 'My Tags') {
jQuery('#all-preferences .tab-nav ul li').removeClass('active');
jQuery('#all-preferences .tab-nav ul li:nth-child(2)').addClass('active');
jQuery('#all-preferences #all-artists').removeClass('active');
jQuery('#all-preferences #all-tags').addClass('active');
} else {
jQuery('#all-preferences .tab-nav ul li').addClass('active');
jQuery('#all-preferences .tab-nav ul li:nth-child(2)').removeClass('active');
jQuery('#all-preferences #all-artists').addClass('active');
jQuery('#all-preferences #all-tags').removeClass('active');
}
jQuery([jQuery(this).parent()[0], jQuery(jQuery(this).data('href'))[0]]).addClass('active').siblings('.active').removeClass('active');
});
// Delete Artists/Tags
jQuery('body').on('click', '.preference-delete, .preference-add.deleteid', function () {
var preftype = jQuery(this).data("preftype");
var currentemailaddress = jQuery("#current-email-address").val();
if (jQuery(this).hasClass('deleteid')) {
jQuery(this).removeClass('deleteid');
jQuery(this).addClass('addid');
jQuery(this).find('span.pref-add').html('').html('✛');
jQuery(this).find('span.pref-add').css('color', '#009b1a');
var delId = jQuery(this).data("addid");
if (preftype == "artist") {
jQuery(".my-artist-list li").each(function () {
if (jQuery(this).find("a").attr("data-delid") == delId) {
jQuery(this).remove();
}
});
} else {
jQuery(".my-tags-list li").each(function () {
if (jQuery(this).find("a").attr("data-delid") == delId) {
jQuery(this).remove();
}
});
}
} else {
var delId = jQuery(this).data("delid");
jQuery(this).parent().remove();
if (preftype == "artist") {
jQuery(".preferences-list ul.artist-list li").each(function () {
if (jQuery(this).find("a").attr("data-addid") == delId) {
jQuery(this).find('span.pref-add').html('').html('✛');
jQuery(this).find('span.pref-add').css('color', '#009b1a');
}
});
} else {
jQuery(".preferences-list ul.post_tag-list li").each(function () {
if (jQuery(this).find("a").attr("data-addid") == delId) {
jQuery(this).find('span.pref-add').html('').html('✛');
jQuery(this).find('span.pref-add').css('color', '#009b1a');
}
});
}
}
jQuery.ajax({
type: 'POST',
url: firebaseAuthAjax.ajax_url,
cache: true,
data: {
action: 'delete_preferences_action',
currentemailaddress: currentemailaddress,
delId: delId,
preftype: preftype,
},
success: function (response) {
if (preftype == "artist") {
if (jQuery('ul.my-artist-list').find('li').length === 0) {
jQuery('.preferences-list.my-artists-ul').html('
Please click the "plus" icon to the right to add Artists to your profile
');
}
} else {
if (jQuery('ul.my-tags-list').find('li').length === 0) {
jQuery('.preferences-list.my-tags-ul').html('Please click the "plus" icon to the right to add Tags to your profile
');
}
}
}
});
});
let currentAjaxRequest = null;
jQuery('.search-preferences').keyup(function (event) {
if ((event.key === 'Enter' && jQuery(this).val().length > 2) || jQuery(this).val().length > 2) {
jQuery('.search-pref-btn').click();
}
if (event.key === 'Backspace') {
jQuery('.search-pref-btn').click();
}
});
jQuery('.search-pref-btn').on('click', function () {
jQuery('.filterButton').removeClass('active');
searchTerm = jQuery(this).prev().val();
var ptype = jQuery(this).data('type');
var preftype = '';
var prefidstring = '';
var textpref = '';
var arrayinside = false;
if (ptype === 'artist') {
preftype = "artist";
prefidstring = jQuery("#artist_id").val();
textpref = "Artist";
} else if (ptype === 'post_tag') {
preftype = "tags";
prefidstring = jQuery("#tag_id").val();
textpref = "Tags";
}
if (searchTerm != "") {
// Make AJAX request
if (currentAjaxRequest) {
currentAjaxRequest.abort();
}
currentAjaxRequest = jQuery.ajax({
type: 'POST',
url: firebaseAuthAjax.ajax_url,
dataType: 'json',
data: {
action: 'preferences_search_action',
nonce: firebaseAuthAjax.nonce,
search_term: searchTerm,
ptype: ptype
},
success: function (response) {
currentAjaxRequest = null;
jQuery('.' + ptype + '-list li').css("display", "none");
jQuery('.' + ptype + '-list li.nonpop-search-data').remove();
var jsonString = JSON.stringify(response);
var dataArray = JSON.parse(jsonString);
setTimeout(function () {
if (Array.isArray(dataArray) && dataArray.length > 0) {
jQuery('.post_tag-list p').remove();
jQuery('.artist-list p').remove();
$.each(dataArray, function (index, item) {
if (prefidstring !== '' && prefidstring.includes(item.term_id)) {
arrayinside = true;
}
if (arrayinside) {
jQuery('.' + ptype + '-list').append('' + item.name + '✕');
} else {
jQuery('.' + ptype + '-list').append('' + item.name + '✛');
}
jQuery('.' + ptype + '-list li.nonpop-search-data').css("display", "block");
});
} else {
if (jQuery('.not-found').length === 0) {
jQuery('.' + ptype + '-list').append('No ' + textpref + ' found
');
}
}
}, 500);
}
});
} else {
jQuery('.filterButton:first-child').addClass('active');
jQuery('.' + ptype + '-list li').css("display", "block");
jQuery('.' + ptype + '-list li.nonpop-search-data').remove();
}
});
jQuery('.filterButton').on('click', function () {
jQuery('.post_tag-list p').remove();
jQuery('.artist-list p').remove();
jQuery('.filterButton').removeClass("active");
var filter = jQuery(this).data('filter');
jQuery(this).addClass("active");
jQuery(this).parent().prev().find('.search-preferences').val(filter);
var preid = jQuery(this).parent().parent().attr('id');
if (preid === 'all-artists') {
var ptype = 'artist';
} else {
var ptype = 'post_tag';
}
if (ptype == "artist") { var customclass = '.artist-list li'; } else if (ptype == "post_tag") { var customclass = '.post_tag-list li'; }
if (filter == "ALL") {
jQuery('.' + ptype + '-list li').css("display", "block");
jQuery('.' + ptype + '-list li.nonpop-search-data').remove();
} else {
jQuery(customclass).each(function () {
var firstLetter = jQuery(this).text().charAt(0).toUpperCase();
if (firstLetter === filter) {
jQuery(this).show();
} else {
jQuery(this).hide();
}
});
jQuery('.' + ptype + '-list li.nonpop-search-data').remove();
}
});
// Add Artists/Tags
jQuery('body').on('click', '.preference-add.addid', function () {
var preftype = jQuery(this).data("preftype");
var currentemailaddress = jQuery("#current-email-address").val();
var newValueartist = '', newValuetags = '', artistadd = '', tagsadd = '';
if (preftype == 'artist') {
newValueartist = jQuery(this).data('addid');
artistname = jQuery(this).data('title');
artistadd = '' + artistname + '✕ ';
} else {
newValuetags = jQuery(this).data('addid');
tagsname = jQuery(this).data('title');
tagsadd = '' + tagsname + '✕';
}
jQuery(this).find('span.pref-add').html('').html('✕');
jQuery(this).find('span.pref-add').css('color', '#ff0000');
jQuery(this).removeClass('addid');
jQuery(this).addClass('deleteid');
jQuery.ajax({
type: 'POST',
url: firebaseAuthAjax.ajax_url,
cache: true,
data: {
action: 'add_preferences_action',
currentemailaddress: currentemailaddress,
preftype: preftype,
newValueartist: newValueartist,
newValuetags: newValuetags,
},
success: function (response) {
if (artistadd != '') {
if (jQuery(".my-artists-ul").find('p').length) {
jQuery(".my-artists-ul").html('');
jQuery(".my-artists-ul").append('');
jQuery(".my-artists-ul p").css("display", "none");
} else {
// jQuery(".my-artists-ul ul").append(artistadd);
appendLi('.my-artist-list', artistadd, artistname);
}
}
if (tagsadd != '') {
if (jQuery(".my-tags-ul").find('p').length) {
jQuery(".my-tags-ul").html('');
jQuery(".my-tags-ul").append('');
jQuery(".my-tags-ul p").css("display", "none");
} else {
// jQuery(".my-tags-ul ul").append(tagsadd);
appendLi('.my-tags-list', tagsadd, tagsname);
}
}
}
});
});
// Delete Artists/Tags
jQuery('body').on('click', '.preference-delete, .preference-add.deleteid', function () {
var preftype = jQuery(this).data("preftype");
var currentemailaddress = jQuery("#current-email-address").val();
if (jQuery(this).hasClass('deleteid')) {
jQuery(this).removeClass('deleteid');
jQuery(this).addClass('addid');
jQuery(this).find('span.pref-add').html('').html('✛');
jQuery(this).find('span.pref-add').css('color', '#009b1a');
var delId = jQuery(this).data("addid");
if (preftype == "artist") {
jQuery(".my-artist-list li").each(function () {
if (jQuery(this).find("a").attr("data-delid") == delId) {
jQuery(this).remove();
}
});
} else {
jQuery(".my-tags-list li").each(function () {
if (jQuery(this).find("a").attr("data-delid") == delId) {
jQuery(this).remove();
}
});
}
} else {
var delId = jQuery(this).data("delid");
if (preftype == "artist") {
jQuery(".preferences-list ul.artist-list li").each(function () {
if (jQuery(this).find("a").attr("data-addid") == delId) {
jQuery(this).find('span.pref-add').html('').html('✛');
jQuery(this).find('span.pref-add').css('color', '#009b1a');
}
});
} else {
jQuery(".preferences-list ul.post_tag-list li").each(function () {
if (jQuery(this).find("a").attr("data-addid") == delId) {
jQuery(this).find('span.pref-add').html('').html('✛');
jQuery(this).find('span.pref-add').css('color', '#009b1a');
}
});
}
}
jQuery.ajax({
type: 'POST',
url: firebaseAuthAjax.ajax_url,
cache: true,
data: {
action: 'delete_preferences_action',
currentemailaddress: currentemailaddress,
delId: delId,
preftype: preftype,
},
success: function (response) {
if (preftype == "artist") {
if (jQuery('ul.my-artist-list').find('li').length === 0) {
jQuery('.preferences-list.my-artists-ul').html('Please click the "plus" icon to the right to add Artists to your profile
');
}
} else {
if (jQuery('ul.my-tags-list').find('li').length === 0) {
jQuery('.preferences-list.my-tags-ul').html('Please click the "plus" icon to the right to add Tags to your profile
');
}
}
}
});
});
function appendLi(selector, litoadd, textname) {
var $list = jQuery(selector);
var $newItem = jQuery(litoadd);
var textnameIsNumeric = !isNaN(textname);
var inserted = false;
$list.children('li').each(function () {
var $currentItem = jQuery(this);
var currentTextName = $currentItem.find('span:first').text();
var currentIsNumeric = !isNaN(currentTextName);
if (textnameIsNumeric && currentIsNumeric) {
if (parseFloat(textname) < parseFloat(currentTextName)) {
$currentItem.before($newItem);
inserted = true;
return false;
}
} else if (!textnameIsNumeric && !currentIsNumeric) {
if (String(textname).toLowerCase() < String(currentTextName).toLowerCase()) {
$currentItem.before($newItem);
inserted = true;
return false;
}
} else if (textnameIsNumeric && !currentIsNumeric) {
$currentItem.before($newItem);
inserted = true;
return false;
}
});
if (!inserted) {
$list.append($newItem);
}
}
jQuery(".sfba-social-btn-link").on("click", async function () {
jQuery(".sfba-link-mask").removeClass('sfba-active');
var existingProvider = localStorage.getItem('existingProvider');
localStorage.removeItem('existingProvider');
var authProvider = getAuthProvider(existingProvider);
try {
// Step 1: Sign in with the existing (original) provider
var result = await firebase.auth().signInWithPopup(authProvider);
var user = result.user;
var idToken = await user.getIdToken();
// Step 2: Log in / create the WordPress user (reuses the same login() helper)
var loginResponse = await login(user, idToken);
if (!loginResponse || !loginResponse.success) {
localStorage.removeItem('loggedInLocally');
throw new Error('Failed to authenticate with WordPress.');
}
// Step 3: Link the pending credential (from the failed sign-in attempt)
if (pendingCred) {
try {
// var linkResult = await user.linkWithCredential(pendingCred);
// // Update cookie with fresh token from the now-linked account
// var newIdToken = await linkResult.user.getIdToken(true);
setCookie('ssosession', idToken, 24, cookieDomain);
firebaseDebugLog(true, 'Account linking successful');
} catch (linkError) {
firebaseDebugLog(true, 'Error linking account (non-fatal): ' + linkError.message);
// Linking failed but user is already logged in — proceed with existing token
}
pendingCred = null;
}
window.location.reload();
} catch (error) {
firebaseDebugLog(true, 'Error during account link flow: ' + error.message);
}
});
/**
* Handle native Facebook OAuth (Option 5)
* Redirects to Facebook OAuth URL
*/
async function handleFacebookNativeAuth() {
firebaseDebugLog(true, '=== NATIVE FACEBOOK OAUTH (Option 5) ===');
// Facebook App ID (from Facebook Developer Console)
const facebookAppId = '2018160385090572';
// Build Facebook OAuth URL
const redirectUri = encodeURIComponent(window.location.origin + window.location.pathname);
const state = Math.random().toString(36).substring(7); // Random state for security
localStorage.setItem('fb_oauth_state', state);
localStorage.setItem('fb_oauth_redirect', window.location.href);
const facebookAuthUrl = `https://www.facebook.com/v12.0/dialog/oauth?` +
`client_id=${facebookAppId}` +
`&redirect_uri=${redirectUri}` +
`&state=${state}` +
`&scope=email,public_profile` +
`&response_type=token`;
firebaseDebugLog(true, 'Redirecting to Facebook OAuth:', facebookAuthUrl);
// Redirect to Facebook
window.location.href = facebookAuthUrl;
}
/**
* Handle Facebook OAuth callback
* Called on page load to check if we're returning from Facebook OAuth
*/
async function handleFacebookOAuthCallback() {
// Check if login just completed (prevent reload loop)
if (sessionStorage.getItem('fb_login_complete') === 'true') {
firebaseDebugLog(true, 'Facebook login already completed this session, skipping callback');
sessionStorage.removeItem('fb_login_complete');
return false;
}
firebaseDebugLog(true, 'Checking for Facebook OAuth callback...');
// Check if URL has Facebook OAuth response (access_token in hash)
const hash = window.location.hash;
if (!hash || hash.indexOf('access_token=') === -1) {
firebaseDebugLog(true, 'No access_token in hash, not a Facebook OAuth callback');
return false;
}
// Prevent multiple executions
if (localStorage.getItem('fb_oauth_processing') === 'true') {
firebaseDebugLog(true, 'Already processing Facebook OAuth, skipping');
return true; // Return true to prevent other handlers
}
localStorage.setItem('fb_oauth_processing', 'true');
firebaseDebugLog(true, '=== FACEBOOK OAUTH CALLBACK DETECTED ===');
try {
// Parse the hash fragment
const params = new URLSearchParams(hash.substring(1));
const accessToken = params.get('access_token');
const state = params.get('state');
firebaseDebugLog(true, 'Parsed access_token length:', accessToken?.length);
firebaseDebugLog(true, 'Parsed state:', state);
// Verify state to prevent CSRF
const savedState = localStorage.getItem('fb_oauth_state');
firebaseDebugLog(true, 'Saved state:', savedState);
if (state !== savedState) {
firebaseDebugLog(true, 'ERROR: State mismatch, possible CSRF attack');
localStorage.removeItem('fb_oauth_processing');
return false;
}
// Exchange Facebook access token for Firebase credential
firebaseDebugLog(true, 'Creating Facebook credential from access token');
const credential = firebase.auth.FacebookAuthProvider.credential(accessToken);
firebaseDebugLog(true, 'Signing into Firebase with Facebook credential');
const result = await firebase.auth().signInWithCredential(credential);
firebaseDebugLog(true, 'Firebase signInWithCredential successful');
const user = result.user;
firebaseDebugLog(true, 'User:', user.email, 'UID:', user.uid);
// Get Firebase ID token
const idToken = await user.getIdToken();
firebaseDebugLog(true, 'Got Firebase ID token, length:', idToken.length);
// Login to WordPress
firebaseDebugLog(true, 'Calling WordPress login');
const loginResponse = await login(user, idToken);
if (!loginResponse || !loginResponse.success) {
firebaseDebugLog(true, 'ERROR: WordPress login failed');
localStorage.removeItem('fb_oauth_processing');
throw new Error('Failed to authenticate with WordPress.');
}
firebaseDebugLog(true, 'WordPress login successful!');
// Clean up
localStorage.removeItem('fb_oauth_state');
localStorage.removeItem('fb_oauth_processing');
localStorage.removeItem('fb_oauth_redirect');
// Set flag to prevent re-processing on reload
sessionStorage.setItem('fb_login_complete', 'true');
// Clean hash from URL and reload
window.location.hash = '';
window.location.reload();
return true;
} catch (error) {
firebaseDebugLog(true, 'ERROR in Facebook OAuth callback:', error.code, error.message);
localStorage.removeItem('fb_oauth_processing');
// Handle account-exists-with-different-credential error (same as standard flow)
if (error.code === 'auth/account-exists-with-different-credential') {
// Clean the hash from URL first
window.location.hash = '';
jQuery('.temp-preferences').show();
jQuery('.temp-preferences .sfba-before-login').show();
jQuery(".socialLogin").hide();
var email = error.email;
// Store credential in memory
pendingCred = error.credential;
try {
var methods = await firebase.auth().fetchSignInMethodsForEmail(email);
if (methods.length > 0) {
localStorage.setItem('existingProvider', methods[0]);
jQuery(".sfba-mask").removeClass("sfba-active");
jQuery(".sfba-link-mask").addClass('sfba-active');
handleLinkModel(methods[0]);
}
} catch (fetchError) {
firebaseDebugLog(true, 'Error fetching sign-in methods: ' + fetchError.message);
}
}
return false;
}
}
});
function logout() {
firebaseDebugLog(true, '---Start Logout');
logoutInProgress = true;
if (localStorage.getItem('localLogout') === null || localStorage.getItem('localLogout') == 1) {
logoutPopup();
}
localStorage.removeItem('localLogout');
// Sign out from Firebase
firebase.auth().signOut().then(function () {
firebaseDebugLog(true, 'User signed out from Firebase.');
// Perform an AJAX request to log the user out from WordPress
jQuery.ajax({
url: firebaseAuthAjax.ajax_url,
type: 'POST',
data: {
action: 'firebase_logout'
// nonce: firebaseAuthAjax.nonce
},
success: function (response) {
if (response.success) {
localStorage.removeItem('loggedInLocally');
logoutInProgress = false;
document.cookie = 'ssosession=; path=/; domain=' + cookieDomain + '; expires=Thu, 01 Jan 1970 00:00:00 UTC;';
window.location.reload(); // Reload the page after successful logout
} else {
firebaseDebugLog(true, 'Logout failed: ', response.data.message);
}
firebaseDebugLog(true, '---End Logout');
},
error: function (xhr, status, error) {
firebaseDebugLog(true, 'Error logging out: ', xhr.responseText);
}
});
}).catch(function (error) {
firebaseDebugLog(true, 'Firebase logout failed: ', error.message);
});
}
function loginPopup() {
const popupOverlay = document.createElement('div');
popupOverlay.className = 'popup-overlay';
popupOverlay.innerHTML = ``;
// Append overlay to the body
document.body.appendChild(popupOverlay);
// Display the popup
popupOverlay.style.display = 'block';
}
function logoutPopup() {
const popupOverlay = document.createElement('div');
popupOverlay.className = 'popup-overlay';
popupOverlay.innerHTML = `
Loading...
Logging out...
`;
// Append overlay to the body
document.body.appendChild(popupOverlay);
// Display the popup
popupOverlay.style.display = 'block';
}
function checkCookieExists() {
const sessionCookie = getCookie('ssosession');
if (sessionCookie) {
return sessionCookie;
}
return null;
}
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
function startTokenRefresh(user) {
firebaseDebugLog('refreshInterval-' + new Date().toLocaleString() + '---' + refreshInterval);
// Clear any existing intervals
clearInterval(refreshInterval);
// Refresh the token every 50 minutes (3000 seconds)
refreshInterval = setInterval(() => {
regenerateIdToken(user);
}, 50 * 60 * 1000); // 50 minutes in milliseconds
}
function regenerateIdToken(user) {
user.getIdToken(true)
.then((idToken) => {
firebaseDebugLog('New ID Token:' + idToken);
setCookie('ssosession', idToken, 24, cookieDomain);
})
.catch((error) => {
firebaseDebugLog('Error getting ID token:', error);
});
}
function setCookie(name, value, hours, domain) {
const expires = new Date(Date.now() + hours * 60 * 60 * 1000).toUTCString();
const cookieValue = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/; domain=${domain}; secure=false; SameSite=Lax`;
firebaseDebugLog('cookieValue' + cookieValue);
document.cookie = cookieValue;
}
function getMainDomain(url) {
const urlObject = new URL(url);
const hostParts = urlObject.hostname.split('.');
// If the host has two or more parts, join the last two parts as the main domain
if (hostParts.length >= 2) {
const mainDomain = hostParts.slice(-2).join('.');
return mainDomain;
}
// Fallback for a single part (e.g., localhost)
return urlObject.hostname;
}
function createDebugOverlay() {
// Create overlay container
debugLogContainer = document.createElement('div');
debugLogContainer.id = 'firebase-debug-overlay';
debugLogContainer.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 300px;
height: 70vh;
max-height: 70vh;
background: rgba(0, 0, 0, 0.9);
color: #0f0;
font-family: monospace;
font-size: 11px;
padding: 10px;
overflow-y: auto;
z-index: 999999;
border-right: 2px solid #0f0;
border-bottom: 2px solid #0f0;
`;
// Add title bar with download button
const titleBar = document.createElement('div');
titleBar.style.cssText = 'display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;';
const title = document.createElement('div');
title.textContent = '🔥 Firebase Debug Log';
title.style.cssText = 'font-weight: bold; color: #ff0;';
const downloadBtn = document.createElement('button');
downloadBtn.textContent = '📥 Download';
downloadBtn.style.cssText = `
background: #0f0;
color: #000;
border: none;
padding: 3px 8px;
font-size: 10px;
font-weight: bold;
cursor: pointer;
border-radius: 3px;
`;
downloadBtn.addEventListener('click', function (e) {
e.stopPropagation();
downloadDebugLog();
});
titleBar.appendChild(title);
titleBar.appendChild(downloadBtn);
debugLogContainer.appendChild(titleBar);
// Add close instruction
const closeMsg = document.createElement('div');
closeMsg.textContent = '(Tap log area to close)';
closeMsg.style.cssText = 'font-size: 9px; color: #888; margin-bottom: 5px;';
debugLogContainer.appendChild(closeMsg);
// Make it closable (but not the download button)
debugLogContainer.addEventListener('click', function (e) {
if (e.target !== downloadBtn) {
debugLogContainer.style.display = 'none';
}
});
document.body.appendChild(debugLogContainer);
console.log('Debug overlay created');
}
function firebaseDebugLog(stat = false, ...messages) {
if (isDebugMode && stat) {
console.log('Firebase:-', ...messages);
// Also write to overlay if it exists
if (debugLogContainer) {
try {
debugLogCounter++;
const logEntry = document.createElement('div');
logEntry.style.cssText = 'margin: 2px 0; padding: 2px; border-bottom: 1px solid #333;';
const timestamp = new Date().toLocaleTimeString();
const messageText = messages.map(m =>
typeof m === 'object' ? JSON.stringify(m) : String(m)
).join(' ');
logEntry.innerHTML = `[${debugLogCounter}] ${timestamp}
${messageText}`;
debugLogContainer.appendChild(logEntry);
// Auto-scroll to bottom
debugLogContainer.scrollTop = debugLogContainer.scrollHeight;
} catch (e) {
console.error('Failed to write to debug log:', e);
}
}
}
}
// Wrapper function for backward compatibility
function debugLog(stat = false, ...messages) {
firebaseDebugLog(stat, ...messages);
}
function downloadDebugLog() {
if (!debugLogContainer) {
console.error('Debug log container not found');
return;
}
// Collect all log entries
const logEntries = debugLogContainer.querySelectorAll('div');
let logText = 'Firebase Authentication Debug Log\n';
logText += '=================================\n';
logText += 'Generated: ' + new Date().toLocaleString() + '\n';
logText += 'URL: ' + window.location.href + '\n';
logText += 'User Agent: ' + navigator.userAgent + '\n';
logText += '=================================\n\n';
// Extract text from each log entry
logEntries.forEach((entry, index) => {
// Skip the title and close message
if (index > 1) {
const text = entry.innerText || entry.textContent;
if (text && text.trim()) {
logText += text + '\n';
}
}
});
// Create blob and download
const blob = new Blob([logText], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'firebase-debug-log-' + Date.now() + '.txt';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
console.log('Debug log downloaded');
}
function isInAppBrowser() {
const ua = navigator.userAgent || "";
return /FBAN|FBAV|Instagram|Line|Twitter|Snapchat|MicroMessenger/i.test(ua);
}
function isMobileDevice() {
const ua = navigator.userAgent || "";
// Check for mobile devices (iPhone, iPad, Android, etc.)
return /iPhone|iPad|iPod|Android|webOS|BlackBerry|IEMobile|Opera Mini/i.test(ua);
}
function getCurrentGeoData() {
return {
country: typeof COS_COUNTRY !== 'undefined' ? COS_COUNTRY : '',
state: typeof COS_STATE !== 'undefined' ? COS_STATE : '',
city: typeof COS_CITY !== 'undefined' ? COS_CITY : '',
latitude: typeof COS_LATITUDE !== 'undefined' ? COS_LATITUDE : '',
longitude: typeof COS_LONGITUDE !== 'undefined' ? COS_LONGITUDE : '',
};
}
function hasGeoChanged(currentGeo, lastSyncedGeo) {
return (
currentGeo.country !== (lastSyncedGeo.country || '') ||
currentGeo.state !== (lastSyncedGeo.state || '') ||
currentGeo.city !== (lastSyncedGeo.city || '') ||
String(currentGeo.latitude) !== String(lastSyncedGeo.latitude || '') ||
String(currentGeo.longitude) !== String(lastSyncedGeo.longitude || '')
);
}
async function syncGeoToLambda(userEmail) {
if (!userEmail) return;
const currentGeo = getCurrentGeoData();
const lastSyncedGeo = JSON.parse(localStorage.getItem('COS_GEO_DATA') || '{}');
if (currentGeo && !hasGeoChanged(currentGeo, lastSyncedGeo)) {
return;
}
try {
const response = await fetch('/wp-admin/admin-ajax.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
action: 'save_geo_to_dynamodb',
geo: JSON.stringify(currentGeo),
userEmail: userEmail
})
});
localStorage.setItem('COS_GEO_DATA', JSON.stringify(currentGeo));
const result = await response.json();
// console.log('Geo synced:', result);
} catch (err) {
console.error('Geo sync failed:', err);
}
}
;
!function(){"use strict";var e,t={noop:function(){},texturize:function(e){return(e=(e=(e=(e+="").replace(/'/g,"’").replace(/'/g,"’")).replace(/"/g,"”").replace(/"/g,"”").replace(/"/g,"”").replace(/[\u201D]/g,"”")).replace(/([\w]+)=[\d]+;(.+?)[\d]+;/g,'$1="$2"')).trim()},applyReplacements:function(e,t){if(e)return t?e.replace(/{(\d+)}/g,function(e,r){return void 0!==t[r]?t[r]:e}):e},getBackgroundImage:function(e){var t=document.createElement("canvas"),r=t.getContext&&t.getContext("2d");if(e){r.filter="blur(20px) ",r.drawImage(e,0,0);var o=t.toDataURL("image/png");return t=null,o}}},r=function(){function e(e,t){return Element.prototype.matches?e.matches(t):Element.prototype.msMatchesSelector?e.msMatchesSelector(t):void 0}function r(e,t,r,o){if(!e)return o();e.style.removeProperty("display"),e.style.opacity=t,e.style.pointerEvents="none";var a=function(i,n){var l=(performance.now()-i)/n;l<1?(e.style.opacity=t+(r-t)*l,requestAnimationFrame(()=>a(i,n))):(e.style.opacity=r,e.style.removeProperty("pointer-events"),o())};requestAnimationFrame(function(){requestAnimationFrame(function(){a(performance.now(),200)})})}return{closest:function(t,r){if(t.closest)return t.closest(r);var o=t;do{if(e(o,r))return o;o=o.parentElement||o.parentNode}while(null!==o&&1===o.nodeType);return null},matches:e,hide:function(e){e&&(e.style.display="none")},show:function(e){e&&(e.style.display="block")},fadeIn:function(e,o){r(e,0,1,o=o||t.noop)},fadeOut:function(e,o){o=o||t.noop,r(e,1,0,function(){e&&(e.style.display="none"),o()})},scrollToElement:function(e,t,r){if(!e||!t)return r?r():void 0;var o=t.querySelector(".jp-carousel-info-extra");o&&(o.style.minHeight=window.innerHeight-64+"px");var a=!0,i=Date.now(),n=t.scrollTop,l=Math.max(0,e.offsetTop-Math.max(0,window.innerHeight-function(e){var t=e.querySelector(".jp-carousel-info-footer"),r=e.querySelector(".jp-carousel-info-extra"),o=e.querySelector(".jp-carousel-info-content-wrapper");if(t&&r&&o){var a=window.getComputedStyle(r),i=parseInt(a.paddingTop,10)+parseInt(a.paddingBottom,10);return i=isNaN(i)?0:i,o.offsetHeight+t.offsetHeight+i}return 0}(t)))-t.scrollTop;function s(){a=!1}l=Math.min(l,t.scrollHeight-window.innerHeight),t.addEventListener("wheel",s),function e(){var c,u=Date.now(),d=(c=(u-i)/300)<.5?2*c*c:1-Math.pow(-2*c+2,2)/2,p=(d=d>1?1:d)*l;if(t.scrollTop=n+p,u<=i+300&&a)return requestAnimationFrame(e);r&&r(),o&&(o.style.minHeight=""),a=!1,t.removeEventListener("wheel",s)}()},getJSONAttribute:function(e,t){if(e&&e.hasAttribute(t))try{return JSON.parse(e.getAttribute(t))}catch{return}},convertToPlainText:function(e){var t=document.createElement("div");return t.textContent=e,t.innerHTML},stripHTML:function(e){return e.replace(/<[^>]*>?/gm,"")},emitEvent:function(e,t,r){var o;try{o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:r||null})}catch{(o=document.createEvent("CustomEvent")).initCustomEvent(t,!0,!0,r||null)}e.dispatchEvent(o)},isTouch:function(){return"ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch}}}();function o(){var o,a,i,n,l="",s=!1,c="div.gallery, div.tiled-gallery, ul.wp-block-gallery, ul.blocks-gallery-grid, figure.wp-block-gallery.has-nested-images, div.wp-block-jetpack-tiled-gallery, a.single-image-gallery",u=".gallery-item, .tiled-gallery-item, .blocks-gallery-item, .tiled-gallery__item",d=u+", .wp-block-image",p={},m="undefined"!=typeof wpcom&&wpcom.carousel&&wpcom.carousel.stat?wpcom.carousel.stat:t.noop,g="undefined"!=typeof wpcom&&wpcom.carousel&&wpcom.carousel.pageview?wpcom.carousel.pageview:t.noop;function h(t){if(!s)switch(t.which){case 38:t.preventDefault(),p.overlay.scrollTop-=100;break;case 40:t.preventDefault(),p.overlay.scrollTop+=100;break;case 39:t.preventDefault(),e.slideNext();break;case 37:case 8:t.preventDefault(),e.slidePrev();break;case 27:t.preventDefault(),k()}}function f(){s=!0}function v(){s=!1}function y(e){e.role="button",e.tabIndex=0,e.ariaLabel=jetpackCarouselStrings.image_label}function w(){p.overlay||(p.overlay=document.querySelector(".jp-carousel-overlay"),p.container=p.overlay.querySelector(".jp-carousel-wrap"),p.gallery=p.container.querySelector(".jp-carousel"),p.info=p.overlay.querySelector(".jp-carousel-info"),p.caption=p.info.querySelector(".jp-carousel-caption"),p.commentField=p.overlay.querySelector("#jp-carousel-comment-form-comment-field"),p.emailField=p.overlay.querySelector("#jp-carousel-comment-form-email-field"),p.authorField=p.overlay.querySelector("#jp-carousel-comment-form-author-field"),p.urlField=p.overlay.querySelector("#jp-carousel-comment-form-url-field"),window.innerWidth<=760&&Math.round(window.innerWidth/760*110)<40&&r.isTouch(),[p.commentField,p.emailField,p.authorField,p.urlField].forEach(function(e){e&&(e.addEventListener("focus",f),e.addEventListener("blur",v))}),p.overlay.addEventListener("click",function(e){var t,o,a=e.target,i=!!r.closest(a,".jp-carousel-close-hint"),n=!!window.matchMedia("(max-device-width: 760px)").matches;a===p.overlay?n||k():i?k():a.classList.contains("jp-carousel-image-download")?m("download_original_click"):a.classList.contains("jp-carousel-comment-login")?(t=p.currentSlide,o=t?t.attrs.attachmentId:"0",window.location.href=jetpackCarouselStrings.login_url+"%23jp-carousel-"+o):r.closest(a,"#jp-carousel-comment-form-container")?function(e){var t=e.target,o=r.getJSONAttribute(p.container,"data-carousel-extra")||{},a=p.currentSlide.attrs.attachmentId,i=document.querySelector("#jp-carousel-comment-form-submit-and-info-wrapper"),n=document.querySelector("#jp-carousel-comment-form-spinner"),l=document.querySelector("#jp-carousel-comment-form-button-submit"),s=document.querySelector("#jp-carousel-comment-form");if(p.commentField&&p.commentField.getAttribute("id")===t.getAttribute("id"))f(),r.show(i);else if(r.matches(t,'input[type="submit"]')){e.preventDefault(),e.stopPropagation(),r.show(n),s.classList.add("jp-carousel-is-disabled");var c={action:"post_attachment_comment",nonce:jetpackCarouselStrings.nonce,blog_id:o.blog_id,id:a,comment:p.commentField.value};if(!c.comment.length)return void j(jetpackCarouselStrings.no_comment_text,!1);if(1!==Number(jetpackCarouselStrings.is_logged_in)&&(c.email=p.emailField.value,c.author=p.authorField.value,c.url=p.urlField.value,1===Number(jetpackCarouselStrings.require_name_email))){if(!c.email.length||!c.email.match("@"))return void j(jetpackCarouselStrings.no_comment_email,!1);if(!c.author.length)return void j(jetpackCarouselStrings.no_comment_author,!1)}var u=new XMLHttpRequest;u.open("POST",jetpackCarouselStrings.ajaxurl,!0),u.setRequestHeader("X-Requested-With","XMLHttpRequest"),u.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"),u.onreadystatechange=function(){if(this.readyState===XMLHttpRequest.DONE&&this.status>=200&&this.status<300){var e;try{e=JSON.parse(this.response)}catch{return void j(jetpackCarouselStrings.comment_post_error,!1)}"approved"===e.comment_status?j(jetpackCarouselStrings.comment_approved,!0):"unapproved"===e.comment_status?j(jetpackCarouselStrings.comment_unapproved,!0):j(jetpackCarouselStrings.comment_post_error,!1),I(),_(a),l.value=jetpackCarouselStrings.post_comment,r.hide(n),s.classList.remove("jp-carousel-is-disabled")}else j(jetpackCarouselStrings.comment_post_error,!1)};var d=[];for(var m in c)if(m){var g=encodeURIComponent(m)+"="+encodeURIComponent(c[m]);d.push(g.replace(/%20/g,"+"))}var h=d.join("&");u.send(h)}}(e):(r.closest(a,".jp-carousel-photo-icons-container")||a.classList.contains("jp-carousel-photo-title"))&&function(e){e.preventDefault();var t=e.target,o=p.info.querySelector(".jp-carousel-info-extra"),a=p.info.querySelector(".jp-carousel-image-meta"),i=p.info.querySelector(".jp-carousel-comments-wrapper"),n=p.info.querySelector(".jp-carousel-icon-info"),l=p.info.querySelector(".jp-carousel-icon-comments");function s(){l&&l.classList.remove("jp-carousel-selected"),n.classList.toggle("jp-carousel-selected"),i&&i.classList.remove("jp-carousel-show"),a&&(a.classList.toggle("jp-carousel-show"),a.classList.contains("jp-carousel-show")?o.classList.add("jp-carousel-show"):o.classList.remove("jp-carousel-show"))}function c(){n&&n.classList.remove("jp-carousel-selected"),l.classList.toggle("jp-carousel-selected"),a&&a.classList.remove("jp-carousel-show"),i&&(i.classList.toggle("jp-carousel-show"),i.classList.contains("jp-carousel-show")?o.classList.add("jp-carousel-show"):o.classList.remove("jp-carousel-show"))}(r.closest(t,".jp-carousel-icon-info")||t.classList.contains("jp-carousel-photo-title"))&&(a&&a.classList.contains("jp-carousel-show")?r.scrollToElement(p.overlay,p.overlay,s):(s(),r.scrollToElement(p.info,p.overlay))),r.closest(t,".jp-carousel-icon-comments")&&(i&&i.classList.contains("jp-carousel-show")?r.scrollToElement(p.overlay,p.overlay,c):(c(),r.scrollToElement(p.info,p.overlay)))}(e)}),window.addEventListener("keydown",h),p.overlay.addEventListener("jp_carousel.afterOpen",function(){v(),p.slides.length<=1||(p.slides.length<=5?r.show(p.info.querySelector(".jp-swiper-pagination")):r.show(p.info.querySelector(".jp-carousel-pagination")))}),p.overlay.addEventListener("jp_carousel.beforeClose",function(){f(),document.documentElement.style.removeProperty("height"),e&&e.enable(),r.hide(p.info.querySelector(".jp-swiper-pagination")),r.hide(p.info.querySelector(".jp-carousel-pagination"))}),p.overlay.addEventListener("jp_carousel.afterClose",function(){window.history.pushState?history.pushState("",document.title,window.location.pathname+window.location.search):window.location.href="",l="",p.isOpen=!1}),p.overlay.addEventListener("touchstart",function(e){e.touches.length>1&&e.preventDefault()}))}function j(e,t){var o=p.overlay.querySelector("#jp-carousel-comment-post-results"),a="jp-carousel-comment-post-"+(t?"success":"error");o.innerHTML=''+e+"",r.hide(p.overlay.querySelector("#jp-carousel-comment-form-spinner")),p.overlay.querySelector("#jp-carousel-comment-form").classList.remove("jp-carousel-is-disabled"),r.show(o)}function b(){var e=document.querySelectorAll("a img[data-attachment-id]");Array.prototype.forEach.call(e,function(e){var t=e.parentElement,o=t.parentElement;if(!o.classList.contains("gallery-icon")&&!r.closest(o,u)&&t.hasAttribute("href")){var a=!1;t.getAttribute("href").split("?")[0]===e.getAttribute("data-orig-file").split("?")[0]&&1===Number(jetpackCarouselStrings.single_image_gallery_media_file)&&(a=!0),t.getAttribute("href")===e.getAttribute("data-permalink")&&(a=!0),a&&(y(e),t.classList.add("single-image-gallery"),t.setAttribute("data-carousel-extra",JSON.stringify({blog_id:Number(jetpackCarouselStrings.blog_id)})))}})}function S(t,r){p.isOpen?(L(r),e.slideTo(r+1)):F(t,{startIndex:r})}function L(e){(!e||e<0||e>p.slides.length)&&(e=0),p.currentSlide=p.slides[e];var o,a,i=p.currentSlide,n=i.attrs.attachmentId;H(p.slides[e]),function(e){var t=[],r=p.slides.length;if(r>1){var o=e>0?e-1:r-1;t.push(o);var a=e"+jetpackCarouselStrings[o]+"
"+a+""}}t.innerHTML=r,t.style.removeProperty("display")}(p.slides[e].attrs.imageMeta),function(e){if(!e)return!1;var r,o=[e.attrs.origWidth,e.attrs.origHeight],a=document.createElement("a");a.href=e.attrs.src.replace(/\?.+$/,""),r=null!==a.hostname.match(/^i[\d]{1}\.wp\.com$/i)?a.href:e.attrs.origFile.replace(/\?.+$/,"");var i=p.info.querySelector(".jp-carousel-download-text"),n=p.info.querySelector(".jp-carousel-image-download");i.innerHTML=t.applyReplacements(jetpackCarouselStrings.download_original,o),n.setAttribute("href",r),n.style.removeProperty("display")}(i),1===Number(jetpackCarouselStrings.display_comments)&&(o=p.slides[e].attrs.commentsOpened,a=p.info.querySelector("#jp-carousel-comment-form-container"),1===parseInt(o,10)?r.fadeIn(a):r.fadeOut(a),_(n),r.hide(p.info.querySelector("#jp-carousel-comment-post-results")));var s=p.info.querySelector(".jp-carousel-pagination");if(s&&p.slides.length>5){var c=e+1;s.innerHTML=""+c+" / "+p.slides.length+""}jetpackCarouselStrings.stats&&p.isOpen&&((new Image).src=document.location.protocol+"//pixel.wp.com/g.gif?"+jetpackCarouselStrings.stats+"&post="+encodeURIComponent(n)+"&rand="+Math.random()),p.isOpen&&g(n),l="#jp-carousel-"+n,window.location.hash=l}function k(){document.body.style.overflow=a,document.documentElement.style.overflow=i,I(),f(),r.emitEvent(p.overlay,"jp_carousel.beforeClose"),window.scrollTo(window.scrollX||window.pageXOffset||0,n||0),p.isOpen=!1,e.destroy(),p.slides=[],p.currentSlide=void 0,p.gallery.innerHTML="",r.fadeOut(p.overlay,function(){r.emitEvent(p.overlay,"jp_carousel.afterClose")})}function x(e){if("object"!=typeof e&&(e={}),void 0===e.origFile)return"";if(void 0===e.origWidth||void 0===e.maxWidth)return e.origFile;if(void 0===e.mediumFile||void 0===e.largeFile)return e.origFile;var t=document.createElement("a");t.href=e.largeFile;var r=/^i[0-2]\.wp\.com$/i.test(t.hostname),o=q(e.largeFile,e.origWidth,r),a=parseInt(o[0],10),i=parseInt(o[1],10);if(e.origMaxWidth=e.maxWidth,e.origMaxHeight=e.maxHeight,void 0!==window.devicePixelRatio&&window.devicePixelRatio>1&&(e.maxWidth=e.maxWidth*window.devicePixelRatio,e.maxHeight=e.maxHeight*window.devicePixelRatio),a>=e.maxWidth||i>=e.maxHeight)return e.largeFile;var n=q(e.mediumFile,e.origWidth,r),l=parseInt(n[0],10),s=parseInt(n[1],10);if(l>=e.maxWidth||s>=e.maxHeight)return e.mediumFile;if(r){if(-1===e.largeFile.lastIndexOf("?"))return e.largeFile;var c=function(e){var t;try{t=new URL(e)}catch(t){return e}var r=["quality","ssl","filter","brightness","contrast","colorize","smooth"],o=Array.from(t.searchParams.entries());return t.search="",o.forEach(([e,o])=>{r.includes(e)&&t.searchParams.append(e,o)}),t}(e.largeFile);return(e.origWidth>e.maxWidth||e.origHeight>e.maxHeight)&&(e.origMaxWidth=2*e.maxWidth,e.origMaxHeight=2*e.maxHeight,c.searchParams.set("fit",e.origMaxWidth+","+e.origMaxHeight)),c.toString()}return e.origFile}function q(e,t,r){var o,a=r?e.replace(/.*=([\d]+%2C[\d]+).*$/,"$1"):e.replace(/.*-([\d]+x[\d]+)\..+$/,"$1");return"9999"===(o=a!==e?r?a.split("%2C"):a.split("x"):[t,0])[0]&&(o[0]="0"),"9999"===o[1]&&(o[1]="0"),o}function A(e){return e>=1?Math.round(10*e)/10+"s":"1/"+Math.round(1/e)+"s"}function E(e){return!e.match(" ")&&e.match("_")?"":e}function _(e,t){var a=void 0===t,i=p.info.querySelector(".jp-carousel-icon-comments .jp-carousel-has-comments-indicator");if(i.classList.remove("jp-carousel-show"),clearInterval(o),e){(!t||t<1)&&(t=0);var n=p.info.querySelector(".jp-carousel-comments"),l=p.info.querySelector("#jp-carousel-comments-loading");r.show(l),a&&(r.hide(n),n.innerHTML="");var s=new XMLHttpRequest,c=jetpackCarouselStrings.ajaxurl+"?action=get_attachment_comments&nonce="+jetpackCarouselStrings.nonce+"&id="+e+"&offset="+t;s.open("GET",c),s.setRequestHeader("X-Requested-With","XMLHttpRequest");var u=function(){r.fadeIn(n),r.fadeOut(l)};s.onload=function(){if(p.currentSlide&&p.currentSlide.attrs.attachmentId===e){var c,d=s.status>=200&&s.status<300;try{c=JSON.parse(s.responseText)}catch{}if(!d||!c||!Array.isArray(c))return u();a&&(n.innerHTML="");for(var m=0;m