MediaWiki:Gadget-skinTogglesNew.js

This is an old revision of this page, as edited by Alex (talk | contribs) at 01:43, 13 October 2024 (Created page with "→‎* * 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', currentFloornumb..."). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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.
/**
 * 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 () {
			// 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() {
			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 () {
			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() {
			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() {
			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(themeName) {
			var removeExistingTheme = function () {
				// 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() {
			// 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() {
			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() {
			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 (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));