GeoGuessr Background Replacer

Replaces the background of the geoguessr pages with your own images

  1. // ==UserScript==
  2. // @name GeoGuessr Background Replacer
  3. // @description Replaces the background of the geoguessr pages with your own images
  4. // @version 2.1.15
  5. // @author Tyow#3742
  6. // @match *://*.geoguessr.com/*
  7. // @license MIT
  8. // @require https://unpkg.com/@popperjs/core@2.11.5/dist/umd/popper.min.js
  9. // @namespace https://greasyfork.org/users/1011193
  10. // @grant GM_addStyle
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // @require https://update.greasyfork.org/scripts/460322/1408713/Geoguessr%20Styles%20Scan.js
  14. // ==/UserScript==
  15.  
  16. // Some code for popup adapted from blink script: https://greasyfork.org/en/scripts/438579-geoguessr-blink-mode
  17.  
  18. /* ############################################################################### */
  19. /* ##### DON'T MODIFY ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING ##### */
  20. /* ############################################################################### */
  21.  
  22. const guiHTMLHeader = `
  23. <div id="backgroundReplacerPopupWrapper">
  24. <div id="backgroundReplacerSearchWrapper">
  25. <div id="backgroundReplacerInputWrapper">
  26. <div id="backgroundReplacerPopup" style="background: rgba(26, 26, 46, 0.9); padding: 15px; border-radius: 10px; max-height: 80vh; overflow-y: auto; width: 28em">
  27. <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 10px;">
  28. <span id="backgroundReplacerLabel1" style="margin: 0; padding-right: 6px;">Add Home Page image</span>
  29. <input type="url" id="homepageInput" name="homepage" style="background: rgba(255,255,255,0.1); color: white; border: none; border-radius: 5px">
  30. </div>
  31. <span>Home Page Images:</span>
  32. <div id="homePageImages" style="display: flex; justify-content: space-between; align-items: center; margin-top: 10px; flex-direction: column"></div>
  33. <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 10px;">
  34. <span id="backgroundReplacerLabel2" style="margin: 0; padding-right: 6px;">Add Other Page Image</span>
  35. <input type="url" id="otherpagesInput" name="otherpages" style="background: rgba(255,255,255,0.1); color: white; border: none; border-radius: 5px">
  36. </div>
  37. <span>Other Pages Images:</span>
  38. <div id="otherPagesImages" style="display: flex; justify-content: space-between; align-items: center; margin-top: 10px; flex-direction: column"></div>
  39. </div>
  40. <button style="width: 59.19px" id="backgroundReplacerToggle"><picture id="backgroundReplacerTogglePicture" style="justify-content: center"><img src="https://www.svgrepo.com/show/342899/wallpaper.svg" style="width: 15px; filter: brightness(0) invert(1); opacity: 100%;"></picture></button>
  41. </div>
  42. </div>
  43. </div>
  44. `
  45. let homePageImageList = GM_getValue("homepageImages");
  46. let otherImages = GM_getValue("otherImages");
  47.  
  48. // Defaults
  49. if (homePageImageList == undefined) {
  50. homePageImageList = [
  51. "https://cdn.wallpapersafari.com/6/80/9ZbpYo.jpg",
  52. "https://cdn.wallpapersafari.com/25/72/dtkc16.jpg",
  53. "https://i.imgur.com/l9K9IOq.jpg",
  54. ];
  55. GM_setValue("homepageImages", homePageImageList);
  56. }
  57. if (otherImages == undefined) {
  58. otherImages = [
  59. "https://imgur.com/eK23SeH.jpg",
  60. "https://i.imgur.com/l9K9IOq.jpg"
  61. ];
  62. GM_setValue("otherImages", otherImages);
  63. }
  64.  
  65. let hide = false;
  66. let styles = GM_getValue("backgroundReplacerStyles");
  67. if (!styles) {
  68. hide = true;
  69. styles = {};
  70. }
  71.  
  72. let homePageImgURL;
  73.  
  74. //console.log(cn("label_variantWhite__"))
  75.  
  76. const setHomePageImg = (img = false) => {
  77. if (img) {
  78. homePageImgURL = img;
  79. } else if(homePageImageList.length) {
  80. homePageImgURL = homePageImageList[Math.floor((Math.random()*homePageImageList.length))];
  81. } else {
  82. homePageImgURL = "";
  83. }
  84. // console.log(homePageImgURL);
  85. }
  86.  
  87. setHomePageImg();
  88.  
  89. let otherPagesImgURL;
  90.  
  91. const setOtherImg = (img = false) => {
  92. if (img) {
  93. otherPagesImgURL = img;
  94. } else if(otherImages.length) {
  95. otherPagesImgURL = otherImages[Math.floor((Math.random()*otherImages.length))];
  96. } else {
  97. otherPagesImgURL = "";
  98. }
  99. }
  100.  
  101. setOtherImg();
  102.  
  103. let css = `.customBackground { bottom: 0;
  104. display: block;
  105. height: 100%;
  106. object-fit: cover;
  107. pointer-events: none;
  108. position: fixed;
  109. right: 0;
  110. transition: .2s ease-in-out;
  111. width: 100%;
  112. z-index: -1;
  113. }
  114. .zindex {
  115. z-index: -1;
  116. }
  117. .deleteIcon {
  118. width: 25px;
  119. filter: brightness(0) invert(1);
  120. opacity: 60%;
  121. }
  122. .backgroundImage {
  123. width: 20em;
  124. }
  125. .deleteButton {
  126. width: 59.19px;
  127. margin-bottom: 8em;
  128. }
  129. .backgroundImageWrapper {
  130. display: flex;
  131. padding: .5em;
  132. }
  133. .backgroundImageWrapper {
  134. position: relative;
  135. display: flex; /* To lay out the imageContainer and button side by side */
  136. align-items: center; /* Vertically center align the contents */
  137. }
  138.  
  139. .imageContainer {
  140. position: relative;
  141. width: /* e.g., 300px; */;
  142. height: /* e.g., 200px; */;
  143. overflow: hidden;
  144. cursor: pointer; /* This line changes the cursor */
  145. }
  146.  
  147. .backgroundImage {
  148. width: 100%;
  149. height: 100%;
  150. transition: opacity 0.3s ease;
  151. vertical-align: bottom;
  152. }
  153.  
  154. .overlay {
  155. position: absolute;
  156. top: 0;
  157. left: 0;
  158. width: 100%;
  159. height: 100%;
  160. background: rgba(0,0,0,0.7);
  161. display: flex;
  162. justify-content: center;
  163. align-items: center;
  164. opacity: 0;
  165. transition: opacity 0.3s ease;
  166. }
  167.  
  168. .imageContainer:hover .backgroundImage {
  169. opacity: 0.3;
  170. }
  171.  
  172. .imageContainer:hover .overlay {
  173. opacity: 1;
  174. }
  175.  
  176. .overlay span {
  177. color: white;
  178. font-size: 18px;
  179. }
  180.  
  181. /* Add some margin if you want space between the image and the button */
  182. .backgroundImageWrapper button {
  183. margin-left: 10px; /* adjust as needed */
  184. }
  185.  
  186.  
  187. /* You can style the text within the overlay here */
  188. .overlay span {
  189. color: white;
  190. font-size: 18px;
  191. text-align: center;
  192. }
  193. .deleteIconPicture {
  194. justifyContent:center;
  195. }
  196. .removeBackground {
  197. display: none
  198. }
  199.  
  200. .shadow {
  201. box-shadow: 0 .25rem 2.75rem rgba(32,17,46,.2),0 1.125rem 2.25rem -1.125rem rgba(0,0,0,.24),0 1.875rem 3.75rem -.625rem rgba(0,0,0,.16);
  202. background: rgba(0, 0, 0, 0.35);
  203. }
  204.  
  205. .blurBefore::before {
  206. content: '';
  207. position: absolute;
  208. top: 0;
  209. left: 0;
  210. right: 0;
  211. bottom: 0;
  212. background: rgba(0, 0, 0, 0.35);
  213. filter: blur(10px);
  214. z-index: -1;
  215. }
  216.  
  217. .highscoreModification {
  218. border-radius: .5rem;
  219. background: var(--ds-color-white-10);
  220. backdrop-filter: blur(11px);
  221. padding: .5rem;
  222. }
  223.  
  224. .mapInfoModification {
  225. padding: 1rem;
  226. border-radius: .5rem;
  227. background: var(--ds-color-white-10);
  228. backdrop-filter: blur(12px);
  229. }
  230.  
  231. .textShadow {
  232. text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
  233. }
  234. .cardModification {
  235. backdrop-filter: blur(12px);
  236. }
  237. .mapSelectorModification {
  238. background: var(--ds-color-white-10);
  239. backdrop-filter: blur(12px);
  240. }
  241. .highScoreTitleModification {
  242. background: var(--ds-color-white-10);
  243. backdrop-filter: blur(12px);
  244. border-radius: .5rem;
  245. padding: .5rem;
  246. }
  247. `;
  248. GM_addStyle(css);
  249.  
  250.  
  251. const showPopup = (showButton, popup) => {
  252. popup.style.display = 'block';
  253. Popper.createPopper(showButton, popup, {
  254. placement: 'bottom',
  255. modifiers: [
  256. {
  257. name: 'offset',
  258. options: {
  259. offset: [0, 10],
  260. },
  261. },
  262. ],
  263. });
  264. }
  265.  
  266. const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
  267.  
  268. const iterativeSetTimeout = async (func, initDelay, cond) => {
  269. while (!cond()) {
  270. await delay(initDelay);
  271. await func();
  272. initDelay *= 2;
  273. stylesUsed.forEach(style => {
  274. styles[style] = cn(style);
  275. });
  276. }
  277. };
  278.  
  279. // Caching system for styles
  280. // Basically, we have a browser stored styles object,
  281. // which contains the most recent classNames found by scanStyles()
  282. // This is what the script will immediately use upon loading,
  283. // so that there's no pause in delivering the UI to the user
  284. // But the script will also fire off this function
  285. // which will use the above iterativeSetTimeout function to call scanStyles
  286. // This is so there aren't a thousand calls in quick succession.
  287. // Once all the classNames we're looking for are found,
  288. // it will update the local storage and the ui with the (possibly) new classnames
  289. const stylesUsed = [
  290. "quick-search_wrapper__",
  291. "quick-search_searchInputWrapper__",
  292. "quick-search_searchInputButton__",
  293. "quick-search_iconSection__",
  294. ];
  295.  
  296. const uploadDownloadStyles = async () => {
  297. stylesUsed.forEach(style => {
  298. // styles[style] = cn(style);
  299. // console.log(style);
  300. // console.log(cn(style));
  301. });
  302. await iterativeSetTimeout(scanStyles, 0.1, () => checkAllStylesFound(stylesUsed) !== undefined);
  303. if (hide) {
  304. document.querySelector("#backgroundReplacerPopupWrapper").hidden = "";
  305. }
  306. stylesUsed.forEach(style => {
  307. styles[style] = cn(style);
  308. // console.log(style);
  309. // console.log(cn(style));
  310. });
  311. setStyles();
  312. GM_setValue("backgroundReplacerStyles", styles);
  313. }
  314.  
  315. const getStyle = style => {
  316. return styles[style];
  317. }
  318.  
  319. const setStyles = () => {
  320. try {
  321. document.querySelector("#backgroundReplacerSearchWrapper").className = getStyle("quick-search_wrapper__");
  322. document.querySelector("#backgroundReplacerInputWrapper").className = getStyle("quick-search_searchInputWrapper__");
  323. document.querySelector("#backgroundReplacerToggle").className = getStyle("quick-search_searchInputButton__");
  324. document.querySelector("#backgroundReplacerLabel1").className = getStyle("label_sizeXSmall__") + getStyle("label_variantWhite__");
  325. document.querySelector("#backgroundReplacerLabel2").className = getStyle("label_sizeXSmall__") + getStyle("label_variantWhite__");
  326. document.querySelector("#backgroundReplacerTogglePicture").className = getStyle("quick-search_iconSection__");
  327. document.querySelectorAll(".deleteButton").forEach(el => el.className = el.className + " " + getStyle("quick-search_searchInputButton__"));
  328. } catch (err) {
  329. console.error(err);
  330. }
  331. }
  332.  
  333.  
  334. const insertHeaderGui = async (header, gui) => {
  335.  
  336. header.insertAdjacentHTML('afterbegin', gui);
  337.  
  338. // Resolve class names
  339. if (hide) {
  340. document.querySelector("#backgroundReplacerPopupWrapper").hidden = "true"
  341. }
  342.  
  343. scanStyles().then(() => uploadDownloadStyles());
  344. setStyles();
  345.  
  346.  
  347.  
  348. const showButton = document.querySelector('#backgroundReplacerToggle');
  349. const popup = document.querySelector('#backgroundReplacerPopup');
  350. popup.style.display = 'none';
  351.  
  352. document.addEventListener('click', (e) => {
  353. const target = e.target;
  354. if (target == popup || popup.contains(target) || !document.contains(target)) return;
  355. if (target.matches('#backgroundReplacerToggle, #backgroundReplacerToggle *')) {
  356. e.preventDefault();
  357. showPopup(showButton, popup);
  358. } else {
  359. popup.style.display = 'none';
  360. }
  361. });
  362. }
  363.  
  364. // Global to track whether the most recent image insertion was done on homepage
  365. let isHomePage = location.pathname == "/";
  366.  
  367. const addShadows = () => {
  368. const mapSelector = document.querySelector("[class^='map-selector_selector__'")
  369. if (mapSelector && !mapSelector.classList.contains("mapSelectorModification")) {
  370. mapSelector.classList.add("mapSelectorModification")
  371. // mapSelector.classList.add("blurBefore")
  372. }
  373. const highscoreRoot = document.querySelector("[class^='map-highscore_root__'")
  374. if (highscoreRoot && !highscoreRoot.classList.contains("highscoreModification")) {
  375. highscoreRoot.classList.add("highscoreModification")
  376. }
  377. const mapStatsText = document.querySelectorAll("[class^='map-stats_mapStatMetricValue__'")
  378. if (mapStatsText) {
  379. for (const el of mapStatsText) {
  380. if (!el.classList.contains("textShadow")) {
  381. el.classList.add("textShadow")
  382. }
  383. }
  384. }
  385. const mapInfo = document.querySelector("[class^='map-block_mapInfo__'")
  386. if (mapInfo && !mapInfo.classList.contains("mapInfoModification")) {
  387. mapInfo.classList.add("mapInfoModification")
  388. }
  389. const howItWorks = document.querySelector("[class^='ranked-system-how-it-works-page_root__'")
  390. if (howItWorks && !howItWorks.classList.contains("mapInfoModification")) {
  391. howItWorks.classList.add("mapInfoModification")
  392. }
  393. const userStatsCards = document.querySelectorAll("[class^='user-stats-overview_card__'")
  394. if (userStatsCards) {
  395. for (const el of userStatsCards) {
  396. if (!el.classList.contains("cardModification")) {
  397. el.classList.add("cardModification")
  398. }
  399. }
  400. }
  401. const mapStats = document.querySelectorAll("[class^='map-stats_mapStat__'")
  402. if (mapStats) {
  403. for (const el of mapStats) {
  404. if (!el.classList.contains("cardModification")) {
  405. el.classList.add("cardModification")
  406. }
  407. }
  408. }
  409. const cards = document.querySelectorAll("[class^='card_card__'")
  410. if (cards) {
  411. for (const el of cards) {
  412. if (!el.classList.contains("cardModification")) {
  413. el.classList.add("cardModification")
  414. }
  415. }
  416. }
  417. // const highScoreTitle = document.querySelectorAll("[class^='headline_heading__'")
  418. // for (const el of highScoreTitle) {
  419. // if (el.textContent == "Highscore" && !el.classList.contains("highScoreTitleModification")) {
  420. // el.classList.add("highScoreTitleModification")
  421. // }
  422. // }
  423. const mapsCenter = document.querySelector("[class^='maps_center__'")
  424. if (mapsCenter && !mapsCenter.classList.contains("mapsCenterMoved")) {
  425. const mapsSwitch = document.querySelector("[class^='map-highscore_switchContainer__'")
  426. highscoreRoot.insertBefore(mapsCenter, mapsSwitch);
  427. mapsCenter.classList.add("mapsCenterMoved")
  428. }
  429. }
  430.  
  431. const homepageModification = () => {
  432. const startPageWrapper = document.querySelector("[class^=startpage_background__")
  433. if (startPageWrapper && !startPageWrapper.classList.contains("removeBackground")) {
  434. startPageWrapper.classList.add('removeBackground');
  435. }
  436. const startPageNewWrapper = document.querySelector("[class^=startpage_newWrapper__")
  437. if (startPageNewWrapper && startPageNewWrapper.style.background != "none") {
  438. startPageNewWrapper.style.background = "none"
  439. };
  440. }
  441.  
  442. const otherPageModification = () => {
  443. const backgroundWrapper = document.querySelector("[class^=background_background__")
  444. if (backgroundWrapper && !backgroundWrapper.classList.contains("removeBackground")) {
  445. backgroundWrapper.classList.add('removeBackground');
  446. }
  447. }
  448.  
  449. const extraStyling = () => {
  450. addShadows()
  451. homepageModification()
  452. otherPageModification()
  453. }
  454.  
  455. const insertBackground = (refresh=false) => {
  456. let inGame = false;
  457. let el = document.querySelector("[class^='background_wrapper']");
  458. if (!el) {
  459. inGame = true;
  460. el = document.querySelector("#__next");
  461. if (!el) return;
  462. // Because this element has multiple classes, we need to use a different selector
  463. const def = document.querySelector("[class*=in-game_backgroundDefault__]");
  464. let reg = /^in-game_backgroundDefault__/;
  465. if (def) {
  466. def.classList = Array.from(def.classList).filter(cl => !cl.match(reg));
  467. }
  468. const partyRoot = document.querySelector("[class^=party_root__]");
  469. if (partyRoot) {
  470. partyRoot.style.background = "none";
  471. }
  472. // Without this, you can see the background behind the map in a game summary
  473.  
  474. // Purple color used by geoguessr, with .9 alpha
  475. const purple9 = "rgba(12 12 46 / .9)";
  476. // .7 alpha
  477. const purple7 = "rgba(12 12 46 / .7)";
  478. const gameSummary = document.querySelector("[class^=game-summary_container__");
  479. if (gameSummary) {
  480. gameSummary.style.opacity = "1";
  481. gameSummary.style.backgroundColor = purple9;
  482. }
  483. const header = document.querySelector("[class^=game-summary_playedRoundsHeader__");
  484. if (header) {
  485. header.style.backgroundColor = purple7;
  486. }
  487.  
  488. }
  489. // We only want the zindex = -1 to exist in game settings, on other pages it's detrimental
  490. let img = document.querySelector('.customBackground');
  491. if (refresh) {
  492. img.remove();
  493. img = document.querySelector('.customBackground');
  494. }
  495. if (img) {
  496. if (!inGame) {
  497. img.classList = Array.from(img.classList).filter(cl => cl != 'zindex');
  498. }
  499. // Return if most recent insertion was in same area (homepage vs not)
  500. if (isHomePage == (location.pathname == "/")) {
  501. return;
  502. }
  503. img.remove();
  504. // Update isHomePage
  505. }
  506. if (!img) {
  507. img = document.createElement("img")
  508. img.classList.add("customBackground");
  509. if (inGame) {
  510. img.classList.add("zindex");
  511. } else {
  512. img.classList = Array.from(img.classList).filter(cl => cl != 'zindex');
  513. }
  514. }
  515. isHomePage = location.pathname == "/";
  516. if (isHomePage && homePageImgURL) {
  517. img.src = homePageImgURL;
  518. } else if (!isHomePage && otherPagesImgURL) {
  519. img.src = otherPagesImgURL;
  520. } else {
  521. return
  522. }
  523. el.appendChild(img);
  524. }
  525.  
  526. const updateStorage = (listName, newList) => {
  527. GM_setValue(listName, newList);
  528. }
  529.  
  530. const validate = (e, homepage) => {
  531. const patt = new RegExp(".*.(jpg|png|gif|jpeg|webp|svg|avif)","i");
  532. if (e.key == "Enter") {
  533. if (patt.test(e.target.value)) {
  534. if (homepage) {
  535. let homepageImages = GM_getValue("homepageImages");
  536. homepageImages.push(e.target.value);
  537. if (homepageImages.length == 1) {
  538. homePageImgURL = homepageImages[0];
  539. }
  540. GM_setValue("homepageImages", homepageImages);
  541. homePageImageList = homepageImages
  542. } else {
  543. let otherImagesNew = GM_getValue("otherImages");
  544. otherImagesNew.push(e.target.value);
  545. if (otherImagesNew.length == 1) {
  546. otherPagesImgURL = otherImagesNew[0];
  547. }
  548. GM_setValue("otherImages", otherImagesNew);
  549. otherImages = otherImagesNew;
  550. }
  551. refreshPopup();
  552. e.target.value = "";
  553. } else {
  554. window.alert("This link doesn't seem to be to an image file, it should end in .jpg, .jpeg, .png, .gif, .webp, .avif, or .svg");
  555. }
  556. }
  557. }
  558.  
  559. const removeImage = (image, div, list, listName) => {
  560. let result = window.confirm("Are you sure you want to remove this image?");
  561. if (!result) {
  562. return
  563. }
  564. let i = list.indexOf(image);
  565. if (i != -1) {
  566. list.splice(i, 1);
  567. updateStorage(listName, list);
  568. refreshPopup();
  569. if (listName == "otherImages" && !list.includes(image)) {
  570. setOtherImg();
  571. updateImage(true);
  572. }
  573. if (listName == "homepageImages" && !list.includes(image)) {
  574. setHomePageImg();
  575. updateImage(true);
  576. }
  577. }
  578. };
  579.  
  580. // displays an image in the popup
  581. const displayImage = (image, imagesDiv, list, listName) => {
  582. const img = document.createElement("img");
  583. const div = document.createElement("div");
  584. div.className = "backgroundImageWrapper";
  585. const container = document.createElement("div");
  586. container.className = "imageContainer";
  587.  
  588. img.src = image
  589. img.className = "backgroundImage";
  590. div.appendChild(container);
  591. container.appendChild(img);
  592.  
  593. const deleteIcon = document.createElement("img");
  594. deleteIcon.className = "deleteIcon";
  595. deleteIcon.src = "https://www.svgrepo.com/show/493964/delete-1.svg";
  596.  
  597. const deleteButton = document.createElement("button");
  598. deleteButton.className = getStyle("quick-search_searchInputButton__") + " " + "deleteButton";
  599. deleteButton.appendChild(deleteIcon);
  600. deleteButton.addEventListener("click", e => {
  601. removeImage(image, div, list, listName);
  602. });
  603.  
  604. const overlay = document.createElement("div");
  605. overlay.className = "overlay";
  606. const span = document.createElement("span");
  607. isHomePage = location.pathname == "/";
  608. span.innerText = ((isHomePage && listName == "homepageImages")
  609. || (!isHomePage && listName == "otherImages"))
  610. ? "Make current image" : "You're not on a page where this image will display";
  611. overlay.appendChild(span);
  612.  
  613. container.appendChild(overlay);
  614. div.appendChild(deleteButton);
  615.  
  616. imagesDiv.appendChild(div);
  617. container.addEventListener('click', function() {
  618. if (listName == "homepageImages") {
  619. setHomePageImg(image);
  620. }
  621. if (listName == "otherImages") {
  622. setOtherImg(image);
  623. }
  624. insertBackground(true);
  625. });
  626. }
  627.  
  628. const refreshPopup = () => {
  629. if (document.querySelector("#backgroundReplacerPopupWrapper") != null && document.querySelector('[class^=header-tablet-desktop_root__]') != null) {
  630. let div = document.querySelector("#homePageImages");
  631. while (div.children.length) {
  632. div.removeChild(div.children[0]);
  633. }
  634. div = document.querySelector("#otherPagesImages");
  635. while (div.children.length) {
  636. div.removeChild(div.children[0]);
  637. }
  638. addPopup(true);
  639. const showButton = document.querySelector('#backgroundReplacerToggle');
  640. const popup = document.querySelector('#backgroundReplacerPopup');
  641. showPopup(showButton, popup);
  642. }
  643. }
  644.  
  645. const addPopup = (refresh=false) => {
  646. if ((refresh || (document.querySelector('[class^=header-tablet-desktop_root__]') || document.querySelector('[class^=header-desktop_root__]')) && document.querySelector('#backgroundReplacerPopupWrapper') === null)) {
  647. if (!refresh) {
  648. let section = document.querySelector('[class^=header-tablet-desktop_desktopSectionRight__]')
  649. if (!section) section = document.querySelector('[class^=header-desktop_desktopSectionRight__]')
  650. insertHeaderGui(section, guiHTMLHeader)
  651. const homepageInput = document.querySelector("#homepageInput");
  652. homepageInput.addEventListener("keyup", e => {
  653. validate(e, true);
  654. });
  655. const otherpagesInput = document.querySelector("#otherpagesInput");
  656. otherpagesInput.addEventListener("keyup", e => {
  657. validate(e, false);
  658. });
  659. }
  660. const homePageImagesDiv = document.querySelector('#homePageImages');
  661. if (homePageImagesDiv) {
  662. // Loop through images and display them
  663. for (let i = 0; i < homePageImageList.length; i++) {
  664. displayImage(homePageImageList[i], homePageImagesDiv,homePageImageList, "homepageImages");
  665. }
  666. }
  667. const otherPagesImagesDiv = document.querySelector("#otherPagesImages");
  668. if (otherPagesImagesDiv) {
  669. // Loop through images and display them
  670. for (let i = 0; i < otherImages.length; i++) {
  671. displayImage(otherImages[i], otherPagesImagesDiv, otherImages, "otherImages");
  672. }
  673. }
  674. }
  675. }
  676.  
  677. const updateImage = (refresh=false) => {
  678. // Don't do anything while the page is loading
  679. if (document.querySelector("[class^=page-loading_loading__]")) return;
  680. addPopup();
  681. insertBackground(refresh);
  682. extraStyling()
  683. }
  684.  
  685.  
  686.  
  687. new MutationObserver(async (mutations) => {
  688. updateImage()
  689. }).observe(document.body, { subtree: true, childList: true });