MediaWiki:Gadget-skinTogglesNew.js

After saving, you may need to bypass your browser's cache to see the changes. For further information, see Wikipedia:Bypass your cache.

  • In most Windows and Linux browsers: Hold down Ctrl and press F5.
  • In Safari: Hold down ⇧ Shift and click the Reload button.
  • In Chrome and Firefox for Mac: Hold down both ⌘ Cmd+⇧ Shift and press R.
"use strict";

/**
 * Handles the full-width toggle, dark mode toggle, and other appearance-related
 * toggles on the page.
 * 
 * @author Gaz Lloyd
 * @author Jayden
 * 
 */
;
(function ($, mw, rs) {
  var DARK_COOKIE = 'darkmode',
    THEME_COOKIE = 'theme',
    FLOORNUMBER_LS = 'floornumber_display',
    theme = $.cookie('theme') !== null ? $.cookie('theme') : $.cookie(DARK_COOKIE) === 'true' ? 'dark' : 'light',
    fixedWidthEnabled = $.cookie('readermode') === 'true',
    currentFloornumber = '_auto',
    themeSwitch,
    floorSelect,
    floorSelectAuto,
    floorSelectUK,
    floorSelectUS,
    closeButton,
    themePortletLink,
    fixedWidthPortletLink,
    $content,
    userLocale = 'UK',
    flsetting,
    browserLocale,
    themePopup;
  var self = {
    init: function init() {
      // Add the theme selector
      self.createThemePortletLink();

      // Add the fixed-width toggle
      self.createFixedWidthPortletLink();

      // Handle the floor numbering modal
      $('.floor-convention').click(function (e) {
        e.preventDefault();
        if (!window.OOUIWindowManager || !window.OOUIWindowManager.hasWindow('floorNumber')) {
          mw.loader.using(['oojs-ui-core', 'oojs-ui-windows', 'oojs-ui-widgets']).then(self.createFloorNumberModal);
        } else {
          window.OOUIWindowManager.openWindow('floorNumber');
        }
      });

      // Perform skin overrides if required
      self.doFloorNumberOverrides();

      // Set the theme cookie
      if ($.cookie('theme') == null) {
        $.cookie(THEME_COOKIE, theme, {
          expires: 365,
          path: '/'
        });
      }
    },
    /**
     * Perform specific overrides to the skin based on the selected
     * floor number preference.
     */
    doFloorNumberOverrides: function doFloorNumberOverrides() {
      if (rs.hasLocalStorage()) {
        currentFloornumber = window.localStorage.getItem(FLOORNUMBER_LS);
        if (currentFloornumber == null) {
          currentFloornumber = '_auto';
        }
      }
      flsetting = currentFloornumber;
      if (window.navigator.languages && window.navigator.languages.length) {
        browserLocale = window.navigator.languages[0];
      } else {
        browserLocale = navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en';
      }
      switch (browserLocale) {
        // all langs in -US or -CA
        case 'en-US':
        case 'es-US':
        case 'en-CA':
        case 'fr-CA':
          userLocale = 'US';
          break;
      }
      if (currentFloornumber == '_auto') {
        flsetting = userLocale;
      }
      switch (flsetting) {
        case 'US':
          flsetting = 'floornumber-setting-us';
          break;
        case 'UK':
        default:
          flsetting = 'floornumber-setting-gb';
          break;
      }
      $('body').addClass(flsetting);
    },
    toggleFixedWidth: function toggleFixedWidth() {
      if (fixedWidthEnabled) {
        // Switch to full width
        $('body').removeClass('wgl-fixedWidth');
      } else {
        // Switch to fixed width
        mw.loader.load('wg.fixedwidth');
        $('body').addClass('wgl-fixedWidth');
      }
      fixedWidthEnabled = !fixedWidthEnabled;
      $.cookie('readermode', fixedWidthEnabled, {
        expires: 365,
        path: '/'
      });
    },
    /**
     * Adds fixed width portlet link to the page
     */
    createFixedWidthPortletLink: function createFixedWidthPortletLink() {
      fixedWidthPortletLink = mw.util.addPortletLink('p-personal', '', '', 'pt-fixed-width', 'Toggle fixed-width mode', null, $('#pt-userpage, #pt-anonuserpage'));
      $(fixedWidthPortletLink).find('a').addClass('oo-ui-icon-advanced').click(function (e) {
        e.preventDefault();
        self.toggleFixedWidth();
      });
    },
    /**
     * Adds the theme select portlet link to the page
     */
    createThemePortletLink: function createThemePortletLink() {
      themePortletLink = mw.util.addPortletLink('p-personal', '', '', 'pt-theme-toggles', 'Change theme', null, $('#pt-userpage, #pt-anonuserpage'));
      $(themePortletLink).find('a').addClass('oo-ui-icon-advanced').click(function (e) {
        e.preventDefault();
        if (!themePopup) {
          mw.loader.using(['oojs-ui-core', 'oojs-ui-windows', 'oojs-ui-widgets']).then(self.createThemePopup);
        } else {
          themePopup.toggle();
        }
      });
    },
    /**
     * Loads a theme by its name
     */
    loadTheme: function loadTheme(themeName) {
      var removeExistingTheme = function removeExistingTheme() {
        // Remove any existing theme class
        $('body').removeClass(function (i, className) {
          return (className.match(/(^|\s)wgl-theme-\S+/g) || []).join(' ');
        });
      };

      // Add new theme class
      if (themeName === 'light') {
        removeExistingTheme();
        $('body').addClass('wgl-theme-light');
      } else {
        mw.loader.using(['wgl.theme.' + themeName]).then(function () {
          removeExistingTheme();
          $('body').addClass('wgl-theme-' + themeName);
        });
      }
    },
    /**
     * Initialises the creation of the theme toggle widget
     */
    createThemeToggle: function createThemeToggle() {
      // Create the theme toggle
      themeSwitch = new OO.ui.ButtonSelectWidget({
        classes: ['appearance-buttons'],
        items: [new OO.ui.ButtonOptionWidget({
          classes: ['light-mode-button'],
          data: 'light',
          title: 'Light',
          framed: false,
          label: new OO.ui.HtmlSnippet('<div class="button-img"></div>')
        }), new OO.ui.ButtonOptionWidget({
          classes: ['dark-mode-button'],
          data: 'dark',
          title: 'Dark',
          framed: false,
          label: new OO.ui.HtmlSnippet('<div class="button-img"></div>')
        }), new OO.ui.ButtonOptionWidget({
          classes: ['brown-mode-button'],
          data: 'browntown',
          title: 'Browntown',
          framed: false,
          label: new OO.ui.HtmlSnippet('<div class="button-img"></div>')
        })]
      });

      // Set the toggle to whatever theme is currently active
      themeSwitch.selectItemByData(theme);
      themeSwitch.on('choose', function () {
        // Change the theme instantly without needing a refresh
        theme = themeSwitch.findSelectedItem().getData();
        $.cookie(THEME_COOKIE, theme, {
          expires: 365,
          path: '/'
        });
        self.loadTheme(theme);
      });
    },
    /**
     * Initialises the creation of the theme popup window, which appears
     * when the moon icon is clicked at the top right of the page.
     */
    createThemePopup: function createThemePopup() {
      self.createThemeToggle();

      // Create the popup
      themePopup = new OO.ui.PopupWidget({
        classes: ['wgl-theme-popup'],
        $content: themeSwitch.$element,
        $floatableContainer: $(themePortletLink),
        width: null,
        autoClose: true
      });
      themePopup.on('toggle', function (visible) {
        // When the popup is opened, change the moon icon to an X
        if (visible) {
          $(themePortletLink).find('a').addClass('wgl-theme-popup-opened');
        } else {
          $(themePortletLink).find('a').removeClass('wgl-theme-popup-opened');
        }
      });
      $(document.body).append(themePopup.$element);

      // Open the popup, since we'll have only created the popup if the
      // user tried to interact with it in the first place.
      themePopup.toggle(true);
    },
    /**
     * Initialises the creation of the gear modal, for other non-theme
     * related appearance settings.
     */

    createFloorNumberModal: function createFloorNumberModal() {
      floorSelectAuto = new OO.ui.RadioOptionWidget({
        data: '_auto',
        label: 'Auto-detect: ' + userLocale
      });
      floorSelectUK = new OO.ui.RadioOptionWidget({
        data: 'UK',
        label: 'UK'
      });
      floorSelectUS = new OO.ui.RadioOptionWidget({
        data: 'US',
        label: 'US'
      });
      floorSelect = new OO.ui.RadioSelectWidget({
        classes: ['floornumber-select'],
        items: [floorSelectAuto, floorSelectUK, floorSelectUS]
      });
      floorSelect.selectItemByData(currentFloornumber);
      floorSelectHelp = 'Adjust how floor numbers are displayed on the wiki - whether the numbering begins at 0 (ground) or 1.';
      if (!rs.hasLocalStorage()) {
        floorSelect.setDisabled(true);
        floorSelectHelp = 'This option requires local storage to be supported and enabled in your browser.';
      }
      floorSelectAuto.$element.attr('title', 'Automatically detect the type to use from your browser.');
      floorSelectUK.$element.attr('title', 'The numbering used in the UK, Europe, and many Commonwealth countries: entrance on the ground floor, then above that is 1st floor, 2nd floor, etc.');
      floorSelectUS.$element.attr('title', 'The numbering used in the US and Canada: entrance on the 1st floor, then above that is 2nd floor, 3rd floor, etc.');
      floorSelect.on('choose', function () {
        if (rs.hasLocalStorage()) {
          window.localStorage.setItem(FLOORNUMBER_LS, floorSelect.findSelectedItem().getData());
        }
      });
      closeButton = new OO.ui.ButtonInputWidget({
        label: 'Close',
        flags: 'destructive'
      });
      $content = $('<div>');
      $content.addClass('appearance-modal').append($('<div>').addClass('reader-mode').append(floorSelect.$element, $('<div>').addClass('setting-header floornumber-header').text('Floor numbering'), $('<p>').addClass('floornumber-desc').text(floorSelectHelp)), $('<div>').addClass('appearance-save').append($('<p>').addClass('save-button-desc').html('<a href="https://weirdgloop.org/privacy">Cookies</a> are used to personalise the wiki.'), $('<div>').addClass('save-button-container').append(closeButton.$element)));
      var initModal = function initModal(modal) {
        modal.$body.append($content);
        closeButton.on('click', function (modal) {
          window.OOUIWindowManager.closeWindow(modal);
        }, [modal]);
      };
      rs.createOOUIWindow('floorNumber', 'Floor numbering', {
        size: 'large',
        classes: ['rsw-skin-toggle-popup']
      }, initModal, true, true);
    }
  };
  mw.loader.using(['ext.gadget.rsw-util'], function () {
    $(self.init);
  });
})(jQuery, mediaWiki, rswiki);