MediaWiki:Common.js: Difference between revisions

From AnarchyMU Wiki
No edit summary
No edit summary
Line 19: Line 19:
   }
   }
})();
})();
/* Update 042: robust nested Stage dropdown regrouping for varying sidebar DOMs */
(function () {
  function textOf(el) {
    return (el && el.textContent ? el.textContent : '').replace(/\s+/g, ' ').trim();
  }
  function norm(s) {
    return (s || '').replace(/\s+/g, ' ').trim().toLowerCase();
  }
  function isStageLabel(label) {
    return /^stage\s+[1-4]$/i.test(label);
  }


/* Update 041: make Stage 1-4 nested dropdown groups inside Stages System menu */
   function isMiniLabel(label) {
(function () {
     return /^mini\s+stage\s+\d+$/i.test(label);
   function txt(el) {
     return (el && el.textContent ? el.textContent : '').trim();
   }
   }


   function normalize(s) {
   function directLink(li) {
     return s.replace(/\s+/g, ' ').trim().toLowerCase();
     if (!li || !li.childNodes) return null;
    var i;
    for (i = 0; i < li.childNodes.length; i++) {
      var n = li.childNodes[i];
      if (n && n.nodeType === 1 && n.tagName && n.tagName.toLowerCase() === 'a') {
        return n;
      }
    }
    return li.querySelector ? li.querySelector('a') : null;
   }
   }


   function findStagesSystemList() {
   function childLis(container) {
     var links = Array.prototype.slice.call(document.querySelectorAll('a'));
     if (!container || !container.children) return [];
     for (var i = 0; i < links.length; i++) {
    var out = [];
       var label = normalize(txt(links[i]));
    var i;
       if (label === 'stages system') {
     for (i = 0; i < container.children.length; i++) {
         var li = links[i].closest('li');
       var c = container.children[i];
        if (!li) continue;
       if (c && c.tagName && c.tagName.toLowerCase() === 'li') {
        var ul = li.querySelector(':scope > ul, :scope > .submenu');
         out.push(c);
        if (ul) return ul;
       }
       }
     }
     }
     return null;
     return out;
   }
   }


   function isStageLabel(label) {
   function scoreContainer(container) {
     return /^stage\s+[1-4]$/i.test(label);
    var lis = childLis(container);
    if (!lis.length) return 0;
 
    var stageCount = 0;
    var miniCount = 0;
    var overviewCount = 0;
    var i;
 
    for (i = 0; i < lis.length; i++) {
      var label = norm(textOf(directLink(lis[i])));
      if (isStageLabel(label)) stageCount++;
      if (isMiniLabel(label)) miniCount++;
      if (label === 'overview') overviewCount++;
    }
 
    if (stageCount >= 4 && miniCount >= 8) {
      return (stageCount * 100) + miniCount + (overviewCount ? 10 : 0);
    }
     return 0;
  }
 
  function findStagesListContainer() {
    var candidates = document.querySelectorAll('ul, ol');
    var best = null;
    var bestScore = 0;
    var i;
 
    for (i = 0; i < candidates.length; i++) {
      var score = scoreContainer(candidates[i]);
      if (score > bestScore) {
        bestScore = score;
        best = candidates[i];
      }
    }
 
    return best;
   }
   }


   function isMiniLabel(label) {
   function makeToggle(stageLi, toggleBtn) {
     return /^mini\s+stage\s+\d+$/i.test(label);
     return function (ev) {
      ev.preventDefault();
      ev.stopPropagation();
      var open = stageLi.classList.toggle('open');
      toggleBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
      toggleBtn.textContent = open ? '▾' : '▸';
    };
   }
   }


   function applyNestedStages() {
   function applyNestedStages() {
     var ul = findStagesSystemList();
     var list = findStagesListContainer();
     if (!ul || ul.dataset.stagesNestedApplied === '1') return;
     if (!list || list.dataset.stagesNestedApplied === '1') return;


     var items = Array.prototype.slice.call(ul.children).filter(function (n) {
     var items = childLis(list);
      return n.tagName && n.tagName.toLowerCase() === 'li';
    });
     if (!items.length) return;
     if (!items.length) return;


Line 64: Line 121:
     var currentStageLi = null;
     var currentStageLi = null;
     var currentMiniUl = null;
     var currentMiniUl = null;
    var i;


     items.forEach(function (li) {
     for (i = 0; i < items.length; i++) {
       var a = li.querySelector(':scope > a');
       var li = items[i];
       var label = txt(a);
       var label = textOf(directLink(li));


       if (isStageLabel(label)) {
       if (isStageLabel(label)) {
         currentStageLi = li.cloneNode(true);
         currentStageLi = li.cloneNode(true);
         currentStageLi.classList.add('stages-inner-parent');
         currentStageLi.className = (currentStageLi.className ? currentStageLi.className + ' ' : '') + 'stages-inner-parent';


         currentMiniUl = document.createElement('ul');
         currentMiniUl = document.createElement('ul');
Line 81: Line 139:
         toggle.setAttribute('aria-expanded', 'false');
         toggle.setAttribute('aria-expanded', 'false');
         toggle.textContent = '▸';
         toggle.textContent = '▸';
         toggle.addEventListener('click', function (ev) {
         toggle.addEventListener('click', makeToggle(currentStageLi, toggle));
          ev.preventDefault();
          ev.stopPropagation();
          var open = currentStageLi.classList.toggle('open');
          toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
          toggle.textContent = open ? '▾' : '▸';
        });


         currentStageLi.appendChild(toggle);
         currentStageLi.appendChild(toggle);
         currentStageLi.appendChild(currentMiniUl);
         currentStageLi.appendChild(currentMiniUl);
         rebuilt.push(currentStageLi);
         rebuilt.push(currentStageLi);
         return;
         continue;
       }
       }


       if (isMiniLabel(label) && currentMiniUl) {
       if (isMiniLabel(label) && currentMiniUl) {
         currentMiniUl.appendChild(li.cloneNode(true));
         currentMiniUl.appendChild(li.cloneNode(true));
         return;
         continue;
       }
       }


Line 103: Line 155:
       currentMiniUl = null;
       currentMiniUl = null;
       rebuilt.push(li.cloneNode(true));
       rebuilt.push(li.cloneNode(true));
     });
     }


     ul.innerHTML = '';
     while (list.firstChild) {
     rebuilt.forEach(function (n) { ul.appendChild(n); });
      list.removeChild(list.firstChild);
     ul.dataset.stagesNestedApplied = '1';
     }
 
    for (i = 0; i < rebuilt.length; i++) {
      list.appendChild(rebuilt[i]);
    }
 
     list.dataset.stagesNestedApplied = '1';
  }
 
  function boot() {
    applyNestedStages();
    window.setTimeout(applyNestedStages, 350);
    window.setTimeout(applyNestedStages, 900);
    window.setTimeout(applyNestedStages, 1800);
   }
   }


   if (document.readyState === 'loading') {
   if (document.readyState === 'loading') {
     document.addEventListener('DOMContentLoaded', applyNestedStages);
     document.addEventListener('DOMContentLoaded', boot);
   } else {
   } else {
     applyNestedStages();
     boot();
   }
   }
})();
})();

Revision as of 08:56, 20 March 2026

/* Any JavaScript here will be loaded for all users on every page load. */
// Ensures class card images use the intended foreground image if data-src is present.
(function () {
  function applyDataSrc() {
    var images = document.querySelectorAll('.mw-card-image img[data-src]');
    for (var i = 0; i < images.length; i++) {
      var img = images[i];
      var dataSrc = img.getAttribute('data-src');
      if (dataSrc && img.getAttribute('src') !== dataSrc) {
        img.setAttribute('src', dataSrc);
      }
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', applyDataSrc);
  } else {
    applyDataSrc();
  }
})();
/* Update 042: robust nested Stage dropdown regrouping for varying sidebar DOMs */
(function () {
  function textOf(el) {
    return (el && el.textContent ? el.textContent : '').replace(/\s+/g, ' ').trim();
  }

  function norm(s) {
    return (s || '').replace(/\s+/g, ' ').trim().toLowerCase();
  }

  function isStageLabel(label) {
    return /^stage\s+[1-4]$/i.test(label);
  }

  function isMiniLabel(label) {
    return /^mini\s+stage\s+\d+$/i.test(label);
  }

  function directLink(li) {
    if (!li || !li.childNodes) return null;
    var i;
    for (i = 0; i < li.childNodes.length; i++) {
      var n = li.childNodes[i];
      if (n && n.nodeType === 1 && n.tagName && n.tagName.toLowerCase() === 'a') {
        return n;
      }
    }
    return li.querySelector ? li.querySelector('a') : null;
  }

  function childLis(container) {
    if (!container || !container.children) return [];
    var out = [];
    var i;
    for (i = 0; i < container.children.length; i++) {
      var c = container.children[i];
      if (c && c.tagName && c.tagName.toLowerCase() === 'li') {
        out.push(c);
      }
    }
    return out;
  }

  function scoreContainer(container) {
    var lis = childLis(container);
    if (!lis.length) return 0;

    var stageCount = 0;
    var miniCount = 0;
    var overviewCount = 0;
    var i;

    for (i = 0; i < lis.length; i++) {
      var label = norm(textOf(directLink(lis[i])));
      if (isStageLabel(label)) stageCount++;
      if (isMiniLabel(label)) miniCount++;
      if (label === 'overview') overviewCount++;
    }

    if (stageCount >= 4 && miniCount >= 8) {
      return (stageCount * 100) + miniCount + (overviewCount ? 10 : 0);
    }
    return 0;
  }

  function findStagesListContainer() {
    var candidates = document.querySelectorAll('ul, ol');
    var best = null;
    var bestScore = 0;
    var i;

    for (i = 0; i < candidates.length; i++) {
      var score = scoreContainer(candidates[i]);
      if (score > bestScore) {
        bestScore = score;
        best = candidates[i];
      }
    }

    return best;
  }

  function makeToggle(stageLi, toggleBtn) {
    return function (ev) {
      ev.preventDefault();
      ev.stopPropagation();
      var open = stageLi.classList.toggle('open');
      toggleBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
      toggleBtn.textContent = open ? '▾' : '▸';
    };
  }

  function applyNestedStages() {
    var list = findStagesListContainer();
    if (!list || list.dataset.stagesNestedApplied === '1') return;

    var items = childLis(list);
    if (!items.length) return;

    var rebuilt = [];
    var currentStageLi = null;
    var currentMiniUl = null;
    var i;

    for (i = 0; i < items.length; i++) {
      var li = items[i];
      var label = textOf(directLink(li));

      if (isStageLabel(label)) {
        currentStageLi = li.cloneNode(true);
        currentStageLi.className = (currentStageLi.className ? currentStageLi.className + ' ' : '') + 'stages-inner-parent';

        currentMiniUl = document.createElement('ul');
        currentMiniUl.className = 'stages-inner-submenu';

        var toggle = document.createElement('button');
        toggle.type = 'button';
        toggle.className = 'stages-inner-toggle';
        toggle.setAttribute('aria-expanded', 'false');
        toggle.textContent = '▸';
        toggle.addEventListener('click', makeToggle(currentStageLi, toggle));

        currentStageLi.appendChild(toggle);
        currentStageLi.appendChild(currentMiniUl);
        rebuilt.push(currentStageLi);
        continue;
      }

      if (isMiniLabel(label) && currentMiniUl) {
        currentMiniUl.appendChild(li.cloneNode(true));
        continue;
      }

      currentStageLi = null;
      currentMiniUl = null;
      rebuilt.push(li.cloneNode(true));
    }

    while (list.firstChild) {
      list.removeChild(list.firstChild);
    }

    for (i = 0; i < rebuilt.length; i++) {
      list.appendChild(rebuilt[i]);
    }

    list.dataset.stagesNestedApplied = '1';
  }

  function boot() {
    applyNestedStages();
    window.setTimeout(applyNestedStages, 350);
    window.setTimeout(applyNestedStages, 900);
    window.setTimeout(applyNestedStages, 1800);
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', boot);
  } else {
    boot();
  }
})();