Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MediaWiki:Common.js: Difference between revisions

MediaWiki interface page
No edit summary
No edit summary
Line 97: Line 97:
   Per-Dungeon Ranking + Filters
   Per-Dungeon Ranking + Filters
   =========================== */
   =========================== */


mw.hook('wikipage.content').add(function () {
mw.hook('wikipage.content').add(function () {


   // Run only if table exists
   // ===== SOLO TABLE =====
   const table = document.getElementById("leaderboardTable");
   const table = document.getElementById("leaderboardTable");
   if (!table) return;
   if (table) {
    const container = document.getElementById("filterContainer");
    if (container) {


  const container = document.getElementById("filterContainer");
      const wrapper = document.createElement("div");
  if (!container) return;
      wrapper.style.marginBottom = "15px";


  /* ---------- CREATE FILTER UI ---------- */
      const dungeonLabel = document.createElement("strong");
      dungeonLabel.innerText = "Dungeon: ";
      wrapper.appendChild(dungeonLabel);


  const wrapper = document.createElement("div");
      const dungeonSelect = document.createElement("select");
  wrapper.style.marginBottom = "15px";
      dungeonSelect.style.marginRight = "20px";


  // Dungeon dropdown
      const dungeons = [
  const dungeonLabel = document.createElement("strong");
        "All",
  dungeonLabel.innerText = "Dungeon: ";
        "Wolf's Den", "Wolf's Den II", "Wolf's Den III",
  wrapper.appendChild(dungeonLabel);
        "The Red Nest", "For The Eggs",
        "Scarlet Revenge", "Scarlet Revenge II",
        "Promised One", "Promised One II", "Promised One III",
        "Lost and Found", "The Hostage", "Cactus On Fire",
        "Deep Echoes", "Deep Echoes II", "Deep Echoes III",
        "Hall of Daggers",
      ];


  const dungeonSelect = document.createElement("select");
      dungeons.forEach(name => {
  dungeonSelect.style.marginRight = "20px";
        const option = document.createElement("option");
        option.value = name;
        option.textContent = name;
        dungeonSelect.appendChild(option);
      });


  const dungeons = [
      wrapper.appendChild(dungeonSelect);
    "All",
    "Wolf's Den",
    "Wolf's Den II",
    "Wolf's Den III",
    "The Red Nest",
    "For The Eggs",
    "Scarlet Revenge",
    "Scarlet Revenge II",
    "Promised One",
    "Promised One II",
    "Promised One III",
    "Lost and Found",
    "The Hostage",
    "Cactus On Fire",
    "Deep Echoes",
    "Deep Echoes II",
    "Deep Echoes III",
    "Hall of Daggers",
  ];


  dungeons.forEach(name => {
      const playerLabel = document.createElement("strong");
    const option = document.createElement("option");
      playerLabel.innerText = "Player: ";
    option.value = name;
      wrapper.appendChild(playerLabel);
    option.textContent = name;
    dungeonSelect.appendChild(option);
  });


  wrapper.appendChild(dungeonSelect);
      const playerInput = document.createElement("input");
      playerInput.type = "text";
      playerInput.placeholder = "Search player name...";
      playerInput.style.padding = "4px";
      wrapper.appendChild(playerInput);


  // Player search
      container.appendChild(wrapper);
  const playerLabel = document.createElement("strong");
  playerLabel.innerText = "Player: ";
  wrapper.appendChild(playerLabel);


  const playerInput = document.createElement("input");
      function parseTime(t) {
  playerInput.type = "text";
        if (!t || !t.includes(":")) return 999999;
  playerInput.placeholder = "Search player name...";
        const parts = t.trim().split(":");
  playerInput.style.padding = "4px";
        return parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10);
  wrapper.appendChild(playerInput);
      }


  container.appendChild(wrapper);
      function sortAndRank() {
        const rows = Array.from(table.querySelectorAll("tr")).slice(1);
        rows.sort((a, b) => {
          const dungeonA = a.cells[1].innerText.trim();
          const dungeonB = b.cells[1].innerText.trim();
          if (dungeonA < dungeonB) return -1;
          if (dungeonA > dungeonB) return 1;
          return parseTime(a.cells[4].innerText) - parseTime(b.cells[4].innerText);
        });
        rows.forEach(row => table.appendChild(row));


  /* ---------- UTILITIES ---------- */
        let currentDungeon = "";
        let dungeonRank = 0;
        rows.forEach(row => {
          if (row.style.display === "none") return;
          const dungeon = row.cells[1].innerText.trim();
          const rankCell = row.cells[0];
          if (dungeon !== currentDungeon) { currentDungeon = dungeon; dungeonRank = 1; }
          else { dungeonRank++; }
          if (dungeonRank === 1) rankCell.innerHTML = "🥇 1";
          else if (dungeonRank === 2) rankCell.innerHTML = "🥈 2";
          else if (dungeonRank === 3) rankCell.innerHTML = "🥉 3";
          else rankCell.innerText = dungeonRank;
        });
      }


  function parseTime(t) {
      function filterTable() {
    if (!t || !t.includes(":")) return 999999;
        const selectedDungeon = dungeonSelect.value;
    const parts = t.trim().split(":");
        const playerSearch = playerInput.value.toLowerCase();
    return parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10);
        const rows = Array.from(table.querySelectorAll("tr")).slice(1);
        rows.forEach(row => {
          const dungeon = row.cells[1].innerText.trim();
          const player = row.cells[2].innerText.toLowerCase();
          row.style.display =
            (selectedDungeon === "All" || dungeon === selectedDungeon) &&
            player.includes(playerSearch) ? "" : "none";
        });
        sortAndRank();
      }
 
      dungeonSelect.addEventListener("change", filterTable);
      playerInput.addEventListener("input", filterTable);
      sortAndRank();
    }
   }
   }


   function sortAndRank() {
   // ===== PARTY TABLE =====
     const rows = Array.from(table.querySelectorAll("tr")).slice(1);
  const partyTable = document.getElementById("partyLeaderboardTable");
  if (partyTable) {
     const partyContainer = document.getElementById("partyFilterContainer");
    if (partyContainer) {


    // Sort by Dungeon first, then Time
       const wrapper = document.createElement("div");
    rows.sort((a, b) => {
       wrapper.style.marginBottom = "15px";
       const dungeonA = a.cells[1].innerText.trim();
       const dungeonB = b.cells[1].innerText.trim();


       if (dungeonA < dungeonB) return -1;
       const dungeonLabel = document.createElement("strong");
       if (dungeonA > dungeonB) return 1;
       dungeonLabel.innerText = "Dungeon: ";
      wrapper.appendChild(dungeonLabel);


       return parseTime(a.cells[4].innerText) -
       const dungeonSelect = document.createElement("select");
            parseTime(b.cells[4].innerText);
      dungeonSelect.style.marginRight = "20px";
    });


    rows.forEach(row => table.appendChild(row));
      const dungeons = [
        "All",
        "Wolf's Den", "Wolf's Den II", "Wolf's Den III",
        "The Red Nest", "For The Eggs",
        "Scarlet Revenge", "Scarlet Revenge II",
        "Promised One", "Promised One II", "Promised One III",
        "Lost and Found", "The Hostage", "Cactus On Fire",
        "Deep Echoes", "Deep Echoes II", "Deep Echoes III",
        "Hall of Daggers",
      ];


    let currentDungeon = "";
      dungeons.forEach(name => {
    let dungeonRank = 0;
        const option = document.createElement("option");
        option.value = name;
        option.textContent = name;
        dungeonSelect.appendChild(option);
      });


    rows.forEach(row => {
      wrapper.appendChild(dungeonSelect);
      if (row.style.display === "none") return;


       const dungeon = row.cells[1].innerText.trim();
       const playerLabel = document.createElement("strong");
       const rankCell = row.cells[0];
       playerLabel.innerText = "Players: ";
      wrapper.appendChild(playerLabel);


       if (dungeon !== currentDungeon) {
       const playerInput = document.createElement("input");
        currentDungeon = dungeon;
      playerInput.type = "text";
        dungeonRank = 1;
      playerInput.placeholder = "Search player name...";
       } else {
       playerInput.style.padding = "4px";
        dungeonRank++;
       wrapper.appendChild(playerInput);
       }


       if (dungeonRank === 1) rankCell.innerHTML = "🥇 1";
       partyContainer.appendChild(wrapper);
      else if (dungeonRank === 2) rankCell.innerHTML = "🥈 2";
      else if (dungeonRank === 3) rankCell.innerHTML = "🥉 3";
      else rankCell.innerText = dungeonRank;
    });
  }


  function filterTable() {
      function parseTime(t) {
    const selectedDungeon = dungeonSelect.value;
        if (!t || !t.includes(":")) return 999999;
    const playerSearch = playerInput.value.toLowerCase();
        const parts = t.trim().split(":");
        return parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10);
      }


    const rows = Array.from(table.querySelectorAll("tr")).slice(1);
      function sortAndRankParty() {
        const rows = Array.from(partyTable.querySelectorAll("tr")).slice(1);
        rows.sort((a, b) => {
          const dungeonA = a.cells[1].innerText.trim();
          const dungeonB = b.cells[1].innerText.trim();
          if (dungeonA < dungeonB) return -1;
          if (dungeonA > dungeonB) return 1;
          // Time is now column 5 (0-indexed) because of the extra Party Size column
          return parseTime(a.cells[5].innerText) - parseTime(b.cells[5].innerText);
        });
        rows.forEach(row => partyTable.appendChild(row));


    rows.forEach(row => {
        let currentDungeon = "";
      const dungeon = row.cells[1].innerText.trim();
        let dungeonRank = 0;
      const player = row.cells[2].innerText.toLowerCase();
        rows.forEach(row => {
          if (row.style.display === "none") return;
          const dungeon = row.cells[1].innerText.trim();
          const rankCell = row.cells[0];
          if (dungeon !== currentDungeon) { currentDungeon = dungeon; dungeonRank = 1; }
          else { dungeonRank++; }
          if (dungeonRank === 1) rankCell.innerHTML = "🥇 1";
          else if (dungeonRank === 2) rankCell.innerHTML = "🥈 2";
          else if (dungeonRank === 3) rankCell.innerHTML = "🥉 3";
          else rankCell.innerText = dungeonRank;
        });
      }


       const dungeonMatch =
       function filterPartyTable() {
         selectedDungeon === "All" || dungeon === selectedDungeon;
        const selectedDungeon = dungeonSelect.value;
         const playerSearch = playerInput.value.toLowerCase();
        const rows = Array.from(partyTable.querySelectorAll("tr")).slice(1);
        rows.forEach(row => {
          const dungeon = row.cells[1].innerText.trim();
          // Players column is now index 3
          const player = row.cells[3].innerText.toLowerCase();
          row.style.display =
            (selectedDungeon === "All" || dungeon === selectedDungeon) &&
            player.includes(playerSearch) ? "" : "none";
        });
        sortAndRankParty();
      }


       const playerMatch =
       dungeonSelect.addEventListener("change", filterPartyTable);
        player.includes(playerSearch);
       playerInput.addEventListener("input", filterPartyTable);
 
      sortAndRankParty();
       row.style.display =
     }
        (dungeonMatch && playerMatch) ? "" : "none";
    });
 
     sortAndRank();
   }
   }


  dungeonSelect.addEventListener("change", filterTable);
});
  playerInput.addEventListener("input", filterTable);


  sortAndRank();
});
/* Open YouTube links in new tab */
/* Open YouTube links in new tab */
mw.hook('wikipage.content').add(function ($content) {
mw.hook('wikipage.content').add(function ($content) {
   $content.find('a[href*="youtube.com"], a[href*="youtu.be"]').each(function () {
   $content.find('a[href*="youtube.com"], a[href*="youtu.be"]').each(function () {
     this.setAttribute("target", "_blank");
     this.setAttribute("target", "_blank");
     this.setAttribute("rel", "noopener noreferrer");
     this.setAttribute("rel", "noopener noreferrer");
   });
   });
});
});