Toggle menu
15
236
75
27.7K
Kenshi Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

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.
/*
 * From https://utg.miraheze.org/wiki/MediaWiki:ThemeToggle.js
 * This script adds a theme selector to the sidebar in the Citizen skin.
 */
(function () {
  const THEME_STORAGE_KEY = 'selectedTheme';

  // Creates the container for the theme selection menu
  function createThemeContainer() {
    const container = document.createElement('div');
    container.id = 'skin-client-prefs-theme-section';
    container.className = 'mw-portlet mw-portlet-js citizen-menu';
    container.innerHTML = `
      <div class="citizen-menu__heading">Accent color</div>
      <div class="citizen-menu__content">
        <ul class="citizen-menu__content-list">
          <li class="mw-list-item mw-list-item-js">
            <div><form id="theme-toggle-form"></form></div>
          </li>
        </ul>
      </div>
    `;
    return container;
  }

  // Ensures the theme section is present on the page, creating it if necessary
  function ensureThemeSection() {
    let container = document.getElementById('skin-client-prefs-theme-section');
    if (!container) {
      container = createThemeContainer();

      const skinThemeEl = document.querySelector('#skin-client-prefs-skin-theme');
      if (skinThemeEl && skinThemeEl.parentNode) {
        skinThemeEl.parentNode.insertBefore(container, skinThemeEl.nextSibling);
      } else {
        const observer = new MutationObserver((mutations, obs) => {
          const target = document.querySelector('#skin-client-prefs-skin-theme');
          if (target && target.parentNode) {
            target.parentNode.insertBefore(container, target.nextSibling);
            obs.disconnect();
          }
        });
        observer.observe(document.body, { childList: true, subtree: true });
        (document.querySelector('#citizen-preferences-content') || document.body).appendChild(container);
      }
    }
    return document.getElementById('theme-toggle-form');
  }

  // Loads a theme's CSS file by creating a <link> element in the head
  function loadThemeCss(className) {
    // DO NOTHING
  }

  // Removes CSS files of other themes to prevent conflicts
  function removeOldThemeCss(currentClass) {
    // DO NOTHING
  }

  // Applies the selected theme class to the <html> element
  function applyTheme(className) {
    document.documentElement.classList.forEach(cls => {
      if (cls.startsWith('theme-')) {
        document.documentElement.classList.remove(cls);
      }
    });
    if (className) {
      document.documentElement.classList.add(className);
      loadThemeCss(className);
      removeOldThemeCss(className);
    }
  }

  /**
   * Adds a new theme option to the selector menu.
   * @param {string} name - The display name of the theme (e.g., "Default").
   * @param {string} backgroundImage - Optional URL for a preview image.
   * @param {string} className - The CSS class for the theme (e.g., "theme-Default").
   */
  window.AddTheme = function (name, backgroundImage = '', className = '') {
    const form = ensureThemeSection();
    const themeClass = className || `theme-${name}`;
    const id = `theme-${name.toLowerCase().replace(/\s+/g, '-')}`;

    if (document.getElementById(id)) return; // Don't add if it already exists

    const wrapper = document.createElement('div');
    wrapper.className = 'citizen-client-prefs-radio';
    wrapper.innerHTML = `
      <input name="theme-toggle" id="${id}" type="radio" value="${themeClass}" class="citizen-client-prefs-radio__input">
      <span class="citizen-client-prefs-radio__icon"></span>
      <label for="${id}" class="citizen-client-prefs-radio__label" data-theme-class="${themeClass}">${name}</label>
    `;
    const input = wrapper.querySelector('input');

    // Event listener to apply theme on change
    input.addEventListener('change', function () {
      if (this.checked) {
        localStorage.setItem(THEME_STORAGE_KEY, themeClass); // Save selection
        applyTheme(themeClass);
      }
    });
    form.appendChild(wrapper);
  };

  // Initializes the available themes
  function initThemes() {
    //
    // === Theme Selection ===
    //
    // AddTheme(ThemeName, PreviewImageURL, CSSClassName)
    // - ThemeName: Name that appears in the menu.
    // - PreviewImageURL: Optional image for the button. Leave as '' for none.
    // - CSSClassName: Must match the class in your CSS file. Defaults to 'theme-ThemeName'.
    //
    AddTheme('Desert', '', 'theme-Default'); // Light Brown Mix
    AddTheme('Outlands', '', 'theme-Outlands'); // Steel+Rust
    AddTheme('Floodlands', '', 'theme-Floodlands'); // Blue+Grey
    AddTheme('Bonefields', '', 'theme-Bonefields'); // Off-White+Tan
  }

  // Add themes to the page
  initThemes();

  // On page load, apply the saved theme from localStorage
  $(document).ready(function(){
    let savedClass = localStorage.getItem(THEME_STORAGE_KEY);

    if (!savedClass) {
      savedClass = 'theme-Default'; // Default theme if none is saved
      localStorage.setItem(THEME_STORAGE_KEY, savedClass);
    }

    applyTheme(savedClass);
    const radio = document.querySelector(`input[name="theme-toggle"][value="${savedClass}"]`);
    if (radio) {
      radio.checked = true;
    }
  });
})();