MediaWiki:ShowFirstTabs.js

From CoraTO Wiki - Official Wiki
Revision as of 02:35, 17 December 2025 by Noorisei (talk | contribs) (Created page with "* * MediaWiki Tab Navigation Module * Extracted from Common copy.js for modularity and customization * Handles tab switching functionality with smooth scrolling support * Enhanced to work with both MediaWiki tabs and nested tabs: (function() { 'use strict'; const CONFIG = { SELECTORS: { TAB_CONTENT: '.tab-content', NAV_TAB: '.nav-tab, .nav-tab-fgod', NESTED_TAB: '.nested-tab', NESTED_CONTENT: '.nested-content' }, CLASSES...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
 * MediaWiki Tab Navigation Module
 * Extracted from Common copy.js for modularity and customization
 * Handles tab switching functionality with smooth scrolling support
 * Enhanced to work with both MediaWiki tabs and nested tabs
 */

(function() {
  'use strict';

  const CONFIG = {
    SELECTORS: {
      TAB_CONTENT: '.tab-content',
      NAV_TAB: '.nav-tab, .nav-tab-fgod',
      NESTED_TAB: '.nested-tab',
      NESTED_CONTENT: '.nested-content'
    },
    CLASSES: {
      ACTIVE: 'active'
    },
    DELAYS: {
      SCROLL_DELAY: 100
    }
  };

  function safeGetElementById(id) {
    try { return document.getElementById(id); } catch (e) { return null; }
  }
  function safeQuerySelectorAll(selector, context = document) {
    try { return context.querySelectorAll(selector); } catch (e) { return []; }
  }
  function safeQuerySelector(selector, context = document) {
    try { return context.querySelector(selector); } catch (e) { return null; }
  }

  const TabNavigation = {
    showTab: function(tabId, tabElement) {
      if (!tabId) return;

      const allNested = document.querySelectorAll(CONFIG.SELECTORS.NESTED_CONTENT);
      allNested.forEach(c => c.classList.remove(CONFIG.CLASSES.ACTIVE));

      const contents = safeQuerySelectorAll(CONFIG.SELECTORS.TAB_CONTENT);
      contents.forEach(c => c.classList.remove(CONFIG.CLASSES.ACTIVE));

      const tabs = safeQuerySelectorAll(CONFIG.SELECTORS.NAV_TAB);
      tabs.forEach(t => t.classList.remove(CONFIG.CLASSES.ACTIVE));

      const target = safeGetElementById(tabId);
      if (target) {
        target.classList.add(CONFIG.CLASSES.ACTIVE);

        setTimeout(() => {
          const first = target.querySelector(CONFIG.SELECTORS.NESTED_TAB + '[data-tab]');
          if (first) {
            const nid = first.getAttribute('data-tab');
            if (nid) TabNavigation.showNestedTab(nid, first);
          }
        }, 50);
      }

      if (tabElement) tabElement.classList.add(CONFIG.CLASSES.ACTIVE);
    },

    showNestedTab: function(tabId, tabElement) {
      if (!tabId) return;
      const container = tabElement
        ? (tabElement.closest('.nested-container, .token-card')
            || tabElement.closest('.tokens-section')
            || tabElement.closest('.tab-content')
            || document)
        : document;

      const nestedContents = container.querySelectorAll(CONFIG.SELECTORS.NESTED_CONTENT);
      nestedContents.forEach(c => c.classList.remove(CONFIG.CLASSES.ACTIVE));

      const nestedTabs = container.querySelectorAll(CONFIG.SELECTORS.NESTED_TAB);
      nestedTabs.forEach(t => t.classList.remove(CONFIG.CLASSES.ACTIVE));

      let target = null;
      if (container && container.querySelector) target = container.querySelector('#' + tabId);
      if (!target) target = safeGetElementById(tabId);
      if (target) target.classList.add(CONFIG.CLASSES.ACTIVE);

      if (tabElement) tabElement.classList.add(CONFIG.CLASSES.ACTIVE);
    },

    handleTabClick: function(event) {
      const tab = event.target.closest('.nav-tab[data-tab], .nav-tab-fgod[data-tab]');
      if (!tab) return;
      event.preventDefault();
      const targetId = tab.getAttribute('data-tab');
      if (targetId) TabNavigation.showTab(targetId, tab);
    },

    handleNestedTabClick: function(event) {
      const nestedTab = event.target.closest('.nested-tab[data-tab]');
      if (!nestedTab) return;
      event.preventDefault();
      const targetId = nestedTab.getAttribute('data-tab');
      if (targetId) TabNavigation.showNestedTab(targetId, nestedTab);
    },

    handleSpecialTabNavigation: function(event) {
      const trigger = event.target.closest('[data-tab-trigger]');
      if (!trigger) return;
      event.preventDefault();
      const tabData = trigger.getAttribute('data-tab-trigger');
      const buttonId = trigger.getAttribute('data-tab-button');
      const href = trigger.getAttribute('href');
      const scrollToAttr = trigger.getAttribute('data-scroll-to');
      let scrollTargetSelector = null;
      if (scrollToAttr && scrollToAttr.trim()) scrollTargetSelector = '#' + scrollToAttr.replace(/^#/, '');
      else if (href && href.charAt(0) === '#') scrollTargetSelector = href;
      if (tabData && buttonId) {
        const btn = safeGetElementById(buttonId);
        if (btn) {
          TabNavigation.showTab(tabData, btn);
          if (scrollTargetSelector) {
            const target = safeQuerySelector(scrollTargetSelector);
            if (target) setTimeout(() => target.scrollIntoView({ behavior: 'smooth' }), CONFIG.DELAYS.SCROLL_DELAY);
          }
        }
      }
    },

    init: function() {
      document.addEventListener('click', this.handleTabClick, false);
      document.addEventListener('click', this.handleNestedTabClick, false);
      document.addEventListener('click', this.handleSpecialTabNavigation, false);
      window.showTab = this.showTab;
    }
  };

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