refactor: refactor skins.citizen.scripts to ES6

This commit is contained in:
alistair3149 2021-04-21 13:44:28 -04:00
parent 117d839f00
commit f44aaa4e4c
No known key found for this signature in database
GPG key ID: 94D081060FD3DD9C
3 changed files with 101 additions and 76 deletions

View file

@ -1,10 +1,3 @@
var DRAWER_ID = 'mw-drawer',
DRAWER_BUTTON_ID = 'mw-drawer-button',
DRAWER_CHECKBOX_ID = 'mw-drawer-checkbox',
PERSONAL_MENU_ID = 'p-personal',
PERSONAL_MENU_BUTTON_ID = 'personalmenu-button',
PERSONAL_MENU_CHECKBOX_ID = 'personalmenu-checkbox';
/**
* Uncheck CSS hack checkbox when clicked outside
*
@ -13,29 +6,29 @@ var DRAWER_ID = 'mw-drawer',
* @param {HTMLElement} checkbox
*/
function uncheckOnClickOutside( clickableElement, button, checkbox ) {
var listener = function ( e ) {
var hideCond = e.target !== clickableElement;
const listener = ( event ) => {
let hideCond = event.target !== clickableElement;
if ( Array.isArray( clickableElement ) ) {
hideCond = clickableElement.indexOf( e.target ) === -1;
hideCond = clickableElement.indexOf( event.target ) === -1;
}
if ( e.target !== checkbox && hideCond ) {
if ( e.target !== button ) {
if ( event.target !== checkbox && hideCond ) {
if ( event.target !== button ) {
checkbox.checked = false;
}
document.removeEventListener( 'click', listener );
}
};
var keyboardListener = function ( event ) {
const keyboardListener = ( event ) => {
if ( event.key === 'Escape' && checkbox.checked === true ) {
checkbox.checked = false;
document.removeEventListener( 'click', listener );
}
};
var checkboxFn = function () {
const checkboxFn = () => {
if ( checkbox.checked ) {
document.addEventListener( 'click', listener );
} else {
@ -51,48 +44,68 @@ function uncheckOnClickOutside( clickableElement, button, checkbox ) {
}
/**
* TODO: This can use some refactoring
* TODO: Merge search handlers to this
*
* @param {Document} document
* @return {void}
*/
function init() {
var drawer = document.getElementById( DRAWER_ID ),
drawerButton = document.getElementById( DRAWER_BUTTON_ID ),
drawerCheckbox = document.getElementById( DRAWER_CHECKBOX_ID ),
drawerSearch = document.getElementById( 'mw-drawer-search-input' ),
personalMenu = document.getElementById( PERSONAL_MENU_ID ),
personalMenuButton = document.getElementById( PERSONAL_MENU_BUTTON_ID ),
personalMenuCheckbox = document.getElementById( PERSONAL_MENU_CHECKBOX_ID ),
toc = document.getElementById( 'toc' ),
tocButton,
tocCheckbox,
clickableDrawerElements = [];
function initCheckboxHack( document ) {
const drawer = {
button: document.getElementById( 'mw-drawer-button' ),
checkbox: document.getElementById( 'mw-drawer-checkbox' )
},
personalMenu = {
button: document.getElementById( 'personalmenu-button' ),
checkbox: document.getElementById( 'personalmenu-checkbox' ),
element: document.getElementById( 'p-personal' )
},
checkboxHackTargets = [ personalMenu ];
drawer.querySelectorAll( '#mw-drawer-menu .mw-portal' ).forEach( function ( portal ) {
clickableDrawerElements.push( portal );
} );
// So that clicking drawer portal header and input won't close the menu
// Maybe there is cleaner way to do this?
const getDrawerElements = () => {
const portals = document.getElementById( 'mw-drawer' ).querySelectorAll( '#mw-drawer-menu .mw-portal' ),
searchInput = document.getElementById( 'mw-drawer-search-input' ),
clickableElements = [];
drawer.querySelectorAll( '#mw-drawer-menu .mw-portal h3' ).forEach( function ( portalHeading ) {
clickableDrawerElements.push( portalHeading );
} );
portals.forEach( ( portal ) => {
clickableElements.push( portal, portal.firstElementChild );
} );
if ( drawerSearch !== null ) {
clickableDrawerElements.push( drawerSearch );
if ( searchInput !== null ) {
clickableElements.push( searchInput );
}
return clickableElements;
};
const getTOC = () => {
const tocContainer = document.getElementById( 'toc' );
return {
button: tocContainer.querySelector( '.toctogglelabel' ),
checkbox: document.getElementById( 'toctogglecheckbox' ),
element: tocContainer.querySelector( 'ul' )
};
};
drawer.element = getDrawerElements();
checkboxHackTargets.push( drawer );
// This should be in ToC script
// And the media query needs to be synced with the less variable
// Also this does not monitor screen size changes
if ( document.body.classList.contains( 'skin-citizen-has-toc' ) &&
window.matchMedia( 'screen and (max-width: 1300px)' ) ) {
checkboxHackTargets.push( getTOC() );
}
uncheckOnClickOutside( clickableDrawerElements, drawerButton, drawerCheckbox );
uncheckOnClickOutside( personalMenu, personalMenuButton, personalMenuCheckbox );
/*
* This should be in ToC script
* And the media query needs to be synced with the less variable
*/
if ( toc && window.matchMedia( 'screen and (max-width: 1300px)' ) ) {
tocButton = document.querySelector( 'toctogglelabel' );
tocCheckbox = document.getElementById( 'toctogglecheckbox' );
uncheckOnClickOutside( toc, tocButton, tocCheckbox );
}
checkboxHackTargets.forEach( ( target ) => {
uncheckOnClickOutside( target.element, target.button, target.checkbox );
} );
}
module.exports = {
init: init
init: initCheckboxHack
};

View file

@ -1,49 +1,61 @@
var searchToggle = document.getElementById( 'search-checkbox' ),
searchInput = document.getElementById( 'searchInput' ),
pageReady = require( ( 'mediawiki.page.ready' ) );
/**
* Focus and unfocus in search box when search toggle checkbox is toggled.
* Focus and unfocus element when checkbox is toggled.
* TODO: This should be a helper function in checkboxHack
*
* @constructor
* @param {HTMLElement} checkbox
* @param {HTMLElement} target
* @return {void}
*/
function searchInputFocus() {
if ( searchToggle.checked === true ) {
searchInput.focus();
function checkboxHackFocusHandler( checkbox, target ) {
if ( checkbox.checked === true ) {
target.focus();
} else {
searchInput.blur();
target.blur();
}
}
/**
* Toggle search bar with slash
* Handle keyup events
* TODO: This should be a helper function in checkboxHack
*
* @constructor
* @param {Event} event
* @param {HTMLElement} checkbox
* @param {HTMLElement} target
* @return {void}
*/
function keyboardEvents() {
if ( searchToggle.checked === false ) {
function checkboxHackOnKeyUp( event, checkbox, target ) {
if ( checkbox.checked === false ) {
if ( event.key === '/' &&
!event.target.matches( 'input' ) &&
!event.target.matches( 'textarea' )
) {
searchToggle.checked = true;
searchInput.focus();
searchInput.value = '';
checkbox.checked = true;
target.focus();
target.value = '';
}
} else {
if ( event.key === 'Escape' ) {
searchToggle.checked = false;
searchInput.blur();
checkbox.checked = false;
target.blur();
}
}
}
/**
* @param {Document} document
* @return {void}
*/
function init() {
searchToggle.addEventListener( 'change', searchInputFocus );
document.addEventListener( 'keyup', keyboardEvents );
function initSearch( document ) {
const toggle = document.getElementById( 'search-checkbox' ),
input = document.getElementById( 'searchInput' ),
pageReady = require( ( 'mediawiki.page.ready' ) );
toggle.addEventListener( 'change', function () {
checkboxHackFocusHandler( this, input );
} );
document.addEventListener( 'keyup', ( event ) => {
checkboxHackOnKeyUp( event, toggle, input );
} );
pageReady.loadSearchModule(
// Decide between new Citizen implementation or core
mw.config.get( 'wgCitizenEnableSearch' ) ?
@ -52,5 +64,5 @@ function init() {
}
module.exports = {
init: init
init: initSearch
};

View file

@ -1,7 +1,3 @@
const theme = require( './theme.js' ),
search = require( './search.js' ),
checkboxHack = require( './checkboxHack.js' );
/**
* Based on Vector
* Wait for first paint before calling this function. That's its whole purpose.
@ -40,10 +36,14 @@ function enableCssAnimations( document ) {
* @return {void}
*/
function main( window ) {
const theme = require( './theme.js' ),
search = require( './search.js' ),
checkboxHack = require( './checkboxHack.js' );
enableCssAnimations( window.document );
theme.init( window );
search.init( window.document );
checkboxHack.init();
checkboxHack.init( window.document );
}
main( window );