1document.addEventListener('DOMContentLoaded', function () { 2 if (!window.ProgressifyUADetector || !window.ProgressifyUADetector.isSupported) return; 3 4 const offlineNotificationJsVars = window['progressify_offline_notification_js_vars'] || {}; 5 6 const getContrastTextColor = (backgroundColor) => { 7 const temp = document.createElement('div'); 8 temp.style.backgroundColor = backgroundColor; 9 temp.style.display = 'none'; 10 document.body.appendChild(temp); 11 12 const computedColor = window.getComputedStyle(temp).backgroundColor; 13 document.body.removeChild(temp); 14 15 const [r, g, b] = computedColor.match(/\d+/g).map(Number); 16 const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255; 17 18 return luminance > 0.5 ? '#000000' : '#ffffff'; 19 }; 20 21 class ProgressifyOfflineNotification extends HTMLElement { 22 constructor() { 23 super(); 24 this.attachShadow({ mode: 'open' }); 25 this.styles = new Set(); 26 } 27 28 connectedCallback() { 29 this.render(); 30 } 31 32 injectStyles(css) { 33 this.styles.add(css); 34 } 35 36 static showReconnecting() { 37 let offlineNotification = document.querySelector('progressify-offline-notification'); 38 39 if (!offlineNotification) { 40 offlineNotification = document.createElement('progressify-offline-notification'); 41 document.body.appendChild(offlineNotification); 42 } 43 44 requestAnimationFrame(() => { 45 const notification = offlineNotification.shadowRoot.querySelector('.offline-notification'); 46 const icon = notification.querySelector('.offline-notification_icon'); 47 const text = notification.querySelector('.offline-notification_text'); 48 49 // Reset to reconnecting state 50 notification.classList.remove('reconnected'); 51 icon.classList.add('spinner'); 52 icon.classList.remove('success'); 53 text.textContent = wp.i18n.__('Connection lost. Attempting to reconnect...', 'progressify'); 54 55 setTimeout(() => { 56 notification.classList.add('visible'); 57 }, 300); 58 }); 59 60 return offlineNotification; 61 } 62 63 static showReconnected() { 64 const offlineNotification = document.querySelector('progressify-offline-notification'); 65 if (!offlineNotification) return; 66 67 const notification = offlineNotification.shadowRoot.querySelector('.offline-notification'); 68 const icon = notification.querySelector('.offline-notification_icon'); 69 const text = notification.querySelector('.offline-notification_text'); 70 71 notification.classList.add('reconnected'); 72 icon.classList.remove('spinner'); 73 icon.classList.add('success'); 74 text.textContent = wp.i18n.__('Successfully reconnected to the internet!', 'progressify'); 75 76 // Clear any existing removal timeout 77 if (offlineNotification._removeTimeout) { 78 clearTimeout(offlineNotification._removeTimeout); 79 } 80 81 offlineNotification._removeTimeout = setTimeout(() => { 82 notification.classList.remove('visible'); 83 notification.addEventListener( 84 'transitionend', 85 () => { 86 offlineNotification.remove(); 87 }, 88 { once: true } 89 ); 90 }, 2000); 91 } 92 93 render() { 94 const themeColor = offlineNotificationJsVars.themeColor ?? '#000000'; 95 const backgroundColor = getContrastTextColor(themeColor); 96 const textColor = getContrastTextColor(backgroundColor); 97 98 this.injectStyles(` 99 .offline-notification { 100 position: fixed; 101 top: 0; 102 left: 50%; 103 -webkit-transform: translateX(-50%) translateY(-100%); 104 -ms-transform: translateX(-50%) translateY(-100%); 105 transform: translateX(-50%) translateY(-100%); 106 display: -webkit-box; 107 display: -ms-flexbox; 108 display: flex; 109 -webkit-box-align: center; 110 -ms-flex-align: center; 111 align-items: center; 112 padding: 0.75rem 1rem; 113 gap: 0.75rem; 114 width: 30rem; 115 max-width: 85%; 116 background-color: ${backgroundColor}; 117 color: ${textColor}; 118 border: 1px solid ${textColor}15; 119 border-radius: 0.75rem; 120 -webkit-box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); 121 box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); 122 z-index: 9999999999999999; 123 -webkit-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); 124 -o-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); 125 transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); 126 opacity: 0; 127 visibility: hidden; 128 } 129 130 .offline-notification.visible { 131 opacity: 1;
132 visibility: visible; 133 -webkit-transform: translateX(-50%) translateY(1rem); 134 -ms-transform: translateX(-50%) translateY(1rem); 135 transform: translateX(-50%) translateY(1rem); 136 } 137 138 .offline-notification_icon { 139 display: inline-block; 140 flex-shrink: 0; 141 width: 12px; 142 height: 12px; 143 border-radius: 9999px; 144 } 145 146 .offline-notification_icon.spinner { 147 -webkit-animation: spin 1s linear infinite; 148 animation: spin 1s linear infinite; 149 border: 3px solid ${themeColor}; 150 border-top-color: transparent; 151 } 152 153 .offline-notification_icon.success { 154 background-color: #22c55e; 155 border-radius: 9999px; 156 } 157 158 .offline-notification_text { 159 font-size: 0.875rem; 160 line-height: 1.25rem; 161 } 162 163 @-webkit-keyframes spin { 164 to { 165 -webkit-transform: rotate(360deg); 166 transform: rotate(360deg); 167 } 168 } 169 170 @keyframes spin { 171 to { 172 -webkit-transform: rotate(360deg); 173 transform: rotate(360deg); 174 } 175 } 176 `); 177 178 const combinedStyles = Array.from(this.styles).join('\n'); 179 180 this.shadowRoot.innerHTML = ` 181 <style>${combinedStyles}</style> 182 <div class="offline-notification" role="alert" tabindex="-1"> 183 <div class="offline-notification_icon spinner" role="status" aria-label="loading"></div> 184 <span class="offline-notification_text"> 185 ${wp.i18n.__('Connection lost. Attempting to reconnect...', 'progressify')} 186 </span> 187 </div> 188 `; 189 } 190 } 191 192 if (!customElements.get('progressify-offline-notification')) { 193 customElements.define('progressify-offline-notification', ProgressifyOfflineNotification); 194 } 195 196 // Check initial state 197 if (!navigator.onLine) { 198 ProgressifyOfflineNotification.showReconnecting(); 199 } 200 201 window.addEventListener('offline', () => { 202 ProgressifyOfflineNotification.showReconnecting(); 203 }); 204 205 window.addEventListener('online', () => { 206 ProgressifyOfflineNotification.showReconnected(); 207 }); 208});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.