Problem/Motivation
The Alt + a shortcut in admin_toolbar_search/js/admin_toolbar_search.keyboard_shortcut.js fails in two ways. Both were reproduced on 3.6.3 with Drupal 11.4.7. The file is the same in 3.x-dev.
1. It throws when the search tab is not on the page.
// Get the search tab which should *always* be loaded.
const searchTab = context.getElementById('admin-toolbar-search-tab');
const searchTabStyle = window.getComputedStyle(searchTab);
A site can remove the administration_search toolbar item in hook_toolbar_alter() to keep only the search field (administration_search_field). The libraries are attached to administration_search only, so the alter hook has to move #attached onto the field item to keep the stylesheet and autocomplete. The shortcut library then loads without the tab, searchTab is null, and every Alt + a logs:
Uncaught TypeError: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
The field placeholder still reads "(Alt + a)".
2. With Gin it focuses a hidden copy of the field.
With Gin 5.0.15 and Gin Toolbar 3.0.3 on the new navigation layout (gin.settings classic_toolbar: new), the toolbar is rendered twice: #toolbar-administration, which is display: none, and #toolbar-administration-secondary, which is visible. Every toolbar id is duplicated, including #admin-toolbar-search-field-tab and #admin-toolbar-search-field-input. getElementById() returns the first match, which is the hidden one, and .focus() on it does nothing. There is no error. Focus stays on body.
This second case needs no custom code. It happens with the search tab present.
Steps to reproduce
Case 1:
- Enable Admin Toolbar Search. Leave "display menu item" off and the keyboard shortcut on.
- In a custom module, implement
hook_toolbar_alter(): copy$items['administration_search']['#attached']onto$items['administration_search_field'], then unset$items['administration_search']. - Rebuild caches, open any admin page at desktop width and press Alt + a.
- The console shows the TypeError above. The field is not focused.
Case 2:
- Install Gin and Gin Toolbar and select the new navigation layout.
- Open any admin page at desktop width. In the console,
document.querySelectorAll('[id="admin-toolbar-search-field-input"]').lengthreturns 2. - Press Alt + a.
- Nothing is focused.
document.activeElementis stillbody.
Proposed resolution
Look the elements up by visibility instead of by first id match, and return when neither is present:
const visible = (id) =>
Array.from(document.querySelectorAll('[id="' + id + '"]')).find(
(element) => element.getClientRects().length > 0,
);
const field = visible('admin-toolbar-search-field-input');
if (field) {
field.focus();
return;
}
const searchTab = visible('admin-toolbar-search-tab');
if (!searchTab) {
return;
}
// Existing tray toggle and focus on #admin-toolbar-search-input.
A visible field input already means the field tab is shown and the search tab is hidden, so the getComputedStyle() check is no longer needed.
#3532249: Uncaught TypeError: toolbarElement.querySelector(...) is null fixed the same kind of null access in admin_toolbar.toggle_shortcut.js with existence checks.
Separately, attaching the libraries to both toolbar items would let a site remove the tab without losing the search stylesheet and autocomplete.
Related: #3571169: Two search inputs display when using Gin theme (two search inputs with Gin), #3557278: Gin theme: Improve compatibility support (Gin compatibility), and the duplicate toolbar ids in Gin Toolbar: https://git.drupalcode.org/project/gin_toolbar/-/work_items/3373687
Remaining tasks
- Merge request with the lookup above.
- Test coverage for a page without the search tab and for a page with a hidden duplicate of the field.
User interface changes
None.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #5 | 3624439 after.png | 172.18 KB | csakiistvan |
| #5 | 3624439 before.png | 1003.55 KB | csakiistvan |
Issue fork admin_toolbar-3624439
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
jmcerdaMerge request !217 is up against 3.x.
The handler now picks the first visible element for each ID instead of the first match. A visible search field is focused directly. Otherwise the visible search tab's tray is toggled and its input focused, as before. When neither exists it returns without calling
preventDefault(), so nothing throws and the keystroke is left alone.One new test,
AdminToolbarSearchEventsTest::testAdminToolbarSearchKeyboardShortcutSearchField(), covers the search field in the toolbar, a hidden duplicate placed before it, a page without the search tab, and a page with nothing to focus.The pipeline is green. The "test-only changes" job fails as expected: on the current code the new test fails at the hidden duplicate step, and the two existing tray tests still pass.
Also checked by hand on a Gin site with the new navigation layout, serving the patched file in place of the released one: Alt + a focuses the visible field with the duplicate present, and still does with the search tab removed.
Comment #4
csakiistvanComment #5
csakiistvan@jmcerda: ❓ Needs more info — with MR !217 applied and caches rebuilt, case 1 is fixed: the
getComputedStyleTypeError on Alt + a is gone once the search tab is removed in hook_toolbar_alter(). Case 2 could not be reproduced as written — with gin.settings classic_toolbar: new no admin toolbar search element is rendered at all, so there is nothing to focus; in the Gin configuration where the ids are duplicated, Alt + a still focuses the first copy, so it is unclear which Gin setup the report means.