[new feature] search result positioning

This commit is contained in:
zzossig 2020-02-07 11:08:14 +09:00
parent 2c3f31db7c
commit 7c549e0d5a
8 changed files with 253 additions and 38 deletions

View File

@ -66,6 +66,65 @@
color: themed('search-highlight-color'); color: themed('search-highlight-color');
} }
} }
&-result {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin: 4px 0;
@include themify($themes) {
background-color: themed('body-background-color');
}
&[data-display="block"] {
display: block;
}
&[data-display="none"] {
display: none;
}
&__header {
}
&__body {
margin-top: 1rem;
padding: 0 1rem;
position: relative;
display: block;
overflow: auto;
height: 100%;
@include themify($themes) {
@include moz-scrollbars(themed('custom-scrollbar-foreground-color'), themed('custom-scrollbar-background-color'));
@include webkit-scrollbars(themed('custom-scrollbar-foreground-color'), themed('custom-scrollbar-background-color'));
}
}
&__item {
&:not(first-child) {
padding-bottom: 2.25rem;
}
&--title {
font-family: $title-font;
font-size: 1.5rem;
margin: 0.25rem 0;
&::before {
content: "📋 ";
}
}
&--desc {
font-size: 1rem;
margin: 0.25rem 0;
}
}
}
} }
.menu-item { .menu-item {
@ -126,7 +185,7 @@
&-item { &-item {
font-size: 1rem; font-size: 1rem;
padding: 0.125rem; padding: 0.125rem 0.25rem;
@include on-event { @include on-event {
@include themify($themes) { @include themify($themes) {
background-color: themed('search-hover-background-color'); background-color: themed('search-hover-background-color');
@ -287,11 +346,23 @@
&__item { &__item {
padding: 0.5rem; padding: 0.5rem;
list-style-type: none;
&:not(first-child) {
padding-bottom: 0.75rem;
}
&--title { &--title {
font-family: $title-font;
font-size: 1.2rem; font-size: 1.2rem;
margin: 0.25rem 0;
@include themify($themes) { @include themify($themes) {
color: themed('body-color'); color: themed('body-color');
} }
&::before {
content: "📋 ";
}
} }
&--desc { &--desc {

View File

@ -1,6 +1,14 @@
.list { .list {
&__main { &__main {
position: relative;
&[data-display="block"] {
display: block;
}
&[data-display="none"] {
display: none;
}
} }
&__sidebar { &__sidebar {

View File

@ -11,14 +11,15 @@
{{ .Content }} {{ .Content }}
</div> </div>
<div class="summary__container"> <div class="summary__container" data-display="block">
{{ $paginator := .Paginate (where .Pages "Type" .Type) }} {{ $paginator := .Paginate (where .Pages "Type" .Type) }}
{{ range $paginator.Pages }} {{ range $paginator.Pages }}
{{ .Render "summary" }} {{ .Render "summary" }}
{{ end }} {{ end }}
</div>
{{ partial "pagination/pagination" . }} {{ partial "pagination/pagination" . }}
</div> </div>
{{ partial "search/search-result-desktop" . }}
</div>
{{ if $.Param "enableSidebar" }} {{ if $.Param "enableSidebar" }}
<aside class="list__sidebar {{ if eq ($.Param "sidebarPosition") "left" }}l{{ else }}r{{ end }}" data-dir="{{ $.Param "languagedir" | default "ltr" }}"> <aside class="list__sidebar {{ if eq ($.Param "sidebarPosition") "left" }}l{{ else }}r{{ end }}" data-dir="{{ $.Param "languagedir" | default "ltr" }}">

View File

@ -11,13 +11,14 @@
{{.Content}} {{.Content}}
</div> </div>
<div class="summary__container"> <div class="summary__container" data-display="block">
{{ range .Paginator.Pages }} {{ range .Paginator.Pages }}
{{ .Render "summary" }} {{ .Render "summary" }}
{{ end }} {{ end }}
</div>
{{ partial "pagination/pagination" . }} {{ partial "pagination/pagination" . }}
</div> </div>
{{ partial "search/search-result-desktop" . }}
</div>
{{ if $.Param "enableSidebar" }} {{ if $.Param "enableSidebar" }}
<aside class="list__sidebar {{ if eq ($.Param "sidebarPosition") "left" }}l{{ else }}r{{ end }}" data-dir="{{ $.Param "languagedir" | default "ltr" }}"> <aside class="list__sidebar {{ if eq ($.Param "sidebarPosition") "left" }}l{{ else }}r{{ end }}" data-dir="{{ $.Param "languagedir" | default "ltr" }}">

View File

@ -4,7 +4,7 @@
<main class="main inner" data-sidebar-position="{{ $.Param "sidebarPosition" }}"> <main class="main inner" data-sidebar-position="{{ $.Param "sidebarPosition" }}">
<div class="list__main {{ if $.Param "enableSidebar" }}{{ if eq ($.Param "sidebarPosition") "left" }}mr{{ else }}lm{{ end }}{{ else }}lmr{{ end }}"> <div class="list__main {{ if $.Param "enableSidebar" }}{{ if eq ($.Param "sidebarPosition") "left" }}mr{{ else }}lm{{ end }}{{ else }}lmr{{ end }}">
<div class="summary__container"> <div class="summary__container" data-display="block">
{{ $filteredPages := .Site.RegularPages }} {{ $filteredPages := .Site.RegularPages }}
{{ range $.Param "notAllowedTypesInHome" }} {{ range $.Param "notAllowedTypesInHome" }}
{{ $filteredPages = (where $filteredPages "Type" "!=" (lower .)) }} {{ $filteredPages = (where $filteredPages "Type" "!=" (lower .)) }}
@ -13,10 +13,10 @@
{{ range $paginator.Pages }} {{ range $paginator.Pages }}
{{ .Render "summary" }} {{ .Render "summary" }}
{{ end }} {{ end }}
</div>
{{ partial "pagination/pagination" . }} {{ partial "pagination/pagination" . }}
</div> </div>
{{ partial "search/search-result-desktop" . }}
</div>
{{ if $.Param "enableSidebar" }} {{ if $.Param "enableSidebar" }}
<aside class="list__sidebar {{ if eq ($.Param "sidebarPosition") "left" }}l{{ else }}r{{ end }}" data-dir="{{ $.Param "languagedir" | default "ltr" }}"> <aside class="list__sidebar {{ if eq ($.Param "sidebarPosition") "left" }}l{{ else }}r{{ end }}" data-dir="{{ $.Param "languagedir" | default "ltr" }}">

View File

@ -79,6 +79,17 @@
// =============================================================== // ===============================================================
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// =================== search-result desktop ==================
var summaryContainer = document.querySelector('.summary__container');
var searchResult = document.querySelector('.search-result');
var searchResultCloseBtn = document.querySelector('.search-result__close');
searchResultCloseBtn ? searchResultCloseBtn.addEventListener('click', function (e) {
searchResult.setAttribute('data-display', 'none');
summaryContainer.setAttribute('data-display', 'block');
}) : null;
// =============================================================
// ============================ tab ============================ // ============================ tab ============================
document.querySelectorAll('.tab') ? document.querySelectorAll('.tab') ?
document.querySelectorAll('.tab').forEach(function(elem, idx) { document.querySelectorAll('.tab').forEach(function(elem, idx) {
@ -485,6 +496,8 @@
{{ $enableSearchHighlight := ($.Param "enableSearchHighlight") }} {{ $enableSearchHighlight := ($.Param "enableSearchHighlight") }}
var enableSearchHighlight = JSON.parse({{ $enableSearchHighlight | jsonify }}); var enableSearchHighlight = JSON.parse({{ $enableSearchHighlight | jsonify }});
{{ $searchResultPosition := ($.Param "searchResultPosition") }}
var searchResultPosition = JSON.parse({{ $searchResultPosition | jsonify }});
var fuse = null; var fuse = null;
@ -512,9 +525,6 @@
xhr.send(); xhr.send();
} }
function makeLi(ulElem, obj) { function makeLi(ulElem, obj) {
var li = document.createElement('li'); var li = document.createElement('li');
li.className = 'search-result__item'; li.className = 'search-result__item';
@ -529,7 +539,7 @@
if (obj.description) { if (obj.description) {
descDiv.innerHTML = obj.description; descDiv.innerHTML = obj.description;
} else if (obj.content) { } else if (obj.content) {
descDiv.innerHTML = obj.content.substring(0, 150); descDiv.innerHTML = obj.content.substring(0, 225);
} }
li.appendChild(a); li.appendChild(a);
@ -589,12 +599,7 @@
} }
} }
function renderSearchResultsSide(searchText, results) {
function renderSearchResults(searchText, results) {
searchResults = document.getElementById('search-results'); searchResults = document.getElementById('search-results');
searchMenu = document.getElementById('search-menu'); searchMenu = document.getElementById('search-menu');
searchResults.setAttribute('class', 'dropdown is-active'); searchResults.setAttribute('class', 'dropdown is-active');
@ -642,7 +647,7 @@
searchMenu.appendChild(ul); searchMenu.appendChild(ul);
} }
function renderSearchHighlightResults(searchText, results) { function renderSearchHighlightResultsSide(searchText, results) {
searchResults = document.getElementById('search-results'); searchResults = document.getElementById('search-results');
searchMenu = document.getElementById('search-menu'); searchMenu = document.getElementById('search-menu');
searchResults.setAttribute('class', 'dropdown is-active'); searchResults.setAttribute('class', 'dropdown is-active');
@ -743,26 +748,69 @@
function renderSearchHighlightResultsMobile(searchText, results) { function renderSearchHighlightResultsMobile(searchText, results) {
searchResults = document.getElementById('search-mobile-results'); searchResults = document.getElementById('search-mobile-results');
var content = document.createElement('div'); var ul = document.createElement('div');
content.setAttribute('class', 'mobile-search__content'); ul.setAttribute('class', 'mobile-search__content');
if (results.length > 0) { if (results.length) {
results.forEach(function (result) { results.forEach(function (result) {
var item = document.createElement('a'); var li = document.createElement('li');
item.setAttribute('href', result.item.uri); var a = document.createElement('a');
item.innerHTML = '<div class="mobile-search__item"><div class="mobile-search__item--title">📄 ' + generateHighlightedText(result.item.title, result.matches[0].indices) + '</div><div class="mobile-search__item--desc">' + (result.matches[1] ? generateHighlightedText(result.item.description, result.matches[1].indices) : result.matches[2] ? generateHighlightedText(result.item.content, result.matches[2].indices) : '') + '</div></div>'; var descDiv = null;
content.appendChild(item);
a.setAttribute('href', result.item.uri);
a.appendChild(li);
li.setAttribute('class', 'mobile-search__item');
var titleDiv = document.createElement('div');
titleDiv.innerHTML = result.item.title;
titleDiv.setAttribute('class', 'mobile-search__item--title');
if (result.matches && result.matches.length) {
for (var i = 0; i < result.matches.length; i++) {
if ('title' === result.matches[i].key) {
titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
}
if ('description' === result.matches[i].key) {
descDiv = document.createElement('div');
descDiv.setAttribute('class', 'mobile-search__item--desc');
descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
} else if ('content' === result.matches[i].key) {
if (!descDiv) {
descDiv = document.createElement('div');
descDiv.setAttribute('class', 'mobile-search__item--desc');
descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 150), result.matches[i].indices);
}
} else {
if (result.item.description) {
descDiv = document.createElement('div');
descDiv.setAttribute('class', 'mobile-search__item--desc');
descDiv.innerHTML = result.item.description;
} else {
descDiv = document.createElement('div');
descDiv.setAttribute('class', 'mobile-search__item--desc');
descDiv.innerHTML = result.item.content.substring(0, 150);
}
}
}
li.appendChild(titleDiv);
if (descDiv) {
li.appendChild(descDiv);
}
ul.appendChild(a);
}
}); });
} else { } else {
var item = document.createElement('span'); var item = document.createElement('span');
content.appendChild(item); ul.appendChild(item);
} }
let wrap = document.getElementById('search-mobile-results'); let wrap = document.getElementById('search-mobile-results');
while (wrap.firstChild) { while (wrap.firstChild) {
wrap.removeChild(wrap.firstChild) wrap.removeChild(wrap.firstChild)
} }
searchResults.appendChild(content); searchResults.appendChild(ul);
} }
function generateHighlightedText(text, regions) { function generateHighlightedText(text, regions) {
@ -800,6 +848,8 @@
searchElem.addEventListener('input', function(e) { searchElem.addEventListener('input', function(e) {
if (!e.target.value) { if (!e.target.value) {
document.getElementById('search-results').setAttribute('class', 'dropdown'); document.getElementById('search-results').setAttribute('class', 'dropdown');
searchResult ? searchResult.setAttribute('data-display', 'none') : null;
summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
return null; return null;
} }
@ -809,10 +859,19 @@
searchText = e.target.value; searchText = e.target.value;
var results = fuse.search(e.target.value); var results = fuse.search(e.target.value);
if (searchResultPosition === "main") {
if (enableSearchHighlight) { if (enableSearchHighlight) {
renderSearchHighlightResults(searchText, results); renderSearchHighlightResultsMain(searchText, results);
} else { } else {
renderSearchResults(searchText, results); renderSearchResultsMain(searchText, results);
}
} else {
if (enableSearchHighlight) {
renderSearchHighlightResultsSide(searchText, results);
} else {
renderSearchResultsSide(searchText, results);
}
} }
}) : null; }) : null;
@ -838,10 +897,19 @@
searchText = e.target.value; searchText = e.target.value;
var results = fuse.search(e.target.value); var results = fuse.search(e.target.value);
if (searchResultPosition === "main") {
if (enableSearchHighlight) { if (enableSearchHighlight) {
renderSearchHighlightResults(searchText, results); renderSearchHighlightResultsMain(searchText, results);
} else { } else {
renderSearchResults(searchText, results); renderSearchResultsMain(searchText, results);
}
} else{
if (enableSearchHighlight) {
renderSearchHighlightResultsSide(searchText, results);
} else {
renderSearchResultsSide(searchText, results);
}
} }
}) : null; }) : null;
@ -867,6 +935,11 @@
return null; return null;
} }
if (e.key === 'Escape') {
searchResult ? searchResult.setAttribute('data-display', 'none') : null;
summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
}
var items = document.querySelectorAll('#search-menu .dropdown-item'); var items = document.querySelectorAll('#search-menu .dropdown-item');
var keyCode = e.which || e.keyCode; var keyCode = e.which || e.keyCode;
@ -1012,5 +1085,52 @@
} }
}) : null; }) : null;
// ============================================================ // ============================================================
// =================== search-result desktop ==================
function renderSearchResultsMain(searchText, results) {
var searchBody = document.querySelector('.search-result__body');
var originUl = searchBody.querySelector('ul');
var ul = document.createElement('ul');
if (!searchText) {
searchResult.setAttribute('data-display', 'none');
summaryContainer.setAttribute('data-display', 'block');
} else if (results) {
if (results && results.length) {
results.forEach(function (result) {
makeLi(ul, result);
});
searchResult.setAttribute('data-display', 'block');
summaryContainer.setAttribute('data-display', 'none');
}
}
originUl.parentNode.replaceChild(ul, originUl);
}
function renderSearchHighlightResultsMain(searchText, results) {
var searchBody = document.querySelector('.search-result__body');
var originUl = searchBody.querySelector('ul');
var ul = document.createElement('ul');
if (!searchText) {
searchResult.setAttribute('data-display', 'none');
summaryContainer.setAttribute('data-display', 'block');
} else if (results) {
if (results && results.length) {
results.forEach(function (result) {
makeHighlightLi(ul, result);
});
searchResult.setAttribute('data-display', 'block');
summaryContainer.setAttribute('data-display', 'none');
}
}
originUl.parentNode.replaceChild(ul, originUl);
}
// ============================================================
}); });
</script> </script>

View File

@ -0,0 +1,14 @@
<div class="search-result" data-display="none">
<div class="search-result__header">
</div>
<div class="search-result__body">
<ul>
<li class="search-result__item">
<div class="search-result__item--title">
</div>
<div class="search-result__item--desc">
</div>
</li>
</ul>
</div>
</div>