MediaWiki:Common.js: Difference between revisions

From UO Renaissance Wiki
Jump to navigation Jump to search
Add Patch Notes Archive submenu to Compendium flyout
Add Unique Shard Systems dropdown to Compendium sidebar
Line 107: Line 107:
       { label: 'Era 4: Veteran & Modern (2016-2020)', href: '/wiki/index.php/Patch_Notes_Archive#Era_4:_Veteran_Shard_.26_Modernization_.28Nov_2016_-_June_2020.29' }
       { label: 'Era 4: Veteran & Modern (2016-2020)', href: '/wiki/index.php/Patch_Notes_Archive#Era_4:_Veteran_Shard_.26_Modernization_.28Nov_2016_-_June_2020.29' }
     ]);
     ]);
    // 9. Unique Shard Systems Submenu
    var uniqueSystemsItems = [
      { label: "The Zookeeper's Quest", href: "/wiki/index.php/The_Zookeeper's_Quest" }
    ];
    // Automatically incorporate any additional unique systems stored in localStorage
    try {
      var storedUnique = localStorage.getItem('uor_unique_shard_systems');
      if (storedUnique) {
        var parsedUnique = JSON.parse(storedUnique);
        if (Array.isArray(parsedUnique)) {
          parsedUnique.forEach(function(item) {
            if (item && item.label && item.href && !uniqueSystemsItems.some(function(x) { return x.href === item.href; })) {
              uniqueSystemsItems.push(item);
            }
          });
        }
      }
    } catch (e) {}
    // Check if the DOM already has sub-items (e.g. from MediaWiki:Sidebar)
    var uniqueLi = compendiumPortal.querySelector('li[id*="Unique"], li#n-Unique-Shard-Systems') ||
                  compendiumPortal.querySelector('a[href*="/wiki/index.php/Unique_Systems"]');
    if (uniqueLi) {
      if (uniqueLi.tagName.toLowerCase() === 'a') uniqueLi = uniqueLi.closest('li');
      if (uniqueLi) {
        var domSubLinks = uniqueLi.querySelectorAll('ul li a');
        domSubLinks.forEach(function(sl) {
          var lbl = sl.textContent.trim();
          var hrf = sl.getAttribute('href');
          if (lbl && hrf && !uniqueSystemsItems.some(function(x) { return x.href === hrf; })) {
            uniqueSystemsItems.push({ label: lbl, href: hrf });
          }
        });
      }
    }
    attachSidebarSubmenu('li[id*="Unique"], li#n-Unique-Shard-Systems', '/wiki/index.php/Unique_Systems', uniqueSystemsItems);
    // Sync any custom unique system links dynamically from the Unique Systems hub page
    if (window.location.pathname.indexOf('/Unique_Systems') !== -1) {
      try {
        var pageLinks = document.querySelectorAll('.uor-unique-system-link, [data-shard-system]');
        if (pageLinks.length > 0) {
          var collected = [];
          pageLinks.forEach(function(pl) {
            var plLabel = pl.getAttribute('data-shard-system') || pl.textContent.trim();
            var plHref = pl.getAttribute('href');
            if (plLabel && plHref && !collected.some(function(x) { return x.href === plHref; })) {
              collected.push({ label: plLabel, href: plHref });
            }
          });
          if (collected.length > 0) {
            localStorage.setItem('uor_unique_shard_systems', JSON.stringify(collected));
          }
        }
      } catch (e) {}
    }


     document.addEventListener('click', function(e) {
     document.addEventListener('click', function(e) {

Revision as of 12:52, 9 September 2026

/* UO Renaissance Wiki Common.js */
(function() {
  var compendiumPortal = document.getElementById('p-Compendium');
  if (compendiumPortal) {
    function attachSidebarSubmenu(liSelector, titleMatch, items) {
      var li = compendiumPortal.querySelector(liSelector) ||
               compendiumPortal.querySelector('a[href*="' + titleMatch + '"]');
      if (li && li.tagName.toLowerCase() === 'a') {
        li = li.closest('li');
      }
      if (!li || li.querySelector('.uor-sidebar-submenu')) return;

      li.classList.add('uor-sidebar-has-submenu');

      var link = li.querySelector(':scope > a');
      if (link && !link.querySelector('.uor-submenu-arrow')) {
        var arrow = document.createElement('span');
        arrow.className = 'uor-submenu-arrow';
        arrow.innerHTML = '▸';
        arrow.title = 'View Sections';
        arrow.addEventListener('click', function(e) {
          e.preventDefault();
          e.stopPropagation();
          li.classList.toggle('is-open');
        });
        link.appendChild(arrow);
      }

      var submenu = document.createElement('ul');
      submenu.className = 'uor-sidebar-submenu';
      var html = '';
      for (var i = 0; i < items.length; i++) {
        html += '<li><a href="' + items[i].href + '">' + items[i].label + '</a></li>';
      }
      submenu.innerHTML = html;
      li.appendChild(submenu);
    }

    // 1. The World Submenu
    attachSidebarSubmenu('li#n-The-World', '/wiki/index.php/The_World', [
      { label: 'Towns', href: '/wiki/index.php/The_World#Towns' },
      { label: 'Dungeons', href: '/wiki/index.php/The_World#Dungeons' },
      { label: 'Points of Interest', href: '/wiki/index.php/The_World#Points_of_Interest' }
    ]);

    // 2. Skills Submenu
    attachSidebarSubmenu('li#n-Skills', '/wiki/index.php/Skills', [
      { label: 'Combat', href: '/wiki/index.php/Skills#Combat' },
      { label: 'Crafting', href: '/wiki/index.php/Skills#Crafting' },
      { label: 'Creatures', href: '/wiki/index.php/Skills#Creatures' },
      { label: 'Lore & Knowledge', href: '/wiki/index.php/Skills#Lore_&_Knowledge' },
      { label: 'Miscellaneous', href: '/wiki/index.php/Skills#Miscellaneous' },
      { label: 'Rogue', href: '/wiki/index.php/Skills#Rogue' },
      { label: 'Spells & Magic', href: '/wiki/index.php/Spells' }
    ]);

    // 3. Factions & Guilds Submenu
    attachSidebarSubmenu('li[id*="Factions"], li#n-Factions', '/wiki/index.php/Factions', [
      { label: 'Factions', href: '/wiki/index.php/Factions_%26_Guilds#Factions' },
      { label: 'Order & Chaos', href: '/wiki/index.php/Factions_%26_Guilds#Order_&_Chaos' },
      { label: 'Player run Guilds', href: '/wiki/index.php/Factions_%26_Guilds#Player_run_Guilds' }
    ]);

    // 4. Champion Spawns Submenu
    attachSidebarSubmenu('li#n-Champion-Spawns', '/wiki/index.php/Champion_Spawns', [
      { label: 'Overview & Altars', href: '/wiki/index.php/Champion_Spawns#Altars' },
      { label: 'The Six Champions', href: '/wiki/index.php/Champion_Spawns#Champions' },
      { label: 'The Harrower', href: '/wiki/index.php/Champion_Spawns#The_Harrower' },
      { label: 'Rewards & Titles', href: '/wiki/index.php/Champion_Spawns#Rewards' }
    ]);

    // 5. Bestiary Submenu
    attachSidebarSubmenu('li#n-Bestiary', '/wiki/index.php/Bestiary', [
      { label: 'Bosses & Champions', href: '/wiki/index.php/Bestiary#Bosses_and_Champions' },
      { label: 'Daemons & Elementals', href: '/wiki/index.php/Bestiary#Daemons_and_Elementals' },
      { label: 'Reptiles & Monstrosities', href: '/wiki/index.php/Bestiary#Reptiles_and_Monstrosities' },
      { label: 'Undead & Tomb Horrors', href: '/wiki/index.php/Bestiary#Undead_and_Horrors' },
      { label: 'Humanoids, Tribes & Beasts', href: '/wiki/index.php/Bestiary#Humanoids_and_Beasts' },
      { label: 'Holiday & Event Specials', href: '/wiki/index.php/Bestiary#Holiday_and_Events' }
    ]);

    // 6. Housing & Vendors Submenu
    attachSidebarSubmenu('li[id*="Housing"], li#n-Housing-Vendors', 'Housing', [
      { label: 'Ownership Rules', href: '/wiki/index.php/Housing_System#Home_Ownership_Fundamentals' },
      { label: 'House Catalog', href: '/wiki/index.php/Housing_System#Complete_House_Catalog' },
      { label: 'Security & Tactics', href: '/wiki/index.php/Housing_System#House_Security_&_Fortification' },
      { label: 'Classic Vendors', href: '/wiki/index.php/Housing_System#Classic_Player_Vendors' },
      { label: 'Enhanced Vendors', href: '/wiki/index.php/Housing_System#Enhanced_Vendor_System' },
      { label: 'Quick Reference', href: '/wiki/index.php/Housing_System#Housing_&_Vendor_Quick_Reference' }
    ]);

    // 7. Murder & Bounties Submenu
    attachSidebarSubmenu('li[id*="Murder"], li#n-Murder-Bounties', 'Murder', [
      { label: 'Murder Counts', href: '/wiki/index.php/The_Murder_System#Understanding_Murder_Counts' },
      { label: 'Stat Loss Formula', href: '/wiki/index.php/The_Murder_System#Stat_Loss_Formula_&_Penalties' },
      { label: 'Reporting & Bounties', href: '/wiki/index.php/The_Murder_System#Reporting_a_Murder_&_Placing_Bounties' },
      { label: 'The Bounty Board', href: '/wiki/index.php/The_Murder_System#The_Bounty_Board_System' },
      { label: 'Claiming Heads', href: '/wiki/index.php/The_Murder_System#Claiming_Bounties_&_Taking_Heads' },
      { label: 'Quick Reference', href: '/wiki/index.php/The_Murder_System#Murder_&_Bounty_Quick_Reference' }
    ]);

    // 8. Patch Notes Archive Submenu
    attachSidebarSubmenu('li#n-Patch-Notes-Archive', '/wiki/index.php/Patch_Notes_Archive', [
      { label: 'Era 1: Alpha & Beta (2012)', href: '/wiki/index.php/Patch_Notes_Archive#Era_1:_Alpha_.26_Beta_Foundations_.28May_2012_-_Sept_2012.29' },
      { label: 'Era 2: Launch & Maturation (2012-2014)', href: '/wiki/index.php/Patch_Notes_Archive#Era_2:_Shard_Launch_.26_Server_Maturation_.28Sept_2012_-_Sept_2014.29' },
      { label: 'Era 3: Golden Age (2014-2016)', href: '/wiki/index.php/Patch_Notes_Archive#Era_3:_The_Golden_Age_.26_Expansions_.28Oct_2014_-_Oct_2016.29' },
      { label: 'Era 4: Veteran & Modern (2016-2020)', href: '/wiki/index.php/Patch_Notes_Archive#Era_4:_Veteran_Shard_.26_Modernization_.28Nov_2016_-_June_2020.29' }
    ]);

    // 9. Unique Shard Systems Submenu
    var uniqueSystemsItems = [
      { label: "The Zookeeper's Quest", href: "/wiki/index.php/The_Zookeeper's_Quest" }
    ];

    // Automatically incorporate any additional unique systems stored in localStorage
    try {
      var storedUnique = localStorage.getItem('uor_unique_shard_systems');
      if (storedUnique) {
        var parsedUnique = JSON.parse(storedUnique);
        if (Array.isArray(parsedUnique)) {
          parsedUnique.forEach(function(item) {
            if (item && item.label && item.href && !uniqueSystemsItems.some(function(x) { return x.href === item.href; })) {
              uniqueSystemsItems.push(item);
            }
          });
        }
      }
    } catch (e) {}

    // Check if the DOM already has sub-items (e.g. from MediaWiki:Sidebar)
    var uniqueLi = compendiumPortal.querySelector('li[id*="Unique"], li#n-Unique-Shard-Systems') ||
                   compendiumPortal.querySelector('a[href*="/wiki/index.php/Unique_Systems"]');
    if (uniqueLi) {
      if (uniqueLi.tagName.toLowerCase() === 'a') uniqueLi = uniqueLi.closest('li');
      if (uniqueLi) {
        var domSubLinks = uniqueLi.querySelectorAll('ul li a');
        domSubLinks.forEach(function(sl) {
          var lbl = sl.textContent.trim();
          var hrf = sl.getAttribute('href');
          if (lbl && hrf && !uniqueSystemsItems.some(function(x) { return x.href === hrf; })) {
            uniqueSystemsItems.push({ label: lbl, href: hrf });
          }
        });
      }
    }

    attachSidebarSubmenu('li[id*="Unique"], li#n-Unique-Shard-Systems', '/wiki/index.php/Unique_Systems', uniqueSystemsItems);

    // Sync any custom unique system links dynamically from the Unique Systems hub page
    if (window.location.pathname.indexOf('/Unique_Systems') !== -1) {
      try {
        var pageLinks = document.querySelectorAll('.uor-unique-system-link, [data-shard-system]');
        if (pageLinks.length > 0) {
          var collected = [];
          pageLinks.forEach(function(pl) {
            var plLabel = pl.getAttribute('data-shard-system') || pl.textContent.trim();
            var plHref = pl.getAttribute('href');
            if (plLabel && plHref && !collected.some(function(x) { return x.href === plHref; })) {
              collected.push({ label: plLabel, href: plHref });
            }
          });
          if (collected.length > 0) {
            localStorage.setItem('uor_unique_shard_systems', JSON.stringify(collected));
          }
        }
      } catch (e) {}
    }

    document.addEventListener('click', function(e) {
      if (!e.target.closest('.uor-sidebar-has-submenu')) {
        var openMenus = document.querySelectorAll('.uor-sidebar-has-submenu.is-open');
        for (var i = 0; i < openMenus.length; i++) {
          openMenus[i].classList.remove('is-open');
        }
      }
    });
  }
})();