Skip to content

Commit

Permalink
feat(search): add advanced search options
Browse files Browse the repository at this point in the history
  • Loading branch information
razonyang committed Aug 5, 2022
1 parent d19afa2 commit 41c0dc4
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 39 deletions.
16 changes: 16 additions & 0 deletions assets/search/languages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Languages {
ele: HTMLSelectElement;

constructor(callback) {
this.ele = document.querySelector('#languages-select');
this.ele.addEventListener('change', () => {
callback();
});
}

getValue() {
return this.ele.value;
}
}

export default Languages;
105 changes: 84 additions & 21 deletions assets/search/search.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Fuse from 'fuse.js';
import Mustache from 'mustache';
import Mark from 'mark.js/dist/mark.js';
import Languages from './languages';

declare global {
interface Window {
Expand Down Expand Up @@ -75,19 +76,42 @@ export class Search {
this.loadMore.addEventListener('click', () => {
this.poplateResults();
});

new Languages(() => {
this.search(this.input.value);
});
}

initFuse() {
this.fuseOptions = window.fuseOptions;
console.debug('Fuse options', this.fuseOptions);
this.fuseOptions = Object.assign(window.fuseOptions, {
useExtendedSearch: true,
keys: [
'title',
'content',
'lang',
'authors.title',
'categories.title',
'series.title',
'tags.title',
],
});
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status !== 200) {
console.error({ error: xhr.statusText });
return;
}
const pages = xhr.response;
const pages = xhr.response.pages;
const taxonomies = ['categories', 'authors', 'series', 'tags'];
for (let i in taxonomies) {
const datalist = document.querySelector('#' + taxonomies[i] + '-list');
for (let j in xhr.response[taxonomies[i]]) {
const option = document.createElement('option');
option.value = xhr.response[taxonomies[i]][j];
datalist.appendChild(option);
}
}
this.fuse = new Fuse(pages, this.fuseOptions);
this.search(this.input.value);
}
Expand All @@ -105,15 +129,15 @@ export class Search {
}
this.updateSearchbar(this.input.value);
document.querySelector('.search-bar input');
this.form.addEventListener('submit', (event) => {
this.handleSubmit(event);
this.form.addEventListener('submit', (e) => {
e.preventDefault();
this.handleSubmit();
});
}

handleSubmit(event) {
handleSubmit() {
this.search(this.input.value);
this.updateSearchbar(this.input.value);
event.preventDefault();
}

updateSearchbar(value) {
Expand Down Expand Up @@ -153,22 +177,61 @@ export class Search {
this.hideLoadingSpinner();
return;
}
this.page = 1;
this.setPage(query);
const results = this.fuse.search(query);
console.debug({ results });
this.results = results;
this.hideLoadingSpinner();
if (this.results.length > this.paginate) {
this.showLoadMoreBtn();
} else {
this.hideLoadMoreBtn();
try {
this.page = 1;
this.setPage(query);
const params = this.serializeForm(query);
const results = this.fuse.search(params);
this.results = results;
if (this.results.length > this.paginate) {
this.showLoadMoreBtn();
} else {
this.hideLoadMoreBtn();
}
if (results.length > 0) {
this.poplateResults();
} else {
this.stat.innerHTML = this.tmplNoResults;
}
} catch (err) {
console.error(err);
} finally {
this.hideLoadingSpinner();
}
if (results.length > 0) {
this.poplateResults();
} else {
this.stat.innerHTML = this.tmplNoResults;
}

serializeForm(query) {
let params = {
$and: [
{
$or: [
{ title: query },
{ content: query },
]
}
]
}
let author = document.querySelector('#author-input').value;
if (author) {
params.$and.push({'authors.title': author});
}
let category = document.querySelector('#category-input').value;
if (category) {
params.$and.push({'categories.title': category});
}
let series = document.querySelector('#series-input').value;
if (series) {
params.$and.push({'series.title': series});
}
let tag = document.querySelector('#tag-input').value;
if (tag) {
params.$and.push({'tags.title': tag});
}
let lang = document.querySelector('select[name="lang"]').value;
if (lang) {
params.$and.push({'lang': '=' + lang});
}
return params;
}

setPage(query) {
Expand Down
3 changes: 3 additions & 0 deletions i18n/en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ other = "Repository"
[search]
other = "Search"

[search_advanced]
other = "Advanced"

[search_missing_keywords]
other = "Please enter search keywords"

Expand Down
3 changes: 3 additions & 0 deletions i18n/zh-cn.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ other = "仓库"
[search]
other = "搜索"

[search_advanced]
other = "高级"

[search_missing_keywords]
other = "请输入搜索关键词"

Expand Down
3 changes: 3 additions & 0 deletions i18n/zh-hans.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ other = "仓库"
[search]
other = "搜索"

[search_advanced]
other = "高级"

[search_missing_keywords]
other = "请输入搜索关键词"

Expand Down
3 changes: 3 additions & 0 deletions i18n/zh-hant.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ other = "倉庫"
[search]
other = "搜尋"

[search_advanced]
other = "高級"

[search_missing_keywords]
other = "請輸入搜尋關鍵詞"

Expand Down
3 changes: 3 additions & 0 deletions i18n/zh-hk.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ other = "倉庫"
[search]
other = "搜索"

[search_advanced]
other = "高級"

[search_missing_keywords]
other = "請輸入搜索關鍵詞"

Expand Down
3 changes: 3 additions & 0 deletions i18n/zh-tw.toml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ other = "倉庫"
[search]
other = "搜尋"

[search_advanced]
other = "高級"

[search_missing_keywords]
other = "請輸入搜尋關鍵詞"

Expand Down
21 changes: 8 additions & 13 deletions layouts/_default/search.html
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
{{ define "content" }}
<div class="search container">
<div class="row">
<div class="d-flex col-12 col-lg-8">
<div class="d-flex col-12 col-lg-8 component py-3 pt-4 px-2 rounded">
{{- $logo := (default "images/logo.webp" .Site.Params.logo) }}
{{- if $logo }}
<div class="flex-shrink-0 d-none d-md-block">
<img src="{{ $logo | absURL }}" width="80px" height="80px">
<img class="position-sticky" src="{{ $logo | absURL }}" width="80px" height="80px" style="top: 84px">
</div>
{{- end -}}
<div class="{{ if $logo }}flex-grow-1 ms-0 ms-md-3{{ end }} container px-0">
<form id="searchForm" class="col-12 search-form mb-3 p-0">
<div class="input-group input-group-lg align-items-center">
<span class="btn btn-search disabled position-absolute left-0 border-0" type="submit" aria-label="submit">
<i class="fas fa-fw fa-search text-primary"></i>
</span>
<input class="form-control rounded ps-5 border-primary" name="q" type="search" aria-label="Search">
</div>
</form>
<div class="search-stat mb-3 p-0 col-12">
<div class="{{ if $logo }}flex-grow-1 ms-0 ms-md-3{{ end }} container">
{{- partial "search/form" . }}
<div class="text-center my-2">
<div id="loadingSpinner" class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div class="search-stat mb-3 col-12">
<span id="searchStat"></span>
</div>
<div id="searchResults" class="search-results mb-3 p-0 row"></div>
<div id="searchResults" class="search-results mb-3 row"></div>
<div class="text-center mb-3">
<button class="btn btn-block btn-outline-primary d-none" type="button" id="btnLoadMore">{{ i18n "load_more" }}</button>
</div>
Expand Down
41 changes: 41 additions & 0 deletions layouts/partials/search/form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<form id="searchForm" class="col-12 search-form mb-3" novalidate>
<div class="input-group input-group-lg align-items-center">
<input class="form-control rounded border-primary pe-5" name="q" type="search" aria-label="Search">
<button class="btn btn-sm btn-search position-absolute end-0 border-0 border-start border-secondary p-2" type="submit">
<i class="fas fa-fw fa-search text-primary"></i>
</button>
</div>
<p class="text-end mt-1">
<a class="" data-bs-toggle="collapse" href="#advanced-search" role="button" aria-expanded="false" aria-controls="advanced-search">
{{- i18n "search_advanced" -}}
</a>
</p>
<div class="row g-1 collapse" id="advanced-search">
<select class="form-select col-12 mb-2" aria-label="Language" name="lang" id="languages-select">
<option selected value="">{{ i18n "language" }}</option>
{{- range .Site.Languages -}}
<option value="{{ .Lang }}">{{ .LanguageName }}</option>
{{- end }}
</select>
<div class="form-floating col-6 col-lg-3">
<input type="text" class="form-control form-control-sm" name="author" id="author-input" list="authors-list" placeholder="{{ i18n "authors" }}">
<label for="author-input">{{ i18n "authors" }}</label>
<datalist id="authors-list"></datalist>
</div>
<div class="form-floating col-6 col-lg-3">
<input type="text" class="form-control form-control-sm" name="category" id="category-input" list="categories-list" placeholder="{{ i18n "categories" }}">
<label for="category-input">{{ i18n "categories" }}</label>
<datalist id="categories-list"></datalist>
</div>
<div class="form-floating col-6 col-lg-3">
<input type="text" class="form-control form-control-sm" name="series" id="series-input" list="series-list" placeholder="{{ i18n "series" }}">
<label for="series-input">{{ i18n "series" }}</label>
<datalist id="series-list"></datalist>
</div>
<div class="form-floating col-6 col-lg-3">
<input type="text" class="form-control form-control-sm" name="tag" id="tag-input" list="tags-list" placeholder="{{ i18n "tags" }}">
<label for="tag-input">{{ i18n "tags" }}</label>
<datalist id="tags-list"></datalist>
</div>
</div>
</form>
21 changes: 17 additions & 4 deletions layouts/partials/search/index.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{{- $.Scratch.Add "index" slice -}}
{{- range .Site.RegularPages -}}
{{- $.Scratch.Add "pages" slice -}}
{{- $.Scratch.Add "authors" slice }}
{{- $.Scratch.Add "categories" slice }}
{{- $.Scratch.Add "series" slice }}
{{- $.Scratch.Add "tags" slice }}
{{- range where .Site.AllPages "Kind" "page" -}}
{{- $page := . }}
{{- $date := .Date | time.Format ":date_long" -}}
{{- $title := .Title }}
Expand All @@ -24,6 +28,7 @@
{{- end -}}
{{- end -}}
{{- $item := (dict
"lang" .Language.Lang
"title" $title
"content" .Plain
"permalink" .Permalink
Expand All @@ -36,9 +41,17 @@
{{- $terms := slice }}
{{- range $page.GetTerms $taxonomyName }}
{{- $terms = $terms | append (dict "title" .Title "url" .Permalink) }}
{{- $.Scratch.Add ($taxonomyName | pluralize) (slice .Title) }}
{{- end }}
{{- $item = merge $item (dict $taxonomyName $terms) }}
{{- end }}
{{- $.Scratch.Add "index" $item -}}
{{- $.Scratch.Add "pages" (slice $item) }}
{{- end -}}
{{- $.Scratch.Get "index" | uniq | jsonify -}}
{{- dict
"pages" ($.Scratch.Get "pages")
"authors" ($.Scratch.Get "authors"| uniq)
"categories" ($.Scratch.Get "categories"| uniq)
"series" ($.Scratch.Get "series" | uniq)
"tags" ($.Scratch.Get "tags"| uniq)
| jsonify
-}}
2 changes: 1 addition & 1 deletion purgecss.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const purgecss = require('@fullhuman/postcss-purgecss')({
// deep: [/blue$/],
greedy: [/carousel-indicators$/]
},
dynamicAttributes: ['data-bs-popper', 'data-theme', 'data-palette', 'role']
dynamicAttributes: ['data-bs-popper', 'data-theme', 'data-palette', 'role', 'placeholder-shown']
});

exports.default = purgecss;

0 comments on commit 41c0dc4

Please sign in to comment.