refactor(search): ♻️ partial cleanup on typeahead DOM

This commit is contained in:
alistair3149 2022-12-04 02:13:37 -05:00
parent 22e1324a80
commit 99b3523cd6
No known key found for this signature in database
3 changed files with 100 additions and 118 deletions

View file

@ -15,9 +15,18 @@
// Well this won't be loaded before .citizen-animation-ready anyways
.citizen-card-transition();
&-suggestion {
padding-top: 0.375rem;
padding-bottom: 0.375rem;
&__item {
&--active {
background-color: var( --background-color-primary--hover );
}
}
&__content {
display: flex;
align-items: center;
padding: 0.375rem 0.75rem;
color: var( --color-base );
}
&__thumbnail {
overflow: hidden;
@ -83,7 +92,6 @@
overflow: hidden;
text-overflow: ellipsis;
}
}
&-footer {
padding-top: var( --border-radius--large );
@ -104,20 +112,6 @@
}
}
&-option {
&--active {
background-color: var( --background-color-primary--hover );
}
}
a {
display: flex;
align-items: center;
padding-right: 0.75rem;
padding-left: 0.75rem;
color: var( --color-base );
}
picture {
width: 100%;
max-width: 70px;

View file

@ -3,26 +3,26 @@
}}
<ol id="searchform-suggestions" class="citizen-typeahead" role="listbox">
<li role="option">
<a href="" id="searchform-suggestions-footer" class="citizen-typeahead-footer">
<li role="option" class="citizen-typeahead__item">
<a href="" id="searchform-suggestions-footer" class="citizen-typeahead-footer citizen-typeahead__content">
<picture class="citizen-typeahead-footer__icon">
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+DQoJPHBhdGggZmlsbD0iIzM2YyIgZD0iTTcuNSAxM2MzLjA0IDAgNS41LTIuNDYgNS41LTUuNVMxMC41NCAyIDcuNSAyIDIgNC40NiAyIDcuNSA0LjQ2IDEzIDcuNSAxM3ptNC41NS40NkE3LjQzMiA3LjQzMiAwIDAgMSA3LjUgMTVDMy4zNiAxNSAwIDExLjY0IDAgNy41UzMuMzYgMCA3LjUgMEMxMS42NCAwIDE1IDMuMzYgMTUgNy41YzAgMS43MS0uNTcgMy4yOS0xLjU0IDQuNTVsNi40OSA2LjQ5LTEuNDEgMS40MS02LjQ5LTYuNDl6Ii8+DQoJPHBhdGggZmlsbD0iIzM2YyIgZD0iTTQgNWg3djFINHptMCAyaDd2MUg0em0wIDJoNS40NDR2MUg0eiIvPg0KPC9zdmc+DQo="/>
</picture>
<div class="citizen-typeahead-footer__text">{{{msg-citizen-search-fulltext}}}</div>
</a>
</li>
<template id="citizen-typeahead-suggestion-template">
<li role="option">
<a href="" class="citizen-typeahead-suggestion">
<picture class="citizen-typeahead-suggestion__thumbnail">
<template id="citizen-typeahead-template">
<li role="option" class="citizen-typeahead__item">
<a href="" class="citizen-typeahead__content">
<picture class="citizen-typeahead__thumbnail">
<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNTYgNTYiPg0KCTxwYXRoIGZpbGw9IiNlYWVjZjAiIGQ9Ik0wIDBoNTZ2NTZIMCIvPg0KCTxwYXRoIGZpbGw9IiM3Mjc3N2QiIGQ9Ik0zNi40IDEzLjVIMTcuOHYyNC45YzAgMS40LjkgMi4zIDIuMyAyLjNoMTguN3YtMjVjLjEtMS40LTEtMi4yLTIuNC0yLjJ6TTMwLjIgMTdoNS4xdjYuNGgtNS4xVjE3em0tOC44IDBoNnYxLjhoLTZWMTd6bTAgNC42aDZ2MS44aC02di0xLjh6bTAgMTUuNXYtMS44aDEzLjh2MS44SDIxLjR6bTEzLjgtNC41SDIxLjR2LTEuOGgxMy44djEuOHptMC00LjdIMjEuNHYtMS44aDEzLjh2MS44eiIvPg0KPC9zdmc+DQo="/>
</picture>
<div class="citizen-typeahead-suggestion__text">
<div class="citizen-typeahead-suggestion__header">
<div class="citizen-typeahead-suggestion__title"></div>
<div class="citizen-typeahead-suggestion__label"></div>
<div class="citizen-typeahead__text">
<div class="citizen-typeahead__header">
<div class="citizen-typeahead__title"></div>
<div class="citizen-typeahead__label"></div>
</div>
<div class="citizen-typeahead-suggestion__description"></div>
<div class="citizen-typeahead__description"></div>
</div>
</a>
</li>

View file

@ -1,6 +1,6 @@
const
config = require( './config.json' ),
PREFIX = 'citizen-typeahead-suggestion',
PREFIX = 'citizen-typeahead',
SEARCH_LOADING_CLASS = 'citizen-loading';
const activeIndex = {
@ -37,8 +37,8 @@ let typeahead, searchInput;
* @return {void}
*/
function toggleActive( element ) {
const typeaheadItems = typeahead.querySelectorAll( 'li > a' ),
activeClass = 'citizen-typeahead-option--active';
const typeaheadItems = typeahead.querySelectorAll( '.' + PREFIX + '__item' ),
activeClass = PREFIX + '__item--active';
for ( let i = 0; i < typeaheadItems.length; i++ ) {
if ( element !== typeaheadItems[ i ] ) {
@ -68,7 +68,7 @@ function keyboardEvents( event ) {
}
// Is children slower?
const typeaheadItems = typeahead.querySelectorAll( 'li > a' );
const typeaheadItems = typeahead.querySelectorAll( '.' + PREFIX + '__item' );
if ( event.key === 'ArrowDown' || event.key === 'ArrowUp' ) {
if ( event.key === 'ArrowDown' ) {
@ -86,6 +86,18 @@ function keyboardEvents( event ) {
}
}
/*
* Attach mouse eventlistener to all typeahead items
*
* @return {void}
*/
function attachMouseListener() {
const items = typeahead.querySelectorAll( '.' + PREFIX + '__item' );
items.forEach( ( item ) => {
bindMouseHoverEvent( item );
} );
}
/*
* Bind mouseenter and mouseleave event to reproduce mouse hover event
*
@ -157,26 +169,10 @@ function getSuggestions( searchQuery ) {
return text.replace( regex, '<span class="' + PREFIX + '__highlight">$&</span>' );
};
const getSuggestionTitle = ( title, matchedTitle ) => {
let html;
// Result is a redirect
// Show the redirect title and highlight it
if ( matchedTitle && isRedirectUseful( title, matchedTitle ) ) {
html = title +
'<span class="' + PREFIX + '__redirect">' +
mw.message( 'search-redirect', highlightTitle( matchedTitle ) ).plain() +
'</span>';
} else {
// Highlight title
html = highlightTitle( title );
}
return html;
};
const getRedirectLabel = ( title, matchedTitle ) => {
// Check if the redirect is useful
// See T303013
const isRedirectUseful = ( title, matchedTitle ) => {
const isRedirectUseful = () => {
// Change to lowercase then remove space and dashes
const cleanup = ( text ) => {
return text.toLowerCase().replace( /-|\s/g, '' );
@ -190,7 +186,7 @@ function getSuggestions( searchQuery ) {
// Result is a redirect
// Show the redirect title and highlight it
if ( matchedTitle && isRedirectUseful( title, matchedTitle ) ) {
if ( matchedTitle && isRedirectUseful() ) {
html = '<div class="' + PREFIX + '__labelItem" title="' + mw.message( 'search-redirect', matchedTitle ).plain() + '">' +
/* Article redirect icon */
'<span class="citizen-ui-icon mw-ui-icon-wikimedia-articleRedirect"></span>' +
@ -217,14 +213,6 @@ function getSuggestions( searchQuery ) {
typeahead.prepend( fragment );
};
// Attach mouseenter events to newly created suggestions
const attachMouseListener = () => {
const suggestions = typeahead.querySelectorAll( '.citizen-typeahead-suggestion' );
suggestions.forEach( ( suggestion ) => {
bindMouseHoverEvent( suggestion );
} );
};
// Add loading animation
searchInput.parentNode.classList.add( SEARCH_LOADING_CLASS );
@ -278,7 +266,7 @@ function getMenuItem( data ) {
const
item = template.content.cloneNode( true ),
link = item.querySelector( '.' + PREFIX ),
link = item.querySelector( '.' + PREFIX + '__content' ),
thumbnail = item.querySelector( '.' + PREFIX + '__thumbnail img' ),
title = item.querySelector( '.' + PREFIX + '__title' ),
label = item.querySelector( '.' + PREFIX + '__label' ),
@ -376,8 +364,8 @@ function initTypeahead( searchForm, input ) {
searchInput.setAttribute( 'aria-autocomplete', 'list' );
searchInput.setAttribute( 'aria-controls', 'searchform-suggestions' );
const footer = document.getElementById( 'searchform-suggestions-footer' );
bindMouseHoverEvent( footer );
// Attach mouse listener to inital typeahead items
attachMouseListener();
// Since searchInput is focused before the event listener is set up
onFocus();