Welcome to Wargaming.net Wiki!
Variants

MediaWiki:Common.js

Jump to: navigation, search
Fix: run rel/target fix immediately if DOMContentLoaded already fired
No edit summary
Line 212: Line 212:
function fixLink() {
function fixLink() {
var link = document.querySelector( '#n-Request-Edit a' );
var link = document.querySelector( '#n-Request-Edit a' );
if ( link ) {
if ( !link ) { return; }
link.setAttribute( 'target', '_blank' );
link.setAttribute( 'target', '_blank' );
link.setAttribute( 'rel', 'noopener noreferrer' );
var relParts = ( link.getAttribute( 'rel' ) || '' ).split( /\s+/ ).filter( Boolean );
}
if ( relParts.indexOf( 'noopener' ) === -1 ) { relParts.push( 'noopener' ); }
link.setAttribute( 'rel', relParts.join( ' ' ) );
}
}
if ( document.readyState === 'loading' ) {
if ( document.readyState === 'loading' ) {
Line 222: Line 223:
fixLink();
fixLink();
}
}
// Re-apply shortly after load in case other scripts modify the link's attributes afterward.
setTimeout( fixLink, 500 );
} )();
} )();

Revision as of 19:30, 13 July 2026

/* Any JavaScript here will be loaded for all users on every page load. */

/* ============================================================
 Light / Dark Mode Toggle
 Adds a fixed pill (top-right) that switches between the
 current dark theme and the live-wiki light theme.
 Styled to match the Wargaming sign-in page mode-switcher.
 Preference is remembered via localStorage.
============================================================ */
( function () {
'use strict';

var STORAGE_KEY = 'wows-theme-mode';
var STYLE_ID    = 'wows-light-mode-styles';

var LIGHT_CSS = [
  'html, body, .b-main {',
  '  background-color: transparent !important;',
  '  background-image: url("https://wiki.wargaming.net/skins/globalwiki/images/bg.jpg?2026-01-22T09:18:20Z") !important;',
  '  background-repeat: repeat !important;',
  '  color: rgb(0, 0, 0) !important;',
  '}',
  '#firstHeading { color: rgb(56, 56, 56) !important; }',
  '.b-game-info > b, .b-game-info .b-heading2 { color: rgb(56, 56, 56) !important; }',
  '.mw-parser-output, .mw-body-content, #mw-content-text { color: rgb(0, 0, 0) !important; }',
  '#mw-panel, #mw-panel a, .b-sidebar, .b-sidebar a, .b-left-menu_item, .b-portlet-link { color: rgb(67, 99, 115) !important; }',
  '#mw-head, #mw-head a, .b-header a { color: rgb(56, 56, 56) !important; }',
  '.b-tabs-wrp { border-color: initial !important; }',
  'table, .wikitable, .b-infobox { background-color: transparent !important; color: rgb(0,0,0) !important; }',
  'th { background-color: rgba(200,220,235,0.9) !important; color: rgb(0,0,0) !important; }',
  'td { color: rgb(0,0,0) !important; }',
  '.mw-body, #content { background-color: transparent !important; }',
  '.b-sidebar_title, #footer, .b-footer { color: rgb(56, 56, 56) !important; }',
  '.b-heading1, .b-heading2, .b-heading3, h1, h2, h3, h4, h5, h6, .mw-parser-output h1, .mw-parser-output h2, .mw-parser-output h3, .mw-parser-output h4, .mw-parser-output h5, .mw-parser-output h6 { color: rgb(56, 56, 56) !important; }',
  '.b-search-input, #searchInput { background-color: rgb(245,245,245) !important; color: rgb(0,0,0) !important; }',
  '.b-game-info { background-color: transparent !important; color: rgb(0,0,0) !important; border-color: transparent !important; }',
  '.b-description.gw-frame-1, .mw-parser-output .gw-frame-1 { background-color: rgba(255,255,255,0.6) !important; border-color: rgba(212,175,55,0.4) !important; box-shadow: none !important; color: rgb(0,0,0) !important; }',
  '.b-description.gw-frame-1 a, .mw-parser-output .gw-frame-1 a { color: rgb(2,93,177) !important; }'
].join( '\n' );

function applyLight() {
  if ( document.getElementById( STYLE_ID ) ) { return; }
  var s = document.createElement( 'style' );
  s.id          = STYLE_ID;
  s.textContent = LIGHT_CSS;
  document.head.appendChild( s );
}

function applyDark() {
  var s = document.getElementById( STYLE_ID );
  if ( s ) { s.remove(); }
}

var DAY_SVG   = 'https://wargaming.net/id/static/2026.4.0/wgnet/img/mode-switcher/day.svg';
var NIGHT_SVG = 'https://wargaming.net/id/static/2026.4.0/wgnet/img/mode-switcher/night.svg';

function buildButton() {
  var isDark = ( localStorage.getItem( STORAGE_KEY ) !== 'light' );

  if ( !isDark ) { applyLight(); }

  var wrap = document.createElement( 'div' );
  wrap.id = 'wows-theme-toggle';
  wrap.style.cssText = [
    'position:fixed', 'top:14px', 'right:16px', 'z-index:9999',
    'background:rgb(30,30,30)', 'border:1px solid rgb(52,52,52)',
    'border-radius:8px', 'padding:3px', 'display:flex', 'gap:4px',
    'align-items:center'
  ].join( ';' );

  var BTN_BASE = [
    'width:30px', 'height:24px', 'border:none', 'cursor:pointer', 'padding:0',
    'border-radius:5px', 'background-color:transparent',
    'background-repeat:no-repeat', 'background-position:center',
    'background-size:20px', 'transition:opacity 0.2s'
  ].join( ';' );

  var btnLight = document.createElement( 'button' );
  btnLight.title = 'Light mode';
  btnLight.style.cssText = BTN_BASE + ';background-image:url("' + DAY_SVG + '")';
  btnLight.style.opacity = isDark ? '0.5' : '1';

  var btnDark = document.createElement( 'button' );
  btnDark.title = 'Dark mode';
  btnDark.style.cssText = BTN_BASE + ';background-image:url("' + NIGHT_SVG + '")';
  btnDark.style.opacity = isDark ? '1' : '0.5';

  function updateOpacity() {
    btnLight.style.opacity = isDark ? '0.5' : '1';
    btnDark.style.opacity  = isDark ? '1'   : '0.5';
  }

  btnLight.addEventListener( 'click', function () {
    if ( !isDark ) { return; }
    isDark = false; applyLight();
    localStorage.setItem( STORAGE_KEY, 'light' ); updateOpacity();
  } );

  btnDark.addEventListener( 'click', function () {
    if ( isDark ) { return; }
    isDark = true; applyDark();
    localStorage.setItem( STORAGE_KEY, 'dark' ); updateOpacity();
  } );

  wrap.appendChild( btnLight );
  wrap.appendChild( btnDark );
  document.body.appendChild( wrap );
}

if ( document.readyState === 'loading' ) {
  document.addEventListener( 'DOMContentLoaded', buildButton );
} else {
  buildButton();
}

}() );


/* Theme class hook — exposes light/dark to CSS for readable theming */
(function () {
  function applyThemeClass() {
    var light = localStorage.getItem('wows-theme-mode') === 'light';
    var h = document.documentElement;
    h.classList.toggle('wows-theme-light', light);
    h.classList.toggle('wows-theme-dark', !light);
  }
  applyThemeClass();
  window.addEventListener('storage', function (e) {
    if (e.key === 'wows-theme-mode') applyThemeClass();
  });
  document.addEventListener('click', function (e) {
    var b = e.target.closest && e.target.closest('button');
    if (b && /Light mode|Dark mode/i.test(b.title || b.textContent)) {
      setTimeout(applyThemeClass, 0);
    }
  }, true);
})();

/* ============================================================
   Ship pages: contextual Nation + Class links in the sidebar nav
   On Ship: namespace pages (ns 10000), read the page's categories
   to find its nation ("Ships of X") and class, then add links to
   the matching overview pages into the navigation menu.
   ============================================================ */
( function () {
'use strict';
if ( !window.mw || mw.config.get( 'wgNamespaceNumber' ) !== 10000 ) { return; }
var cats = mw.config.get( 'wgCategories' ) || [];
var CLASSES = [ 'Aircraft Carriers', 'Battleships', 'Cruisers', 'Destroyers', 'Submarines' ];
var nation = null, klass = null;
cats.forEach( function ( c ) {
	if ( /^Ships of /.test( c ) ) { nation = c; }
	if ( CLASSES.indexOf( c ) !== -1 ) { klass = c; }
} );
if ( !nation && !klass ) { return; }
var artPath = mw.config.get( 'wgArticlePath' );
function url( t ) { return artPath.replace( '$1', t.replace( / /g, '_' ) ); }
function addItem( menu, id, label, target ) {
	if ( document.getElementById( id ) ) { return; }
	var li = document.createElement( 'li' );
	li.id = id;
	li.className = 'b-left-menu_item mw-list-item';
	var a = document.createElement( 'a' );
	a.className = 'b-left-menu_link b-darklink';
	a.href = url( target );
	var point = document.createElement( 'span' );
	point.className = 'b-left-menu_point';
	point.title = label;
	point.textContent = label;
	a.appendChild( point );
	li.appendChild( a );
	menu.appendChild( li );
}
function inject() {
	var menu = document.querySelector( '#p-navigation .b-left-menu' ) ||
		document.querySelector( '#mw-panel .b-left-menu' );
	if ( !menu ) { return; }
	if ( nation ) { addItem( menu, 'n-ship-nation', nation, 'Ship:' + nation ); }
	if ( klass ) { addItem( menu, 'n-ship-class', klass, 'Ship:' + klass ); }
}
if ( document.readyState === 'loading' ) {
	document.addEventListener( 'DOMContentLoaded', inject );
} else {
	inject();
}
}() );

/* ============================================================
   Article pages: move the table of contents into the sidebar
   On any page with a TOC (#toc), relocate it into #mw-panel so it
   scrolls with the reader (the sidebar is sticky). Pages without a
   TOC (e.g. ship stat pages using __NOTOC__) are unaffected.
   ============================================================ */
( function () {
'use strict';
var toc = document.getElementById( 'toc' );
var panel = document.getElementById( 'mw-panel' );
if ( !toc || !panel ) { return; }
var sec = document.createElement( 'div' );
sec.id = 'p-toc';
sec.className = 'b-sidebar_item';
sec.appendChild( toc );
panel.appendChild( sec );
}() );


/* ===================================================================
   Sidebar "Request Edit" link - open in new tab
   =================================================================== */
( function () {
	'use strict';
	function fixLink() {
		var link = document.querySelector( '#n-Request-Edit a' );
		if ( !link ) { return; }
		link.setAttribute( 'target', '_blank' );
		var relParts = ( link.getAttribute( 'rel' ) || '' ).split( /\s+/ ).filter( Boolean );
		if ( relParts.indexOf( 'noopener' ) === -1 ) { relParts.push( 'noopener' ); }
		link.setAttribute( 'rel', relParts.join( ' ' ) );
	}
	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', fixLink );
	} else {
		fixLink();
	}
	// Re-apply shortly after load in case other scripts modify the link's attributes afterward.
	setTimeout( fixLink, 500 );
} )();