MediaWiki:Gadget-skinTogglesNew.js

From EverVoid Wiki
Revision as of 11:49, 28 December 2023 by Carmin (talk | contribs) (New updated for 139.6)
(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)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * Toggles for various appearance-related cookies, including the current theme.
 * 
 * @author Gaz Lloyd
 * @author Jayden
 * 
 */
;(function($, mw, rs){
	var DARK_COOKIE = 'darkmode',
		STICKY_HEADER_COOKIE = 'stickyheader',
		THEME_COOKIE = 'theme',
		FLOORNUMBER_LS = 'floornumber_display',
		theme = ($.cookie('theme') !== null) ? $.cookie('theme') : (($.cookie(DARK_COOKIE) === 'true') ? 'dark' : 'light'),
		currentSticky = $.cookie(STICKY_HEADER_COOKIE) === 'true',
		currentFloornumber = '_auto',
		themeSwitch,
		stickySwitch,
		floorSelect,
		floorSelectAuto,
		floorSelectUK,
		floorSelectUS,
		closeButton,
		themePortletLink,
		$content,
		userLocale = 'UK',
		flsetting,
		browserLocale,
		themePopup;

	var self = {
		init: function () {
			// Add the theme selector
			self.createThemePortletLink();
			
			// Add the appearance settings button
			self.createSettingsPortletLink();
			
			// Perform skin overrides if required
			self.doFloorNumberOverrides();
			
			if (currentSticky) self.doStickyHeaderOverrides();
			
			// Transition to the theme cookie
			if ( $.cookie('theme') == null ) {
				$.cookie(THEME_COOKIE, theme, {expires: 365, path: '/'});
			}
	
		},
	
		/**
	
		 * Perform specific overrides to the skin if the user is currently
	
		 * using the sticky header option.
	
		 */
	
		doStickyHeaderOverrides: function() {
			$('body').addClass('wgl-stickyheader');
			function onScroll() {
	
				var personal = $('#p-personal');
	
				var targetEle = document.getElementById("mw-head");
	
				var head = $('#mw-head');
	
				if (mw.config.get('wgAction') === 'edit' || window.location.search.includes('veaction')) {
	
					// We're on an edit page, do nothing and reset all the stuff
	
					if (personal.is(":hidden")) {
	
						personal.show();
	
						head.removeClass('sticky-hidden');
	
					}
	
				} else {
	
					if (window.scrollY > (targetEle.offsetTop + targetEle.offsetHeight)) {
	
						if (personal.is(":visible")) {
	
							personal.hide();
	
							head.addClass('sticky-hidden');
	
						}
	
					} else {
	
						if (personal.is(":hidden")) {
	
							personal.show();
	
							head.removeClass('sticky-hidden');
	
						}
	
					}
	
				}
	
			}
	
			
	
			onScroll();
	
			$(window).scroll(onScroll);
	
			
	
			// hidden by css when sticky-hidden is not on
	
			if (mw.config.get('wgIsMainPage') !== true) {
	
				mw.util.addPortletLink('p-namespaces', '/', 'Main Page', 'ca-nstab-mainpage', 'Visit the main page');
			}
		},
		
		/**
		 * 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);
		},

		/**
		 * 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();
				}
			});
		},
		
		/**
		 * Adds the appearance settings portlet link to the page
		 */
		createSettingsPortletLink: function() {
			settingsPortletLink = mw.util.addPortletLink('p-personal', '', '', 'pt-skin-toggles', 'Appearance settings', null, $('#pt-userpage, #pt-anonuserpage'));
			$(settingsPortletLink).find('a').addClass('oo-ui-icon-advanced').add('.floor-convention').click(function(e) {
				e.preventDefault();
				if (!window.OOUIWindowManager || !window.OOUIWindowManager.hasWindow('skin')) {
					mw.loader.using(['oojs-ui-core','oojs-ui-windows','oojs-ui-widgets']).then(self.createAppearanceModal);
				} else {
					window.OOUIWindowManager.openWindow('skin');
				}
			});
		},
		
		/**
		 * 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>'),
					}),
				]
			});

			// 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.
		 */
		 
		createAppearanceModal: function() {
			stickySwitch = new OO.ui.ToggleSwitchWidget({
	
				value: currentSticky,
	
				classes: ['reader-toggle'],
	
				align: 'right'
	
			});
			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 = 'Changes 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());
				}
			});
	
	
			stickySwitch.on('change', function() {
	
				$.cookie(STICKY_HEADER_COOKIE, stickySwitch.getValue(), {expires: 365, path: '/'});
			})
			
			closeButton = new OO.ui.ButtonInputWidget({ label: 'Close', flags: 'destructive'});

			$content = $('<div>');
			$content
				.addClass('appearance-modal')
				.append(
					$('<div>')
						.addClass('reader-mode')
						.append(
							stickySwitch.$element,
							$('<div>').addClass('setting-header sticky-header-header').text('Sticky header'),
							$('<p>').addClass('sticky-header-desc').text('Pin the navigation bar and search to the top when scrolling.'),
							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('We use <a href="https://weirdgloop.org/privacy">cookies</a> 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('skin', 'Appearance settings', {size: 'large', classes: ['rsw-skin-toggle-popup']}, initModal, true, true).then(function () {
	
				window.OOUIWindowManager.on('closing', function (win, closed, data) {
	
					if (win.$element.hasClass('rsw-skin-toggle-popup')) {
	
						// If the window that closed is this one, finalise some stuff (mostly reader mode etc).
	
						var requireReload = false;
	
							
	
						if ((stickySwitch.getValue() !== currentSticky)) {
	
							requireReload = true;
	
						}
	
						
	
						if (requireReload === true) {
	
							window.location.reload(true);
	
							return;
	
						}
	
					}
	
				})
	
			})
		}
	}

	mw.loader.using(['ext.gadget.rsw-util'], function () {
		$(self.init);
	})

}(jQuery, mediaWiki, rswiki));