Make search results appear in a fixed window; (#3858)

This commit is contained in:
Clyde Stubbs 2024-05-30 08:08:17 +10:00 committed by GitHub
parent 0138eca827
commit 13fbdb1d00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 162 additions and 35 deletions

View File

@ -1,3 +1,9 @@
/* provide this to be queried in JS. Sadly can't be used in media-queries just yet*/
:root {
--mobile-width-stop: 875;
}
.row-odd {
background-color: #f3f6f6;
}
@ -263,9 +269,8 @@ div.body p, div.body dd, div.body li, div.body blockquote {
.search-results {
background-color: #f8f8f8;
box-shadow: 0 6px 10px rgb(0 0 0 / 0.2);
position: absolute;
position: fixed;
z-index: 1500;
margin-top: 4px;
padding-right: 6px;
padding-left: 6px;
border-radius: 12px;
@ -277,6 +282,21 @@ div.body p, div.body dd, div.body li, div.body blockquote {
display: none;
}
@media screen and (max-width: 875px) {
/* hide search result thumbnails on mobile */
.pagefind-modular-list-thumb {
width: 0;
}
/* reduce height of search box */
.pagefind-modular-input-wrapper {
scale: 90%;
}
.logo {
scale: 60%;
}
}
/* dark theme */
@media (prefers-color-scheme: dark) {
@ -383,6 +403,7 @@ div.body p, div.body dd, div.body li, div.body blockquote {
.pagefind-ui__form, .pagefind-modular-input, .search-results {
color: #ececec !important;
}
:root {
--pagefind-ui-primary: #eeeeee;
--pagefind-ui-text: #eeeeee;

View File

@ -26,7 +26,8 @@
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta property="og:site_name" content="ESPHome">
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=3, interactive-widget=overlays-content">
{% endblock %}
{% block relbar_top %}
@ -39,7 +40,6 @@
{% endif %}
</ul>
<div class="search-results" id="search-results"></div>
{% endblock %}
{% block footer %}

View File

@ -1,42 +1,150 @@
<script src="/pagefind/pagefind-modular-ui.js"></script>
<div class="pagefind-ui__form" id="search"></div>
<div class="search-results" id="mobile-search-results"></div>
<script>
let callbackAdded = null;
class El {
constructor(tagname) {
this.element = document.createElement(tagname);
}
id(s) {
this.element.id = s;
return this;
}
class(s) {
this.element.classList.add(s);
return this;
}
attrs(obj) {
for (const [k,v] of Object.entries(obj)) {
this.element.setAttribute(k, v);
}
return this;
}
text(t) {
this.element.innerText = t;
return this;
}
html(t) {
this.element.innerHTML = t;
return this;
}
handle(e, f) {
this.element.addEventListener(e, f);
return this;
}
addTo(el) {
if (el instanceof El) {
el.element.appendChild(this.element);
} else {
el.appendChild(this.element);
}
return this.element;
}
}
window.addEventListener('DOMContentLoaded', (event) => {
const std_target = document.getElementById("search-results");
const mobile_target = document.getElementById("mobile-search-results");
const targetClass = "search-results";
const docel = document.getElementsByClassName("document");
if (docel.length === 0)
return;
const inpel = document.getElementById("search");
if (!inpel)
return;
var mobileWidth = getComputedStyle(document.body).getPropertyValue("--mobile-width-stop");
function isMobile() {
return window.innerWidth <= mobileWidth;
}
const target = document.createElement("div");
target.classList.add(targetClass);
target.id = targetClass;
target.style.display = "none";
docel.item(0).appendChild(target);
const margin = 20;
const resultTemplate = (result) => {
let wrapper = new El("li").class("pagefind-modular-list-result");
let thumb = new El("div").class("pagefind-modular-list-thumb").addTo(wrapper);
if (result?.meta?.image) {
new El("img").class("pagefind-modular-list-image").attrs({
src: result.meta.image,
alt: result.meta.image_alt || result.meta.title
}).addTo(thumb);
}
let inner = new El("div").class("pagefind-modular-list-inner").addTo(wrapper);
let title = new El("p").class("pagefind-modular-list-title").addTo(inner);
new El("a").class("pagefind-modular-list-link").text(result.meta?.title).attrs({
href: result.meta?.url || result.url
}).addTo(title);
let excerpt = new El("p").class("pagefind-modular-list-excerpt").addTo(inner);
new El("a").class("pagefind-modular-list-link").html(result.excerpt).attrs({
href: result.meta?.url || result.url
}).addTo(excerpt);
return wrapper.element;
}
function resizeTarget() {
const searchPos = inpel.getBoundingClientRect();
var leftPos;
var topPos;
var maxWidth = 650;
target.style.width = "auto;"
target.style.height = "fit-content";
target.style.maxWidth = maxWidth + "px";
let rightPos = margin;
if (isMobile()) {
// position search results left aligned with the search box, and below.
leftPos = margin / 2;
topPos = searchPos.bottom + margin / 2;
rightPos = margin / 2;
} else {
// position search results top aligned with the search box, and to its right.
leftPos = searchPos.right + margin * 2;
topPos = searchPos.top;
if (rightPos - leftPos > maxWidth)
rightPos = leftPos + maxWidth;
}
target.style.right = rightPos + "px";
target.style.top = topPos + "px";
target.style.left = leftPos + "px";
let twidth = window.innerWidth - margin - leftPos;
if (twidth > maxWidth)
twidth = maxWidth;
target.style.width = twidth + "px";
target.style.maxHeight = (window.innerHeight - margin - topPos) + "px";
}
window.addEventListener("resize", (event) => { resizeTarget(); });
function showTarget() {
var target = std_target;
if (window.innerWidth <= 875) {
target = mobile_target;
std_target.style.display = "none";
} else {
mobile_target.style.display = "none";
}
target.style.display = "block";
const rect = target.getBoundingClientRect();
const height = window.innerHeight;
target.style.width = "100%";
target.style.height = "fit-content";
target.style.maxHeight = (height - rect.top - 10) + "px";
if (!callbackAdded) {
callbackAdded = true;
if (target.style.display !== "block") {
target.style.display = "block";
document.addEventListener('click', clickCallback);
}
resizeTarget();
}
function hideTargets() {
std_target.style.display = "none";
mobile_target.style.display = "none";
std_target.style.height = "0";
mobile_target.style.height = "0";
if (callbackAdded) {
if (target.style.display !== "none") {
target.style.display = "none";
document.removeEventListener('click', clickCallback);
callbackAdded = false;
}
}
@ -57,19 +165,17 @@
}));
instance.add(new PagefindModularUI.ResultList({
containerElement: "#search-results"
}));
instance.add(new PagefindModularUI.ResultList({
containerElement: "#mobile-search-results"
containerElement: "#search-results",
resultTemplate: resultTemplate
}));
const clickCallback = (event) => {
const path = event.composedPath();
if (path.includes(std_target) || path.includes(mobile_target) || path.includes(inpel))
if (path.includes(target) || path.includes(inpel))
return;
hideTargets();
};
if (std_target && mobile_target) {
if (target) {
instance.on("results", (results) => {
if (results.results.length) {
showTarget();