mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-14 11:15:33 +00:00
ce77018b7c
[Visual changes] This should result in 9 visual regression failures relating to increased height of search results and loading bar [More details about change] - Migrate search app from Vue 2 to Vue 3; update tests accordingly - Remove dependence on WVUI and use Codex instead, via the special `@wikimedia/codex-search` package - Update search app to use CdxTypeaheadSearch, which no longer takes in props related to the search client or fetch start/end instrumentation. Instead, directly use the restSearchClient and call fetch start/end events in the search app. - Handle hideDirection in the search app/API response formatting code, not within the TypeaheadSearch component - Handle showing/hiding the search button in the app - Move the WVUI URL generator into Vector - Update server-rendered search box styles to match design updates included with CdxTypeaheadSearch - Replace references to WVUI with references to Codex - Update values of various LESS variables to match Codex, and update searchBox styling to prevent jankiness when the searchBox is replaced with the Codex TypeaheadSearch component The VectorWvuiSearchOptions config variable has been maintained and will be updated to a code-agnostic name in a future patch. Bug: T300573 Bug: T302137 Bug: T303558 Bug: T309722 Bug: T310525 Co-Authored-By: Anne Tomasevich <atomasevich@wikimedia.org> Change-Id: I59fa3a006d988b14ebd8020cbd58e8d7bedbfe01
125 lines
4.2 KiB
JavaScript
125 lines
4.2 KiB
JavaScript
const
|
|
HEADER_SELECTOR = 'header',
|
|
SEARCH_BOX_SELECTOR = '.vector-search-box',
|
|
SEARCH_VISIBLE_CLASS = 'vector-header-search-toggled';
|
|
|
|
/**
|
|
* Binds event handlers necessary for the searchBox to disappear when the user
|
|
* clicks outside the searchBox.
|
|
*
|
|
* @param {HTMLElement} searchBox
|
|
* @param {HTMLElement} header
|
|
*/
|
|
function bindSearchBoxHandler( searchBox, header ) {
|
|
/**
|
|
* @param {Event} ev
|
|
* @ignore
|
|
*/
|
|
const clickHandler = ( ev ) => {
|
|
if (
|
|
ev.target instanceof HTMLElement &&
|
|
// Check if the click target was a suggestion link. Codex clears the
|
|
// suggestion elements from the DOM when a suggestion is clicked so we
|
|
// can't test if the suggestion is a child of the searchBox.
|
|
//
|
|
// Note: The .closest API is feature detected in `initSearchToggle`.
|
|
!ev.target.closest( '.cdx-typeahead-search .cdx-menu-item__content' ) &&
|
|
!searchBox.contains( ev.target )
|
|
) {
|
|
header.classList.remove( SEARCH_VISIBLE_CLASS );
|
|
|
|
document.removeEventListener( 'click', clickHandler );
|
|
}
|
|
};
|
|
|
|
document.addEventListener( 'click', clickHandler );
|
|
}
|
|
|
|
/**
|
|
* Binds event handlers necessary for the searchBox to show when the toggle is
|
|
* clicked.
|
|
*
|
|
* @param {HTMLElement} searchBox
|
|
* @param {HTMLElement} header
|
|
* @param {Element} searchToggle
|
|
*/
|
|
function bindToggleClickHandler( searchBox, header, searchToggle ) {
|
|
/**
|
|
* @param {Event} ev
|
|
* @ignore
|
|
*/
|
|
const handler = ( ev ) => {
|
|
// The toggle is an anchor element. Prevent the browser from navigating away
|
|
// from the page when clicked.
|
|
ev.preventDefault();
|
|
|
|
header.classList.add( SEARCH_VISIBLE_CLASS );
|
|
|
|
// Defer binding the search box handler until after the event bubbles to the
|
|
// top of the document so that the handler isn't called when the user clicks
|
|
// the search toggle. Event bubbled callbacks execute within the same task
|
|
// in the event loop.
|
|
//
|
|
// Also, defer focusing the input to another task in the event loop. At the time
|
|
// of this writing, Safari 14.0.3 has trouble changing the visibility of the
|
|
// element and focusing the input within the same task.
|
|
setTimeout( () => {
|
|
bindSearchBoxHandler( searchBox, header );
|
|
|
|
const searchInput = /** @type {HTMLInputElement|null} */ ( searchBox.querySelector( 'input[type="search"]' ) );
|
|
|
|
if ( searchInput ) {
|
|
const beforeScrollX = window.scrollX;
|
|
const beforeScrollY = window.scrollY;
|
|
searchInput.focus();
|
|
// For some reason, Safari 14,15 tends to undesirably change the scroll
|
|
// position of `input` elements inside fixed position elements.
|
|
// While an Internet search suggests similar problems with mobile Safari
|
|
// it didn't yield any results for desktop Safari.
|
|
// This line resets any unexpected scrolling that occurred while the
|
|
// input received focus.
|
|
// If you are in the future with a modern version of Safari, where 14 and 15
|
|
// receive a low amount of page views, please reference T297636 and test
|
|
// to see whether this line of code can be removed.
|
|
// Additionally, these lines might become unnecessary when/if Safari
|
|
// supports the `preventScroll` focus option [1] in the future:
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#parameters
|
|
if ( beforeScrollX !== undefined && beforeScrollY !== undefined ) {
|
|
window.scroll( beforeScrollX, beforeScrollY );
|
|
}
|
|
}
|
|
} );
|
|
};
|
|
|
|
searchToggle.addEventListener( 'click', handler );
|
|
}
|
|
|
|
/**
|
|
* Enables search toggling behavior in a header given a toggle element (e.g.
|
|
* search icon). When the toggle element is clicked, a class,
|
|
* `SEARCH_VISIBLE_CLASS`, will be applied to a header matching the selector
|
|
* `HEADER_SELECTOR` and the input inside the element, SEARCH_BOX_SELECTOR, will
|
|
* be focused. This class can be used in CSS to show/hide the necessary
|
|
* elements. When the user clicks outside of SEARCH_BOX_SELECTOR, the class will
|
|
* be removed.
|
|
*
|
|
* @param {HTMLElement|Element} searchToggle
|
|
*/
|
|
module.exports = function initSearchToggle( searchToggle ) {
|
|
const header =
|
|
/** @type {HTMLElement|null} */ ( searchToggle.closest( HEADER_SELECTOR ) );
|
|
|
|
if ( !header ) {
|
|
return;
|
|
}
|
|
|
|
const searchBox =
|
|
/** @type {HTMLElement|null} */ ( header.querySelector( SEARCH_BOX_SELECTOR ) );
|
|
|
|
if ( !searchBox ) {
|
|
return;
|
|
}
|
|
|
|
bindToggleClickHandler( searchBox, header, searchToggle );
|
|
};
|