Skip to content

Commit 5943ffc

Browse files
danilsomsikovDevtools-frontend LUCI CQ
authored andcommitted
Remove searchInputElement from SearchView outputs
The `SearchView` now stores the search query in a `#query` property and updates it via an `@input` event handler on the search input element. Focus and selection of the input are now triggered by a `#focusSearchInput` state. Tests have been updated to query for the input element and dispatch an `input` event after programmatically setting its value. Bug: 407750483 Change-Id: I4082e246e75e9bc52d00a52086e5837aef18c763 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6953923 Auto-Submit: Danil Somsikov <[email protected]> Reviewed-by: Philip Pfaffe <[email protected]> Commit-Queue: Philip Pfaffe <[email protected]>
1 parent 5eecf28 commit 5943ffc

File tree

2 files changed

+39
-34
lines changed

2 files changed

+39
-34
lines changed

front_end/panels/search/SearchView.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import * as Common from '../../core/common/common.js';
66
import type * as Workspace from '../../models/workspace/workspace.js';
7-
import {dispatchClickEvent, dispatchKeyDownEvent} from '../../testing/DOMHelpers.js';
7+
import {dispatchClickEvent, dispatchInputEvent, dispatchKeyDownEvent} from '../../testing/DOMHelpers.js';
88
import {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';
99
import * as UI from '../../ui/legacy/legacy.js';
1010

@@ -77,15 +77,17 @@ class TestSearchView extends Search.SearchView.SearchView {
7777

7878
/** Fills in the UI elements of the SearchView and hits 'Enter'. */
7979
triggerSearch(query: string, matchCase: boolean, isRegex: boolean): void {
80-
this.search.value = query;
80+
const search = this.contentElement.querySelector<HTMLInputElement>('.search-toolbar-input')!;
81+
search.value = query;
82+
dispatchInputEvent(search);
8183
if (matchCase) {
8284
this.matchCaseButton.click();
8385
}
8486
if (isRegex) {
8587
this.regexButton.click();
8688
}
8789

88-
dispatchKeyDownEvent(this.search, {keyCode: UI.KeyboardShortcut.Keys.Enter.code});
90+
dispatchKeyDownEvent(search, {keyCode: UI.KeyboardShortcut.Keys.Enter.code});
8991
}
9092

9193
get currentSearchResultMessage(): string {

front_end/panels/search/SearchView.ts

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,13 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
109109
const {ref} = Directives;
110110

111111
interface SearchViewInput {
112+
query: string;
113+
focusSearchInput: boolean;
112114
matchCase: boolean;
113115
isRegex: boolean;
114116
searchMessage: string;
115117
searchResultsMessage: string;
118+
onQueryChange: (query: string) => void;
116119
onQueryKeyDown: (evt: KeyboardEvent) => void;
117120
onPanelKeyDown: (evt: KeyboardEvent) => void;
118121
onClearSearchInput: () => void;
@@ -123,7 +126,6 @@ interface SearchViewInput {
123126
}
124127

125128
interface SearchViewOutput {
126-
searchInputElement?: HTMLInputElement;
127129
searchResultsElement?: HTMLElement;
128130
searchProgressPlaceholderElement?: HTMLElement;
129131
matchCaseButton?: Buttons.Button.Button;
@@ -134,10 +136,13 @@ type View = (input: SearchViewInput, output: SearchViewOutput, target: HTMLEleme
134136

135137
export const DEFAULT_VIEW: View = (input, output, target) => {
136138
const {
139+
query,
140+
focusSearchInput,
137141
matchCase,
138142
isRegex,
139143
searchMessage,
140144
searchResultsMessage,
145+
onQueryChange,
141146
onQueryKeyDown,
142147
onPanelKeyDown,
143148
onClearSearchInput,
@@ -160,8 +165,15 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
160165
change: true, keydown: 'ArrowUp|ArrowDown|Enter'})}
161166
aria-label=${i18nString(UIStrings.find)}
162167
size="100" results="0"
168+
.value=${query}
163169
@keydown=${onQueryKeyDown}
164-
${ref(e => {output.searchInputElement = e as HTMLInputElement;})}>
170+
@input=${(e: Event) => onQueryChange((e.target as HTMLInputElement).value)}
171+
${ref(e => {
172+
if (e instanceof HTMLInputElement && focusSearchInput) {
173+
e.focus();
174+
e.select();
175+
}
176+
})}>
165177
<devtools-button class="clear-button" tabindex="-1"
166178
@click=${onClearSearchInput}
167179
.data=${{
@@ -227,7 +239,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
227239

228240
export class SearchView extends UI.Widget.VBox {
229241
readonly #view: View;
230-
#focusOnShow: boolean;
242+
#focusSearchInput: boolean;
231243
#isIndexing: boolean;
232244
#searchId: number;
233245
#searchMatchesCount: number;
@@ -241,7 +253,7 @@ export class SearchView extends UI.Widget.VBox {
241253
#progressIndicator: UI.ProgressIndicator.ProgressIndicator|null;
242254
#visiblePane: UI.Widget.Widget|null;
243255
#searchResultsElement!: HTMLElement;
244-
#searchInputElement!: HTMLInputElement;
256+
#query: string;
245257
#matchCase = false;
246258
#matchCaseButton!: Buttons.Button.Button;
247259
#isRegex = false;
@@ -270,9 +282,10 @@ export class SearchView extends UI.Widget.VBox {
270282
this.#view = view;
271283
this.setMinimumSize(0, 40);
272284

273-
this.#focusOnShow = false;
285+
this.#focusSearchInput = false;
274286
this.#isIndexing = false;
275287
this.#searchId = 1;
288+
this.#query = '';
276289
this.#searchMatchesCount = 0;
277290
this.#searchResultsCount = 0;
278291
this.#nonEmptySearchResultsCount = 0;
@@ -302,10 +315,15 @@ export class SearchView extends UI.Widget.VBox {
302315

303316
override performUpdate(): void {
304317
const input: SearchViewInput = {
318+
query: this.#query,
319+
focusSearchInput: this.#focusSearchInput,
305320
matchCase: this.#matchCase,
306321
isRegex: this.#isRegex,
307322
searchMessage: this.#searchMessage,
308323
searchResultsMessage: this.#searchResultsMessage,
324+
onQueryChange: (query: string) => {
325+
this.#query = query;
326+
},
309327
onQueryKeyDown: this.#onQueryKeyDown.bind(this),
310328
onPanelKeyDown: this.#onPanelKeyDown.bind(this),
311329
onClearSearchInput: this.#onClearSearchInput.bind(this),
@@ -316,9 +334,7 @@ export class SearchView extends UI.Widget.VBox {
316334
};
317335
const output: SearchViewOutput = {};
318336
this.#view(input, output, this.contentElement);
319-
if (output.searchInputElement) {
320-
this.#searchInputElement = output.searchInputElement;
321-
}
337+
this.#focusSearchInput = false;
322338
if (output.searchResultsElement) {
323339
this.#searchResultsElement = output.searchResultsElement;
324340
}
@@ -344,16 +360,13 @@ export class SearchView extends UI.Widget.VBox {
344360
}
345361

346362
#buildSearchConfig(): Workspace.SearchConfig.SearchConfig {
347-
return new Workspace.SearchConfig.SearchConfig(this.#searchInputElement.value, !this.#matchCase, this.#isRegex);
363+
return new Workspace.SearchConfig.SearchConfig(this.#query, !this.#matchCase, this.#isRegex);
348364
}
349365

350366
toggle(queryCandidate: string, searchImmediately?: boolean): void {
351-
this.#searchInputElement.value = queryCandidate;
352-
if (this.isShowing()) {
353-
this.focus();
354-
} else {
355-
this.#focusOnShow = true;
356-
}
367+
this.#query = queryCandidate;
368+
this.requestUpdate();
369+
this.focus();
357370

358371
this.#initScope();
359372
if (searchImmediately) {
@@ -371,14 +384,6 @@ export class SearchView extends UI.Widget.VBox {
371384
this.#searchScope = this.createScope();
372385
}
373386

374-
override wasShown(): void {
375-
super.wasShown();
376-
if (this.#focusOnShow) {
377-
this.focus();
378-
this.#focusOnShow = false;
379-
}
380-
}
381-
382387
#onIndexingFinished(): void {
383388
if (!this.#progressIndicator) {
384389
return;
@@ -417,7 +422,8 @@ export class SearchView extends UI.Widget.VBox {
417422
}
418423

419424
#onClearSearchInput(): void {
420-
this.#searchInputElement.value = '';
425+
this.#query = '';
426+
this.requestUpdate();
421427
this.#save();
422428
this.focus();
423429
this.#showPane(this.#emptyStartView);
@@ -563,8 +569,8 @@ export class SearchView extends UI.Widget.VBox {
563569
}
564570

565571
override focus(): void {
566-
this.#searchInputElement.focus();
567-
this.#searchInputElement.select();
572+
this.#focusSearchInput = true;
573+
this.requestUpdate();
568574
}
569575

570576
override willHide(): void {
@@ -628,10 +634,11 @@ export class SearchView extends UI.Widget.VBox {
628634

629635
#load(): void {
630636
const searchConfig = Workspace.SearchConfig.SearchConfig.fromPlainObject(this.#advancedSearchConfig.get());
631-
this.#searchInputElement.value = searchConfig.query();
637+
this.#query = searchConfig.query();
632638

633639
this.#matchCase = !searchConfig.ignoreCase();
634640
this.#isRegex = searchConfig.isRegex();
641+
this.requestUpdate();
635642
}
636643

637644
#onRefresh(): void {
@@ -657,10 +664,6 @@ export class SearchView extends UI.Widget.VBox {
657664
return this.#throttler;
658665
}
659666

660-
get search(): HTMLInputElement {
661-
return this.#searchInputElement;
662-
}
663-
664667
get matchCaseButton(): Buttons.Button.Button {
665668
return this.#matchCaseButton;
666669
}

0 commit comments

Comments
 (0)