Skip to content

Commit

Permalink
refactor: ♻️ convert to ES6
Browse files Browse the repository at this point in the history
Signed-off-by: WaitSpring <[email protected]>
  • Loading branch information
WaitSpringQW committed Nov 19, 2023
1 parent 76c2f72 commit 3f3b2a3
Show file tree
Hide file tree
Showing 13 changed files with 398 additions and 404 deletions.
102 changes: 58 additions & 44 deletions resources/skins.citizen.scripts/checkboxHack.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
* @return {void}
* @ignore
*/
function updateAriaExpanded( checkbox ) {
const updateAriaExpanded = ( checkbox ) => {
checkbox.setAttribute( 'aria-expanded', checkbox.checked.toString() );
}
};

/**
* Set the checked state and fire the 'input' event.
Expand All @@ -41,7 +41,7 @@ function updateAriaExpanded( checkbox ) {
* @return {void}
* @ignore
*/
function setCheckedState( checkbox, checked ) {
const setCheckedState = ( checkbox, checked ) => {
/** @type {Event} @ignore */
let e;
checkbox.checked = checked;
Expand All @@ -57,7 +57,7 @@ function setCheckedState( checkbox, checked ) {
e.initCustomEvent( 'input', true /* canBubble */, false, false );
}
checkbox.dispatchEvent( e );
}
};

/**
* Returns true if the Event's target is an inclusive descendant of any the checkbox hack's
Expand All @@ -70,13 +70,14 @@ function setCheckedState( checkbox, checked ) {
* @return {boolean}
* @ignore
*/
function containsEventTarget( checkbox, button, target, event ) {
return event.target instanceof Node && (
checkbox.contains( event.target ) ||
button.contains( event.target ) ||
target.contains( event.target )
const containsEventTarget = ( checkbox, button, target, event ) => {
return (
event.target instanceof Node &&
( checkbox.contains( event.target ) ||
button.contains( event.target ) ||
target.contains( event.target ) )
);
}
};

/**
* Dismiss the target when event is outside the checkbox, button, and target.
Expand All @@ -89,11 +90,14 @@ function containsEventTarget( checkbox, button, target, event ) {
* @return {void}
* @ignore
*/
function dismissIfExternalEventTarget( checkbox, button, target, event ) {
if ( checkbox.checked && !containsEventTarget( checkbox, button, target, event ) ) {
const dismissIfExternalEventTarget = ( checkbox, button, target, event ) => {
if (
checkbox.checked &&
!containsEventTarget( checkbox, button, target, event )
) {
setCheckedState( checkbox, false );
}
}
};

/**
* Update the `aria-expanded` attribute based on checkbox state (target visibility) changes.
Expand All @@ -102,15 +106,15 @@ function dismissIfExternalEventTarget( checkbox, button, target, event ) {
* @return {function(): void} Cleanup function that removes the added event listeners.
* @ignore
*/
function bindUpdateAriaExpandedOnInput( checkbox ) {
const bindUpdateAriaExpandedOnInput = ( checkbox ) => {
const listener = updateAriaExpanded.bind( undefined, checkbox );
// Whenever the checkbox state changes, update the `aria-expanded` state.
checkbox.addEventListener( 'input', listener );

return function () {
return () => {
checkbox.removeEventListener( 'input', listener );
};
}
};

/**
* Manually change the checkbox state to avoid a focus change when using a pointing device.
Expand All @@ -120,19 +124,19 @@ function bindUpdateAriaExpandedOnInput( checkbox ) {
* @return {function(): void} Cleanup function that removes the added event listeners.
* @ignore
*/
function bindToggleOnClick( checkbox, button ) {
function listener( event ) {
const bindToggleOnClick = ( checkbox, button ) => {
const listener = ( event ) => {
// Do not allow the browser to handle the checkbox. Instead, manually toggle it which does
// not alter focus.
event.preventDefault();
setCheckedState( checkbox, !checkbox.checked );
}
};
button.addEventListener( 'click', listener, true );

return function () {
return () => {
button.removeEventListener( 'click', listener, true );
};
}
};

/**
* Manually change the checkbox state when the button is focused and Enter is pressed.
Expand All @@ -141,22 +145,22 @@ function bindToggleOnClick( checkbox, button ) {
* @return {function(): void} Cleanup function that removes the added event listeners.
* @ignore
*/
function bindToggleOnEnter( checkbox ) {
function onKeyup( /** @type {KeyboardEvent} @ignore */ event ) {
const bindToggleOnEnter = ( checkbox ) => {
const onKeyup = ( { key } ) => {
// Only handle ENTER.
if ( event.key !== 'Enter' ) {
if ( key !== 'Enter' ) {
return;
}

setCheckedState( checkbox, !checkbox.checked );
}
};

checkbox.addEventListener( 'keyup', onKeyup );

return function () {
return () => {
checkbox.removeEventListener( 'keyup', onKeyup );
};
}
};

/**
* Dismiss the target when clicking elsewhere and update the `aria-expanded` attribute based on
Expand All @@ -169,14 +173,19 @@ function bindToggleOnEnter( checkbox ) {
* @return {function(): void} Cleanup function that removes the added event listeners.
* @ignore
*/
function bindDismissOnClickOutside( window, checkbox, button, target ) {
const listener = dismissIfExternalEventTarget.bind( undefined, checkbox, button, target );
const bindDismissOnClickOutside = ( window, checkbox, button, target ) => {
const listener = dismissIfExternalEventTarget.bind(
undefined,
checkbox,
button,
target
);
window.addEventListener( 'click', listener, true );

return function () {
return () => {
window.removeEventListener( 'click', listener, true );
};
}
};

/**
* Dismiss the target when focusing elsewhere and update the `aria-expanded` attribute based on
Expand All @@ -189,16 +198,21 @@ function bindDismissOnClickOutside( window, checkbox, button, target ) {
* @return {function(): void} Cleanup function that removes the added event listeners.
* @ignore
*/
function bindDismissOnFocusLoss( window, checkbox, button, target ) {
const bindDismissOnFocusLoss = ( window, checkbox, button, target ) => {
// If focus is given to any element outside the target, dismiss the target. Setting a focusout
// listener on the target would be preferable, but this interferes with the click listener.
const listener = dismissIfExternalEventTarget.bind( undefined, checkbox, button, target );
const listener = dismissIfExternalEventTarget.bind(
undefined,
checkbox,
button,
target
);
window.addEventListener( 'focusin', listener, true );

return function () {
return () => {
window.removeEventListener( 'focusin', listener, true );
};
}
};

/**
* Dismiss the target when ESCAPE is pressed.
Expand All @@ -209,20 +223,20 @@ function bindDismissOnFocusLoss( window, checkbox, button, target ) {
* @return {function(): void} Cleanup function that removes the added event listeners.
* @ignore
*/
function bindDismissOnEscape( window, checkbox ) {
const onKeyup = function ( /** @type {KeyboardEvent} */ event ) {
const bindDismissOnEscape = ( window, checkbox ) => {
const onKeyup = ( { key } ) => {
// Only handle ESCAPE
if ( event.key !== 'Escape' ) {
if ( key !== 'Escape' ) {
return;
}
setCheckedState( checkbox, false );
};

window.addEventListener( 'keyup', onKeyup, true );
return function () {
return () => {
window.removeEventListener( 'keyup', onKeyup );
};
}
};

/**
* Dismiss the target when clicking or focusing elsewhere and update the `aria-expanded` attribute
Expand All @@ -241,7 +255,7 @@ function bindDismissOnEscape( window, checkbox ) {
* @return {function(): void} Cleanup function that removes the added event listeners.
* @ignore
*/
function bind( window, checkbox, button, target ) {
const bind = ( window, checkbox, button, target ) => {
const cleanups = [
bindUpdateAriaExpandedOnInput( checkbox ),
bindToggleOnClick( checkbox, button ),
Expand All @@ -251,12 +265,12 @@ function bind( window, checkbox, button, target ) {
bindDismissOnEscape( window, checkbox )
];

return function () {
cleanups.forEach( function ( cleanup ) {
return () => {
cleanups.forEach( ( cleanup ) => {
cleanup();
} );
};
}
};

module.exports = {
updateAriaExpanded: updateAriaExpanded,
Expand Down
14 changes: 7 additions & 7 deletions resources/skins.citizen.scripts/scrollObserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* @param {number} threshold minimum scrolled px to trigger the function
* @return {void}
*/
function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
const initDirectionObserver = ( onScrollDown, onScrollUp, threshold ) => {
const throttle = require( 'mediawiki.util' ).throttle;

let lastScrollTop = window.scrollY;

function onScroll() {
const onScroll = () => {
const scrollTop = window.scrollY;

if ( Math.abs( scrollTop - lastScrollTop ) < threshold ) {
Expand All @@ -24,10 +24,10 @@ function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
onScrollUp();
}
lastScrollTop = scrollTop;
}
};

window.addEventListener( 'scroll', throttle( onScroll, 250 ) );
}
};

/**
* Create an observer based on element visiblity.
Expand All @@ -37,9 +37,9 @@ function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
* @param {Function} onVisible functionality for when the element is hidden
* @return {IntersectionObserver}
*/
function initIntersectionObserver( onHidden, onVisible ) {
const initIntersectionObserver = ( onHidden, onVisible ) => {
/* eslint-disable-next-line compat/compat */
return new IntersectionObserver( function ( entries ) {
return new IntersectionObserver( ( entries ) => {
if ( !entries[ 0 ].isIntersecting && entries[ 0 ].boundingClientRect.top < 0 ) {
// Viewport has crossed the bottom edge of the target element.
onHidden();
Expand All @@ -48,7 +48,7 @@ function initIntersectionObserver( onHidden, onVisible ) {
onVisible();
}
} );
}
};

module.exports = {
initDirectionObserver,
Expand Down
Loading

0 comments on commit 3f3b2a3

Please sign in to comment.