2021-04-27 16:57:54 +00:00
|
|
|
/* global applyPref */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO: Maybe combine the localStorage keys into one object
|
|
|
|
*/
|
|
|
|
|
2022-05-25 20:38:10 +00:00
|
|
|
const
|
|
|
|
CLASS = 'citizen-pref',
|
2022-05-11 01:45:30 +00:00
|
|
|
PREFIX_KEY = 'skin-citizen-';
|
|
|
|
|
2024-04-24 04:21:36 +00:00
|
|
|
/**
|
|
|
|
* Clientprefs names theme differently from Citizen, we will need to translate it
|
|
|
|
* TODO: Migrate to clientprefs fully on MW 1.43
|
|
|
|
*/
|
|
|
|
const CLIENTPREFS_THEME_MAP = {
|
|
|
|
auto: 'os',
|
|
|
|
light: 'day',
|
|
|
|
dark: 'night'
|
|
|
|
};
|
|
|
|
|
2024-04-25 00:23:45 +00:00
|
|
|
const clientPrefs = require( './clientPrefs.polyfill.js' )();
|
2024-04-24 04:21:36 +00:00
|
|
|
|
2021-04-27 16:57:54 +00:00
|
|
|
/**
|
2021-04-28 15:36:44 +00:00
|
|
|
* Set the value of the input element
|
|
|
|
*
|
|
|
|
* @param {string} key
|
|
|
|
* @param {string} value
|
|
|
|
*/
|
|
|
|
function setInputValue( key, value ) {
|
2022-05-11 01:45:30 +00:00
|
|
|
const element = document.getElementById( CLASS + '-' + key + '__input' );
|
2021-04-28 15:36:44 +00:00
|
|
|
|
|
|
|
if ( element ) {
|
|
|
|
element.value = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the text of the indicator element
|
|
|
|
*
|
|
|
|
* @param {string} key
|
|
|
|
* @param {string} value
|
|
|
|
*/
|
|
|
|
function setIndicator( key, value ) {
|
2022-05-11 01:45:30 +00:00
|
|
|
const element = document.getElementById( CLASS + '-' + key + '__value' );
|
2021-04-28 15:36:44 +00:00
|
|
|
|
|
|
|
if ( element ) {
|
|
|
|
element.innerText = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-05-25 20:38:10 +00:00
|
|
|
* Convert the pref values for use with the form input
|
2021-04-28 15:36:44 +00:00
|
|
|
*
|
|
|
|
* @param {Object} pref
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
2022-05-25 20:38:10 +00:00
|
|
|
function convertForForm( pref ) {
|
2021-04-28 15:36:44 +00:00
|
|
|
return {
|
2022-05-11 01:45:30 +00:00
|
|
|
fontsize: Number( pref.fontsize.slice( 0, -1 ) ) / 10 - 8,
|
2021-08-05 15:24:52 +00:00
|
|
|
pagewidth: Number( pref.pagewidth.slice( 0, -2 ) ) / 120 - 6,
|
|
|
|
lineheight: ( pref.lineheight - 1 ) * 10
|
2021-04-28 15:36:44 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve localstorage or default preferences
|
2021-04-27 16:57:54 +00:00
|
|
|
*
|
|
|
|
* @return {Object} pref
|
|
|
|
*/
|
|
|
|
function getPref() {
|
2022-05-25 20:38:10 +00:00
|
|
|
const rootStyle = window.getComputedStyle( document.documentElement );
|
2021-04-27 16:57:54 +00:00
|
|
|
|
2022-05-11 01:45:30 +00:00
|
|
|
// Create an initial value for font size
|
|
|
|
const initFontSize = () => {
|
|
|
|
// Get browser default font size
|
|
|
|
const getDefaultFontSize = () => {
|
|
|
|
const element = document.createElement( 'div' );
|
|
|
|
element.style.width = '1rem';
|
|
|
|
element.style.display = 'none';
|
|
|
|
document.body.append( element );
|
|
|
|
|
|
|
|
const widthMatch = window
|
|
|
|
.getComputedStyle( element )
|
|
|
|
.getPropertyValue( 'width' )
|
|
|
|
.match( /\d+/ );
|
|
|
|
|
|
|
|
element.remove();
|
|
|
|
|
|
|
|
if ( !widthMatch || widthMatch.length < 1 ) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = Number( widthMatch[ 0 ] );
|
|
|
|
return !isNaN( result ) ? result : null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const browserFontSize = getDefaultFontSize() + 'px',
|
|
|
|
rootFontSize = rootStyle.getPropertyValue( 'font-size' );
|
|
|
|
|
|
|
|
// If browser font size is same as HTML font size, return 100%
|
|
|
|
// Some wiki might have custom font size defined in root/HTML,
|
|
|
|
// in that case return the defined value
|
|
|
|
return ( ( browserFontSize === rootFontSize ) ? '100%' : rootFontSize );
|
|
|
|
};
|
|
|
|
|
2022-05-25 20:38:10 +00:00
|
|
|
const pref = {
|
2024-04-24 04:25:09 +00:00
|
|
|
fontsize: mw.storage.get( PREFIX_KEY + 'fontsize' ) || initFontSize(),
|
|
|
|
pagewidth: mw.storage.get( PREFIX_KEY + 'pagewidth' ) || rootStyle.getPropertyValue( '--width-layout' ),
|
|
|
|
lineheight: mw.storage.get( PREFIX_KEY + 'lineheight' ) || rootStyle.getPropertyValue( '--line-height' )
|
2022-05-25 20:38:10 +00:00
|
|
|
};
|
2021-04-27 16:57:54 +00:00
|
|
|
|
|
|
|
return pref;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save to localstorage if preference is changed
|
|
|
|
*
|
|
|
|
* @return {void}
|
|
|
|
*/
|
2023-07-07 22:00:14 +00:00
|
|
|
function setPref() {
|
2022-05-25 20:38:10 +00:00
|
|
|
const
|
|
|
|
// eslint-disable-next-line compat/compat
|
2023-07-03 12:48:41 +00:00
|
|
|
formData = Object.fromEntries( new FormData( document.getElementById( CLASS + '-form' ) ) ),
|
2022-05-25 20:38:10 +00:00
|
|
|
currentPref = convertForForm( getPref() ),
|
2021-04-27 16:57:54 +00:00
|
|
|
newPref = {
|
2022-05-11 01:45:30 +00:00
|
|
|
fontsize: Number( formData[ CLASS + '-fontsize' ] ),
|
|
|
|
pagewidth: Number( formData[ CLASS + '-pagewidth' ] ),
|
|
|
|
lineheight: Number( formData[ CLASS + '-lineheight' ] )
|
2021-04-27 16:57:54 +00:00
|
|
|
};
|
|
|
|
|
2024-04-25 00:23:45 +00:00
|
|
|
if ( currentPref.fontsize !== newPref.fontsize ) {
|
2022-05-11 01:45:30 +00:00
|
|
|
const formattedFontSize = ( newPref.fontsize + 8 ) * 10 + '%';
|
2024-04-24 04:25:09 +00:00
|
|
|
mw.storage.set( PREFIX_KEY + 'fontsize', formattedFontSize );
|
2021-04-28 15:36:44 +00:00
|
|
|
setIndicator( 'fontsize', formattedFontSize );
|
2022-05-25 20:38:10 +00:00
|
|
|
|
2021-04-27 16:57:54 +00:00
|
|
|
} else if ( currentPref.pagewidth !== newPref.pagewidth ) {
|
|
|
|
let formattedPageWidth;
|
|
|
|
// Max setting would be full browser width
|
|
|
|
if ( newPref.pagewidth === 10 ) {
|
|
|
|
formattedPageWidth = '100vw';
|
|
|
|
} else {
|
|
|
|
formattedPageWidth = ( newPref.pagewidth + 6 ) * 120 + 'px';
|
|
|
|
}
|
2024-04-24 04:25:09 +00:00
|
|
|
mw.storage.set( PREFIX_KEY + 'pagewidth', formattedPageWidth );
|
2021-04-28 15:36:44 +00:00
|
|
|
setIndicator( 'pagewidth', formattedPageWidth );
|
2022-05-25 20:38:10 +00:00
|
|
|
|
2021-08-05 15:24:52 +00:00
|
|
|
} else if ( currentPref.lineheight !== newPref.lineheight ) {
|
|
|
|
const formattedLineHeight = newPref.lineheight / 10 + 1;
|
2024-04-24 04:25:09 +00:00
|
|
|
mw.storage.set( PREFIX_KEY + 'lineheight', formattedLineHeight );
|
2021-08-05 15:24:52 +00:00
|
|
|
setIndicator( 'lineheight', formattedLineHeight );
|
2021-04-27 16:57:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
applyPref();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reset preference by clearing localStorage and inline styles
|
|
|
|
*
|
|
|
|
* @return {void}
|
|
|
|
*/
|
|
|
|
function resetPref() {
|
2022-05-11 01:45:30 +00:00
|
|
|
const keys = [ 'fontsize', 'pagewidth', 'lineheight' ];
|
2021-04-27 16:57:54 +00:00
|
|
|
|
2022-04-26 00:29:29 +00:00
|
|
|
// Remove style
|
2023-06-21 18:30:45 +00:00
|
|
|
if ( document.getElementById( 'citizen-style' ) ) {
|
|
|
|
document.getElementById( 'citizen-style' ).remove();
|
|
|
|
}
|
2021-04-27 16:57:54 +00:00
|
|
|
|
2021-04-28 15:36:44 +00:00
|
|
|
// Remove localStorage
|
|
|
|
keys.forEach( ( key ) => {
|
2022-05-11 01:45:30 +00:00
|
|
|
const keyName = PREFIX_KEY + key;
|
2021-04-27 16:57:54 +00:00
|
|
|
|
2024-04-24 04:25:09 +00:00
|
|
|
if ( mw.storage.get( keyName ) ) {
|
2021-04-28 15:36:44 +00:00
|
|
|
localStorage.removeItem( keyName );
|
|
|
|
}
|
|
|
|
} );
|
2021-04-27 16:57:54 +00:00
|
|
|
|
2021-04-28 15:36:44 +00:00
|
|
|
const pref = getPref(),
|
2022-05-25 20:38:10 +00:00
|
|
|
prefValue = convertForForm( pref );
|
2021-04-28 15:36:44 +00:00
|
|
|
|
|
|
|
keys.forEach( ( key ) => {
|
2022-05-11 01:45:30 +00:00
|
|
|
const keyName = PREFIX_KEY + key;
|
2021-04-28 15:36:44 +00:00
|
|
|
|
2024-04-24 04:25:09 +00:00
|
|
|
mw.storage.set( keyName, pref[ key ] );
|
2021-04-28 15:36:44 +00:00
|
|
|
setIndicator( key, pref[ key ] );
|
|
|
|
setInputValue( key, prefValue[ key ] );
|
|
|
|
} );
|
2021-04-27 16:57:54 +00:00
|
|
|
|
|
|
|
applyPref();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-05-10 17:25:10 +00:00
|
|
|
* Dismiss the prefernce panel when clicked outside
|
|
|
|
*
|
|
|
|
* @param {Event} event
|
|
|
|
*/
|
|
|
|
function dismissOnClickOutside( event ) {
|
2022-05-11 01:45:30 +00:00
|
|
|
const pref = document.getElementById( CLASS );
|
2021-05-10 17:25:10 +00:00
|
|
|
|
|
|
|
if ( event.target instanceof Node && !pref.contains( event.target ) ) {
|
2022-05-11 01:45:30 +00:00
|
|
|
const panel = document.getElementById( CLASS + '-panel' );
|
2022-02-19 20:09:01 +00:00
|
|
|
|
2022-05-11 01:45:30 +00:00
|
|
|
if ( panel.classList.contains( CLASS + '-panel--active' ) ) {
|
2021-05-10 17:25:10 +00:00
|
|
|
togglePanel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dismiss the prefernce panel when ESCAPE is pressed
|
2021-04-27 16:57:54 +00:00
|
|
|
*
|
|
|
|
* @param {Event} event
|
2021-05-10 17:25:10 +00:00
|
|
|
*/
|
|
|
|
function dismissOnEscape( event ) {
|
|
|
|
if ( event.key !== 'Escape' ) {
|
|
|
|
return;
|
|
|
|
}
|
2022-02-19 20:09:01 +00:00
|
|
|
|
2021-05-10 17:25:10 +00:00
|
|
|
togglePanel();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add/remove toggle class and form input eventlistener
|
|
|
|
*
|
2021-04-27 16:57:54 +00:00
|
|
|
* @return {void}
|
|
|
|
*/
|
2021-05-10 17:25:10 +00:00
|
|
|
function togglePanel() {
|
2022-05-11 01:45:30 +00:00
|
|
|
// .citizen-pref-panel--active
|
|
|
|
const CLASS_PANEL_ACTIVE = CLASS + '-panel--active';
|
2022-05-25 20:38:10 +00:00
|
|
|
const
|
|
|
|
toggle = document.getElementById( CLASS + '-toggle' ),
|
2022-05-11 01:45:30 +00:00
|
|
|
panel = document.getElementById( CLASS + '-panel' ),
|
|
|
|
form = document.getElementById( CLASS + '-form' ),
|
|
|
|
resetButton = document.getElementById( CLASS + '-resetbutton' );
|
|
|
|
|
|
|
|
if ( !panel.classList.contains( CLASS_PANEL_ACTIVE ) ) {
|
|
|
|
panel.classList.add( CLASS_PANEL_ACTIVE );
|
2021-05-10 17:25:10 +00:00
|
|
|
toggle.setAttribute( 'aria-expanded', true );
|
2021-04-27 16:57:54 +00:00
|
|
|
form.addEventListener( 'input', setPref );
|
|
|
|
resetButton.addEventListener( 'click', resetPref );
|
2021-05-10 17:25:10 +00:00
|
|
|
window.addEventListener( 'click', dismissOnClickOutside );
|
|
|
|
window.addEventListener( 'keydown', dismissOnEscape );
|
2021-04-27 16:57:54 +00:00
|
|
|
} else {
|
2022-05-11 01:45:30 +00:00
|
|
|
panel.classList.remove( CLASS_PANEL_ACTIVE );
|
2021-05-10 17:25:10 +00:00
|
|
|
toggle.setAttribute( 'aria-expanded', false );
|
2021-04-27 16:57:54 +00:00
|
|
|
form.removeEventListener( 'input', setPref );
|
|
|
|
resetButton.removeEventListener( 'click', resetPref );
|
2021-05-18 16:27:10 +00:00
|
|
|
window.removeEventListener( 'click', dismissOnClickOutside );
|
2021-05-10 17:25:10 +00:00
|
|
|
window.removeEventListener( 'keydown', dismissOnEscape );
|
2021-04-27 16:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get MW message and return as object to be used in Mustache
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
|
|
|
function getMessages() {
|
|
|
|
const keys = [
|
|
|
|
'preferences',
|
|
|
|
'prefs-citizen-fontsize-label',
|
|
|
|
'prefs-citizen-pagewidth-label',
|
2021-08-05 15:24:52 +00:00
|
|
|
'prefs-citizen-lineheight-label',
|
2021-04-27 16:57:54 +00:00
|
|
|
'prefs-citizen-resetbutton-label'
|
|
|
|
],
|
|
|
|
data = {};
|
|
|
|
|
|
|
|
keys.forEach( ( key ) => {
|
|
|
|
const templateKey = 'msg-' + key;
|
|
|
|
|
|
|
|
// Message keys already defined above
|
|
|
|
// eslint-disable-next-line mediawiki/msg-doc
|
|
|
|
data[ templateKey ] = mw.message( key ).text();
|
|
|
|
} );
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up the DOM and initial input states for the panel
|
|
|
|
* It only loads when user first clicked the toggle
|
|
|
|
*
|
|
|
|
* @param {Event} event
|
|
|
|
* @return {void}
|
|
|
|
*/
|
|
|
|
function initPanel( event ) {
|
|
|
|
const template = mw.template.get(
|
|
|
|
'skins.citizen.preferences',
|
|
|
|
'resources/skins.citizen.preferences/templates/preferences.mustache'
|
|
|
|
),
|
|
|
|
data = getMessages(),
|
2021-04-28 15:36:44 +00:00
|
|
|
pref = getPref(),
|
2022-05-25 20:38:10 +00:00
|
|
|
prefValue = convertForForm( pref ),
|
2021-08-05 15:24:52 +00:00
|
|
|
keys = [ 'fontsize', 'pagewidth', 'lineheight' ];
|
2021-04-27 16:57:54 +00:00
|
|
|
|
|
|
|
// To Mustache is to jQuery sigh
|
|
|
|
// TODO: Use ES6 template literals when RL does not screw up multiline
|
|
|
|
const panel = template.render( data ).get()[ 1 ];
|
2022-04-27 20:44:53 +00:00
|
|
|
|
2021-04-27 16:57:54 +00:00
|
|
|
// Attach panel after button
|
|
|
|
event.currentTarget.parentNode.insertBefore( panel, event.currentTarget.nextSibling );
|
|
|
|
|
|
|
|
// Set up initial state
|
2021-04-28 15:36:44 +00:00
|
|
|
keys.forEach( ( key ) => {
|
|
|
|
setIndicator( key, pref[ key ] );
|
|
|
|
setInputValue( key, prefValue[ key ] );
|
|
|
|
} );
|
2021-04-27 16:57:54 +00:00
|
|
|
|
2021-05-10 17:25:10 +00:00
|
|
|
togglePanel();
|
2021-04-27 16:57:54 +00:00
|
|
|
event.currentTarget.addEventListener( 'click', togglePanel );
|
2023-07-03 12:48:41 +00:00
|
|
|
event.currentTarget.removeEventListener( 'click', initPanel );
|
2024-04-25 00:23:45 +00:00
|
|
|
|
|
|
|
const clientPreferenceSelector = '#citizen-client-prefs';
|
|
|
|
const clientPreferenceExists = document.querySelectorAll( clientPreferenceSelector ).length > 0;
|
|
|
|
if ( clientPreferenceExists ) {
|
|
|
|
const clientPreferences = require( /** @type {string} */ ( './clientPreferences.js' ) );
|
|
|
|
const clientPreferenceConfig = ( require( './clientPreferences.json' ) );
|
|
|
|
|
|
|
|
// Support legacy skin-citizen-* class
|
|
|
|
// TODO: Remove it in the future version after sufficient time
|
|
|
|
clientPreferenceConfig[ 'skin-theme' ].callback = () => {
|
|
|
|
const LEGACY_THEME_CLASSES = [
|
|
|
|
'skin-citizen-auto',
|
|
|
|
'skin-citizen-light',
|
|
|
|
'skin-citizen-dark'
|
|
|
|
];
|
|
|
|
const legacyThemeKey = Object.keys( CLIENTPREFS_THEME_MAP ).find( ( key ) => {
|
|
|
|
return CLIENTPREFS_THEME_MAP[ key ] === clientPrefs.get( 'skin-theme' );
|
|
|
|
} );
|
|
|
|
document.documentElement.classList.remove( ...LEGACY_THEME_CLASSES );
|
|
|
|
document.documentElement.classList.add( `skin-citizen-${ legacyThemeKey }` );
|
|
|
|
};
|
|
|
|
|
|
|
|
clientPreferences.render( clientPreferenceSelector, clientPreferenceConfig );
|
|
|
|
}
|
2021-04-27 16:57:54 +00:00
|
|
|
}
|
|
|
|
|
2021-04-28 14:52:20 +00:00
|
|
|
/**
|
|
|
|
* Test if storage is avaliable
|
|
|
|
* Taken from https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
|
|
|
|
*
|
|
|
|
* @param {string} type
|
|
|
|
* @return {boolean|Error}
|
|
|
|
*/
|
|
|
|
function storageAvailable( type ) {
|
|
|
|
let storage;
|
|
|
|
|
|
|
|
try {
|
|
|
|
storage = window[ type ];
|
|
|
|
const x = '__storage_test__';
|
|
|
|
storage.setItem( x, x );
|
|
|
|
storage.removeItem( x );
|
|
|
|
return true;
|
|
|
|
} catch ( /** @type {Error} */ e ) {
|
|
|
|
return e instanceof DOMException && (
|
|
|
|
// everything except Firefox
|
|
|
|
e.code === 22 ||
|
|
|
|
// Firefox
|
|
|
|
e.code === 1014 ||
|
|
|
|
// test name field too, because code might not be present
|
|
|
|
// everything except Firefox
|
|
|
|
e.name === 'QuotaExceededError' ||
|
|
|
|
// Firefox
|
|
|
|
e.name === 'NS_ERROR_DOM_QUOTA_REACHED' ) &&
|
|
|
|
// acknowledge QuotaExceededError only if there's something already stored
|
|
|
|
( storage && storage.length !== 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-27 16:57:54 +00:00
|
|
|
/**
|
|
|
|
* Set up the container and toggle
|
|
|
|
*
|
|
|
|
* @param {Window} window
|
|
|
|
* @return {void}
|
|
|
|
*/
|
|
|
|
function initPref( window ) {
|
2023-07-03 12:48:41 +00:00
|
|
|
// Object.fromEntries() polyfill https://github.com/feross/fromentries
|
|
|
|
// MIT. Copyright (c) Feross Aboukhadijeh.
|
2023-06-21 18:30:45 +00:00
|
|
|
if ( typeof Object.fromEntries !== 'function' ) {
|
2023-07-03 12:48:41 +00:00
|
|
|
Object.defineProperty( Object, 'fromEntries', {
|
2023-07-07 22:00:14 +00:00
|
|
|
value( iterable ) {
|
2023-07-03 12:49:36 +00:00
|
|
|
return Array.from( iterable ).reduce( ( obj, [ key, val ] ) => {
|
|
|
|
obj[ key ] = val;
|
2023-07-03 12:48:41 +00:00
|
|
|
return obj;
|
2023-07-03 12:49:36 +00:00
|
|
|
}, {} );
|
|
|
|
}
|
|
|
|
} );
|
2023-06-21 18:30:45 +00:00
|
|
|
}
|
|
|
|
|
2021-04-28 14:52:20 +00:00
|
|
|
if ( storageAvailable( 'localStorage' ) ) {
|
|
|
|
if ( typeof window.mw !== 'undefined' ) {
|
2022-05-10 14:50:01 +00:00
|
|
|
const headerTools = document.querySelector( '.citizen-header__end' ),
|
2021-04-28 14:52:20 +00:00
|
|
|
container = document.createElement( 'div' ),
|
2022-11-03 22:30:41 +00:00
|
|
|
button = document.createElement( 'button' ),
|
|
|
|
icon = document.createElement( 'span' );
|
2021-04-28 14:52:20 +00:00
|
|
|
|
2022-05-11 01:45:30 +00:00
|
|
|
// citizen-pref
|
|
|
|
container.id = CLASS;
|
2022-05-13 04:17:27 +00:00
|
|
|
|
2022-05-11 01:45:30 +00:00
|
|
|
container.classList.add( CLASS, 'citizen-header__item' );
|
|
|
|
button.id = CLASS + '-toggle';
|
2022-05-13 04:17:27 +00:00
|
|
|
|
2023-07-10 20:23:48 +00:00
|
|
|
button.classList.add( CLASS + '__button', 'citizen-header__button', 'citizen-button' );
|
2022-05-11 22:47:02 +00:00
|
|
|
button.setAttribute( 'title', mw.message( 'preferences' ).text() );
|
2022-04-30 22:01:38 +00:00
|
|
|
button.setAttribute( 'aria-label', mw.message( 'preferences' ).text() );
|
2022-05-11 01:45:30 +00:00
|
|
|
button.setAttribute( 'aria-controls', CLASS + '-panel' );
|
2021-04-28 14:52:20 +00:00
|
|
|
button.setAttribute( 'aria-expanded', false );
|
2022-11-03 22:30:41 +00:00
|
|
|
icon.classList.add( 'citizen-ui-icon', 'mw-ui-icon-wikimedia-settings' );
|
|
|
|
button.prepend( icon );
|
2021-04-28 14:52:20 +00:00
|
|
|
container.prepend( button );
|
|
|
|
headerTools.prepend( container );
|
|
|
|
|
|
|
|
button.addEventListener( 'click', initPanel, { once: true } );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console.log( 'Preference module is disabled due to localStoarge being not avaliable.' );
|
2021-04-27 16:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
initPref( window );
|