Upstream mozilla-firefox/firefox state of the touched files before d3fbb52d97
This commit is contained in:
1 parent
edfad4e281
commit
35563aaab9
2 files changed
+678
No files matched your search
@@ -0,0 +1,306 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||||
|
|
||||||
|
// Testing various project search features
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
requestLongerTimeout(3);
|
||||||
|
|
||||||
|
add_task(async function testProjectSearchCloseOnNavigation() {
|
||||||
|
const dbg = await initDebugger(
|
||||||
|
"doc-script-switching.html",
|
||||||
|
"script-switching-01.js"
|
||||||
|
);
|
||||||
|
|
||||||
|
await selectSource(dbg, "script-switching-01.js");
|
||||||
|
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
|
||||||
|
ok(
|
||||||
|
!findElement(dbg, "projectSearchRefreshButton"),
|
||||||
|
"The refresh button is only visible after having done a search"
|
||||||
|
);
|
||||||
|
|
||||||
|
await doProjectSearch(dbg, "function", 2);
|
||||||
|
|
||||||
|
is(getExpandedResultsCount(dbg), 9);
|
||||||
|
|
||||||
|
is(dbg.selectors.getActiveSearch(), "project");
|
||||||
|
|
||||||
|
const refreshButton = findElement(dbg, "projectSearchRefreshButton");
|
||||||
|
ok(
|
||||||
|
refreshButton,
|
||||||
|
"Refresh button is visible right after search is completed"
|
||||||
|
);
|
||||||
|
ok(
|
||||||
|
!refreshButton.classList.contains("highlight"),
|
||||||
|
"Refresh button is *not* highlighted by default"
|
||||||
|
);
|
||||||
|
|
||||||
|
await navigate(dbg, "doc-scripts.html");
|
||||||
|
|
||||||
|
// Project search is still visible after navigation
|
||||||
|
is(dbg.selectors.getActiveSearch(), "project");
|
||||||
|
// With same search results
|
||||||
|
is(getExpandedResultsCount(dbg), 9);
|
||||||
|
|
||||||
|
ok(
|
||||||
|
refreshButton.classList.contains("highlight"),
|
||||||
|
"Refresh button is highlighted after navigation"
|
||||||
|
);
|
||||||
|
|
||||||
|
info("Try to open a discarded source");
|
||||||
|
await clickElement(dbg, "fileMatch");
|
||||||
|
|
||||||
|
info("Wait for the warning popup to be visible");
|
||||||
|
// We are waiting for the popup to be added...
|
||||||
|
await waitFor(() => dbg.win.document.querySelector(".unavailable-source"));
|
||||||
|
// ...and verify that the popup is made visible.
|
||||||
|
await waitFor(() => dbg.win.document.querySelector(".tooltip-shown"));
|
||||||
|
info("Retry to open the discard source, this should hide the popup");
|
||||||
|
await clickElement(dbg, "fileMatch");
|
||||||
|
info("Wait for the popup to be hidden");
|
||||||
|
// Note that .unavailable-source won't be removed from the DOM
|
||||||
|
await waitFor(() => !dbg.win.document.querySelector(".tooltip-visible"));
|
||||||
|
|
||||||
|
info("Refresh results against the new page");
|
||||||
|
refreshButton.click();
|
||||||
|
|
||||||
|
// Wait for the search to be updated against the new page
|
||||||
|
await waitForSearchResults(dbg, 5);
|
||||||
|
is(getExpandedResultsCount(dbg), 39);
|
||||||
|
ok(
|
||||||
|
!refreshButton.classList.contains("highlight"),
|
||||||
|
"Refresh button is no longer highlighted after refreshing the search"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testSimpleProjectSearch() {
|
||||||
|
// Start with side panel collapsed so we can assert that the project search keyboard
|
||||||
|
// shortcut will open it.
|
||||||
|
await pushPref("devtools.debugger.start-panel-collapsed", true);
|
||||||
|
|
||||||
|
const dbg = await initDebugger(
|
||||||
|
"doc-script-switching.html",
|
||||||
|
"script-switching-01.js"
|
||||||
|
);
|
||||||
|
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
|
||||||
|
ok(
|
||||||
|
!!findElementWithSelector(dbg, ".project-text-search"),
|
||||||
|
"Project search is visible"
|
||||||
|
);
|
||||||
|
|
||||||
|
const searchTerm = "first";
|
||||||
|
await doProjectSearch(dbg, searchTerm, 1);
|
||||||
|
|
||||||
|
const queryMatch = findElement(dbg, "fileMatch").querySelector(
|
||||||
|
".query-match"
|
||||||
|
);
|
||||||
|
is(
|
||||||
|
queryMatch.innerText,
|
||||||
|
searchTerm,
|
||||||
|
"The highlighted text matches the search term"
|
||||||
|
);
|
||||||
|
|
||||||
|
info("Select a result match to open the location in the source");
|
||||||
|
await clickElement(dbg, "fileMatch");
|
||||||
|
await waitForSelectedSource(dbg, "script-switching-01.js");
|
||||||
|
|
||||||
|
info("Close start sidebar");
|
||||||
|
const startPanelToggleButtonEl = findElementWithSelector(
|
||||||
|
dbg,
|
||||||
|
".toggle-button.start"
|
||||||
|
);
|
||||||
|
startPanelToggleButtonEl.click();
|
||||||
|
await waitFor(() => startPanelToggleButtonEl.classList.contains("collapsed"));
|
||||||
|
|
||||||
|
info("Try to open project search again");
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
ok(
|
||||||
|
!!findElementWithSelector(dbg, ".project-text-search"),
|
||||||
|
"Project search is visible"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testMatchesForRegexSearches() {
|
||||||
|
const dbg = await initDebugger("doc-react.html", "App.js");
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
|
||||||
|
type(dbg, "import .* from 'react'");
|
||||||
|
await clickElement(dbg, "projectSearchModifiersRegexMatch");
|
||||||
|
|
||||||
|
await waitForSearchResults(dbg, 2);
|
||||||
|
|
||||||
|
const queryMatch = findAllElements(dbg, "fileMatch")[1].querySelector(
|
||||||
|
".query-match"
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
queryMatch.innerText,
|
||||||
|
"import React, { Component } from 'react'",
|
||||||
|
"The highlighted text matches the search term"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Turn off the regex modifier so does not break tests below
|
||||||
|
await clickElement(dbg, "projectSearchModifiersRegexMatch");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test expanding search results to reveal the search matches.
|
||||||
|
add_task(async function testExpandSearchResultsToShowMatches() {
|
||||||
|
const dbg = await initDebugger("doc-react.html", "App.js");
|
||||||
|
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
await doProjectSearch(dbg, "we", 19);
|
||||||
|
|
||||||
|
is(getExpandedResultsCount(dbg), 159);
|
||||||
|
|
||||||
|
const collapsedNodes = findAllElements(dbg, "projectSearchCollapsed");
|
||||||
|
is(collapsedNodes.length, 1);
|
||||||
|
|
||||||
|
collapsedNodes[0].click();
|
||||||
|
|
||||||
|
is(getExpandedResultsCount(dbg), 367);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testSearchModifiers() {
|
||||||
|
const dbg = await initDebugger("doc-react.html", "App.js");
|
||||||
|
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
|
||||||
|
await assertProjectSearchModifier(
|
||||||
|
dbg,
|
||||||
|
"projectSearchModifiersCaseSensitive",
|
||||||
|
"FIELDS",
|
||||||
|
"case sensitive",
|
||||||
|
{ resultWithModifierOn: 0, resultWithModifierOff: 2 }
|
||||||
|
);
|
||||||
|
await assertProjectSearchModifier(
|
||||||
|
dbg,
|
||||||
|
"projectSearchModifiersRegexMatch",
|
||||||
|
`\\*`,
|
||||||
|
"regex match",
|
||||||
|
{ resultWithModifierOn: 12, resultWithModifierOff: 0 }
|
||||||
|
);
|
||||||
|
await assertProjectSearchModifier(
|
||||||
|
dbg,
|
||||||
|
"projectSearchModifiersWholeWordMatch",
|
||||||
|
"so",
|
||||||
|
"whole word match",
|
||||||
|
{ resultWithModifierOn: 6, resultWithModifierOff: 16 }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function testSearchExcludePatterns() {
|
||||||
|
const dbg = await initDebugger("doc-react.html", "App.js");
|
||||||
|
|
||||||
|
info("Search across all files");
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
let fileResults = await doProjectSearch(dbg, "console", 5);
|
||||||
|
|
||||||
|
let resultsFromNodeModules = [...fileResults].filter(result =>
|
||||||
|
result.innerText.includes("node_modules")
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
resultsFromNodeModules.length,
|
||||||
|
3,
|
||||||
|
"3 results were found from node_modules"
|
||||||
|
);
|
||||||
|
|
||||||
|
info("Excludes search results based on multiple search patterns");
|
||||||
|
|
||||||
|
await clickElement(dbg, "excludePatternsInput");
|
||||||
|
type(dbg, "App.js, main.js");
|
||||||
|
pressKey(dbg, "Enter");
|
||||||
|
|
||||||
|
fileResults = await waitForSearchResults(dbg, 3);
|
||||||
|
|
||||||
|
const resultsFromAppJS = [...fileResults].filter(result =>
|
||||||
|
result.innerText.includes("App.js")
|
||||||
|
);
|
||||||
|
|
||||||
|
is(resultsFromAppJS.length, 0, "None of the results is from the App.js file");
|
||||||
|
|
||||||
|
const resultsFromMainJS = [...fileResults].filter(result =>
|
||||||
|
result.innerText.includes("main.js")
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
resultsFromMainJS.length,
|
||||||
|
0,
|
||||||
|
"None of the results is from the main.js file"
|
||||||
|
);
|
||||||
|
|
||||||
|
info("Excludes search results from node modules files");
|
||||||
|
|
||||||
|
await clearElement(dbg, "excludePatternsInput");
|
||||||
|
type(dbg, "**/node_modules/**");
|
||||||
|
pressKey(dbg, "Enter");
|
||||||
|
|
||||||
|
fileResults = await waitForSearchResults(dbg, 2);
|
||||||
|
|
||||||
|
resultsFromNodeModules = [...fileResults].filter(result =>
|
||||||
|
result.innerText.includes("node_modules")
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
resultsFromNodeModules.length,
|
||||||
|
0,
|
||||||
|
"None of the results is from the node modules files"
|
||||||
|
);
|
||||||
|
|
||||||
|
info("Assert that the exclude pattern is persisted across reloads");
|
||||||
|
await reloadSelectedTab();
|
||||||
|
await openProjectSearch(dbg);
|
||||||
|
|
||||||
|
const excludePatternsInputElement = await waitForElement(
|
||||||
|
dbg,
|
||||||
|
"excludePatternsInput"
|
||||||
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
excludePatternsInputElement.value,
|
||||||
|
"**/node_modules/**",
|
||||||
|
"The exclude pattern for node modules is persisted accross reloads"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clear the fields so that it does not impact on the subsequent tests
|
||||||
|
await clearElement(dbg, "projectSearchSearchInput");
|
||||||
|
await clearElement(dbg, "excludePatternsInput");
|
||||||
|
pressKey(dbg, "Enter");
|
||||||
|
});
|
||||||
|
|
||||||
|
async function assertProjectSearchModifier(
|
||||||
|
dbg,
|
||||||
|
searchModifierBtn,
|
||||||
|
searchTerm,
|
||||||
|
title,
|
||||||
|
expected
|
||||||
|
) {
|
||||||
|
info(`Assert ${title} search modifier`);
|
||||||
|
|
||||||
|
type(dbg, searchTerm);
|
||||||
|
info(`Turn on the ${title} search modifier option`);
|
||||||
|
await clickElement(dbg, searchModifierBtn);
|
||||||
|
let results = await waitForSearchResults(dbg, expected.resultWithModifierOn);
|
||||||
|
is(
|
||||||
|
results.length,
|
||||||
|
expected.resultWithModifierOn,
|
||||||
|
`${results.length} results where found`
|
||||||
|
);
|
||||||
|
|
||||||
|
info(`Turn off the ${title} search modifier`);
|
||||||
|
await clickElement(dbg, searchModifierBtn);
|
||||||
|
|
||||||
|
results = await waitForSearchResults(dbg, expected.resultWithModifierOff);
|
||||||
|
is(
|
||||||
|
results.length,
|
||||||
|
expected.resultWithModifierOff,
|
||||||
|
`${results.length} results where found`
|
||||||
|
);
|
||||||
|
await clearElement(dbg, "projectSearchSearchInput");
|
||||||
|
}
|
||||||
@@ -0,0 +1,372 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const React = require("devtools/client/shared/vendor/react");
|
||||||
|
const { Component } = React;
|
||||||
|
|
||||||
|
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||||
|
const {
|
||||||
|
button,
|
||||||
|
div,
|
||||||
|
label,
|
||||||
|
input,
|
||||||
|
span,
|
||||||
|
} = require("devtools/client/shared/vendor/react-dom-factories");
|
||||||
|
|
||||||
|
const DebuggerImage = require("devtools/client/shared/components/DebuggerImage");
|
||||||
|
const CloseButton = require("devtools/client/shared/components/CloseButton");
|
||||||
|
|
||||||
|
const classnames = require("resource://devtools/client/shared/classnames.js");
|
||||||
|
const SearchModifiers = require("resource://devtools/client/shared/components/SearchModifiers.js");
|
||||||
|
|
||||||
|
const { LocalizationHelper } = require("resource://devtools/shared/l10n.js");
|
||||||
|
const locale = new LocalizationHelper(
|
||||||
|
"devtools/client/locales/components.properties"
|
||||||
|
);
|
||||||
|
|
||||||
|
const arrowBtn = (onClick, type, className, tooltip) => {
|
||||||
|
const props = {
|
||||||
|
className,
|
||||||
|
key: type,
|
||||||
|
onClick,
|
||||||
|
title: tooltip,
|
||||||
|
type,
|
||||||
|
};
|
||||||
|
return button(
|
||||||
|
props,
|
||||||
|
React.createElement(DebuggerImage, {
|
||||||
|
name: type,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SearchInput extends Component {
|
||||||
|
static get propTypes() {
|
||||||
|
return {
|
||||||
|
count: PropTypes.number.isRequired,
|
||||||
|
expanded: PropTypes.bool.isRequired,
|
||||||
|
handleClose: PropTypes.func,
|
||||||
|
handleNext: PropTypes.func,
|
||||||
|
handlePrev: PropTypes.func,
|
||||||
|
hasPrefix: PropTypes.bool.isRequired,
|
||||||
|
isLoading: PropTypes.bool.isRequired,
|
||||||
|
onBlur: PropTypes.func,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
onFocus: PropTypes.func,
|
||||||
|
onHistoryScroll: PropTypes.func,
|
||||||
|
onKeyDown: PropTypes.func,
|
||||||
|
onKeyUp: PropTypes.func,
|
||||||
|
placeholder: PropTypes.string,
|
||||||
|
query: PropTypes.string,
|
||||||
|
selectedItemId: PropTypes.string,
|
||||||
|
shouldFocus: PropTypes.bool,
|
||||||
|
showClose: PropTypes.bool.isRequired,
|
||||||
|
showExcludePatterns: PropTypes.bool.isRequired,
|
||||||
|
excludePatternsLabel: PropTypes.string,
|
||||||
|
excludePatternsPlaceholder: PropTypes.string,
|
||||||
|
showErrorEmoji: PropTypes.bool.isRequired,
|
||||||
|
size: PropTypes.string,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
summaryMsg: PropTypes.string,
|
||||||
|
searchKey: PropTypes.string.isRequired,
|
||||||
|
searchOptions: PropTypes.object.isRequired,
|
||||||
|
setSearchOptions: PropTypes.func.isRequired,
|
||||||
|
showSearchModifiers: PropTypes.bool.isRequired,
|
||||||
|
onToggleSearchModifier: PropTypes.func,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
expanded: false,
|
||||||
|
hasPrefix: false,
|
||||||
|
selectedItemId: "",
|
||||||
|
size: "",
|
||||||
|
showClose: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
history: [],
|
||||||
|
excludePatterns: this.props.showSearchModifiers
|
||||||
|
? (props.searchOptions?.excludePatterns ?? "")
|
||||||
|
: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (this.props.shouldFocus && !prevProps.shouldFocus) {
|
||||||
|
this.setFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setFocus() {
|
||||||
|
if (this.$input) {
|
||||||
|
const _input = this.$input;
|
||||||
|
_input.focus();
|
||||||
|
|
||||||
|
if (!_input.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// omit prefix @:# from being selected
|
||||||
|
const selectStartPos = this.props.hasPrefix ? 1 : 0;
|
||||||
|
_input.setSelectionRange(selectStartPos, _input.value.length + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderArrowButtons() {
|
||||||
|
const { handleNext, handlePrev } = this.props;
|
||||||
|
|
||||||
|
return [
|
||||||
|
arrowBtn(
|
||||||
|
handlePrev,
|
||||||
|
"arrow-up",
|
||||||
|
classnames("nav-btn", "prev"),
|
||||||
|
locale.getStr("editor.searchResults.prevResult"),
|
||||||
|
DebuggerImage
|
||||||
|
),
|
||||||
|
arrowBtn(
|
||||||
|
handleNext,
|
||||||
|
"arrow-down",
|
||||||
|
classnames("nav-btn", "next"),
|
||||||
|
locale.getStr("editor.searchResults.nextResult"),
|
||||||
|
DebuggerImage
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocus = e => {
|
||||||
|
const { onFocus } = this.props;
|
||||||
|
|
||||||
|
if (onFocus) {
|
||||||
|
onFocus(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onBlur = e => {
|
||||||
|
const { onBlur } = this.props;
|
||||||
|
|
||||||
|
if (onBlur) {
|
||||||
|
onBlur(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onKeyDown = e => {
|
||||||
|
const { onHistoryScroll, onKeyDown } = this.props;
|
||||||
|
if (!onHistoryScroll) {
|
||||||
|
onKeyDown(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputValue = e.target.value;
|
||||||
|
const { history } = this.state;
|
||||||
|
const currentHistoryIndex = history.indexOf(inputValue);
|
||||||
|
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
this.saveEnteredTerm(inputValue);
|
||||||
|
onKeyDown(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === "ArrowUp") {
|
||||||
|
const previous =
|
||||||
|
currentHistoryIndex > -1 ? currentHistoryIndex - 1 : history.length - 1;
|
||||||
|
const previousInHistory = history[previous];
|
||||||
|
if (previousInHistory) {
|
||||||
|
e.preventDefault();
|
||||||
|
onHistoryScroll(previousInHistory);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === "ArrowDown") {
|
||||||
|
const next = currentHistoryIndex + 1;
|
||||||
|
const nextInHistory = history[next];
|
||||||
|
if (nextInHistory) {
|
||||||
|
onHistoryScroll(nextInHistory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onExcludeKeyDown = e => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
this.props.setSearchOptions(this.props.searchKey, {
|
||||||
|
excludePatterns: this.state.excludePatterns,
|
||||||
|
});
|
||||||
|
this.props.onKeyDown(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
saveEnteredTerm(query) {
|
||||||
|
const { history } = this.state;
|
||||||
|
const previousIndex = history.indexOf(query);
|
||||||
|
if (previousIndex !== -1) {
|
||||||
|
history.splice(previousIndex, 1);
|
||||||
|
}
|
||||||
|
history.push(query);
|
||||||
|
this.setState({ history });
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSummaryMsg() {
|
||||||
|
const { summaryMsg } = this.props;
|
||||||
|
|
||||||
|
if (!summaryMsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return div(
|
||||||
|
{
|
||||||
|
className: "search-field-summary",
|
||||||
|
},
|
||||||
|
summaryMsg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSpinner() {
|
||||||
|
const { isLoading } = this.props;
|
||||||
|
if (!isLoading) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return React.createElement(DebuggerImage, {
|
||||||
|
name: "loader",
|
||||||
|
className: "spin",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNav() {
|
||||||
|
const { count, handleNext, handlePrev } = this.props;
|
||||||
|
if ((!handleNext && !handlePrev) || !count || count == 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return div(
|
||||||
|
{
|
||||||
|
className: "search-nav-buttons",
|
||||||
|
},
|
||||||
|
this.renderArrowButtons()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSearchModifiers() {
|
||||||
|
if (!this.props.showSearchModifiers) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return React.createElement(SearchModifiers, {
|
||||||
|
modifiers: this.props.searchOptions,
|
||||||
|
onToggleSearchModifier: updatedOptions => {
|
||||||
|
this.props.setSearchOptions(this.props.searchKey, updatedOptions);
|
||||||
|
this.props.onToggleSearchModifier();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderExcludePatterns() {
|
||||||
|
if (!this.props.showExcludePatterns) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return div(
|
||||||
|
{
|
||||||
|
className: classnames("exclude-patterns-field", this.props.size),
|
||||||
|
},
|
||||||
|
label(null, this.props.excludePatternsLabel),
|
||||||
|
input({
|
||||||
|
placeholder: this.props.excludePatternsPlaceholder,
|
||||||
|
value: this.state.excludePatterns,
|
||||||
|
onKeyDown: this.onExcludeKeyDown,
|
||||||
|
onChange: e =>
|
||||||
|
this.setState({
|
||||||
|
excludePatterns: e.target.value,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderClose() {
|
||||||
|
if (!this.props.showClose) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return React.createElement(
|
||||||
|
React.Fragment,
|
||||||
|
null,
|
||||||
|
span({
|
||||||
|
className: "pipe-divider",
|
||||||
|
}),
|
||||||
|
React.createElement(CloseButton, {
|
||||||
|
handleClick: this.props.handleClose,
|
||||||
|
buttonClass: this.props.size,
|
||||||
|
tooltip: locale.getStr("editor.searchResults.close"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
expanded,
|
||||||
|
onChange,
|
||||||
|
onKeyUp,
|
||||||
|
placeholder,
|
||||||
|
query,
|
||||||
|
selectedItemId,
|
||||||
|
showErrorEmoji,
|
||||||
|
size,
|
||||||
|
disabled,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const inputProps = {
|
||||||
|
className: classnames({
|
||||||
|
empty: showErrorEmoji,
|
||||||
|
}),
|
||||||
|
disabled,
|
||||||
|
onChange,
|
||||||
|
onKeyDown: e => this.onKeyDown(e),
|
||||||
|
onKeyUp,
|
||||||
|
onFocus: e => this.onFocus(e),
|
||||||
|
onBlur: e => this.onBlur(e),
|
||||||
|
"aria-autocomplete": "list",
|
||||||
|
"aria-controls": "result-list",
|
||||||
|
"aria-activedescendant":
|
||||||
|
expanded && selectedItemId ? `${selectedItemId}-title` : "",
|
||||||
|
placeholder,
|
||||||
|
value: query,
|
||||||
|
spellCheck: false,
|
||||||
|
ref: c => (this.$input = c),
|
||||||
|
};
|
||||||
|
return div(
|
||||||
|
{
|
||||||
|
className: "search-outline",
|
||||||
|
},
|
||||||
|
div(
|
||||||
|
{
|
||||||
|
className: classnames("search-field", size),
|
||||||
|
role: "combobox",
|
||||||
|
"aria-haspopup": "listbox",
|
||||||
|
"aria-owns": "result-list",
|
||||||
|
"aria-expanded": expanded,
|
||||||
|
},
|
||||||
|
React.createElement(DebuggerImage, {
|
||||||
|
name: "search",
|
||||||
|
}),
|
||||||
|
input(inputProps),
|
||||||
|
this.renderSpinner(),
|
||||||
|
this.renderSummaryMsg(),
|
||||||
|
this.renderNav(),
|
||||||
|
div(
|
||||||
|
{
|
||||||
|
className: "search-buttons-bar",
|
||||||
|
},
|
||||||
|
this.renderSearchModifiers(),
|
||||||
|
this.renderClose()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
this.renderExcludePatterns()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SearchInput;
|
||||||
Reference in new issue
Block a user