8236935: Improve UX of the search control

Reviewed-by: jjg, prappo
This commit is contained in:
Hannes Wallnöfer 2020-07-13 11:33:50 +02:00
parent 5b2fd36a6d
commit 77c83d9ee6
5 changed files with 136 additions and 116 deletions
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets
formats/html
toolkit/resources
test/langtools/jdk/javadoc
doclet/testSearch
tool/api/basic

@ -317,11 +317,9 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
* @throws DocFileIOException if there is a problem creating any of the search index files
*/
protected void createSearchIndexFiles() throws DocFileIOException {
if (configuration.showModules) {
createSearchIndexFile(DocPaths.MODULE_SEARCH_INDEX_JS,
searchItems.itemsOfCategories(Category.MODULES),
"moduleSearchIndex");
}
createSearchIndexFile(DocPaths.MODULE_SEARCH_INDEX_JS,
searchItems.itemsOfCategories(Category.MODULES),
"moduleSearchIndex");
if (!configuration.packages.isEmpty()) {
SearchIndexItem si = new SearchIndexItem();
si.setCategory(Category.PACKAGES);
@ -364,28 +362,27 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
// The file needs to be created even if there are no searchIndex items
// File could be written straight-through, without an intermediate StringBuilder
Iterator<SearchIndexItem> index = searchIndex.iterator();
if (index.hasNext()) {
StringBuilder searchVar = new StringBuilder("[");
boolean first = true;
while (index.hasNext()) {
SearchIndexItem item = index.next();
if (first) {
searchVar.append(item.toString());
first = false;
} else {
searchVar.append(",").append(item.toString());
}
}
searchVar.append("]");
DocFile jsFile = DocFile.createFileForOutput(configuration, searchIndexJS);
try (Writer wr = jsFile.openWriter()) {
wr.write(varName);
wr.write(" = ");
wr.write(searchVar.toString());
} catch (IOException ie) {
throw new DocFileIOException(jsFile, DocFileIOException.Mode.WRITE, ie);
StringBuilder searchVar = new StringBuilder("[");
boolean first = true;
while (index.hasNext()) {
SearchIndexItem item = index.next();
if (first) {
searchVar.append(item.toString());
first = false;
} else {
searchVar.append(",").append(item.toString());
}
}
searchVar.append("];");
DocFile jsFile = DocFile.createFileForOutput(configuration, searchIndexJS);
try (Writer wr = jsFile.openWriter()) {
wr.write(varName);
wr.write(" = ");
wr.write(searchVar.toString());
wr.write("updateSearchResults();");
} catch (IOException ie) {
throw new DocFileIOException(jsFile, DocFileIOException.Mode.WRITE, ie);
}
}
private static Map<Character, List<SearchIndexItem>> buildSearchTagIndex(

@ -24,6 +24,7 @@
*/
var noResult = {l: "No results found"};
var loading = {l: "Loading search index..."};
var catModules = "Modules";
var catPackages = "Packages";
var catTypes = "Types";
@ -219,96 +220,105 @@ function rankMatch(match, category) {
return leftBoundaryMatch + periferalMatch + (delta / 200);
}
function doSearch(request, response) {
var result = [];
var newResults = [];
searchPattern = makeCamelCaseRegex(request.term);
if (searchPattern === "") {
return this.close();
}
var camelCaseMatcher = createMatcher(searchPattern, "");
var boundaryMatcher = createMatcher("\\b" + searchPattern, "");
function concatResults(a1, a2) {
a2.sort(function(e1, e2) {
return e1.ranking - e2.ranking;
});
a1 = a1.concat(a2.map(function(e) { return e.item; }));
a2.length = 0;
return a1;
}
if (moduleSearchIndex) {
$.each(moduleSearchIndex, function(index, item) {
item.category = catModules;
var ranking = rankMatch(boundaryMatcher.exec(item.l), catModules);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (packageSearchIndex) {
$.each(packageSearchIndex, function(index, item) {
item.category = catPackages;
var name = (item.m && request.term.indexOf("/") > -1)
? (item.m + "/" + item.l)
: item.l;
var ranking = rankMatch(boundaryMatcher.exec(name), catPackages);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (typeSearchIndex) {
$.each(typeSearchIndex, function(index, item) {
item.category = catTypes;
var name = request.term.indexOf(".") > -1
? item.p + "." + item.l
: item.l;
var ranking = rankMatch(camelCaseMatcher.exec(name), catTypes);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (memberSearchIndex) {
$.each(memberSearchIndex, function(index, item) {
item.category = catMembers;
var name = request.term.indexOf(".") > -1
? item.p + "." + item.c + "." + item.l
: item.l;
var ranking = rankMatch(camelCaseMatcher.exec(name), catMembers);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (tagSearchIndex) {
$.each(tagSearchIndex, function(index, item) {
item.category = catSearchTags;
var ranking = rankMatch(boundaryMatcher.exec(item.l), catSearchTags);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (!indexFilesLoaded()) {
updateSearchResults = function() {
doSearch(request, response);
}
result.unshift(loading);
} else {
updateSearchResults = function() {};
}
response(result);
}
$(function() {
$("#search").catcomplete({
minLength: 1,
delay: 300,
source: function(request, response) {
var result = [];
var newResults = [];
searchPattern = makeCamelCaseRegex(request.term);
if (searchPattern === "") {
return this.close();
}
var camelCaseMatcher = createMatcher(searchPattern, "");
var boundaryMatcher = createMatcher("\\b" + searchPattern, "");
function concatResults(a1, a2) {
a2.sort(function(e1, e2) {
return e1.ranking - e2.ranking;
});
a1 = a1.concat(a2.map(function(e) { return e.item; }));
a2.length = 0;
return a1;
}
if (moduleSearchIndex) {
$.each(moduleSearchIndex, function(index, item) {
item.category = catModules;
var ranking = rankMatch(boundaryMatcher.exec(item.l), catModules);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (packageSearchIndex) {
$.each(packageSearchIndex, function(index, item) {
item.category = catPackages;
var name = (item.m && request.term.indexOf("/") > -1)
? (item.m + "/" + item.l)
: item.l;
var ranking = rankMatch(boundaryMatcher.exec(name), catPackages);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (typeSearchIndex) {
$.each(typeSearchIndex, function(index, item) {
item.category = catTypes;
var name = request.term.indexOf(".") > -1
? item.p + "." + item.l
: item.l;
var ranking = rankMatch(camelCaseMatcher.exec(name), catTypes);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (memberSearchIndex) {
$.each(memberSearchIndex, function(index, item) {
item.category = catMembers;
var name = request.term.indexOf(".") > -1
? item.p + "." + item.c + "." + item.l
: item.l;
var ranking = rankMatch(camelCaseMatcher.exec(name), catMembers);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
if (tagSearchIndex) {
$.each(tagSearchIndex, function(index, item) {
item.category = catSearchTags;
var ranking = rankMatch(boundaryMatcher.exec(item.l), catSearchTags);
if (ranking < RANKING_THRESHOLD) {
newResults.push({ ranking: ranking, item: item });
}
return newResults.length < MAX_RESULTS_PER_CATEGORY;
});
result = concatResults(result, newResults);
}
response(result);
},
source: doSearch,
response: function(event, ui) {
if (!ui.content.length) {
ui.content.push(noResult);

@ -91,3 +91,13 @@ function switchTab(e) {
e.preventDefault();
}
}
var updateSearchResults = function() {};
function indexFilesLoaded() {
return moduleSearchIndex
&& packageSearchIndex
&& typeSearchIndex
&& memberSearchIndex
&& tagSearchIndex;
}

@ -58,11 +58,11 @@ public class TestSearch extends JavadocTester {
checkSearchOutput("UnnamedPkgClass.html", true, true);
checkJqueryAndImageFiles(true);
checkSearchJS();
checkFiles(false,
"tag-search-index.js");
checkFiles(true,
"package-search-index.js",
"member-search-index.js",
"module-search-index.js",
"package-search-index.js",
"tag-search-index.js",
"type-search-index.js");
}
@ -83,6 +83,7 @@ public class TestSearch extends JavadocTester {
checkAllPkgsAllClasses();
checkFiles(true,
"member-search-index.js",
"module-search-index.js",
"package-search-index.js",
"tag-search-index.js",
"type-search-index.js");
@ -248,11 +249,11 @@ public class TestSearch extends JavadocTester {
checkJavaFXOutput();
checkJqueryAndImageFiles(true);
checkSearchJS();
checkFiles(false,
"tag-search-index.js");
checkFiles(true,
"member-search-index.js",
"module-search-index.js",
"package-search-index.js",
"tag-search-index.js",
"type-search-index.js");
}

@ -213,6 +213,7 @@ class APITest {
"script-dir/images/ui-icons_222222_256x240.png",
"script-dir/images/ui-bg_glass_75_e6e6e6_1x400.png",
"member-search-index.js",
"module-search-index.js",
"overview-tree.html",
"element-list",
"package-search-index.js",
@ -225,6 +226,7 @@ class APITest {
"search.js",
"jquery-ui.overrides.css",
"stylesheet.css",
"tag-search-index.js",
"type-search-index.js"
));