<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://hokutonoken.wiki/en/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-dark-mode-toggle.js</id>
	<title>MediaWiki:Gadget-dark-mode-toggle.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://hokutonoken.wiki/en/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-dark-mode-toggle.js"/>
	<link rel="alternate" type="text/html" href="https://hokutonoken.wiki/en/index.php?title=MediaWiki:Gadget-dark-mode-toggle.js&amp;action=history"/>
	<updated>2026-04-29T22:35:38Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://hokutonoken.wiki/en/index.php?title=MediaWiki:Gadget-dark-mode-toggle.js&amp;diff=32860&amp;oldid=prev</id>
		<title>Madness: Created page with &quot;/**  * Enables or disables the dark-mode gadget.  *  * Authors: User:SD0001, User:Nardog  */  // &#039;Dark mode&#039; and &#039;Light mode&#039; messages must match the ::before content in // MediaWiki:Gadget-dark-mode-toggle-pagestyles.css and MediaWiki:Gadget-dark-mode.css, respectively. // Don&#039;t overwrite existing messages, if already set on a foreign wiki prior to loading this file if (!mw.messages.get(&#039;darkmode-turn-on-label&#039;)) { 	mw.messages.set({ 		&#039;darkmode-turn-on-...&quot;</title>
		<link rel="alternate" type="text/html" href="https://hokutonoken.wiki/en/index.php?title=MediaWiki:Gadget-dark-mode-toggle.js&amp;diff=32860&amp;oldid=prev"/>
		<updated>2024-02-07T16:53:03Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&lt;span class=&quot;autocomment&quot;&gt;*  * Enables or disables the dark-mode gadget.  *  * Authors: &lt;a href=&quot;/en/User:SD0001&quot; title=&quot;User:SD0001&quot;&gt;User:SD0001&lt;/a&gt;, &lt;a href=&quot;/en/User:Nardog&quot; title=&quot;User:Nardog&quot;&gt;User:Nardog&lt;/a&gt;: &lt;/span&gt;  // &amp;#039;Dark mode&amp;#039; and &amp;#039;Light mode&amp;#039; messages must match the ::before content in // &lt;a href=&quot;/en/MediaWiki:Gadget-dark-mode-toggle-pagestyles.css&quot; title=&quot;MediaWiki:Gadget-dark-mode-toggle-pagestyles.css&quot;&gt;MediaWiki:Gadget-dark-mode-toggle-pagestyles.css&lt;/a&gt; and &lt;a href=&quot;/en/index.php?title=MediaWiki:Gadget-dark-mode.css&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;MediaWiki:Gadget-dark-mode.css (page does not exist)&quot;&gt;MediaWiki:Gadget-dark-mode.css&lt;/a&gt;, respectively. // Don&amp;#039;t overwrite existing messages, if already set on a foreign wiki prior to loading this file if (!mw.messages.get(&amp;#039;darkmode-turn-on-label&amp;#039;)) { 	mw.messages.set({ 		&amp;#039;darkmode-turn-on-...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/**&lt;br /&gt;
 * Enables or disables the dark-mode gadget.&lt;br /&gt;
 *&lt;br /&gt;
 * Authors: [[User:SD0001]], [[User:Nardog]]&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
// &amp;#039;Dark mode&amp;#039; and &amp;#039;Light mode&amp;#039; messages must match the ::before content in&lt;br /&gt;
// [[MediaWiki:Gadget-dark-mode-toggle-pagestyles.css]] and [[MediaWiki:Gadget-dark-mode.css]], respectively.&lt;br /&gt;
// Don&amp;#039;t overwrite existing messages, if already set on a foreign wiki prior to loading this file&lt;br /&gt;
if (!mw.messages.get(&amp;#039;darkmode-turn-on-label&amp;#039;)) {&lt;br /&gt;
	mw.messages.set({&lt;br /&gt;
		&amp;#039;darkmode-turn-on-label&amp;#039;: &amp;#039;Dark mode&amp;#039;,&lt;br /&gt;
		&amp;#039;darkmode-turn-on-tooltip&amp;#039;: &amp;#039;Turn dark mode on&amp;#039;,&lt;br /&gt;
		&amp;#039;darkmode-turn-off-label&amp;#039;: &amp;#039;Light mode&amp;#039;,&lt;br /&gt;
		&amp;#039;darkmode-turn-off-tooltip&amp;#039;: &amp;#039;Turn dark mode off&amp;#039;,&lt;br /&gt;
	});&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var isOn = mw.loader.getState(&amp;#039;ext.gadget.dark-mode&amp;#039;) === &amp;#039;ready&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
var broadcastChannel = new BroadcastChannel(&amp;#039;gadget-dark-mode&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
function setThemeColor() {&lt;br /&gt;
	// Update the theme-color used by some browsers for coloration of the tab headers and surrounding UI&lt;br /&gt;
	$(&amp;#039;meta[name=&amp;quot;theme-color&amp;quot;]&amp;#039;).attr(&amp;#039;content&amp;#039;, isOn ? &amp;#039;#000000&amp;#039; : &amp;#039;#eaecf0&amp;#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function setHtmlClass() {&lt;br /&gt;
	// CSS class for externally styling elements in dark mode via TemplateStyles (or CSS from other gadgets or common.css)&lt;br /&gt;
	// A brief flash of the original styles will occur, so this is only suitable for style changes for which flashes are tolerable.&lt;br /&gt;
	// For others, update Gadget-dark-mode.css directly which is loaded without FOUCs&lt;br /&gt;
	$(document.documentElement).toggleClass(&amp;#039;client-dark-mode&amp;#039;, isOn);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function vectorStickyCallback() {&lt;br /&gt;
	mw.hook(&amp;#039;vector.page_title_scroll&amp;#039;).remove(vectorStickyCallback);&lt;br /&gt;
	if (document.getElementById(&amp;#039;pt-darkmode-sticky-header&amp;#039;)) return;&lt;br /&gt;
	makePortletLink(&amp;#039;p-personal-sticky-header&amp;#039;, &amp;#039;pt-darkmode-sticky-header&amp;#039;, &amp;#039;#pt-watchlist-sticky-header&amp;#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function addPortlets() {&lt;br /&gt;
	makePortletLink(&amp;#039;p-personal&amp;#039;, &amp;#039;pt-darkmode&amp;#039;, &amp;#039;#pt-watchlist&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
	if (mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;vector-2022&amp;#039;) {&lt;br /&gt;
		mw.hook(&amp;#039;vector.page_title_scroll&amp;#039;).add(vectorStickyCallback);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function getMsg(suffix) {&lt;br /&gt;
	var key = &amp;#039;darkmode-turn-&amp;#039; + (isOn ? &amp;#039;off&amp;#039; : &amp;#039;on&amp;#039;) + &amp;#039;-&amp;#039; + suffix;&lt;br /&gt;
	return mw.msg(key);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function makePortletLink(portletId, portletLinkId, nextnode) {&lt;br /&gt;
	var label = getMsg(&amp;#039;label&amp;#039;);&lt;br /&gt;
	var tooltip = getMsg(&amp;#039;tooltip&amp;#039;);&lt;br /&gt;
	$(mw.util.addPortletLink(portletId, &amp;#039;#&amp;#039;, label, portletLinkId, tooltip, &amp;#039;&amp;#039;, nextnode))&lt;br /&gt;
		.children().on(&amp;#039;click&amp;#039;, function (e) {&lt;br /&gt;
			e.preventDefault();&lt;br /&gt;
			toggleMode();&lt;br /&gt;
		});&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function togglePortlets() {&lt;br /&gt;
	var labelSelector;&lt;br /&gt;
	switch (mw.config.get(&amp;#039;skin&amp;#039;)) {&lt;br /&gt;
		case &amp;#039;vector&amp;#039;:&lt;br /&gt;
		case &amp;#039;vector-2022&amp;#039;:&lt;br /&gt;
		case &amp;#039;minerva&amp;#039;:&lt;br /&gt;
			labelSelector = &amp;#039;#pt-darkmode span:not(:empty), #pt-darkmode-sticky-header span:not(:empty)&amp;#039;;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			labelSelector = &amp;#039;#pt-darkmode a&amp;#039;;&lt;br /&gt;
	}&lt;br /&gt;
	$(labelSelector).text(getMsg(&amp;#039;label&amp;#039;));&lt;br /&gt;
	$(&amp;#039;#pt-darkmode a, #pt-darkmode-sticky-header a&amp;#039;)&lt;br /&gt;
		.attr(&amp;#039;title&amp;#039;, getMsg(&amp;#039;tooltip&amp;#039;));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function actuallyToggleDarkMode() {&lt;br /&gt;
	// Modify the &amp;lt;link&amp;gt; element on the page to include/exclude dark-mode styles&lt;br /&gt;
	// We can&amp;#039;t use mw.loader as it doesn&amp;#039;t work both ways (see talk page)&lt;br /&gt;
	var scriptPath = mw.util.wikiScript(&amp;#039;load&amp;#039;);&lt;br /&gt;
	var $gadgetsLink = $(&amp;#039;link[rel=&amp;quot;stylesheet&amp;quot;][href^=&amp;quot;&amp;#039; + scriptPath + &amp;#039;?&amp;quot;][href*=&amp;quot;ext.gadget.&amp;quot;]&amp;#039;);&lt;br /&gt;
	if ($gadgetsLink.length) {&lt;br /&gt;
		var uri = new mw.Uri($gadgetsLink.prop(&amp;#039;href&amp;#039;));&lt;br /&gt;
		if (isOn) {&lt;br /&gt;
			uri.query.modules += &amp;#039;,dark-mode&amp;#039;;&lt;br /&gt;
		} else {&lt;br /&gt;
			if (uri.query.modules === &amp;#039;ext.gadget.dark-mode&amp;#039;) {&lt;br /&gt;
				// dark-mode is the only module in this link&lt;br /&gt;
				$gadgetsLink.remove();&lt;br /&gt;
				return;&lt;br /&gt;
			}&lt;br /&gt;
			uri.query.modules = uri.query.modules&lt;br /&gt;
				.replace(&amp;#039;ext.gadget.dark-mode,&amp;#039;, &amp;#039;ext.gadget.&amp;#039;) // dark-mode is first in the gadget list&lt;br /&gt;
				.replace(/,dark-mode(,|$)/, &amp;#039;$1&amp;#039;); // dark-mode is in middle or end of the list&lt;br /&gt;
		}&lt;br /&gt;
		$gadgetsLink.prop(&amp;#039;href&amp;#039;, uri.getRelativePath());&lt;br /&gt;
	} else {&lt;br /&gt;
		// No gadget-containing styles are enabled&lt;br /&gt;
		$(&amp;#039;&amp;lt;link&amp;gt;&amp;#039;).attr({&lt;br /&gt;
			rel: &amp;#039;stylesheet&amp;#039;,&lt;br /&gt;
			href: scriptPath + &amp;#039;?lang=&amp;#039; + mw.config.get(&amp;#039;wgUserLanguage&amp;#039;) +&lt;br /&gt;
				&amp;#039;&amp;amp;modules=ext.gadget.dark-mode&amp;amp;only=styles&amp;amp;skin=&amp;#039; + mw.config.get(&amp;#039;skin&amp;#039;)&lt;br /&gt;
		}).appendTo(document.head);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function savePreference() {&lt;br /&gt;
	new mw.Api().saveOption(&amp;#039;gadget-dark-mode&amp;#039;, isOn ? &amp;#039;1&amp;#039; : &amp;#039;0&amp;#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function savePreferenceLocally() {&lt;br /&gt;
	mw.user.options.set(&amp;#039;gadget-dark-mode&amp;#039;, Number(isOn));&lt;br /&gt;
&lt;br /&gt;
	// In case the user navigates to another page too quickly&lt;br /&gt;
	mw.storage.session.set(&amp;#039;dark-mode-toggled&amp;#039;, isOn ? &amp;#039;1&amp;#039; : &amp;#039;0&amp;#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function notifyOtherTabs() {&lt;br /&gt;
	// Broadcast state change to other tabs&lt;br /&gt;
	broadcastChannel.postMessage(isOn);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function toggleMode(offline) {&lt;br /&gt;
	isOn = !isOn;&lt;br /&gt;
	if (!offline) {&lt;br /&gt;
		savePreference();&lt;br /&gt;
		notifyOtherTabs();&lt;br /&gt;
	}&lt;br /&gt;
	setHtmlClass();&lt;br /&gt;
	setThemeColor();&lt;br /&gt;
	savePreferenceLocally();&lt;br /&gt;
	togglePortlets();&lt;br /&gt;
	actuallyToggleDarkMode();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function toggleBasedOnSystemColourScheme() {&lt;br /&gt;
	var systemSchemeNow = matchMedia(&amp;#039;(prefers-color-scheme: dark)&amp;#039;).matches;&lt;br /&gt;
	var systemSchemeLast = mw.storage.get(&amp;#039;dark-mode-system-scheme&amp;#039;) === &amp;#039;1&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
	if (systemSchemeNow !== systemSchemeLast) {&lt;br /&gt;
		if (systemSchemeNow !== isOn) {&lt;br /&gt;
			toggleMode();&lt;br /&gt;
		}&lt;br /&gt;
		mw.requestIdleCallback(function () {&lt;br /&gt;
			mw.storage.set(&amp;#039;dark-mode-system-scheme&amp;#039;, systemSchemeNow ? &amp;#039;1&amp;#039; : &amp;#039;0&amp;#039;);&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$.when($.ready, mw.loader.using([&amp;#039;mediawiki.util&amp;#039;, &amp;#039;mediawiki.api&amp;#039;, &amp;#039;mediawiki.Uri&amp;#039;, &amp;#039;mediawiki.storage&amp;#039;])).then(function () {&lt;br /&gt;
	setHtmlClass();&lt;br /&gt;
	setThemeColor();&lt;br /&gt;
	addPortlets();&lt;br /&gt;
&lt;br /&gt;
	// Recover state if the navigation was too quick&lt;br /&gt;
	var storageState = mw.storage.session.get(&amp;#039;dark-mode-toggled&amp;#039;);&lt;br /&gt;
	if (storageState &amp;amp;&amp;amp; Number(storageState) !== Number(isOn)) {&lt;br /&gt;
		toggleMode(true);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Listen to dark mode state change made on other tabs&lt;br /&gt;
	broadcastChannel.onmessage = function (msg) {&lt;br /&gt;
		if (msg.data !== isOn) {&lt;br /&gt;
			toggleMode(true);&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	if (window.wpDarkModeAutoToggle) {&lt;br /&gt;
		toggleBasedOnSystemColourScheme();&lt;br /&gt;
&lt;br /&gt;
		// If system colour scheme changes while user is viewing, toggle immediately&lt;br /&gt;
		var mediaQuery = matchMedia(&amp;#039;(prefers-color-scheme: dark)&amp;#039;);&lt;br /&gt;
		if (mediaQuery.addEventListener) {&lt;br /&gt;
			mediaQuery.addEventListener(&amp;#039;change&amp;#039;, toggleBasedOnSystemColourScheme);&lt;br /&gt;
		} else if (mediaQuery.addListener) { // Safari 13 and older&lt;br /&gt;
			mediaQuery.addListener(toggleBasedOnSystemColourScheme);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Madness</name></author>
	</entry>
</feed>