1class GoogleTranslateManager { 2 constructor() { 3 this.googleTranslateLoaded = false; 4 this.googleTranslateScriptAdded = false; // Keep track of script loading 5 this.loadingPromise = null; 6 this.firstClick = false; 7 this.isOpeningMenu = false; // Estää ikuisen silmukan 8 this.init(); 9 } 10 11 init() { 12 const translateButton = document.getElementById('google_translate_language_button'); 13 if (translateButton) { 14 translateButton.addEventListener("click", () => { 15 16 // Jos tämä on ohjelmallinen klikkaus, älä tee mitään. 17 if (this.isOpeningMenu) { 18 return; 19 } 20 21 if (!this.googleTranslateScriptAdded) { 22 this.firstClick = true; 23 this.loadGoogleTranslateScript().catch(error => console.error(error)); 24 } else if (this.googleTranslateLoaded) { 25 this.openTranslateMenu(); 26 } 27 28 this.resetGoogleTranslate(); 29 this.startToCheckIfGoogleTranslatedPage(); 30 return true; 31 }); 32 33 this.implementLoadingStrategy(); 34 } 35 } 36 37 implementLoadingStrategy() { 38 const wasUsedBefore = localStorage.getItem('googleTranslateUsed') === 'true'; 39 40 if (wasUsedBefore) { 41 this.loadGoogleTranslateScript().catch(error => console.error(error)); 42 } 43 } 44 45 loadGoogleTranslateScript() { 46 if (this.loadingPromise) { 47 return this.loadingPromise; 48 } 49 50 this.loadingPromise = new Promise((resolve, reject) => { 51 if (this.googleTranslateLoaded) { 52 resolve(); 53 return; 54 } 55 56 window.googleTranslateElementInit = () => { 57 this.googleTranslateElementInit(); 58 resolve(); 59 }; 60 61 const script = document.createElement('script'); 62 script.type = 'text/javascript'; 63 script.src = '//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit'; 64 script.async = true; 65 script.onerror = () => { 66 reject('Google Translate -skriptin lataus epäonnistui.'); 67 }; 68 document.body.appendChild(script); 69 }); 70 71 this.googleTranslateScriptAdded = true; 72 return this.loadingPromise; 73 } 74 75 googleTranslateElementInit() { 76 if (this.googleTranslateLoaded) return; 77 78 new google.translate.TranslateElement({ 79 pageLanguage: 'fi', 80 layout: google.translate.TranslateElement.InlineLayout.SIMPLE, 81 includedLanguages: 'sv,en,uk,ar,fa,ru,es' 82 }, 'google_translate_element'); 83 84 this.googleTranslateLoaded = true; 85 86 if (this.firstClick) { 87 this.openTranslateMenu(); 88 this.firstClick = false; 89 } 90 91 this.startToCheckIfGoogleTranslatedPage(); 92 } 93 94 async openTranslateMenu() { 95 try { 96 const link = await this.waitForElement('#google_translate_element .skiptranslate a'); 97 98 // Aseta lippu estämään silmukka ja klikkaa linkkiä. 99 this.isOpeningMenu = true; 100 link.click(); 101 this.isOpeningMenu = false;
102 103 } catch (error) { 104 console.error(error); 105 this.isOpeningMenu = false; // Varmista, että lippu nollataan myös virhetilanteessa. 106 } 107 } 108 109 waitForElement(selector, timeout = 5000) { 110 return new Promise((resolve, reject) => { 111 const intervalTime = 100; 112 let elapsedTime = 0; 113 114 const interval = setInterval(() => { 115 const element = document.querySelector(selector); 116 if (element) { 117 clearInterval(interval); 118 resolve(element); 119 } 120 121 elapsedTime += intervalTime; 122 if (elapsedTime >= timeout) { 123 clearInterval(interval); 124 reject(`Elementtiä "${selector}" ei löytynyt ${timeout}ms aikana.`); 125 } 126 }, intervalTime); 127 }); 128 } 129 130 startToCheckIfGoogleTranslatedPage() { 131 // Odotetaan käännöstä vain 20 sekuntia 132 let elapsed = 0; 133 const maxWait = 10000; // 10 sekuntia 134 135 const checkInterval = setInterval(() => { 136 if (document.documentElement.className.indexOf('translated-ltr') !== -1 || document.documentElement.className.indexOf('translated-rtl') !== -1) { 137 // Sivu on käännetty, talleta tieto localStorageen 138 localStorage.setItem('googleTranslateUsed', 'true'); 139 140 // Näytä käännösinfo 141 const googleTranslateInfo = document.getElementById('google_translate_notice'); 142 if (googleTranslateInfo) { 143 144 googleTranslateInfo.style.display = 'block'; 145 } 146 clearInterval(checkInterval); 147 } 148 149 elapsed += 500; 150 if (elapsed >= maxWait) { 151 clearInterval(checkInterval); 152 } 153 154 }, 500); 155 } 156 157 resetGoogleTranslate() { 158 159 localStorage.setItem('googleTranslateUsed', 'false'); 160 161 const googleTranslateInfo = document.getElementById('google_translate_notice'); 162 if (googleTranslateInfo) { 163 googleTranslateInfo.style.display = 'none'; 164 } 165 166 const iframes = document.getElementsByTagName("iframe"); 167 for (let i = 0; i < iframes.length; i++) { 168 const iframe = iframes[i]; 169 if (iframe.className.indexOf("skiptranslate") !== -1) { 170 this.tryPressClose(iframe); 171 } 172 } 173 } 174 175 tryPressClose(iframe) { 176 const innerDoc = iframe.contentDocument || iframe.contentWindow.document; 177 if (!innerDoc) { 178 return; 179 } 180 const anchors = innerDoc.getElementsByTagName("a"); 181 if (!anchors) { 182 return; 183 } 184 for (let i = 0; i < anchors.length; i++) { 185 if (anchors[i].id.indexOf("close") !== -1) { 186 anchors[i].click(); 187 } 188 } 189 } 190} 191 192 193setTimeout(() => { 194 // Script is loaded using <script async defer ...> so we cannot use DOMContentLoaded 195 // because script may also load after that event. 196 new GoogleTranslateManager(); 197}, 5);
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.