MediaWiki:Common.js: Różnice pomiędzy wersjami
Przejdź do nawigacji
Przejdź do wyszukiwania
(UWAGA! Zastąpienie treści hasła bardzo krótkim tekstem: „→Umieszczony tutaj kod JavaScript zostanie załadowany przez każdego użytkownika, podczas każdego ładowania strony.: ”) Znaczniki: Zastąpiono Ręczne wycofanie zmian |
Nie podano opisu zmian |
||
| Linia 1: | Linia 1: | ||
/* Umieszczony tutaj kod JavaScript zostanie załadowany przez każdego użytkownika, podczas każdego ładowania strony. */ | /* Umieszczony tutaj kod JavaScript zostanie załadowany przez każdego użytkownika, podczas każdego ładowania strony. */ | ||
// Dark Mode Manager with Cookie Storage | |||
(function() { | |||
'use strict'; | |||
const DARK_MODE_CLASS = 'skin-dark-mode'; | |||
const COOKIE_NAME = 'mw_dark_mode'; | |||
const COOKIE_EXPIRE_DAYS = 365; | |||
class DarkModeManager { | |||
constructor() { | |||
this.init(); | |||
} | |||
init() { | |||
this.applySavedPreference(); | |||
this.processTemplateMarkers(); | |||
this.createFixedToggle(); | |||
this.watchForDynamicContent(); | |||
} | |||
// Cookie management | |||
setCookie(name, value, days) { | |||
const date = new Date(); | |||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); | |||
const expires = "expires=" + date.toUTCString(); | |||
document.cookie = name + "=" + value + ";" + expires + ";path=/"; | |||
} | |||
getCookie(name) { | |||
const nameEQ = name + "="; | |||
const ca = document.cookie.split(';'); | |||
for(let i = 0; i < ca.length; i++) { | |||
let c = ca[i]; | |||
while (c.charAt(0) === ' ') c = c.substring(1, c.length); | |||
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); | |||
} | |||
return null; | |||
} | |||
isDarkMode() { | |||
const cookie = this.getCookie(COOKIE_NAME); | |||
return cookie === 'true'; | |||
} | |||
setDarkMode(enabled) { | |||
this.setCookie(COOKIE_NAME, enabled, COOKIE_EXPIRE_DAYS); | |||
this.applyDarkMode(enabled); | |||
this.updateAllToggleButtons(enabled); | |||
} | |||
toggle() { | |||
this.setDarkMode(!this.isDarkMode()); | |||
} | |||
applyDarkMode(enabled) { | |||
if (enabled) { | |||
document.documentElement.classList.add(DARK_MODE_CLASS); | |||
} else { | |||
document.documentElement.classList.remove(DARK_MODE_CLASS); | |||
} | |||
// Protect images from any dark mode filters | |||
this.protectImages(); | |||
} | |||
applySavedPreference() { | |||
const isDark = this.isDarkMode(); | |||
this.applyDarkMode(isDark); | |||
} | |||
// Protect images from any color modifications | |||
protectImages() { | |||
const images = document.querySelectorAll('img, .image, .thumbimage, .mw-file-element'); | |||
images.forEach(img => { | |||
img.style.filter = 'none'; | |||
img.style.backgroundColor = 'transparent'; | |||
}); | |||
} | |||
// Process {{dark_toggle}} template markers | |||
processTemplateMarkers() { | |||
// Method 1: Look for specific text patterns | |||
this.replaceTextMarkers(); | |||
// Method 2: Look for elements with specific classes (if your template adds them) | |||
this.replaceElementMarkers(); | |||
} | |||
replaceTextMarkers() { | |||
const walker = document.createTreeWalker( | |||
document.body, | |||
NodeFilter.SHOW_TEXT, | |||
null, | |||
false | |||
); | |||
let node; | |||
while (node = walker.nextNode()) { | |||
if (node.nodeValue.includes('{{dark_toggle}}')) { | |||
const span = document.createElement('span'); | |||
span.className = 'dark-toggle-container'; | |||
span.innerHTML = this.createToggleButtonHTML(this.isDarkMode()); | |||
const parent = node.parentNode; | |||
if (parent.nodeType === Node.ELEMENT_NODE) { | |||
parent.replaceChild(span, node); | |||
} | |||
} | |||
} | |||
} | |||
replaceElementMarkers() { | |||
const markers = document.querySelectorAll('[class*="dark_toggle"], [id*="dark_toggle"]'); | |||
markers.forEach(marker => { | |||
marker.innerHTML = this.createToggleButtonHTML(this.isDarkMode()); | |||
marker.className = 'dark-toggle-container'; | |||
}); | |||
} | |||
createToggleButtonHTML(isDark) { | |||
const icon = isDark ? '☀️' : '🌙'; | |||
const text = isDark ? ' Light Mode' : ' Dark Mode'; | |||
const modeClass = isDark ? 'light' : ''; | |||
return `<button class="dark-mode-toggle-button ${modeClass}" onclick="window.DarkModeManager.toggle()"> | |||
<span class="toggle-icon">${icon}</span> | |||
<span class="toggle-text">${text}</span> | |||
</button>`; | |||
} | |||
createFixedToggle() { | |||
// Remove existing fixed toggle if any | |||
const existingToggle = document.getElementById('darkModeToggleFixed'); | |||
if (existingToggle) { | |||
existingToggle.remove(); | |||
} | |||
const button = document.createElement('button'); | |||
button.id = 'darkModeToggleFixed'; | |||
button.className = `dark-mode-toggle-fixed ${this.isDarkMode() ? 'light' : ''}`; | |||
button.innerHTML = this.isDarkMode() ? | |||
'<span class="toggle-icon">☀️</span><span class="toggle-text">Light Mode</span>' : | |||
'<span class="toggle-icon">🌙</span><span class="toggle-text">Dark Mode</span>'; | |||
button.title = this.isDarkMode() ? 'Switch to light mode' : 'Switch to dark mode'; | |||
button.addEventListener('click', () => this.toggle()); | |||
document.body.appendChild(button); | |||
} | |||
updateAllToggleButtons(isDark) { | |||
// Update inline toggle buttons | |||
const inlineButtons = document.querySelectorAll('.dark-mode-toggle-button'); | |||
inlineButtons.forEach(button => { | |||
const icon = button.querySelector('.toggle-icon'); | |||
const text = button.querySelector('.toggle-text'); | |||
if (isDark) { | |||
icon.textContent = '☀️'; | |||
text.textContent = ' Light Mode'; | |||
button.classList.add('light'); | |||
} else { | |||
icon.textContent = '🌙'; | |||
text.textContent = ' Dark Mode'; | |||
button.classList.remove('light'); | |||
} | |||
}); | |||
// Update fixed toggle button | |||
const fixedButton = document.getElementById('darkModeToggleFixed'); | |||
if (fixedButton) { | |||
const icon = fixedButton.querySelector('.toggle-icon'); | |||
const text = fixedButton.querySelector('.toggle-text'); | |||
if (isDark) { | |||
icon.textContent = '☀️'; | |||
text.textContent = 'Light Mode'; | |||
fixedButton.classList.add('light'); | |||
fixedButton.title = 'Switch to light mode'; | |||
} else { | |||
icon.textContent = '🌙'; | |||
text.textContent = 'Dark Mode'; | |||
fixedButton.classList.remove('light'); | |||
fixedButton.title = 'Switch to dark mode'; | |||
} | |||
} | |||
} | |||
watchForDynamicContent() { | |||
// Watch for DOM changes to process new {{dark_toggle}} markers | |||
const observer = new MutationObserver((mutations) => { | |||
mutations.forEach((mutation) => { | |||
if (mutation.addedNodes.length) { | |||
mutation.addedNodes.forEach((node) => { | |||
if (node.nodeType === Node.ELEMENT_NODE) { | |||
if (node.textContent.includes('{{dark_toggle}}')) { | |||
this.processTemplateMarkers(); | |||
} | |||
} | |||
}); | |||
} | |||
}); | |||
}); | |||
observer.observe(document.body, { | |||
childList: true, | |||
subtree: true | |||
}); | |||
} | |||
} | |||
// Initialize when DOM is ready | |||
if (document.readyState === 'loading') { | |||
document.addEventListener('DOMContentLoaded', () => { | |||
window.DarkModeManager = new DarkModeManager(); | |||
}); | |||
} else { | |||
window.DarkModeManager = new DarkModeManager(); | |||
} | |||
})(); | |||
Wersja z 15:18, 16 paź 2025
/* Umieszczony tutaj kod JavaScript zostanie załadowany przez każdego użytkownika, podczas każdego ładowania strony. */
// Dark Mode Manager with Cookie Storage
(function() {
'use strict';
const DARK_MODE_CLASS = 'skin-dark-mode';
const COOKIE_NAME = 'mw_dark_mode';
const COOKIE_EXPIRE_DAYS = 365;
class DarkModeManager {
constructor() {
this.init();
}
init() {
this.applySavedPreference();
this.processTemplateMarkers();
this.createFixedToggle();
this.watchForDynamicContent();
}
// Cookie management
setCookie(name, value, days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = "expires=" + date.toUTCString();
document.cookie = name + "=" + value + ";" + expires + ";path=/";
}
getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for(let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
isDarkMode() {
const cookie = this.getCookie(COOKIE_NAME);
return cookie === 'true';
}
setDarkMode(enabled) {
this.setCookie(COOKIE_NAME, enabled, COOKIE_EXPIRE_DAYS);
this.applyDarkMode(enabled);
this.updateAllToggleButtons(enabled);
}
toggle() {
this.setDarkMode(!this.isDarkMode());
}
applyDarkMode(enabled) {
if (enabled) {
document.documentElement.classList.add(DARK_MODE_CLASS);
} else {
document.documentElement.classList.remove(DARK_MODE_CLASS);
}
// Protect images from any dark mode filters
this.protectImages();
}
applySavedPreference() {
const isDark = this.isDarkMode();
this.applyDarkMode(isDark);
}
// Protect images from any color modifications
protectImages() {
const images = document.querySelectorAll('img, .image, .thumbimage, .mw-file-element');
images.forEach(img => {
img.style.filter = 'none';
img.style.backgroundColor = 'transparent';
});
}
// Process {{dark_toggle}} template markers
processTemplateMarkers() {
// Method 1: Look for specific text patterns
this.replaceTextMarkers();
// Method 2: Look for elements with specific classes (if your template adds them)
this.replaceElementMarkers();
}
replaceTextMarkers() {
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
let node;
while (node = walker.nextNode()) {
if (node.nodeValue.includes('{{dark_toggle}}')) {
const span = document.createElement('span');
span.className = 'dark-toggle-container';
span.innerHTML = this.createToggleButtonHTML(this.isDarkMode());
const parent = node.parentNode;
if (parent.nodeType === Node.ELEMENT_NODE) {
parent.replaceChild(span, node);
}
}
}
}
replaceElementMarkers() {
const markers = document.querySelectorAll('[class*="dark_toggle"], [id*="dark_toggle"]');
markers.forEach(marker => {
marker.innerHTML = this.createToggleButtonHTML(this.isDarkMode());
marker.className = 'dark-toggle-container';
});
}
createToggleButtonHTML(isDark) {
const icon = isDark ? '☀️' : '🌙';
const text = isDark ? ' Light Mode' : ' Dark Mode';
const modeClass = isDark ? 'light' : '';
return `<button class="dark-mode-toggle-button ${modeClass}" onclick="window.DarkModeManager.toggle()">
<span class="toggle-icon">${icon}</span>
<span class="toggle-text">${text}</span>
</button>`;
}
createFixedToggle() {
// Remove existing fixed toggle if any
const existingToggle = document.getElementById('darkModeToggleFixed');
if (existingToggle) {
existingToggle.remove();
}
const button = document.createElement('button');
button.id = 'darkModeToggleFixed';
button.className = `dark-mode-toggle-fixed ${this.isDarkMode() ? 'light' : ''}`;
button.innerHTML = this.isDarkMode() ?
'<span class="toggle-icon">☀️</span><span class="toggle-text">Light Mode</span>' :
'<span class="toggle-icon">🌙</span><span class="toggle-text">Dark Mode</span>';
button.title = this.isDarkMode() ? 'Switch to light mode' : 'Switch to dark mode';
button.addEventListener('click', () => this.toggle());
document.body.appendChild(button);
}
updateAllToggleButtons(isDark) {
// Update inline toggle buttons
const inlineButtons = document.querySelectorAll('.dark-mode-toggle-button');
inlineButtons.forEach(button => {
const icon = button.querySelector('.toggle-icon');
const text = button.querySelector('.toggle-text');
if (isDark) {
icon.textContent = '☀️';
text.textContent = ' Light Mode';
button.classList.add('light');
} else {
icon.textContent = '🌙';
text.textContent = ' Dark Mode';
button.classList.remove('light');
}
});
// Update fixed toggle button
const fixedButton = document.getElementById('darkModeToggleFixed');
if (fixedButton) {
const icon = fixedButton.querySelector('.toggle-icon');
const text = fixedButton.querySelector('.toggle-text');
if (isDark) {
icon.textContent = '☀️';
text.textContent = 'Light Mode';
fixedButton.classList.add('light');
fixedButton.title = 'Switch to light mode';
} else {
icon.textContent = '🌙';
text.textContent = 'Dark Mode';
fixedButton.classList.remove('light');
fixedButton.title = 'Switch to dark mode';
}
}
}
watchForDynamicContent() {
// Watch for DOM changes to process new {{dark_toggle}} markers
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.textContent.includes('{{dark_toggle}}')) {
this.processTemplateMarkers();
}
}
});
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
window.DarkModeManager = new DarkModeManager();
});
} else {
window.DarkModeManager = new DarkModeManager();
}
})();