MediaWiki:Common.js: Difference between revisions

Automated page publish
gave the mobile menu some actual links
 
(12 intermediate revisions by the same user not shown)
Line 4: Line 4:
     $('#ca-view a').text('Read');
     $('#ca-view a').text('Read');
});
});
// ==========================================================================
// Minerva (mobile skin) main menu only ships Home/Random by default; it does
// not pull in MediaWiki:Sidebar the way Vector's portlets do. This injects
// the same section links (kept in sync with MediaWiki:Sidebar by hand) into
// the native menu markup so mobile visitors actually get real navigation
// instead of just Home/Random/Settings/About/Disclaimers.
(function () {
  function initMinervaNav() {
    try {
      if (!document.body || !document.body.classList.contains('skin-minerva')) return;
      var nav = document.getElementById('p-navigation');
      if (!nav || document.getElementById('wov-minerva-extra-nav')) return;
      var sections = [
        { heading: 'Guides', items: [
          ['Getting started', '/w/Getting_Started'],
          ['Interactive Map (Fullscreen)', 'https://jxlife.github.io/WindsOfValenMap/'],
          ['All skills', '/w/Skills'],
          ['All quests', '/w/Quests'],
          ['Combat guide', '/w/Combat']
        ]},
        { heading: 'Database', items: [
          ['Item database', '/w/Items'],
          ['NPC database', '/w/NPCs'],
          ['Set bonuses', '/w/Set_bonuses']
        ]},
        { heading: 'Skills', items: [
          ['Skill Calculator', '/w/Calculators'],
          ['Mining', '/w/Mining'],
          ['Smithing', '/w/Smithing'],
          ['Fishing', '/w/Fishing'],
          ['Potion Making', '/w/Potion_Making']
        ]},
        { heading: 'Tools', items: [
          ['About this wiki', '/w/Project:About'],
          ['Random page', '/w/Special:Random'],
          ['New files', '/w/Special:NewFiles'],
          ['Wanted pages', '/w/Special:WantedPages'],
          ['Wiki statistics', '/w/Special:Statistics']
        ]},
        { heading: 'Updates', items: [
          ['Recent changes', '/w/Special:RecentChanges']
        ]}
      ];
      var container = document.createElement('div');
      container.id = 'wov-minerva-extra-nav';
      sections.forEach(function (section) {
        var heading = document.createElement('div');
        heading.className = 'wov-minerva-nav-heading';
        heading.textContent = section.heading;
        container.appendChild(heading);
        var ul = document.createElement('ul');
        ul.className = 'toggle-list__list';
        section.items.forEach(function (item) {
          var li = document.createElement('li');
          li.className = 'toggle-list-item';
          var a = document.createElement('a');
          a.className = 'toggle-list-item__anchor';
          a.href = item[1];
          var label = document.createElement('span');
          label.className = 'toggle-list-item__label';
          label.textContent = item[0];
          a.appendChild(label);
          li.appendChild(a);
          ul.appendChild(li);
        });
        container.appendChild(ul);
      });
      nav.parentNode.insertBefore(container, nav.nextSibling);
    } catch (e) {}
  }
  if (document.body) {
    initMinervaNav();
  } else {
    document.addEventListener('DOMContentLoaded', initMinervaNav);
  }
})();
// ==========================================================================
// ==========================================================================
// Valen Ledger — Gathering & Combat XP Calculator
// Valen Ledger — Gathering & Combat XP Calculator
Line 26: Line 108:
     smithing: [
     smithing: [
       // Bronze
       // Bronze
       {name:'Bronze Bar',xp:15},
       {name:'Bronze Bar',xp:15},{name:'Bronze Helmet',xp:60},{name:'Bronze Platebody',xp:60},{name:'Bronze Platelegs',xp:120},{name:'Bronze Sword',xp:90},
       // Iron
       // Iron
       {name:'Iron Bar',xp:30},{name:'Iron Rod',xp:10},{name:'Iron Plate',xp:30},
       {name:'Iron Bar',xp:30},{name:'Iron Rod',xp:10},{name:'Iron Plate',xp:30},{name:'Iron Helmet',xp:120},{name:'Iron Platebody',xp:300},{name:'Iron Platelegs',xp:240},{name:'Iron Sword',xp:180},
       // Steel
       // Steel
       {name:'Steel Bar',xp:55},{name:'Steel Rod',xp:30},{name:'Large Steel Rod',xp:40},{name:'Steel Plate',xp:60},{name:'Large Steel Plate',xp:70},
       {name:'Steel Bar',xp:55},{name:'Steel Rod',xp:30},{name:'Large Steel Rod',xp:40},{name:'Steel Plate',xp:60},{name:'Large Steel Plate',xp:70},{name:'Steel Helmet',xp:220},{name:'Steel Platebody',xp:550},{name:'Steel Platelegs',xp:440},{name:'Steel Sword',xp:330},
       // Mithril
       // Mithril
       {name:'Mithril Bar',xp:155},{name:'Large Mithril Rod',xp:275},{name:'Mithril Rod',xp:250},{name:'Large Mithril Plate',xp:550},{name:'Mithril Plate',xp:500},
       {name:'Mithril Bar',xp:155},{name:'Large Mithril Rod',xp:275},{name:'Mithril Rod',xp:250},{name:'Large Mithril Plate',xp:550},{name:'Mithril Plate',xp:500},{name:'Mithril Helmet',xp:620},{name:'Mithril Platebody',xp:1550},{name:'Mithril Platelegs',xp:1240},{name:'Mithril Sword',xp:930},
       // Silver
       // Silver
       {name:'Silver Plate',xp:400},{name:'Silver Foil',xp:400},
       {name:'Silver Bar',xp:675},{name:'Silver Plate',xp:400},{name:'Silver Foil',xp:400},
       // Gold
       // Gold
       {name:'Gold Bar',xp:800},{name:'Gold Plate',xp:400},{name:'Golden Shield Frame',xp:1000},
       {name:'Gold Bar',xp:800},{name:'Gold Plate',xp:400},{name:'Golden Shield Frame',xp:1000},
       // Ebony
       // Ebony
       {name:'Small Ebony Rod',xp:3000},{name:'Large Ebony Rod',xp:3500},{name:'Ebony Rod',xp:3250},{name:'Small Ebony Plate',xp:6000},{name:'Ebony Plate',xp:6500},{name:'Large Ebony Plate',xp:7000},
       {name:'Ebony Bar',xp:1800},{name:'Small Ebony Rod',xp:3000},{name:'Large Ebony Rod',xp:3500},{name:'Ebony Rod',xp:3250},{name:'Small Ebony Plate',xp:6000},{name:'Ebony Plate',xp:6500},{name:'Large Ebony Plate',xp:7000},
       // Duskknight
       // Duskknight
       {name:'Duskknight Boot Left Sabaton',xp:10000},{name:'Duskknight Boot Right Sabaton',xp:10000},{name:'Duskknight Leg Tuille',xp:10000},{name:'Duskknight Leg Poleyn',xp:10000},{name:'Duskknight Body Pauldron',xp:10000},{name:'Duskknight Body Couter',xp:10000},{name:'Duskknight Body Rerebrace',xp:12000},{name:'Duskknight Body Vambrace',xp:12000},{name:'Duskknight Leg Tasset',xp:14000},{name:'Duskknight Boot Greave',xp:15000},{name:'Duskknight Leg Cuisses',xp:15000},{name:'Duskknight Helmet Face Plate',xp:15000},{name:'Duskknight Helmet Head Plate',xp:15000},{name:'Duskknight Helmet Spike',xp:15000},{name:'Duskknight Body Breastplate',xp:18000}
       {name:'Duskknight Boot Left Sabaton',xp:10000},{name:'Duskknight Boot Right Sabaton',xp:10000},{name:'Duskknight Leg Tuille',xp:10000},{name:'Duskknight Leg Poleyn',xp:10000},{name:'Duskknight Body Pauldron',xp:10000},{name:'Duskknight Body Couter',xp:10000},{name:'Duskknight Body Rerebrace',xp:12000},{name:'Duskknight Body Vambrace',xp:12000},{name:'Duskknight Leg Tasset',xp:14000},{name:'Duskknight Boot Greave',xp:15000},{name:'Duskknight Leg Cuisses',xp:15000},{name:'Duskknight Helmet Face Plate',xp:15000},{name:'Duskknight Helmet Head Plate',xp:15000},{name:'Duskknight Helmet Spike',xp:15000},{name:'Duskknight Body Breastplate',xp:18000}
Line 86: Line 168:
     'Duskknight Body Breastplate': [{name:'Large Ebony Plate', count:4},{name:'Silver Foil', count:8}],
     'Duskknight Body Breastplate': [{name:'Large Ebony Plate', count:4},{name:'Silver Foil', count:8}],
     'Bronze Bar': [{name:'Copper Ore', count:1},{name:'Tin Ore', count:1}],
     'Bronze Bar': [{name:'Copper Ore', count:1},{name:'Tin Ore', count:1}],
    'Bronze Helmet': [{name:'Bronze Bar', count:4}],
    'Bronze Platebody': [{name:'Bronze Bar', count:10}],
    'Bronze Platelegs': [{name:'Bronze Bar', count:8}],
    'Bronze Sword': [{name:'Bronze Bar', count:6}],
     'Iron Bar': [{name:'Iron Ore', count:2}],
     'Iron Bar': [{name:'Iron Ore', count:2}],
    'Iron Helmet': [{name:'Iron Bar', count:4}],
    'Iron Platebody': [{name:'Iron Bar', count:10}],
    'Iron Platelegs': [{name:'Iron Bar', count:8}],
    'Iron Sword': [{name:'Iron Bar', count:6}],
     'Steel Bar': [{name:'Iron Ore', count:1},{name:'Coal Ore', count:1}],
     'Steel Bar': [{name:'Iron Ore', count:1},{name:'Coal Ore', count:1}],
    'Steel Helmet': [{name:'Steel Bar', count:4}],
    'Steel Platebody': [{name:'Steel Bar', count:10}],
    'Steel Platelegs': [{name:'Steel Bar', count:8}],
    'Steel Sword': [{name:'Steel Bar', count:6}],
     'Mithril Bar': [{name:'Mithril Ore', count:1},{name:'Coal Ore', count:2}],
     'Mithril Bar': [{name:'Mithril Ore', count:1},{name:'Coal Ore', count:2}],
    'Mithril Helmet': [{name:'Mithril Bar', count:4}],
    'Mithril Platebody': [{name:'Mithril Bar', count:10}],
    'Mithril Platelegs': [{name:'Mithril Bar', count:8}],
    'Mithril Sword': [{name:'Mithril Bar', count:6}],
     'Gold Bar': [{name:'Gold Ore', count:8}],
     'Gold Bar': [{name:'Gold Ore', count:8}],
     'Silver Bar': [{name:'Silver Ore', count:7}],
     'Silver Bar': [{name:'Silver Ore', count:7}],
Line 103: Line 201:
     return null;
     return null;
   }
   }
  // Seconds per craft at the Anvil/Furnace, one entry per RECIPES key. Bar/Helmet/Platebody/
  // Platelegs/Sword durations for Bronze-Mithril come straight off the Smithing Guide tables;
  // everything else comes from the game's own recipe data.
  var CRAFT_DURATION = {
    'Bronze Bar':3, 'Bronze Helmet':6, 'Bronze Platebody':18, 'Bronze Platelegs':16, 'Bronze Sword':8,
    'Iron Bar':4, 'Iron Rod':15, 'Iron Plate':4, 'Iron Helmet':10, 'Iron Platebody':28, 'Iron Platelegs':24, 'Iron Sword':12,
    'Steel Bar':5, 'Steel Rod':3, 'Large Steel Rod':3, 'Steel Plate':5, 'Large Steel Plate':5, 'Steel Helmet':14, 'Steel Platebody':38, 'Steel Platelegs':32, 'Steel Sword':16,
    'Mithril Bar':6, 'Large Mithril Rod':13, 'Mithril Rod':13, 'Large Mithril Plate':22, 'Mithril Plate':22, 'Mithril Helmet':18, 'Mithril Platebody':48, 'Mithril Platelegs':40, 'Mithril Sword':20,
    'Silver Bar':10, 'Silver Plate':15, 'Silver Foil':15,
    'Gold Bar':15, 'Gold Plate':15, 'Golden Shield Frame':60,
    'Small Ebony Rod':40, 'Large Ebony Rod':40, 'Ebony Rod':40, 'Small Ebony Plate':60, 'Ebony Plate':60, 'Large Ebony Plate':60, 'Ebony Bar':20,
    'Duskknight Boot Left Sabaton':120, 'Duskknight Boot Right Sabaton':120, 'Duskknight Leg Tuille':120, 'Duskknight Leg Poleyn':120, 'Duskknight Body Pauldron':120, 'Duskknight Body Couter':120, 'Duskknight Body Rerebrace':120, 'Duskknight Body Vambrace':120, 'Duskknight Leg Tasset':120, 'Duskknight Boot Greave':120, 'Duskknight Leg Cuisses':120, 'Duskknight Helmet Face Plate':120, 'Duskknight Helmet Head Plate':120, 'Duskknight Helmet Spike':120, 'Duskknight Body Breastplate':120
  };


   // Walks RECIPES tier-by-tier from `qty` of `name`, merging same-name items within a tier.
   // Walks RECIPES tier-by-tier from `qty` of `name`, merging same-name items within a tier.
Line 363: Line 475:
       if (rawNames.length){
       if (rawNames.length){
         text += '\n\nTotal raw materials: ' + rawNames.map(function(n){ return fmt(breakdown.totals[n]) + ' ' + n; }).join(', ');
         text += '\n\nTotal raw materials: ' + rawNames.map(function(n){ return fmt(breakdown.totals[n]) + ' ' + n; }).join(', ');
      }
      var totalSeconds = breakdown.entries.reduce(function(sum, e){
        var dur = CRAFT_DURATION[e.name];
        return dur ? sum + e.qty * dur : sum;
      }, 0);
      if (totalSeconds > 0){
        text += '\nTotal craft time (Anvil/Furnace only, not counting ore gathering): ' + formatTime(totalSeconds);
       }
       }
       breakdownText.textContent = text;
       breakdownText.textContent = text;
Line 779: Line 898:
   selectTab('fishing');
   selectTab('fishing');
});
});
// ==========================================================================
// Mobile nav toggle — the sidebar (#mw-panel) renders inline far down the
// page on narrow screens, so add a fixed hamburger button that slides it in
// as an overlay drawer instead. CSS in Common.css keeps this hidden/inert
// on desktop widths (>=1000px).
// ==========================================================================
(function () {
  function initMobileNav() {
    var panel = document.getElementById('mw-panel');
    if (!panel || document.getElementById('mobile-nav-toggle')) return;
    var toggle = document.createElement('button');
    toggle.id = 'mobile-nav-toggle';
    toggle.type = 'button';
    toggle.setAttribute('aria-label', 'Toggle navigation menu');
    toggle.textContent = '\u2630 Menu';
    var backdrop = document.createElement('div');
    backdrop.id = 'mobile-nav-backdrop';
    document.body.insertBefore(backdrop, document.body.firstChild);
    document.body.insertBefore(toggle, document.body.firstChild);
    function closeNav() {
      panel.classList.remove('mobile-nav-open');
      backdrop.classList.remove('mobile-nav-open');
    }
    function toggleNav() {
      panel.classList.toggle('mobile-nav-open');
      backdrop.classList.toggle('mobile-nav-open');
    }
    toggle.addEventListener('click', toggleNav);
    backdrop.addEventListener('click', closeNav);
    panel.querySelectorAll('a').forEach(function (a) {
      a.addEventListener('click', closeNav);
    });
  }
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initMobileNav);
  } else {
    initMobileNav();
  }
})();