MediaWiki:Common.js: Difference between revisions

From Kintara
Jump to navigation Jump to search
Plausible: use site-specific tracking script
Build calculator UI via JS (wikitext strips form tags)
 
(2 intermediate revisions by the same user not shown)
Line 58: Line 58:
   document.head.appendChild(s);
   document.head.appendChild(s);
})();
})();
/* Resources Calculator — interactive widget on Category:Resources Calculator */
(function () {
  'use strict';
  var RATES = {
    wood_1: { label: 'Wood · Lvl 1 Axe', min: 60, max: 96, unit: 'Wood' },
    wood_2: { label: 'Wood · Lvl 2 Axe', min: 120, max: 192, unit: 'Wood' },
    mine_1: { label: 'Stone/Coal/Metal · Lvl 1 Pickaxe', min: 84, max: 120, unit: 'resources' },
    mine_2: { label: 'Stone/Coal/Metal · Lvl 2 Pickaxe', min: 168, max: 240, unit: 'resources' },
    fish_1: { label: 'Fish · Fishing Rod', min: 2, max: 4, unit: 'Fish' },
  };
  function fmtDuration(minutes) {
    if (!isFinite(minutes) || minutes <= 0) return '—';
    if (minutes < 60) return Math.round(minutes * 10) / 10 + ' minutes';
    var h = minutes / 60;
    if (h < 24) return Math.round(h * 10) / 10 + ' hours';
    return Math.round((h / 24) * 10) / 10 + ' days';
  }
  function buildCalc(root) {
    if (!root || root.dataset.ready) return;
    root.dataset.ready = '1';
    root.className = 'kin-resource-calc';
    root.innerHTML =
      '<div class="kin-rc-card">' +
        '<div class="kin-rc-head">Gathering time estimator</div>' +
        '<p class="kin-rc-note">Uses midpoint rate: (min + max) ÷ 2 per minute. Does not include travel between nodes or competition.</p>' +
        '<div class="kin-rc-fields">' +
          '<label class="kin-rc-field"><span>Setup</span><select id="kin-rc-setup"></select></label>' +
          '<label class="kin-rc-field"><span>Target amount</span><input id="kin-rc-target" type="number" min="1" step="1" value="1000" /></label>' +
        '</div>' +
        '<div class="kin-rc-results">' +
          '<div class="kin-rc-stat"><span class="kin-rc-stat-label">Rate range</span><strong id="kin-rc-rate">—</strong></div>' +
          '<div class="kin-rc-stat"><span class="kin-rc-stat-label">Midpoint rate</span><strong id="kin-rc-mid">—</strong></div>' +
          '<div class="kin-rc-stat kin-rc-stat--highlight"><span class="kin-rc-stat-label">Estimated time</span><strong id="kin-rc-time">—</strong></div>' +
        '</div>' +
      '</div>';
    var setup = root.querySelector('#kin-rc-setup');
    Object.keys(RATES).forEach(function (key) {
      var opt = document.createElement('option');
      opt.value = key;
      opt.textContent = RATES[key].label;
      setup.appendChild(opt);
    });
    function update() {
      var cfg = RATES[setup.value];
      var target = parseFloat(root.querySelector('#kin-rc-target').value, 10);
      var mid = (cfg.min + cfg.max) / 2;
      root.querySelector('#kin-rc-rate').textContent = cfg.min + '–' + cfg.max + ' / min';
      root.querySelector('#kin-rc-mid').textContent = mid + ' ' + cfg.unit + ' / min';
      root.querySelector('#kin-rc-time').textContent = (!target || target <= 0)
        ? 'Enter a target amount'
        : fmtDuration(target / mid);
    }
    setup.addEventListener('change', update);
    root.querySelector('#kin-rc-target').addEventListener('input', update);
    update();
  }
  function init() {
    var root = document.getElementById('kin-resource-calc');
    if (!root) return;
    var setup = root.querySelector('#kin-rc-setup');
    if (!setup || setup.tagName !== 'SELECT') {
      root.dataset.ready = '';
      root.textContent = '';
    }
    buildCalc(root);
  }
  function boot() {
    init();
    if (window.mw && mw.hook) {
      mw.hook('wikipage.content').add(function ($content) {
        var el = $content[0].querySelector('#kin-resource-calc');
        if (el) {
          el.dataset.ready = '';
          buildCalc(el);
        }
      });
    }
  }
  if (window.mw && mw.loader) {
    mw.loader.using('mediawiki.util').then(boot);
  } else if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', boot);
  } else {
    boot();
  }
})();
/* cache-bust: 2026-06-25b */

Latest revision as of 05:53, 25 June 2026

/* Kintara dashboard sky — drifting geo clouds (matches kintara.com leaderboard backdrop) */
(function () {
  function injectKinSky() {
    if (document.getElementById('kin-sky-backdrop')) return;
    var el = document.createElement('div');
    el.id = 'kin-sky-backdrop';
    el.setAttribute('aria-hidden', 'true');
    el.innerHTML =
      '<div class="kin-sky-clouds">' +
      '<div class="kin-geo-puff kin-geo-puff--1"><span class="kin-geo-block kin-geo-block--a"></span><span class="kin-geo-block kin-geo-block--b"></span><span class="kin-geo-block kin-geo-block--c"></span></div>' +
      '<div class="kin-geo-puff kin-geo-puff--2"><span class="kin-geo-block kin-geo-block--a"></span><span class="kin-geo-block kin-geo-block--b"></span><span class="kin-geo-block kin-geo-block--c"></span><span class="kin-geo-block kin-geo-block--d"></span></div>' +
      '<div class="kin-geo-puff kin-geo-puff--3"><span class="kin-geo-block kin-geo-block--a"></span><span class="kin-geo-block kin-geo-block--b"></span><span class="kin-geo-block kin-geo-block--c"></span></div>' +
      '<div class="kin-geo-puff kin-geo-puff--4"><span class="kin-geo-block kin-geo-block--a"></span><span class="kin-geo-block kin-geo-block--b"></span><span class="kin-geo-block kin-geo-block--c"></span><span class="kin-geo-block kin-geo-block--d"></span></div>' +
      '<div class="kin-geo-puff kin-geo-puff--5"><span class="kin-geo-block kin-geo-block--a"></span><span class="kin-geo-block kin-geo-block--b"></span><span class="kin-geo-block kin-geo-block--c"></span></div>' +
      '<div class="kin-geo-puff kin-geo-puff--6"><span class="kin-geo-block kin-geo-block--a"></span><span class="kin-geo-block kin-geo-block--b"></span><span class="kin-geo-block kin-geo-block--c"></span><span class="kin-geo-block kin-geo-block--d"></span></div>' +
      '</div>';
    document.body.insertBefore(el, document.body.firstChild);
  }
  if (document.body) injectKinSky();
  else document.addEventListener('DOMContentLoaded', injectKinSky);
})();

mw.loader.using('mediawiki.util').then(function () {
  if (mw.config.get('wgPageName') === 'Main_Page') {
    document.querySelectorAll(
      '.kin-promo.discord .pbody a, .kin-promo.xbox .pbody a'
    ).forEach(function (link) {
      link.setAttribute('target', '_blank');
      link.setAttribute('rel', 'nofollow noopener noreferrer');
    });
  }

  var tabs = document.querySelector('#p-namespaces ul');
  if (tabs && !document.getElementById('ca-kintara-play')) {
    var playTab = document.createElement('li');
    playTab.id = 'ca-kintara-play';
    playTab.className = 'mw-list-item';
    playTab.innerHTML =
      '<a href="https://kintara.com/" target="_blank" rel="nofollow noopener noreferrer"><span>Play Now</span></a>';

    tabs.appendChild(playTab);
  }
});

/* Plausible Analytics — privacy-friendly pageviews for kintara.wiki */
(function () {
  if (document.querySelector('script[src*="pa-QBNr94JQzRuLvqXz02DEQ.js"]')) return;
  window.plausible = window.plausible || function () {
    (plausible.q = plausible.q || []).push(arguments);
  };
  plausible.init = plausible.init || function (i) {
    plausible.o = i || {};
  };
  var s = document.createElement('script');
  s.async = true;
  s.src = 'https://plausible.io/js/pa-QBNr94JQzRuLvqXz02DEQ.js';
  s.onload = function () { plausible.init(); };
  document.head.appendChild(s);
})();
/* Resources Calculator — interactive widget on Category:Resources Calculator */
(function () {
  'use strict';
  var RATES = {
    wood_1: { label: 'Wood · Lvl 1 Axe', min: 60, max: 96, unit: 'Wood' },
    wood_2: { label: 'Wood · Lvl 2 Axe', min: 120, max: 192, unit: 'Wood' },
    mine_1: { label: 'Stone/Coal/Metal · Lvl 1 Pickaxe', min: 84, max: 120, unit: 'resources' },
    mine_2: { label: 'Stone/Coal/Metal · Lvl 2 Pickaxe', min: 168, max: 240, unit: 'resources' },
    fish_1: { label: 'Fish · Fishing Rod', min: 2, max: 4, unit: 'Fish' },
  };

  function fmtDuration(minutes) {
    if (!isFinite(minutes) || minutes <= 0) return '—';
    if (minutes < 60) return Math.round(minutes * 10) / 10 + ' minutes';
    var h = minutes / 60;
    if (h < 24) return Math.round(h * 10) / 10 + ' hours';
    return Math.round((h / 24) * 10) / 10 + ' days';
  }

  function buildCalc(root) {
    if (!root || root.dataset.ready) return;
    root.dataset.ready = '1';
    root.className = 'kin-resource-calc';
    root.innerHTML =
      '<div class="kin-rc-card">' +
        '<div class="kin-rc-head">Gathering time estimator</div>' +
        '<p class="kin-rc-note">Uses midpoint rate: (min + max) ÷ 2 per minute. Does not include travel between nodes or competition.</p>' +
        '<div class="kin-rc-fields">' +
          '<label class="kin-rc-field"><span>Setup</span><select id="kin-rc-setup"></select></label>' +
          '<label class="kin-rc-field"><span>Target amount</span><input id="kin-rc-target" type="number" min="1" step="1" value="1000" /></label>' +
        '</div>' +
        '<div class="kin-rc-results">' +
          '<div class="kin-rc-stat"><span class="kin-rc-stat-label">Rate range</span><strong id="kin-rc-rate">—</strong></div>' +
          '<div class="kin-rc-stat"><span class="kin-rc-stat-label">Midpoint rate</span><strong id="kin-rc-mid">—</strong></div>' +
          '<div class="kin-rc-stat kin-rc-stat--highlight"><span class="kin-rc-stat-label">Estimated time</span><strong id="kin-rc-time">—</strong></div>' +
        '</div>' +
      '</div>';

    var setup = root.querySelector('#kin-rc-setup');
    Object.keys(RATES).forEach(function (key) {
      var opt = document.createElement('option');
      opt.value = key;
      opt.textContent = RATES[key].label;
      setup.appendChild(opt);
    });

    function update() {
      var cfg = RATES[setup.value];
      var target = parseFloat(root.querySelector('#kin-rc-target').value, 10);
      var mid = (cfg.min + cfg.max) / 2;
      root.querySelector('#kin-rc-rate').textContent = cfg.min + '–' + cfg.max + ' / min';
      root.querySelector('#kin-rc-mid').textContent = mid + ' ' + cfg.unit + ' / min';
      root.querySelector('#kin-rc-time').textContent = (!target || target <= 0)
        ? 'Enter a target amount'
        : fmtDuration(target / mid);
    }

    setup.addEventListener('change', update);
    root.querySelector('#kin-rc-target').addEventListener('input', update);
    update();
  }

  function init() {
    var root = document.getElementById('kin-resource-calc');
    if (!root) return;
    var setup = root.querySelector('#kin-rc-setup');
    if (!setup || setup.tagName !== 'SELECT') {
      root.dataset.ready = '';
      root.textContent = '';
    }
    buildCalc(root);
  }

  function boot() {
    init();
    if (window.mw && mw.hook) {
      mw.hook('wikipage.content').add(function ($content) {
        var el = $content[0].querySelector('#kin-resource-calc');
        if (el) {
          el.dataset.ready = '';
          buildCalc(el);
        }
      });
    }
  }

  if (window.mw && mw.loader) {
    mw.loader.using('mediawiki.util').then(boot);
  } else if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', boot);
  } else {
    boot();
  }
})();
/* cache-bust: 2026-06-25b */