1window.Fog = window.Fog || {}; 2window.Fog.Webapp = window.Fog.Webapp || {}; 3window.Fog.Webapp.Common = { 4 5 updateContentHeight: function () { 6 const navbar = document.querySelector('nav'); 7 const footer = document.querySelector('footer'); 8 9 if (navbar && footer) { 10 const navHeight = navbar.offsetHeight; 11 const footerHeight = footer.offsetHeight; 12 13 document.documentElement.style.setProperty('--actual-nav-height', `${navHeight}px`); 14 document.documentElement.style.setProperty('--actual-footer-height', `${footerHeight}px`); 15 } 16 }, 17 18 getDimensions: function (selector) { 19 try { 20 let element; 21 22 // Handle different input types 23 if (!selector) { 24 console.warn('Selector is null or undefined'); 25 return null; 26 } 27 28 // If it's already an element 29 if (selector instanceof Element) { 30 element = selector; 31 } 32 // If it's a string (ID or class or any CSS selector) 33 else if (typeof selector === 'string') { 34 // Try as ID first 35 element = document.getElementById(selector.replace('#', '')); 36 37 // If not found, try as any CSS selector 38 if (!element) { 39 element = document.querySelector(selector); 40 } 41 42 // If still not found, try getting all elements (for class) 43 if (!element) { 44 const elements = document.querySelectorAll(selector); 45 if (elements.length > 0) { 46 // Return array of dimensions for all matching elements 47 return Array.from(elements).map(el => this.getMeasurements(el)); 48 } 49 } 50 } 51 52 if (!element) { 53 console.warn('No element found for selector:', selector); 54 return null; 55 } 56 57 return this.getMeasurements(element); 58 59 } catch (error) { 60 console.error('Error measuring element:', error, 'Selector:', selector); 61 return null; 62 } 63 }, 64 65 getMeasurements: function (element) { 66 // For SKCanvasView or similar custom components that wrap canvas 67 const canvas = element.querySelector('canvas'); 68 if (canvas) { 69 return { 70 width: canvas.clientWidth, 71 height: canvas.clientHeight 72 }; 73 } 74 75 // For direct Canvas elements 76 if (element instanceof HTMLCanvasElement) { 77 return { 78 width: element.clientWidth, 79 height: element.clientHeight 80 }; 81 } 82 83 // For standard HTML elements 84 if (element instanceof HTMLElement) { 85 const rect = element.getBoundingClientRect(); 86 return { 87 width: rect.width, 88 height: rect.height 89 }; 90 } 91 92 return { 93 width: 0, 94 height: 0 95 }; 96 }, 97 98 calculateAndSetAvailableHeight: function (inputDivId) { 99 // Get the input div element 100 const inputDiv = document.getElementById(inputDivId); 101 if (!inputDiv) return; 102 103 // Get the div's offset from the top of the page 104 const divOffset = inputDiv.getBoundingClientRect().top; 105 106 // Calculate available height (viewport height - offset - buffer for padding) 107 const buffer = 120; // Adjust this value as needed 108 const availableHeight = window.innerHeight - divOffset - buffer; 109 110 // Set the height 111 inputDiv.style.height = `${availableHeight}px`; 112 }, 113 114 resetScrollPosition: function () { 115 window.scrollTo(0, 1); 116 window.scrollTo(0, 0); 117 }, 118 119 hidePageLoadingIndicator: () => { 120 const loadingElement = document.getElementById('page-loading-indicator'); 121 if (loadingElement) { 122 loadingElement.style.display = 'none'; 123 } 124 }, 125 126 showPageLoadingIndicator: () => { 127 const loadingElement = document.getElementById('page-loading-indicator'); 128 if (loadingElement) { 129 loadingElement.style.display = 'flex'; 130 } 131 }, 132 133 copyToClipboard: async (text) => { 134 try { 135 await navigator.clipboard.writeText(text); 136 return true; 137 } catch (err) { 138 console.error('Failed to copy:', err); 139 return false;
140 } 141 }, 142 143 isMobile: () => { 144 return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); 145 }, 146 147 scrollTo: (elem, position, smooth) => { 148 let behavior = 'instant'; 149 if (smooth === true) { 150 behavior = 'smooth' 151 } 152 elem.scrollTo({top: position, behavior: behavior}); 153 }, 154 155 scrollToBottom: (elem, smooth) => { 156 if (!elem) return; 157 window.Fog.Webapp.Common.scrollTo(elem, elem.scrollHeight, smooth); 158 }, 159 160 saveFile: (filename, contentType, content) => { 161 const blob = new Blob([content], {type: contentType}); 162 const link = document.createElement('a'); 163 link.href = URL.createObjectURL(blob); 164 link.download = filename; 165 link.click(); 166 URL.revokeObjectURL(link.href); 167 } 168}; 169 170window.Fog.Webapp.Analytics = { 171 gtag: window.gtag || function () { 172 dataLayer.push(arguments); 173 }, 174} 175 176window.Fog.Webapp.AdSense = { 177 initializeAd: (adSlotId) => { 178 try { 179 // Push the ad to AdSense queue 180 (adsbygoogle = window.adsbygoogle || []).push({}); 181 return true; 182 183 } catch (e) { 184 console.error('Error initializing ad:', e); 185 return false; 186 } 187 }, 188} 189 190window.Fog.Webapp.Google = { 191 openPrivacySettings: () => { 192 try { 193 if (window.googlefc && typeof googlefc.showRevocationMessage === "function") { 194 googlefc.showRevocationMessage(); 195 } else { 196 console.warn("Funding Choices not loaded yet."); 197 } 198 199 } catch (e) { 200 console.error('Error initializing ad:', e); 201 } 202 }, 203}
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.