Skip to content

Commit 2ab5703

Browse files
authored
Merge pull request plone#1176 from plone/searching
- Add breadcrumbs to search results - Add reset button to search form - Search form nicer with bootstrap - Search results without type icon
2 parents 11d05dd + 1df3efd commit 2ab5703

File tree

8 files changed

+203
-70
lines changed

8 files changed

+203
-70
lines changed

docs/_static/custom.css

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ pre {
1414
box-shadow: none;
1515
}
1616
a,
17-
a:visited {
17+
a:visited,
18+
main.bd-content #main-content a,
19+
main.bd-content #main-content a:visited {
1820
color: #2980b9;
1921
}
20-
a:hover {
21-
color: #176aa1;
22-
text-decoration: underline;
22+
a:hover,
23+
main.bd-content #main-content a:hover {
24+
color: #1a567e;
25+
text-decoration: none;
2326
}
2427
ul {
2528
list-style-type: square;
@@ -48,6 +51,9 @@ span.linenos {
4851
p.ploneorglink img {
4952
vertical-align: bottom;
5053
}
54+
dt:target, span.highlighted {
55+
background-color: #7ddf4493;
56+
}
5157

5258
.bd-sidebar .nav ul {
5359
padding: 0 0 0 1rem;
@@ -126,36 +132,62 @@ div.admonition.admonition-todo > .admonition-title::before {
126132
font-weight: bold;
127133
}
128134

129-
#search-form {
130-
display: flex;
131-
flex-direction: row;
132-
align-items: baseline;
133-
flex-wrap: wrap;
134-
}
135-
#search-form select,
136-
#search-form input[type="text"] {
137-
height: 2rem;
138-
margin-right: 1rem;
139-
margin-bottom: 1rem;
140-
background-color: white;
141-
border: 1px solid darkgrey;
135+
136+
/* Bootstrap */
137+
.btn-primary {
138+
color: #fff;
139+
background-color: #2980b9;
140+
border-color: #2980b9;
142141
}
143-
#search-form input[type="submit"] {
144-
margin-right: 1rem;
142+
.btn-primary {
143+
background-color: #1f86ca;
144+
border-color: #2980b9;
145145
}
146-
ul.search .title_doc_section::before {
147-
content: ' – ';
146+
147+
/* Search */
148+
ul.search {
149+
margin-left: 0;
148150
}
149151
p.search-summary {
150-
margin-top: 1em;
152+
margin: 1em 0 2rem 0;
151153
}
152154
#search-results ul {
153155
list-style-type: none;
154156
padding-left: 0;
155157
}
156-
#search-results ul li {
157-
margin-bottom: 1em;
158+
#search-results ul li,
159+
ul.search li {
160+
margin-bottom: 2rem;
161+
padding: 0;
162+
background-image: none;
163+
}
164+
#search-results ul li h3 {
165+
margin: 0.4rem 0 .5rem;
166+
font-size: 1.5rem;
158167
}
168+
#search-results ul li .breadcrumbs {
169+
display: flex;
170+
flex-direction: row;
171+
flex-wrap: wrap;
172+
}
173+
#search-results ul li .breadcrumbs a {
174+
font-weight: normal;
175+
}
176+
#search-results ul li .breadcrumbs .lastbreadcrumb {
177+
white-space: nowrap;
178+
display: inline-block;
179+
max-width: 12rem;
180+
overflow: hidden; /* "overflow"-Wert darf nicht "visible" sein */
181+
182+
text-overflow: ellipsis;
183+
}
184+
ul.search li p.context {
185+
margin-left: 0;
186+
}
187+
.pathseparator {
188+
padding: 0 0.7rem;
189+
}
190+
159191

160192
/* submenu */
161193
.bd-toc {

docs/_static/file.sketch

4.61 KB
Binary file not shown.

docs/_static/file.svg

Lines changed: 10 additions & 0 deletions
Loading

docs/_static/file_original.png

286 Bytes
Loading

docs/_static/plone_mini.png

1012 Bytes
Loading

docs/_static/searchtools.js

Lines changed: 71 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*
1010
*/
1111

12+
var title_documentation = 'Plone Documentation';
1213

1314
if (!Scorer) {
1415
/**
@@ -74,14 +75,12 @@ var Search = {
7475

7576
init : function() {
7677
var params = $.getQueryParameters();
78+
let doc_section = params.doc_section ? params.doc_section[0] : 'all';
79+
$('input[id="doc_section_' + doc_section + '"]').prop("checked", true)
7780
if (params.q) {
7881
var query = params.q[0];
7982
$('input[name="q"]')[0].value = query;
8083
$('input[name="q"]')[1].value = query;
81-
if (params.doc_section) {
82-
var doc_section = params.doc_section[0];
83-
$('select[name="doc_section"]')[0].value = doc_section;
84-
}
8584
this.performSearch(query, doc_section);
8685
}
8786
},
@@ -199,10 +198,6 @@ var Search = {
199198
}
200199
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
201200

202-
// console.debug('SEARCH: searching for:');
203-
// console.info('required: ', searchterms);
204-
// console.info('excluded: ', excluded);
205-
206201
// prepare search
207202
var terms = this._index.terms;
208203
var titleterms = this._index.titleterms;
@@ -237,7 +232,7 @@ var Search = {
237232

238233
// Enrich item with parent doc_section title
239234
for (i = 0; i < results.length; i++)
240-
results[i][6] = results[i][6] || 'TODO Documentation title';
235+
results[i][6] = results[i][6] || 'Plone Documentation';
241236

242237
// now sort the results by score (in opposite order of appearance, since the
243238
// display function below uses pop() to retrieve items) and then
@@ -257,8 +252,25 @@ var Search = {
257252
}
258253
});
259254

255+
function _getBreadcrumbs(item, linkUrl) {
256+
let parentTitles = item[6];
257+
let path = item[0].split('/')
258+
.slice(0, -1);
259+
path = path.map((el, index) => {
260+
return {
261+
"path": path.slice(0, index+1).join('/'),
262+
"title": parentTitles[index]
263+
}
264+
})
265+
let markup = path
266+
.map((el, idx) => {
267+
return `<a href="/${el.path}">${el.title}</a>`
268+
})
269+
markup.push(`<span class="lastbreadcrumb">${item[1]}</span>`)
270+
return markup.join('<span class="pathseparator">&gt;</span>');
271+
}
260272

261-
// print the results
273+
// Print the results.
262274
var resultCount = results.length;
263275
function displayNextItem() {
264276
// results left, load the summary and display it
@@ -283,11 +295,15 @@ var Search = {
283295
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
284296
linkUrl = item[0] + DOCUMENTATION_OPTIONS.LINK_SUFFIX;
285297
}
286-
listItem.append($('<a/>').attr('href',
287-
linkUrl +
288-
highlightstring + item[2]).html(item[1]));
298+
let breadcrumbs = _getBreadcrumbs(item, linkUrl);
299+
breadcrumbs = $("<div class='breadcrumbs'>" + breadcrumbs + "</div>");
300+
listItem.append(breadcrumbs);
301+
let headline = $('<h3/>');
302+
headline.append($('<a/>').attr('href',
303+
linkUrl +
304+
highlightstring + item[2]).html(item[1]));
289305

290-
listItem.append($('<span class="title_doc_section">' + item[6] + '</span>'));
306+
listItem.append(headline);
291307

292308
if (item[3]) {
293309
listItem.append($('<span> (' + item[3] + ')</span>'));
@@ -321,9 +337,9 @@ var Search = {
321337
Search.stopPulse();
322338
Search.title.text(_('Search Results'));
323339
if (!resultCount)
324-
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
340+
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly. Searching for multiple words only shows matches that contain all words.'));
325341
else
326-
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
342+
Search.status.text(_('Found %s page(s) matching the search query.').replace('%s', resultCount));
327343
Search.status.fadeIn(500);
328344
}
329345
}
@@ -344,7 +360,9 @@ var Search = {
344360
var results = [];
345361

346362
for (var prefix in objects) {
347-
for (var name in objects[prefix]) {
363+
for (var iMatch = 0; iMatch != objects[prefix].length; ++iMatch) {
364+
var match = objects[prefix][iMatch];
365+
var name = match[4];
348366
var fullname = (prefix ? prefix + '.' : '') + name;
349367
var fullnameLower = fullname.toLowerCase()
350368
if (fullnameLower.indexOf(object) > -1) {
@@ -358,7 +376,6 @@ var Search = {
358376
} else if (parts[parts.length - 1].indexOf(object) > -1) {
359377
score += Scorer.objPartialMatch;
360378
}
361-
var match = objects[prefix][name];
362379
var objname = objnames[match[1]][2];
363380
var title = titles[match[0]];
364381
// If more than one term searched for, we require other words to be
@@ -496,19 +513,40 @@ var Search = {
496513
break;
497514
}
498515
}
499-
500516
// if we have still a valid result we can add it to the result list
501517
if (valid) {
518+
/**
519+
* file: index
520+
* docnames: array of paths
521+
* titles: array of titles
522+
*/
523+
502524
// select one (max) score for the file.
503525
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
504526
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
505-
function getParentTitle(f) {
506-
let parentdocname = docnames[f].split('/')[0] + '/index';
507-
let parentID = docnames.indexOf(parentdocname);
508-
let title = parentID === -1 ? 'Plone Documentation' : titles[parentID];
509-
return title
527+
528+
/**
529+
* Return array with titles of ancestors of file.
530+
* @param {number} idx - The index of the result item in global list of files
531+
* @returns array
532+
*/
533+
function getParentTitles(idx) {
534+
let path = docnames[idx]
535+
536+
let foo = path.split('/').slice(0, -1);
537+
foo = foo.map((el, index) => {
538+
return `${foo.slice(0, index+1).join('/')}/index`
539+
})
540+
541+
let parentTitles = foo.map(el => {
542+
let parentId = docnames.indexOf(el);
543+
let title = parentId === -1 ? title_documentation : titles[parentId];
544+
return title
545+
})
546+
return parentTitles
510547
}
511-
results.push([docnames[file], titles[file], '', null, score, filenames[file], getParentTitle(file)]);
548+
549+
results.push([docnames[file], titles[file], '', null, score, filenames[file], getParentTitles(file)]);
512550
}
513551
}
514552
return results;
@@ -544,10 +582,14 @@ var Search = {
544582

545583
$(document).ready(function() {
546584
Search.init();
547-
if ($.trim($(".topbar-contents .bd-toc").html()) === "") {
548-
$(".topbar-contents .bd-toc").css("visibility", "hidden");
549-
}
550-
$('select[name="doc_section"]').change(function() {
585+
$('#q').focus();
586+
$('input[name="doc_section"]').change(function() {
551587
this.form.submit();
552588
});
589+
590+
function clearSearchField() {
591+
$('#q').val('');
592+
this.form.submit();
593+
}
594+
$( "button.clear_search" ).on( "click", clearSearchField );
553595
});

docs/_templates/page.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
{% block footer %}
88
<script type="text/javascript">
99
$(document).ready(function() {
10+
// Hide empty sub menu.
1011
if ($.trim($(".topbar-contents .bd-toc").html()) === "") {
1112
$(".topbar-contents .bd-toc").css("visibility", "hidden");
1213
}
14+
// Add toggle to exercise solutions (admonition with class 'toggle')
1315
$(".toggle > *").hide();
1416
$(".toggle .admonition-title").show();
1517
$(".toggle .admonition-title").click(function() {

0 commit comments

Comments
 (0)