let isLeavingPage = false; let notificationTimeout; // Request notification permission function requestPermission() { if (!('Notification' in window)) { alert('This browser does not support desktop notifications'); return; } Notification.requestPermission().then(permission => { if (permission === 'granted') { document.getElementById('status').textContent = 'Notifications enabled!'; setupTabCloseDetection(); } }); } // Method 1: Using visibilitychange event document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'hidden' && !isLeavingPage) { tryToSendNotification('Tab Hidden', 'Come back soon!'); } }); // Method 2: Using beforeunload event window.addEventListener('beforeunload', function(e) { isLeavingPage = true; // Try to send notification before page unloads tryToSendNotification('Thanks for visiting!', 'We hope to see you again soon!'); // Some browsers require returnValue to be set e.preventDefault(); e.returnValue = ''; // Set a flag in localStorage that we can check on next visit localStorage.setItem('lastVisitEndTime', Date.now()); }); // Method 3: Using page show event to detect return after close window.addEventListener('pageshow', function() { const lastVisitEndTime = localStorage.getItem('lastVisitEndTime'); if (lastVisitEndTime) { const timeSinceLastVisit = Date.now() - parseInt(lastVisitEndTime); // If it's been more than 1 second since last visit, assume it was a genuine close if (timeSinceLastVisit > 1000) { tryToSendNotification('Welcome Back!', 'It\'s been ' + Math.round(timeSinceLastVisit/1000) + ' seconds since your last visit'); } localStorage.removeItem('lastVisitEndTime'); } }); // Method 4: Using blur event window.addEventListener('blur', function() { if (!isLeavingPage) { // Wait a bit to see if it's a genuine tab close notificationTimeout = setTimeout(() => { tryToSendNotification('Missing You!', 'Don\'t forget to come back and finish what you started!'); }, 1000); } }); // Method 5: Using focus event to clear timeout window.addEventListener('focus', function() { clearTimeout(notificationTimeout); }); // Helper function to send notifications function tryToSendNotification(title, body) { if (Notification.permission === 'granted') { // Store the notification in a variable to prevent garbage collection const notification = new Notification(title, { body: body, icon: 'https://via.placeholder.com/64', requireInteraction: true, tag: 'tab-close' // This ensures only one notification is shown }); // Handle notification click notification.onclick = function() { window.focus(); notification.close(); }; // Store notification reference in localStorage const notificationData = { title: title, body: body, timestamp: Date.now() }; localStorage.setItem('lastNotification', JSON.stringify(notificationData)); } } // Setup tab close detection systems function setupTabCloseDetection() { // Check if there was a previous notification const lastNotification = localStorage.getItem('lastNotification'); if (lastNotification) { const data = JSON.parse(lastNotification); const timeSince = Date.now() - data.timestamp; // If it's been less than 5 seconds, show a welcome back notification if (timeSince < 5000) { tryToSendNotification('Welcome Back!', 'Looks like you were just here ' + Math.round(timeSince/1000) + ' seconds ago'); } localStorage.removeItem('lastNotification'); } } // Initialize on load if (Notification.permission === 'granted') { setupTabCloseDetection(); }