Skip to content

Commit a853252

Browse files
FloEdelmannfxedel
authored andcommitted
Search filters (#30)
closes #14 and closes #29
1 parent ac0e570 commit a853252

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

views/pages/search.js

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
module.exports = function(options) {
2-
const {query, register} = options;
2+
const {query, register, manufacturers} = options;
33

4-
let searchQuery;
4+
const searchQuery = (query.q || '').trim();
55

6-
if (!('q' in query) || (searchQuery = query.q.trim()).length == 0) {
6+
if (!('q' in query) || (searchQuery.length == 0)) {
77
options.title = 'Search - Open Fixture Library';
88

99
let str = require('../partials/header')(options);
@@ -16,37 +16,86 @@ module.exports = function(options) {
1616
return str;
1717
}
1818

19+
const searchQueryCompare = searchQuery.toLowerCase();
1920
const searchQueryEscaped = htmlescape(searchQuery);
2021

2122
options.title = `Search "${searchQueryEscaped}" - Open Fixture Library`;
23+
options.searchQueryEscaped = searchQueryEscaped;
24+
25+
if (!('m' in query) || query.m === '') {
26+
query.m = [];
27+
}
28+
else if (typeof query.m == 'string') {
29+
query.m = [query.m];
30+
}
31+
32+
if (!('c' in query) || query.c === '') {
33+
query.c = [];
34+
}
35+
else if (typeof query.c == 'string') {
36+
query.c = [query.c];
37+
}
38+
query.c = query.c.map(decodeURIComponent);
2239

2340
let results = [];
24-
for (const fix in register.filesystem) {
25-
const fixData = register.filesystem[fix];
26-
if (fix.indexOf(query.q.toLowerCase()) > -1 || (fixData.manufacturerName + ' ' + fixData.name).toLowerCase().indexOf(query.q.toLowerCase()) > -1) {
27-
results.push(fix);
41+
for (const key in register.filesystem) {
42+
const [man, fix] = key.split('/');
43+
const fixData = register.filesystem[key];
44+
const name = (fixData.manufacturerName + ' ' + fixData.name).toLowerCase();
45+
46+
// very primitive match algorithm, maybe put more effort into it sometime
47+
if (
48+
(key.indexOf(searchQueryCompare) > -1 || name.indexOf(searchQueryCompare) > -1) // name matches
49+
&& (query.m.length == 0 || query.m.indexOf(man) > -1) // manufacturer is not relevant or matches
50+
&& (query.c.length == 0 || categoryMatch(query.c, key, register)) // categories are not relevant or match
51+
) {
52+
results.push(key);
2853
}
2954
}
30-
55+
3156
let str = require('../partials/header')(options);
3257

3358
str += `<h1>Search <em>${searchQueryEscaped}</em></h1>`;
3459

60+
str += '<form class="filter" action="/search">';
61+
str += ` <input type="search" name="q" value="${searchQueryEscaped}" />`;
62+
str += ' <select name="m" multiple>';
63+
str += ' <option value="">Filter by manufacturer</option>';
64+
str += Object.keys(manufacturers).map(man => `<option value="${man}"${query.m.indexOf(man) > -1 ? ' selected' : ''}>${manufacturers[man].name}</option>`).join('');
65+
str += ' </select>';
66+
str += ' <select name="c" multiple>';
67+
str += ' <option value="">Filter by category</option>';
68+
str += Object.keys(register.categories).map(cat => `<option value="${cat}"${query.c.indexOf(cat) > -1 ? ' selected' : ''}>${cat}</option>`).join('');
69+
str += ' </select>';
70+
str += ' <button type="submit">Search</button>';
71+
str += '</form>';
72+
73+
str += '<div class="search-results">';
3574
if (results.length > 0) {
36-
for (const fix of results) {
37-
const fixData = register.filesystem[fix];
38-
str += `<p><a href="/${fix}">${fixData.manufacturerName} ${fixData.name}</p>`;
75+
for (const key of results) {
76+
const fixData = register.filesystem[key];
77+
str += `<p><a href="/${key}">${fixData.manufacturerName} ${fixData.name}</p>`;
3978
}
4079
}
4180
else {
4281
str += `<p>Your search for <em>${searchQueryEscaped}</em> did not match any fixtures. Try using another query or browse by <a href="/manufacturers">manufacturer</a> or <a href="/categories">category</a>.</p>`;
4382
}
83+
str += '</div>';
4484

4585
str += require('../partials/footer')(options);
4686

4787
return str;
4888
};
4989

90+
function categoryMatch(categoryQuery, key, register) {
91+
for (const cat of categoryQuery) {
92+
if (cat in register.categories && register.categories[cat].indexOf(key) > -1) {
93+
return true;
94+
}
95+
}
96+
return false;
97+
}
98+
5099
function htmlescape(str) {
51100
return str.replace(/[^0-9A-Za-z ]/g, c => `&#${c.charCodeAt(0)};`);
52101
}

views/partials/header.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = function(options) {
1313
<a href="/" class="home-logo" title="Open Fixture Library">Open Fixture Library</a>
1414
1515
<form action="/search">
16-
<input type="search" name="q" placeholder="Search fixture" />
16+
<input type="search" name="q" placeholder="Search fixtures" value="${options.searchQueryEscaped || ''}" />
1717
<button type="submit">Search</button>
1818
</form>
1919

0 commit comments

Comments
 (0)