Skip to content

Commit 6b3258a

Browse files
authored
Add search facet: main chapters of documentation (#2063)
* Add search facet: main chapters of documentation * Enhance layout search form
1 parent 2b5fef8 commit 6b3258a

File tree

3 files changed

+127
-9
lines changed

3 files changed

+127
-9
lines changed

docs/_static/documentation.css

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,55 @@ a:not([title="(in Plone Documentation v6)"]).reference.external::after {
1515
font: var(--fa-font-solid);
1616
font-size: .75em;
1717
}
18+
19+
/* Search form styling */
20+
.bd-search {
21+
max-width: 600px;
22+
}
23+
24+
.bd-search .input-group-text {
25+
background-color: var(--pst-color-surface);
26+
border-color: var(--pst-color-border);
27+
color: var(--pst-color-text-muted);
28+
}
29+
30+
.bd-search .form-control,
31+
.bd-search .form-select {
32+
border-color: var(--pst-color-border);
33+
background-color: var(--pst-color-surface);
34+
color: var(--pst-color-text-base);
35+
}
36+
37+
.bd-search .form-control:focus,
38+
.bd-search .form-select:focus {
39+
border-color: var(--pst-color-primary);
40+
box-shadow: 0 0 0 0.2rem rgba(var(--pst-color-primary-rgb), 0.25);
41+
}
42+
43+
.bd-search .form-label {
44+
font-weight: 500;
45+
color: var(--pst-color-text-base);
46+
}
47+
48+
.bd-search .search-button__kbd-shortcut kbd {
49+
background-color: var(--pst-color-text-muted);
50+
color: var(--pst-color-surface);
51+
padding: 0.1rem 0.3rem;
52+
border-radius: 3px;
53+
font-size: 0.85em;
54+
}
55+
56+
.bd-search-container ul.search {
57+
padding-inline-start: 0;
58+
}
59+
60+
/* Search results styling */
61+
#search-results .breadcrumbs {
62+
font-size: 0.85em;
63+
color: var(--pst-color-text-muted);
64+
margin-bottom: 0.25rem;
65+
}
66+
67+
#search-results .breadcrumbs .pathseparator {
68+
padding: 0 0.5em;
69+
}

docs/_static/searchtools.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ if (typeof splitQuery === "undefined") {
244244
const Search = {
245245
_index: null,
246246
_queued_query: null,
247+
_queued_section: null,
247248
_pulse_status: -1,
248249

249250
htmlToText: (htmlString, anchor) => {
@@ -272,10 +273,15 @@ const Search = {
272273

273274
init: () => {
274275
const query = new URLSearchParams(window.location.search).get("q");
276+
const section = new URLSearchParams(window.location.search).get("section");
277+
const select = document
278+
.querySelector('select[name="section"]')
275279
document
276280
.querySelectorAll('input[name="q"]')
277281
.forEach((el) => (el.value = query));
278-
if (query) Search.performSearch(query);
282+
if (section) select.value = section;
283+
else select.value = "all";
284+
if (query) Search.performSearch(query, section);
279285
},
280286

281287
loadIndex: (url) =>
@@ -285,14 +291,19 @@ const Search = {
285291
Search._index = index;
286292
if (Search._queued_query !== null) {
287293
const query = Search._queued_query;
294+
const section = Search._queued_section;
288295
Search._queued_query = null;
289-
Search.query(query);
296+
Search._queued_section = null;
297+
Search.query(query, section);
290298
}
291299
},
292300

293301
hasIndex: () => Search._index !== null,
294302

295-
deferQuery: (query) => (Search._queued_query = query),
303+
deferQuery: (query, section) => {
304+
Search._queued_query = query;
305+
Search._queued_section = section;
306+
},
296307

297308
stopPulse: () => (Search._pulse_status = -1),
298309

@@ -310,7 +321,7 @@ const Search = {
310321
/**
311322
* perform a search for something (or wait until index is loaded)
312323
*/
313-
performSearch: (query) => {
324+
performSearch: (query, section) => {
314325
// create the required interface elements
315326
const searchText = document.createElement("h2");
316327
searchText.textContent = _("Searching");
@@ -335,8 +346,8 @@ const Search = {
335346
Search.startPulse();
336347

337348
// index already loaded, the browser was quick!
338-
if (Search.hasIndex()) Search.query(query);
339-
else Search.deferQuery(query);
349+
if (Search.hasIndex()) Search.query(query, section);
350+
else Search.deferQuery(query, section);
340351
},
341352

342353
_parseQuery: (query) => {
@@ -475,10 +486,16 @@ const Search = {
475486
return results.reverse();
476487
},
477488

478-
query: (query) => {
489+
query: (query, section) => {
479490
const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query);
480-
const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms);
481-
const qresults = results;
491+
let results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms);
492+
493+
// Filter results by section
494+
if (section && section !== 'all') {
495+
results = results.filter(result => {
496+
return result[0].split('/')[0] === section;
497+
});
498+
}
482499

483500
// for debugging
484501
//Search.lastresults = results.slice(); // a copy
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{# A bootstrap-styled field that will direct to the `search.html` page when submitted #}
2+
<form class="bd-search mt-3 mb-5 p-3"
3+
action="{{ pathto('search') }}"
4+
method="get">
5+
<div class="input-group">
6+
<input type="search"
7+
class="form-control"
8+
name="q"
9+
id="search-input"
10+
placeholder="{{ theme_search_bar_text }}"
11+
aria-label="{{ theme_search_bar_text }}"
12+
autocomplete="off"
13+
autocorrect="off"
14+
autocapitalize="off"
15+
spellcheck="false"/>
16+
<button class="btn btn-primary" type="submit">
17+
<i class="fa-solid fa-magnifying-glass"></i>
18+
</button>
19+
<!-- <span class="input-group-text search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span> -->
20+
</div>
21+
<div class="facet mt-3">
22+
<label for="section" class="form-label">Filter by section</label>
23+
<select class="form-select" name="section" id="section" onchange="this.form.submit()">
24+
<option value="all">All sections</option>
25+
{% for id, title in
26+
[
27+
['admin-guide', 'Admin Guide'],
28+
['backend', 'Backend'],
29+
['classic-ui', 'Classic UI'],
30+
['conceptual-guides', 'Conceptual Guides'],
31+
['contributing', 'Contributing'],
32+
['deployment', 'Deployment'],
33+
['developer-guide', 'Developer Guide'],
34+
['i18n-l10n', 'i18n/l10n'],
35+
['install', 'Install'],
36+
['overview', 'Overview'],
37+
['reference-guide', 'Reference Guide'],
38+
['training', 'Training'],
39+
['upgrade', 'Upgrade'],
40+
['user-guide', 'User Guide'],
41+
['plone.restapi', 'Plone REST API'],
42+
['plone.api', 'Plone API'],
43+
['volto', 'Volto'],
44+
] %}
45+
<option value="{{id}}">{{ title }}</option>
46+
{% endfor %}
47+
</select>
48+
</div>
49+
</form>

0 commit comments

Comments
 (0)