MediaWiki:Vector.js
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)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* All JavaScript here will be loaded for users of the Vector skin */
/***************************/
/* Interface Modification **/
/***************************/
/* JavaScript Load Class (REQUIRED BY DEFAULT VECTOR.CSS) */
$(function () {
document.body.classList.add('has-vector-mobile-menu');
});
/* Adapt standard Vector's structure for the imported stylesheet. */
$(function () {
if (!document.body.classList.contains('skin-vector-legacy')) return;
var content = document.getElementById('content');
var navigation = document.getElementById('mw-navigation');
if (!content || !navigation) return;
if (!content.parentElement.classList.contains('content-wrapper')) {
var wrapper = document.createElement('div');
wrapper.className = 'content-wrapper';
content.before(wrapper);
wrapper.append(navigation, content);
}
if (!content.querySelector('.content-body')) {
$(content).wrapInner('<div class="content-body"></div>');
}
});
/* Search Toggle Button */
$(function () {
var buttonClass = 'button-toggle button-toggle-search';
var expandedClass = 'search--expanded';
let searchButton = document.createElement('button');
let sidebar = document.getElementById('mw-navigation');
searchButton.className = buttonClass;
searchButton.addEventListener('click', function () {
searchButton.classList.toggle(expandedClass);
sidebar.classList.toggle(expandedClass);
});
sidebar.prepend(searchButton);
});
/* Mobile Sidebar Toggle Button */
$(function () {
var buttonClass = 'button-toggle button-toggle-sidebar-mobile';
var expandedClass = 'sidebar-mobile--expanded';
let mobileSidebarButton = document.createElement('button');
let sidebar = document.getElementById('mw-navigation');
mobileSidebarButton.className = buttonClass;
mobileSidebarButton.addEventListener('click', function () {
mobileSidebarButton.classList.toggle(expandedClass);
sidebar.classList.toggle(expandedClass);
});
sidebar.prepend(mobileSidebarButton);
});
/* Sidebar Toggle Button */
$(function () {
var buttonClass = 'button-toggle button-toggle-sidebar';
var expandedClass = 'sidebar--collapsed';
let sidebarButton = document.createElement('button');
let sidebar = document.getElementById('mw-navigation');
sidebarButton.className = buttonClass;
sidebarButton.addEventListener('click', function () {
sidebarButton.classList.toggle(expandedClass);
sidebar.classList.toggle(expandedClass);
});
sidebar.prepend(sidebarButton);
});
/* Sidebar Box Content Collaspible Toggles */
$(function() {
// configure sections (by header string) to initially collapse for all users by default
var initiallyCollapsedIDs = []; /* e.g. ['Character_Classes', 'Items', 'External_Links'] */
// add the p- onto ids for ease of use, if not present
initiallyCollapsedIDs.forEach(function(id, index) {
if(!id.startsWith('p-')) {initiallyCollapsedIDs[index] = 'p-' + id;}
});
var $portals = $("#mw-panel .vector-menu-portal");
var setup = function() {
$portals.each(function(index, el) {
if(window.innerWidth < 721) {return;}
var $el = $(el);
var $id = $el.attr("id");
if(!$id) {return;}
// check if this portal should be collapsed - portal is set to be initially collapsed and user has not indicated wanting it open || user has indicated wanting this portal collapsed
if(
(initiallyCollapsedIDs.includes($id) && localStorage.getItem('sidebar_c_'+$id) != "n") || (localStorage.getItem('sidebar_c_'+$id) === "y")
) {$el.addClass('collapsed').find('.vector-menu-content').slideUp(0);}
});
};
setup();
$(window).on('resize', setup);
$portals.on("click", "h3", function(event) {
if(window.innerWidth < 721) {return;}
var $el = $(this).parent();
var $id = $el.attr("id");
if(!$id) {return;}
$el.toggleClass('collapsed');
if($el.hasClass('collapsed')) { // more consistent between class and slide status
localStorage.setItem('sidebar_c_'+$id, "y");
$el.find('.vector-menu-content').slideUp('fast');
}
else {
localStorage.setItem('sidebar_c_'+$id, "n");
$el.find('.vector-menu-content').slideDown('fast');
}
});
});
/* Header Dropdown Menu Purge Cache Link */
$(function() {
if (mw.config.get('wgNamespaceNumber') === -1 ) {return;} // disable on special pages
var url = new URL(window.location.href);
url.searchParams.set('action', 'purge');
var button = mw.util.addPortletLink('p-cactions', url.href, 'Purge cache', 'ca-gadget-purgecache', 'Purge the server cache for this page', '1');
button.addEventListener('click', (function(event) {
event.preventDefault();
var api = new mw.Api();
api.post({
action: 'purge',
titles: mw.config.get('wgPageName'),
forcerecursivelinkupdate: true
}).then(function() {
window.location.reload(true);
}).fail(function(code) {
mw.notify('Page purge unsuccessful. Error code: $1'.replace('$1', code));
});
}));
console.log('purge loaded');
});
/* Independent GD Wiki header: themes and existing account links. */
(function () {
'use strict';
var themes = [
['blue', 'Geometry Dash'], ['purple', 'Vault'],
['green', 'Vault of Secrets'], ['red', 'Chamber of Time'],
['dark', 'Dark'], ['blackout', 'Blackout']
];
var storageKey = 'gdwiki-theme';
function applyTheme(key) {
if (!themes.some(function (theme) { return theme[0] === key; })) key = 'blue';
var root = document.documentElement;
themes.forEach(function (theme) { root.classList.remove('theme-' + theme[0]); });
root.classList.remove('view-light');
root.classList.add('view-dark', 'theme-' + key);
return key;
}
var selected = 'blue';
try { selected = localStorage.getItem(storageKey) || selected; } catch (error) {}
selected = applyTheme(selected);
$(function () {
if (!document.body.classList.contains('skin-vector-legacy')) return;
var personal = document.getElementById('p-personal');
if (!personal || personal.querySelector('.gd-header-controls')) return;
var links = personal.querySelector('ul');
if (!links) return;
var controls = document.createElement('div');
controls.className = 'gd-header-controls';
var appearance = document.createElement('details');
appearance.className = 'gd-header-menu';
var appearanceLabel = document.createElement('summary');
appearanceLabel.textContent = 'Appearance';
appearance.appendChild(appearanceLabel);
var themePanel = document.createElement('div');
themePanel.className = 'gd-header-dropdown';
var themeLabel = document.createElement('label');
themeLabel.textContent = 'Theme';
themeLabel.htmlFor = 'gd-theme-selector';
var selector = document.createElement('select');
selector.id = 'gd-theme-selector';
themes.forEach(function (theme) { selector.add(new Option(theme[1], theme[0])); });
selector.value = selected;
selector.addEventListener('change', function () {
applyTheme(selector.value);
try { localStorage.setItem(storageKey, selector.value); } catch (error) {}
});
themePanel.append(themeLabel, selector);
appearance.appendChild(themePanel);
controls.appendChild(appearance);
var icons = {
gear: '<path d="m10 2 .5 2a8 8 0 0 1 3 0l.5-2 3 1 0 2a8 8 0 0 1 2 2l2 0 1 3-2 .5a8 8 0 0 1 0 3l2 .5-1 3-2 0a8 8 0 0 1-2 2l0 2-3 1-.5-2a8 8 0 0 1-3 0L10 22l-3-1 0-2a8 8 0 0 1-2-2l-2 0-1-3 2-.5a8 8 0 0 1 0-3L2 10l1-3 2 0a8 8 0 0 1 2-2l0-2z"/><circle cx="12" cy="12" r="3" fill="#03052f"/>',
watch: '<path d="M3 3h18v15h-6l-2 3h-2l-2-3H3zm2 2v11h5l2 3 2-3h5V5z"/>',
user: '<circle cx="12" cy="7" r="4"/><path d="M3 22v-2a9 9 0 0 1 18 0v2z"/>'
};
function iconMarkup(name) {
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">' + icons[name] + '</svg>';
}
function iconLink(id, name, label) {
var original = document.querySelector('#' + id + ' a');
if (!original) return;
var link = original.cloneNode(false);
link.className = 'gd-header-icon';
link.title = label;
link.setAttribute('aria-label', label);
link.innerHTML = iconMarkup(name);
controls.appendChild(link);
}
iconLink('pt-preferences', 'gear', 'Preferences');
iconLink('pt-watchlist', 'watch', 'Watchlist');
var account = document.createElement('details');
account.className = 'gd-header-menu gd-account-menu';
var accountLabel = document.createElement('summary');
accountLabel.innerHTML = iconMarkup('user');
var accountName = document.createElement('span');
accountName.textContent = mw.config.get('wgUserName') || 'Account';
accountLabel.appendChild(accountName);
account.appendChild(accountLabel);
links.classList.add('gd-account-links');
account.appendChild(links);
controls.appendChild(account);
personal.appendChild(controls);
personal.classList.add('gd-header-ready');
document.addEventListener('click', function (event) {
[appearance, account].forEach(function (menu) {
if (!menu.contains(event.target)) menu.open = false;
});
});
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape') { appearance.open = false; account.open = false; }
});
});
}());