A Better Search

My attempt to improve the search function in geoguessr.

目前為 2024-02-13 提交的版本,檢視 最新版本

// ==UserScript==
// @name         A Better Search
// @namespace    http://tampermonkey.net/
// @version      0.1.0
// @description  My attempt to improve the search function in geoguessr.
// @author       Lemson
// @match        https://www.geoguessr.com/
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @license      MIT
// @grant        GM_addStyle
// ==/UserScript==

const CSS = `
        .top-search-bar{
          width: 30%;
          margin-left: 34%;
          position: absolute;
          border-radius: 2rem;
          padding-left: 1rem;
          font-size: 1rem;
          background-color: rgba(0,0,0,.8);
          color: white;
          border: 1px solid white;
          scale: 1;
        }
        .inactive-search-bar{
          scale: 0;
        }
        .modal {
          width: 70%;
          height: 70%;
          background-color: #d9d9d9;
          border-radius: 2.5rem;
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          scale: 0;
          transition: 0.1s;
          box-shadow: 0 0 5rem 1rem rgb(0, 0, 0);
          display: flex;
          z-index:5;
        }
        .active {
          transition: 0.1s;
          scale: 1;
        }
        .sidebar {
          height: 100%;
          width: 4rem;
          background-color: #545454;
          border-top-left-radius: 2.5rem;
          border-bottom-left-radius: 2.5rem;
          border-right: 1px solid black;
        }
        .maincontent {
          display: flex;
          flex-direction: column;
          width: 100%;
        }
        .search {
          height: 2.5rem;
          margin: 2rem;
          display: flex;
          justify-content: space-between;
        }
        .searchbar {
          width: 50%;
          border-radius: 1.1rem;
          border: 0.1rem solid black;
          padding-left: 1rem;
          box-shadow: 0 0 7rem black;
          font-size: 1rem;
        }
        .filter-btn {
            height: 100%;
            width: 2.5rem;
            border-radius: 0.4rem;
            border: 1px solid black;
            background-color: rgb(192, 192, 192);
          }
        .filter-btn:active {
          background-color: rgb(145, 145, 145);
        }
        .filter-window{
          width: 40%;
          height: 70%;
          border: .2rem solid black;
          transform: translateX(52%);
          z-index: 1000;
        }
        .filter-window-content{
          width:100%;
          height: 100%;
          display: flex;
          flex-direction: row;
        }
        .filter-window-content>*{
          display: flex;
          flex-direction: column;
          width: 50%;
          height: 100%;
        }
        .filter-header{
          display: flex;
          justify-content: space-between;
        }
        .apply-filter-button{
          width: 4rem;
          height: 2rem;
          border: 1px solid red;
        }
        .apply-filter-button:active{
          background-color: rgba(0,0,0,.5);
        }
        .filter-close-button:hover{
          transition: 0.1s;
          scale: 1.1;
          cursor: pointer;
        }



        .close {
            margin-left: 5rem;
            font-size: 2rem;
            cursor: pointer;
          }
        .close:hover{
          transition: .2s;
          scale: 1.1;
        }
        .windows {
          width: 95%;
          height: 80%;
          margin-left: 2rem;
          border: 1px solid black;
          display: flex;
          flex-direction: row;
          justify-content: space-evenly;
        }
        .results {
          background-color: rgba(0, 0, 0, 0.112);
          width: 100%;
          height: 100%;
          overflow: auto;
          overflow-x: hidden;
        }
        .selection-info {
          background-color: rgba(0, 0, 0, 0.112);
          border-left: 0.1rem solid black;
          width: 100%;
          height: 100%;
          display: flex;
          flex-direction: column;
          overflow: auto;
          overflow-x: hidden;
        }
        .result-container {
          width: 99%;
          border: 1px solid rgb(0, 0, 0);
          margin: 0.2rem;
          display: flex;
        }
        .result-container:hover {
          background-color: rgba(0, 0, 0, 0.107);
        }
        .result-container:active {
          background-color: rgba(0, 0, 0, 0.25);
        }
        .result-title-author {
          width: 90%;
        }
        .result-title {
          font-size: 1.6rem;
        }
        .result-creator {
          font-size: 1rem;
        }
        .author-space {
          text-decoration: underline;
          color: rgb(15, 0, 88);
        }
        .likesdisplay {
          width: 10%;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          color: red;
          font-size: 1.2rem;
          -webkit-text-stroke: .5px black;
        }
        .selected {
          background-color: rgba(0, 0, 255, 0.1);
        }
        .selected-header {
          display: flex;
          flex-direction: row;
          padding-left: 1rem;
          border-bottom: .1rem solid black;
          justify-content: space-between;
          padding-right: 1rem;
        }
        .header-likes {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
        }
        .selected-title {
          font-size: 1.4rem;
        }
        .selected-creator {
          font-size: .8rem;
          font-weight: bold;
          color: black;
        }
        .selected-creator:hover{
          color: blue;
        }
        .selected-desc {
          margin: .5rem;
          border: 1px solid black;
          padding: .3rem;
          border-radius: .5rem;
          height: 3.5rem;
          overflow: auto;
        }
        .tags {
          display: flex;
          flex-direction: row;
          gap: .7rem;
          margin-left: .5rem;
          flex-wrap: wrap;
          row-gap: 0.5rem;
        }
        .searchAndFilter{
          width: 100%;
        }
        .tag{
          border: 1px solid black;
          padding: .2rem;
          padding-left: .5rem;
          padding-right: .5rem;
          border-radius: 2rem;
          height: .9rem;
          font-size: .8rem;
        }
        .game {
          position: relative;
          width: 100%;
          height: 100%;
          margin: 0.5rem;
          margin-top: 1.5rem;
          border-radius: 1rem;
          border: 1px solid black;
          overflow: auto;
          display: flex; /* Use flexbox layout */
        }
  
        .game:before {
          content: "";
          background-image: url('https://img.freepik.com/free-photo/planet-earth-background_23-2150564685.jpg');
          background-size: cover;
          background-position: center;
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          z-index: -10;
          overflow: hidden;
        }
        .game-settings {
          width: 50%;
          height: 100%;
          display: flex;
          flex-direction: column;
          align-items: center;
        }
        .ol-selected-leaderboard{
          width: 50%;
          height: 100%;
        }
        ::-webkit-scrollbar {
          width: 0.1rem;
        }
        ::-webkit-scrollbar-thumb {
          background-color: rgb(0, 0, 0);
        }
        .game-mode-select{
          color: white;
          display: flex;
          align-items: center;
          flex-direction: column;
          margin-top: .6rem;
          width: 100%;
          justify-content: center;
          margin-top: .7vh;
        }
        .game-mode-select>h1{
          font-weight: 500;
          letter-spacing: .06vw;
          margin-bottom: .4vh;
          font-size: 1.6vh;
        }
        .gamemode-buttons{
          display: flex;
          flex-direction: row;
          justify-content: space-evenly;
          background-color: rgba(255, 255, 255, 0.06);
          border: .1rem solid white;
          border-radius: .4rem;
          width: 95%;
          text-wrap: nowrap;
        }
        .gamemode-buttons>*{
          font-size: 1.2rem;
          color: white;
          padding-left: 1rem;
          padding-right: 1rem;
          border-radius: .5rem;
          margin: .2rem;
          font-style: italic;
        }
  
        .selected-mode {
          background-color: #7950E5;
        }
  
        .round-select{
          color: white;
          display: flex;
          align-items: center;
          justify-content: center;
          flex-direction: column;
          margin-top: 1.2rem;
          width: 100%;
        }
        .round-select>h1{
          font-size: 1.3rem;
          font-weight: 500;
          letter-spacing: .1rem;
          margin-bottom: .3rem;
        }
        .round-numbers{
          display: flex;
          flex-direction: row;
          justify-content: space-evenly;
          background-color: rgba(255, 255, 255, 0.06);
          border: .1rem solid white;
          border-radius: .4rem;
          width: 95%;
          height: 3rem;
        }
        .round-numbers>*{
          color: white;
          width: 3.5rem;
          margin-top: .2rem;
          margin-bottom: .2rem;
          display: flex;
          align-items: center;
          justify-content: center;
          border-radius: .5rem;
        }
  
  
        .round-time{
          color: white;
          display: flex;
          align-items: center;
          justify-content: center;
          flex-direction: column;
          margin-top: 1.2rem;
          width: 95%;
          background-color: rgba(0,0,0,0.7);;
          border: .1rem solid white;
          border-radius: .5rem;
          padding-top: 1rem;
          padding-bottom: 1rem;
        }
        .round-time>h1, .round-time>h2{
          font-size: 1.3rem;
          font-weight: 500;
          letter-spacing: .1rem;
          margin-bottom: .3rem;
        }
        .time-slider{
          width: 90%;
          padding:0;
        }
  
  
        .start-game-btn{
          width: 95%;
          height: 4rem;
          background-color: #97E851;
          border-radius: 2rem;
          box-shadow: inset 0 1px 10px white;
          font-size: 2rem;
          font-weight: bold;
          font-style: italic;
          color: white;
          -webkit-text-stroke: 1px black;
          margin-top: 1rem;
          border: .1rem solid white;
        }
        .like-filter, .loc-filter, .avg-score-filter, .games-played-filter{
          margin-top:1rem;
        }
        .filter-title{
          font-size:1rem;
        }
        .apply-filter-button{
          border: 1px solid black;
        }
  `;
GM_addStyle(CSS);

const HTML = `
<div id="overlay-main" class="modal">
  <div class="sidebar"></div>
  <div class="maincontent">
    <div class="search">
      <div class="searchAndFilter">
        <input type="text" placeholder="Search..." class="searchbar" id="search-term" />
        <button class="filter-btn">Filter</button>
        <dialog class="filter-window">
          <header class="filter-header">
            <h1>Filters</h1>
            <h2 class="filter-close-button">✖</h2>
          </header>
          <div class="filter-window-content">
            <div class="variable-filters">
              <div class="like-filter">
                <h1 class="filter-title">Minimum likes</h1>
                <div>
                  <input type="checkbox" name="toggle-min-likes" id="toggle-min-likes" />
                  <input type="number" name="num-min-likes" id="num-min-likes" placeholder="Minimum likes..." />
                </div>
              </div>
              <div class="loc-filter">
                <h1 class="filter-title">Minimum locations</h1>
                <div>
                  <input type="checkbox" name="toggle-min-loc" id="toggle-min-loc" />
                  <input type="number" name="num-min-loc" id="num-min-loc" placeholder="Minimum location..." />
                </div>
              </div>
              <div class="avg-score-filter">
                <h1 class="filter-title">Minimum average score</h1>
                <div>
                  <input type="checkbox" name="toggle-min-avg-score" id="toggle-min-avg-score" />
                  <input
                    type="number"
                    name="num-min-avg-score"
                    id="num-min-avg-score"
                    placeholder="Minimum average score..."
                  />
                </div>
              </div>
              <div class="games-played-filter">
                <h1 class="filter-title">Minimum games played</h1>
                <div>
                  <input type="checkbox" name="toggle-min-games-played" id="toggle-min-games-played" />
                  <input
                    type="number"
                    name="num-min-games-played"
                    id="num-min-games-played"
                    placeholder="Minimum games played..."
                  />
                </div>
              </div>
            </div>
            <div class="toggle-filters">
              <button class="apply-filter-button">Apply</button>
            </div>
          </div>
        </dialog>
      </div>
      <button class="close">✖</button>
    </div>
    <div class="windows">
      <div class="results"></div>
      <div class="selection-info"></div>
    </div>
  </div>
</div>


  `;
let div = document.createElement("div");
div.innerHTML = HTML;
document.body.append(div);

const startGameBaseUrl = "https://www.geoguessr.com/api/v3/games";
let searchBarParent = document.querySelector("[class^='header_logoWrapper__']");
searchBarParent.style = "justify-content: space-between;";
let topSearchBar = document.createElement("input");
topSearchBar.placeholder = "Search for a map...";
topSearchBar.classList.add("top-search-bar");
topSearchBar.id = "search-term";
searchBarParent.appendChild(topSearchBar);
const everything = document.querySelector(".modal");
const resultsBox = document.querySelector(".results");
const infoBox = document.querySelector(".selection-info");
const overlay = document.querySelector(".modal");
const closeButton = document.querySelector(".close");
const searchBar = document.querySelector(".searchbar");

let chosenMode = "no move";
let roundAmount = 5;
let roundTimeSeconds = 30;

//Filter stuff \/
const filterPopup = document.querySelector(".filter-window");
const filterButton = document.querySelector(".filter-btn");
const applyFilterBtn = document.querySelector(".apply-filter-button");
const closeFiltersButton = document.querySelector(".filter-close-button");

//Get all checkbox for filters
const minLikesToggle = document.getElementById("toggle-min-likes");
const minLocToggle = document.getElementById("toggle-min-loc");
const minAvgScoreToggle = document.getElementById("toggle-min-avg-score");
const minGamesPlayedToggle = document.getElementById("toggle-min-games-played");

//Get all input boxes for filters
const minLikesInput = document.getElementById("num-min-likes");
const minLocInput = document.getElementById("num-min-loc");
const minAvgScoreInput = document.getElementById("num-min-avg-score");
const minGamesPlayed = document.getElementById("num-min-games-played");

//Set the checkbox to saved value
minLikesToggle.checked = localStorage.getItem("minLikesToggle") === "true";
minLocToggle.checked = localStorage.getItem("minLocToggle") === "true";
minAvgScoreToggle.checked = localStorage.getItem("minAvgScoreToggle") === "true";
minGamesPlayedToggle.checked = localStorage.getItem("minGamesPlayedToggle") === "true";

//Set the value to saved value
minLikesInput.value = localStorage.getItem("minLikeNum");
minLocInput.value = localStorage.getItem("minLocNum");
minAvgScoreInput.value = localStorage.getItem("minAvgScoreNum");
minGamesPlayed.value = localStorage.getItem("minGamesPlayed");

let filterMinLikes = true;
let filterMinLocs = false;
let filterAverageScore = false;
let filterGamesplayed = false;
let filterDifficulty = false;
let filterDesc = false;
let filterOfficial = false;
let filterHandpicked = false;

const saveFilters = () => {
  console.log("saving filters...");
  //Save checkboxes
  localStorage.setItem("minLikesToggle", minLikesToggle.checked);
  localStorage.setItem("minLocToggle", minLocToggle.checked);
  localStorage.setItem("minAvgScoreToggle", minAvgScoreToggle.checked);
  localStorage.setItem("minGamesPlayedToggle", minGamesPlayedToggle.checked);

  console.log(minGamesPlayedToggle.checked);
  //Save values
  localStorage.setItem("minLikeNum", minLikesInput.value);
  localStorage.setItem("minLocNum", minLocInput.value);
  localStorage.setItem("minAvgScoreNum", minAvgScoreInput.value);
  localStorage.setItem("minGamesPlayed", minGamesPlayed.value);
};

const search = async (searchTerm) => {
  try {
    let resp = await fetch(`https://www.geoguessr.com/api/v3/search/map?page=0&count=50&q=${searchTerm}`);
    if (!resp.ok) {
      throw new Error(`Error searching for ${searchTerm}`);
    }
    const data = await resp.json();

    // Get additional map data concurrently
    const extraMapData = await getAdditionalMapDataConcurrently(data);

    // Combine data and extraMapData so the filter can use all the crazy cool stats.
    const combinedData = combineDatas(data, extraMapData);
    console.log(combinedData);

    applyFilters(combinedData);
    /* if (activeFilters > 0) {
      applyFilters(combinedData);
    } else createResults(combinedData); */
  } catch (error) {
    console.error(error);
  }
};

const getAdditionalMapDataConcurrently = async (data) => {
  const promises = data.map((map) => fetch(`https://www.geoguessr.com/api/maps/${map.id}`));
  const responses = await Promise.all(promises);
  const extraMapData = await Promise.all(responses.map((resp) => resp.json()));
  return extraMapData;
};

const combineDatas = (data, extraMapData) => {
  const combinedData = [];
  const minLength = Math.min(data.length, extraMapData.length);
  for (let i = 0; i < minLength; i++) {
    combinedData.push({ ...extraMapData[i], ...data[i] });
  }
  return combinedData;
};

const applyFilters = (searchResults) => {
  let filteredResults = searchResults;

  if (minLikesToggle.checked) {
    filteredResults = filteredResults.filter((result) => {
      return result.likes >= minLikesInput.value;
    });
  }
  if (minLocToggle.checked) {
    filteredResults = filteredResults.filter((result) => {
      return result.coordinateCount >= minLocInput.value;
    });
  }
  if (minAvgScoreToggle.checked) {
    filteredResults = filteredResults.filter((result) => {
      return result.averageScore >= minAvgScoreInput.value;
    });
  }
  if (minGamesPlayedToggle.checked) {
    filteredResults = filteredResults.filter((result) => {
      return result.numberOfGamesPlayed >= minGamesPlayed.value;
    });
  }

  createResults(filteredResults);
};

const createResults = (searchData) => {
  //removes any HTML, if there is any. So that new HTML can be added.
  resultsBox.innerHTML = null;

  searchData.forEach((item) => {
    //Create and add the HTML for result
    let resultContainerHTML = `
      <div class="result-container">
        <div class="result-title-author">
          <h1 class="result-title">${item.name}</h1>
          <h2 class="result-creator">created by: <a target="_blank" id="author-link" href="user/${item.creatorId}">${item.creator}</a></h2>
        </div>
        <div class="likesdisplay">
          <div class="heartSVG">♥</div>
          <h3 class="like-ount">${item.likes}</h3>
        </div>
      </div>`;
    //Create element to append the created HTML onto
    let resultContainerParent = document.createElement("div");
    resultContainerParent.innerHTML = resultContainerHTML;
    resultsBox.appendChild(resultContainerParent);

    //click on result
    resultContainerParent.addEventListener("click", function () {
      let resultContainer = resultContainerParent.querySelector(".result-container");
      let clearSelections = document.querySelectorAll(".result-container");

      clearSelections.forEach((thing) => {
        //Remove selections
        thing.classList.remove("selected");
      });
      displaySelectedMap(item, resultContainer);
    });
  });
};

const startGame = (map) => {
  let gameSettings;
  if (chosenMode == "move") {
    gameSettings = {
      forbidMoving: false,
      forbidRotating: false,
      forbidZooming: false,
      map: map,
      rounds: roundAmount,
      timeLimit: roundTimeSeconds,
    };
  }
  if (chosenMode == "no move") {
    gameSettings = {
      forbidMoving: true,
      forbidRotating: false,
      forbidZooming: false,
      map: map,
      rounds: roundAmount,
      timeLimit: roundTimeSeconds,
    };
  }
  if (chosenMode == "nmpz") {
    gameSettings = {
      forbidMoving: true,
      forbidRotating: true,
      forbidZooming: true,
      map: map,
      rounds: roundAmount,
      timeLimit: roundTimeSeconds,
    };
  }

  //start game?
  fetch(startGameBaseUrl, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(gameSettings),
  })
    .then((response) => response.json())
    .then((data) => {
      console.log(`https://www.geoguessr.com/game/${data.token}`);
      return data;
    })
    .then((data) => {
      window.location.href = `https://www.geoguessr.com/game/${data.token}`;
    })
    .catch((error) => console.error("error", error));
};

const setMode = (mode, buttons, button) => {
  buttons.forEach((a) => {
    a.classList.remove("selected-mode");
  });
  switch (mode) {
    case "MOVE":
      chosenMode = "move";
      button.classList.add("selected-mode");
      break;
    case "NO MOVE":
      chosenMode = "no move";
      button.classList.add("selected-mode");
      break;
    case "NMPZ":
      chosenMode = "nmpz";
      button.classList.add("selected-mode");
      break;
  }
  console.log(mode);
};

const setRounds = (roundNum, nums, selectedNum) => {
  nums.forEach((a) => {
    a.classList.remove("selected-mode");
  });

  switch (roundNum) {
    case "1":
      roundAmount = 1;
      selectedNum.classList.add("selected-mode");
      break;
    case "2":
      roundAmount = 2;
      selectedNum.classList.add("selected-mode");
      break;
    case "3":
      roundAmount = 3;
      selectedNum.classList.add("selected-mode");
      break;
    case "4":
      roundAmount = 4;
      selectedNum.classList.add("selected-mode");
      break;
    case "5":
      roundAmount = 5;
      selectedNum.classList.add("selected-mode");
      break;
  }
  console.log(roundNum);
};

const displaySelectedMap = (item, resultContainer) => {
  resultContainer.classList.add("selected");

  //clear the infobox
  infoBox.innerHTML = null;
  if (item.description == "" || item.description == null) {
    item.description = "The creator of this map has not added a description";
  }

  item.created = item.created.slice(0, 10);

  let officialState;
  if (!item.isUserMap) {
    officialState = "Official Map";
  } else {
    officialState = "Usermade Map";
  }

  //yuck
  let selectedItemHTML = `           
    <header class="selected-header">
      <div class="header-title-container">
        <h1 class="selected-title">${item.name}</h1>
        <a class="selected-creator" href="user/${item.creatorId}" target="_blank">${item.creator}</a>
      </div>
      <div class="header-likes">
        <h3 class="header-likes-num">${item.likes}</h3>
        <div>♥</div>
      </div>
    </header>
    <div class="selected-info-container">
      <div class="selected-desc">${item.description}</div>  
      <div class="tags">
        <div class="tag">
          <b>${item.coordinateCount} locations</b>
        </div>
        <div class="tag">
          <b>Created: ${item.created}</b>
        </div>
        <div class="tag">
          <b>${item.numberOfGamesPlayed} games played</b>
        </div>
        <div class="tag">
          <b>${officialState}</b>
        </div>
      </div>
    </div>
    <div class="game">
      <div class="game-settings">
        <div class="game-mode-select">
          <h1>Game settings</h1>
          <div class="gamemode-buttons">
            <button class="mode-button selected-mode">MOVE</button>
            <button class="mode-button">NO MOVE</button>
            <button class="mode-button">NMPZ</button>
          </div>
        </div>
        <div class="round-select">
          <h1>ROUNDS</h1>
          <div class="round-numbers">
            <button class="round-number ">1</button>
            <button class="round-number">2</button>
            <button class="round-number">3</button>
            <button class="round-number">4</button>
            <button class="round-number selected-mode">5</button>
          </div>
        </div>
        <div class="round-time">
          <h1>ROUND TIME</h1>
          <input type="range" min="0" max="600" step="10" class="time-slider" value="30"/>
          <h2 class="time-display">30 seconds</h2>
        </div>
        <button class="start-game-btn">START GAME!</button>
      </div>
      <div class="ol-selected-leaderboard"></div>
    </div> 
    `;
  infoBox.innerHTML = selectedItemHTML;

  const slider = document.querySelector(".time-slider");
  const timeDisplay = document.querySelector(".time-display");

  slider.addEventListener("input", function () {
    if (slider.value < 60) {
      timeDisplay.textContent = `${slider.value} seconds`;
    } else if (slider.value >= 60) {
      let timeMin = Math.floor(slider.value / 60);
      let timeSec = slider.value % 60;
      if (timeSec == "0") timeDisplay.textContent = `${timeMin} minutes`;
      else timeDisplay.textContent = `${timeMin} minutes, ${timeSec} seconds`;
    }
    roundTimeSeconds = slider.value;
  });

  const startButton = document.querySelector(".start-game-btn");
  const modeButtons = document.querySelectorAll(".mode-button");
  const roundNumbers = document.querySelectorAll(".round-number");

  modeButtons.forEach((button) => {
    button.addEventListener("click", () => setMode(button.textContent, modeButtons, button));
  });

  roundNumbers.forEach((number) => {
    number.addEventListener("click", () => setRounds(number.textContent, roundNumbers, number));
  });

  //start button, get every piece of data that's needed to start a game on the currently selected settings.
  startButton.addEventListener("click", () => {
    //item.id is map
    startGame(item.id);
  });
};

document.addEventListener("keydown", function (event) {
  if (document.activeElement == searchBar && event.key === "Enter") {
    let searchTerm = searchBar.value;

    search(searchTerm);
  }
});

closeButton.addEventListener("click", function () {
  overlay.classList.remove("active");
});

document.addEventListener("keydown", function (event) {
  if (document.activeElement == topSearchBar && event.key === "Enter") {
    let searchTerm = topSearchBar.value;
    everything.classList.add("active");
    search(searchTerm);
  }
});

function checkUrl() {
  setTimeout(() => {
    if (window.location.href != "https://www.geoguessr.com/") {
      topSearchBar.classList.add("inactive-search-bar");
    } else if (window.location.href == "https://www.geoguessr.com/") {
      topSearchBar.classList.remove("inactive-search-bar");
    }
  }, 200);
}

document.addEventListener("click", checkUrl);

filterButton.addEventListener("click", () => filterPopup.show());

closeFiltersButton.addEventListener("click", () => filterPopup.close());

applyFilterBtn.addEventListener("click", saveFilters);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址