fix: 🐛 JS

Signed-off-by: WaitSpring <me@waitspring.com>
这个提交包含在:
WaitSpring 2023-02-12 13:55:25 +08:00
父节点 c0bd16bda3
当前提交 346b68ed77
共有 8 个文件被更改,包括 66 次插入79 次删除

查看文件

@ -210,7 +210,7 @@ function bindDismissOnFocusLoss( window, checkbox, button, target ) {
* @ignore
*/
function bindDismissOnEscape( window, checkbox ) {
const onKeyup = ( /** @type {KeyboardEvent} */ event ) => {
const onKeyup = function ( /** @type {KeyboardEvent} */ event ) {
// Only handle ESCAPE
if ( event.key !== 'Escape' ) {
return;

查看文件

@ -11,7 +11,7 @@ function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
let lastScrollTop = window.scrollY;
const onScroll = () => {
function onScroll() {
const scrollTop = window.scrollY;
if ( Math.abs( scrollTop - lastScrollTop ) < threshold ) {
@ -24,7 +24,7 @@ function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
onScrollUp();
}
lastScrollTop = scrollTop;
};
}
window.addEventListener( 'scroll', throttle( onScroll, 250 ) );
}
@ -39,7 +39,7 @@ function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
*/
function initIntersectionObserver( onHidden, onVisible ) {
/* eslint-disable-next-line compat/compat */
return new IntersectionObserver( ( entries ) => {
return new IntersectionObserver( function ( entries ) {
if ( !entries[ 0 ].isIntersecting && entries[ 0 ].boundingClientRect.top < 0 ) {
// Viewport has crossed the bottom edge of the target element.
onHidden();

查看文件

@ -15,10 +15,10 @@ const SEARCH_LOADING_CLASS = 'citizen-loading';
* @param {function(): void} afterLoadFn function to execute after search module loads.
*/
function loadSearchModule( element, moduleName, afterLoadFn ) {
const requestSearchModule = () => {
function requestSearchModule() {
mw.loader.using( moduleName, afterLoadFn );
element.removeEventListener( 'focus', requestSearchModule );
};
}
if ( document.activeElement === element ) {
requestSearchModule();
@ -123,7 +123,7 @@ function isFormField( element ) {
* @return {void}
*/
function bindExpandOnSlash( window, checkbox, input ) {
const onExpandOnSlash = ( /** @type {KeyboardEvent} */ event ) => {
const onExpandOnSlash = function ( /** @type {KeyboardEvent} */ event ) {
// Only handle SPACE and ENTER.
if ( event.key === '/' && !isFormField( event.target ) ) {
// Since Firefox quickfind interfere with this
@ -149,10 +149,9 @@ function initSearch( window ) {
return;
}
searchBoxes.forEach( ( searchBox ) => {
searchBoxes.forEach( function ( searchBox ) {
const
input = searchBox.querySelector( 'input[name="search"]' ),
isPrimarySearch = input && input.getAttribute( 'id' ) === 'searchInput';
input = searchBox.querySelector( 'input[name="search"]' ), isPrimarySearch = input && input.getAttribute( 'id' ) === 'searchInput';
if ( !input ) {
return;
@ -163,13 +162,13 @@ function initSearch( window ) {
const checkbox = document.getElementById( 'citizen-search__checkbox' );
bindExpandOnSlash( window, checkbox, input );
// Focus when toggled
checkbox.addEventListener( 'input', () => {
checkbox.addEventListener( 'input', function () {
focusOnChecked( checkbox, input );
} );
}
setLoadingIndicatorListeners( searchBox, true, renderSearchLoadingIndicator );
loadSearchModule( input, searchModule, () => {
loadSearchModule( input, searchModule, function () {
setLoadingIndicatorListeners( searchBox, false, renderSearchLoadingIndicator );
} );
} );

查看文件

@ -48,44 +48,37 @@ function sectionObserver( props ) {
props = Object.assign( {
topMargin: 0,
throttleMs: 200,
onIntersection: () => {}
onIntersection: function () { }
}, props );
let /** @type {boolean} */ inThrottle = false;
let /** @type {HTMLElement | undefined} */ current;
// eslint-disable-next-line compat/compat
const observer = new IntersectionObserver( ( entries ) => {
const observer = new IntersectionObserver( function ( entries ) {
let /** @type {IntersectionObserverEntry | undefined} */ closestNegativeEntry;
let /** @type {IntersectionObserverEntry | undefined} */ closestPositiveEntry;
const topMargin = /** @type {number} */ ( props.topMargin );
entries.forEach( ( entry ) => {
const top =
entry.boundingClientRect.top - topMargin;
if (
top > 0 &&
(
closestPositiveEntry === undefined ||
top < closestPositiveEntry.boundingClientRect.top - topMargin
)
entries.forEach( function ( entry ) {
const top = entry.boundingClientRect.top - topMargin;
if ( top > 0 &&
( closestPositiveEntry === undefined ||
top < closestPositiveEntry.boundingClientRect.top - topMargin )
) {
closestPositiveEntry = entry;
}
if (
top <= 0 &&
(
closestNegativeEntry === undefined ||
top > closestNegativeEntry.boundingClientRect.top - topMargin
)
if ( top <= 0 &&
( closestNegativeEntry === undefined ||
top > closestNegativeEntry.boundingClientRect.top - topMargin )
) {
closestNegativeEntry = entry;
}
} );
const closestTag =
/** @type {HTMLElement} */ ( closestNegativeEntry ? closestNegativeEntry.target :
/** @type {IntersectionObserverEntry} */ ( closestPositiveEntry ).target
/** @type {HTMLElement} */ ( closestNegativeEntry ? closestNegativeEntry.target :
/** @type {IntersectionObserverEntry} */ ( closestPositiveEntry ).target
);
// If the intersection is new, fire the `onIntersection` callback.
@ -109,8 +102,8 @@ function sectionObserver( props ) {
function calcIntersection() {
// IntersectionObserver will asynchronously calculate the boundingClientRect
// of each observed element off the main thread after `observe` is called.
props.elements.forEach( ( element ) => {
observer.observe( /** @type {HTMLElement} */ ( element ) );
props.elements.forEach( function ( element ) {
observer.observe( /** @type {HTMLElement} */( element ) );
} );
}
@ -119,7 +112,7 @@ function sectionObserver( props ) {
if ( !inThrottle ) {
inThrottle = true;
setTimeout( () => {
setTimeout( function () {
calcIntersection();
inThrottle = false;
}, props.throttleMs );

查看文件

@ -28,9 +28,8 @@ function bind() {
// Search for all dropdown containers using the CHECKBOX_HACK_CONTAINER_SELECTOR.
const containers = document.querySelectorAll( CHECKBOX_HACK_CONTAINER_SELECTOR );
containers.forEach( ( container ) => {
const
checkbox = container.querySelector( CHECKBOX_HACK_CHECKBOX_SELECTOR ),
containers.forEach( function ( container ) {
const checkbox = container.querySelector( CHECKBOX_HACK_CHECKBOX_SELECTOR ),
button = container.querySelector( CHECKBOX_HACK_BUTTON_SELECTOR ),
target = container.querySelector( CHECKBOX_HACK_TARGET_SELECTOR );
@ -50,7 +49,7 @@ function bind() {
function uncheckCheckboxHacks() {
const checkboxes = document.querySelectorAll( CHECKBOX_HACK_CHECKBOX_SELECTOR + ':checked' );
checkboxes.forEach( ( checkbox ) => {
checkboxes.forEach( function ( checkbox ) {
/** @type {HTMLInputElement} */ ( checkbox ).checked = false;
} );
}
@ -66,11 +65,11 @@ function initStickyHeader( document ) {
// Detect scroll direction and add the right class
// scrollObserver.initDirectionObserver(
// () => {
// function () {
// document.body.classList.remove( 'citizen-scroll--up' );
// document.body.classList.add( 'citizen-scroll--down' );
// },
// () => {
// function () {
// document.body.classList.remove( 'citizen-scroll--down' );
// document.body.classList.add( 'citizen-scroll--up' );
// },
@ -83,10 +82,10 @@ function initStickyHeader( document ) {
// Do not start observer if it is set to display:none
if ( sentinel && getComputedStyle( sentinel ).getPropertyValue( 'display' ) !== 'none' ) {
const observer = scrollObserver.initIntersectionObserver(
() => {
function () {
document.body.classList.add( 'citizen-body-header--sticky' );
},
() => {
function () {
document.body.classList.remove( 'citizen-body-header--sticky' );
}
);
@ -122,7 +121,7 @@ function main( window ) {
sections.init();
}
window.addEventListener( 'beforeunload', () => {
window.addEventListener( 'beforeunload', function () {
// T295085: Close all dropdown menus when page is unloaded to prevent them
// from being open when navigating back to a page.
uncheckCheckboxHacks();

查看文件

@ -8,10 +8,8 @@ let /** @type {HTMLElement | undefined} */ activeSection;
function changeActiveSection( id ) {
const toc = document.getElementById( 'mw-panel-toc' );
const getLink = ( hash ) => {
const
prefix = 'a[href="#',
suffix = '"]';
const getLink = function ( hash ) {
const prefix = 'a[href="#', suffix = '"]';
let el = toc.querySelector( prefix + hash + suffix );
@ -45,7 +43,7 @@ function initToC() {
// We use scroll-padding-top to handle scrolling with fixed header
// It is better to respect that so it is consistent
const getTopMargin = () => {
const getTopMargin = function () {
return Number(
window.getComputedStyle( document.documentElement )
.getPropertyValue( 'scroll-padding-top' )
@ -59,7 +57,9 @@ function initToC() {
/* T13555 */
elements: bodyContent.querySelectorAll( '.mw-headline' ) ? bodyContent.querySelectorAll( '.mw-headline' ) : bodyContent.querySelectorAll( '.mw-heading' ),
topMargin: getTopMargin(),
onIntersection: ( section ) => { changeActiveSection( section.id ); }
onIntersection: function ( section ) {
changeActiveSection( section.id );
}
} );
// TODO: Pause section observer on ToC link click

查看文件

@ -61,7 +61,7 @@ function getUrl( input ) {
* @return {Object} Results
*/
function convertDataToResults( data ) {
const getDisplayTitle = ( item ) => {
const getDisplayTitle = function ( item ) {
if ( item.pageprops && item.pageprops.displaytitle ) {
return item.pageprops.displaytitle;
} else {
@ -69,7 +69,7 @@ function convertDataToResults( data ) {
}
};
const getDescription = ( item ) => {
const getDescription = function ( item ) {
switch ( descriptionSource ) {
case 'wikidata':
return item.description || '';
@ -90,7 +90,7 @@ function convertDataToResults( data ) {
data = Object.values( data.query.pages );
// Sort the data with the index property since it is not in order
data.sort( ( a, b ) => {
data.sort( function ( a, b ) {
return a.index - b.index;
} );

查看文件

@ -120,15 +120,15 @@ function keyboardEvents( event ) {
}
/**
* Bind mouseenter and mouseleave event to reproduce mouse hover event
* Bind mouseenter and mouseleave event to reproduce mouse hover event
*
* @param {HTMLElement} element
*/
function bindMouseHoverEvent( element ) {
element.addEventListener( 'mouseenter', ( event ) => {
element.addEventListener( 'mouseenter', function ( event ) {
toggleActive( event.currentTarget );
} );
element.addEventListener( 'mouseleave', ( event ) => {
element.addEventListener( 'mouseleave', function ( event ) {
toggleActive( event.currentTarget );
} );
}
@ -146,7 +146,7 @@ function clearSuggestions() {
fragment = new DocumentFragment(),
template = document.getElementById( `${PREFIX}-template` );
[ ...typeaheadItems ].forEach( ( item ) => {
[ ...typeaheadItems ].forEach( function ( item ) {
if ( !item.classList.contains( `${ITEM_CLASS}--page` ) ) {
fragment.append( item );
}
@ -169,18 +169,17 @@ function clearSuggestions() {
* @param {HTMLElement} placeholder
*/
function getSuggestions( searchQuery, htmlSafeSearchQuery, placeholder ) {
const renderSuggestions = ( results ) => {
function renderSuggestions( results ) {
if ( results.length > 0 ) {
const
fragment = document.createDocumentFragment(),
suggestionLinkPrefix = `${config.wgScriptPath}/index.php?title=Special:Search&search=`;
fragment = document.createDocumentFragment(), suggestionLinkPrefix = `${config.wgScriptPath}/index.php?title=Special:Search&search=`;
/**
* Return the redirect title with search query highlight
*
* @param {string} text
* @return {string}
*/
const highlightTitle = ( text ) => {
const highlightTitle = function ( text ) {
const regex = new RegExp( mw.util.escapeRegExp( htmlSafeSearchQuery ), 'i' );
return text.replace( regex, `<span class="${PREFIX}__highlight">$&</span>` );
};
@ -191,24 +190,23 @@ function getSuggestions( searchQuery, htmlSafeSearchQuery, placeholder ) {
* @param {string} matchedTitle
* @return {string}
*/
const getRedirectLabel = ( title, matchedTitle ) => {
const getRedirectLabel = function ( title, matchedTitle ) {
/**
* Check if the redirect is useful (T303013)
*
* @return {boolean}
*/
const isRedirectUseful = () => {
const isRedirectUseful = function () {
// Change to lowercase then remove space and dashes
const cleanup = ( text ) => {
const cleanup = function ( text ) {
return text.toLowerCase().replace( /-|\s/g, '' );
};
const
cleanTitle = cleanup( title ),
cleanMatchedTitle = cleanup( matchedTitle );
cleanTitle = cleanup( title ), cleanMatchedTitle = cleanup( matchedTitle );
return !(
cleanTitle.includes( cleanMatchedTitle ) ||
cleanMatchedTitle.includes( cleanTitle )
cleanMatchedTitle.includes( cleanTitle )
);
};
@ -226,7 +224,7 @@ function getSuggestions( searchQuery, htmlSafeSearchQuery, placeholder ) {
};
// Create suggestion items
results.forEach( ( result, index ) => {
results.forEach( function ( result, index ) {
const data = {
id: `${PREFIX}-suggestion-${index}`,
type: 'page',
@ -262,7 +260,7 @@ function getSuggestions( searchQuery, htmlSafeSearchQuery, placeholder ) {
);
placeholder.classList.remove( HIDDEN_CLASS );
}
};
}
// Add loading animation
searchInput.parentNode.classList.add( SEARCH_LOADING_CLASS );
@ -270,7 +268,7 @@ function getSuggestions( searchQuery, htmlSafeSearchQuery, placeholder ) {
const
// eslint-disable-next-line compat/compat
controller = new AbortController(),
abortFetch = () => {
abortFetch = function () {
controller.abort();
};
@ -282,13 +280,13 @@ function getSuggestions( searchQuery, htmlSafeSearchQuery, placeholder ) {
// So that fetch request won't be queued up
searchInput.addEventListener( 'input', abortFetch, { once: true } );
getResults.then( ( results ) => {
getResults.then( function ( results ) {
searchInput.removeEventListener( 'input', abortFetch );
clearSuggestions();
if ( results !== null ) {
renderSuggestions( results );
}
} ).catch( ( error ) => {
} ).catch( function ( error ) {
searchInput.removeEventListener( 'input', abortFetch );
searchInput.parentNode.classList.remove( SEARCH_LOADING_CLASS );
// User can trigger the abort when the fetch event is pending
@ -382,11 +380,9 @@ function updateTypeahead( messages ) {
*
* @param {Object} data
*/
const updateToolItem = ( data ) => {
const updateToolItem = function ( data ) {
const
itemId = `${PREFIX}-${data.id}`,
query = `<span class="citizen-typeahead__query">${htmlSafeSearchQuery}</span>`,
itemLink = data.link + htmlSafeSearchQuery,
itemId = `${PREFIX}-${data.id}`, query = `<span class="citizen-typeahead__query">${htmlSafeSearchQuery}</span>`, itemLink = data.link + htmlSafeSearchQuery,
/* eslint-disable-next-line mediawiki/msg-doc */
itemDesc = mw.message( data.msg, query );
@ -478,13 +474,13 @@ function initTypeahead( searchForm, input ) {
'msg-citizen-search-empty-desc': messages.emptyDesc
};
const onBlur = ( event ) => {
const onBlur = function ( event ) {
const focusIn = typeahead.contains( event.relatedTarget );
if ( !focusIn ) {
// HACK: On Safari, users are unable to click any links because the blur
// event dismiss the links before it is clicked. This should fix it.
setTimeout( () => {
setTimeout( function () {
searchInput.setAttribute( 'aria-activedescendant', '' );
typeahead.classList.remove( EXPANDED_CLASS );
searchInput.removeEventListener( 'keydown', keyboardEvents );
@ -493,7 +489,7 @@ function initTypeahead( searchForm, input ) {
}
};
const onFocus = () => {
const onFocus = function () {
// Refresh the typeahead since the query will be emptied when blurred
updateTypeahead( messages );
typeahead.classList.add( EXPANDED_CLASS );
@ -519,7 +515,7 @@ function initTypeahead( searchForm, input ) {
updateTypeahead( messages );
}
searchInput.addEventListener( 'input', () => {
searchInput.addEventListener( 'input', function () {
mw.util.debounce( 100, updateTypeahead( messages ) );
} );