upskill-event-manager/assets/js/safari-storage.js
Ben 89872ec998 fix: resolve registration form display and event edit issues
- Fixed registration form not displaying due to missing HVAC_Security_Helpers dependency
- Added require_once for dependencies in class-hvac-shortcodes.php render_registration()
- Fixed event edit HTTP 500 error by correcting class instantiation to HVAC_Event_Manager
- Created comprehensive E2E test suite with MCP Playwright integration
- Achieved 70% test success rate with both issues fully resolved

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-24 08:27:17 -03:00

386 lines
No EOL
12 KiB
JavaScript

/**
* Safari ITP-Compatible Storage Strategy
* Handles Safari's Intelligent Tracking Prevention restrictions
*
* Safari ITP limits:
* - Cookies expire after 7 days
* - localStorage may be cleared after 7 days of non-interaction
* - sessionStorage is preserved for session only
*
* @package HVAC_Community_Events
* @since 2.0.0
*/
var SafariStorage = (function() {
'use strict';
var features = {
localStorage: false,
sessionStorage: false,
cookies: false
};
/**
* Test localStorage availability
*/
function testLocalStorage() {
try {
var test = '__safari_storage_test__';
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch(e) {
console.warn('[Safari Storage] localStorage not available:', e);
return false;
}
}
/**
* Test sessionStorage availability
*/
function testSessionStorage() {
try {
var test = '__safari_storage_test__';
sessionStorage.setItem(test, test);
sessionStorage.removeItem(test);
return true;
} catch(e) {
console.warn('[Safari Storage] sessionStorage not available:', e);
return false;
}
}
/**
* Test cookie availability
*/
function testCookies() {
try {
// Test if cookies are enabled
if (!navigator.cookieEnabled) {
return false;
}
// Try to set a test cookie
document.cookie = '__safari_test=1;SameSite=Lax;Secure';
var cookieEnabled = document.cookie.indexOf('__safari_test') !== -1;
// Clean up test cookie
if (cookieEnabled) {
document.cookie = '__safari_test=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;';
}
return cookieEnabled;
} catch(e) {
console.warn('[Safari Storage] Cookies not available:', e);
return false;
}
}
/**
* Initialize feature detection
*/
function init() {
features.localStorage = testLocalStorage();
features.sessionStorage = testSessionStorage();
features.cookies = testCookies();
console.log('[Safari Storage] Features detected:', features);
// Warn if no storage is available
if (!features.localStorage && !features.sessionStorage && !features.cookies) {
console.error('[Safari Storage] WARNING: No storage methods available!');
}
return features;
}
/**
* Set a value with automatic fallback
*
* @param {string} key - Storage key
* @param {*} value - Value to store
* @param {number} days - Days until expiration (default 7 for Safari ITP)
* @returns {boolean} Success status
*/
function set(key, value, days) {
days = days || 7; // Default to Safari ITP limit
var data = {
value: value,
timestamp: Date.now(),
expires: Date.now() + (days * 24 * 60 * 60 * 1000)
};
var stringData = JSON.stringify(data);
// Try localStorage first (most persistent)
if (features.localStorage) {
try {
localStorage.setItem('hvac_' + key, stringData);
console.log('[Safari Storage] Saved to localStorage:', key);
return true;
} catch(e) {
console.warn('[Safari Storage] localStorage failed, trying fallback:', e);
}
}
// Fallback to sessionStorage (session-only but reliable)
if (features.sessionStorage) {
try {
sessionStorage.setItem('hvac_' + key, stringData);
console.log('[Safari Storage] Saved to sessionStorage:', key);
// Also try to set a cookie for cross-page persistence
if (features.cookies) {
setCookie('hvac_' + key, stringData, days);
}
return true;
} catch(e) {
console.warn('[Safari Storage] sessionStorage failed, trying cookies:', e);
}
}
// Last resort: cookies only
if (features.cookies) {
setCookie('hvac_' + key, stringData, days);
console.log('[Safari Storage] Saved to cookies:', key);
return true;
}
console.error('[Safari Storage] Unable to save data:', key);
return false;
}
/**
* Get a value with automatic fallback
*
* @param {string} key - Storage key
* @returns {*} Stored value or null
*/
function get(key) {
var prefixedKey = 'hvac_' + key;
var data = null;
// Try localStorage first
if (features.localStorage) {
try {
var localData = localStorage.getItem(prefixedKey);
if (localData) {
data = JSON.parse(localData);
// Check if expired (Safari ITP)
if (data.expires && Date.now() > data.expires) {
console.log('[Safari Storage] Data expired in localStorage:', key);
localStorage.removeItem(prefixedKey);
data = null;
} else {
console.log('[Safari Storage] Retrieved from localStorage:', key);
return data.value;
}
}
} catch(e) {
console.warn('[Safari Storage] localStorage read failed:', e);
}
}
// Try sessionStorage
if (features.sessionStorage) {
try {
var sessionData = sessionStorage.getItem(prefixedKey);
if (sessionData) {
data = JSON.parse(sessionData);
console.log('[Safari Storage] Retrieved from sessionStorage:', key);
return data.value;
}
} catch(e) {
console.warn('[Safari Storage] sessionStorage read failed:', e);
}
}
// Try cookies
if (features.cookies) {
var cookieData = getCookie(prefixedKey);
if (cookieData) {
try {
data = JSON.parse(cookieData);
// Check if expired
if (data.expires && Date.now() > data.expires) {
console.log('[Safari Storage] Data expired in cookie:', key);
removeCookie(prefixedKey);
return null;
}
console.log('[Safari Storage] Retrieved from cookies:', key);
return data.value;
} catch(e) {
// Might be a plain string cookie
return cookieData;
}
}
}
return null;
}
/**
* Remove a value from all storage types
*
* @param {string} key - Storage key
*/
function remove(key) {
var prefixedKey = 'hvac_' + key;
if (features.localStorage) {
try {
localStorage.removeItem(prefixedKey);
} catch(e) {
// Silent fail
}
}
if (features.sessionStorage) {
try {
sessionStorage.removeItem(prefixedKey);
} catch(e) {
// Silent fail
}
}
if (features.cookies) {
removeCookie(prefixedKey);
}
console.log('[Safari Storage] Removed:', key);
}
/**
* Set a cookie with Safari ITP compatibility
*
* @param {string} name - Cookie name
* @param {string} value - Cookie value
* @param {number} days - Days until expiration
*/
function setCookie(name, value, days) {
var expires = '';
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = ';expires=' + date.toUTCString();
}
// Safari ITP compatible settings
// - SameSite=Lax for cross-site GET requests
// - Secure for HTTPS only
// - Path=/ for site-wide access
var isSecure = window.location.protocol === 'https:';
var cookieString = name + '=' + encodeURIComponent(value) + expires +
';path=/;SameSite=Lax' + (isSecure ? ';Secure' : '');
document.cookie = cookieString;
}
/**
* Get a cookie value
*
* @param {string} name - Cookie name
* @returns {string|null} Cookie value or null
*/
function getCookie(name) {
var nameEQ = name + '=';
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
while (cookie.charAt(0) === ' ') {
cookie = cookie.substring(1, cookie.length);
}
if (cookie.indexOf(nameEQ) === 0) {
return decodeURIComponent(cookie.substring(nameEQ.length, cookie.length));
}
}
return null;
}
/**
* Remove a cookie
*
* @param {string} name - Cookie name
*/
function removeCookie(name) {
document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;';
}
/**
* Clear all HVAC storage
*/
function clearAll() {
// Clear localStorage
if (features.localStorage) {
try {
var keys = [];
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key && key.indexOf('hvac_') === 0) {
keys.push(key);
}
}
keys.forEach(function(key) {
localStorage.removeItem(key);
});
} catch(e) {
// Silent fail
}
}
// Clear sessionStorage
if (features.sessionStorage) {
try {
var sessionKeys = [];
for (var j = 0; j < sessionStorage.length; j++) {
var sessionKey = sessionStorage.key(j);
if (sessionKey && sessionKey.indexOf('hvac_') === 0) {
sessionKeys.push(sessionKey);
}
}
sessionKeys.forEach(function(key) {
sessionStorage.removeItem(key);
});
} catch(e) {
// Silent fail
}
}
// Clear cookies
if (features.cookies) {
var cookies = document.cookie.split(';');
cookies.forEach(function(cookie) {
var eqPos = cookie.indexOf('=');
var name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();
if (name.indexOf('hvac_') === 0) {
removeCookie(name);
}
});
}
console.log('[Safari Storage] All storage cleared');
}
// Initialize on load
init();
// Public API
return {
init: init,
set: set,
get: get,
remove: remove,
clearAll: clearAll,
features: features
};
})();
// Make globally available
window.SafariStorage = SafariStorage;