Fix MkDocs search results not displaying with custom header
Use inline JS styles (applySearchLayout) instead of CSS-only approach for search panel layout - fixes Firefox compatibility where cross-origin Material stylesheets override !important rules. Adds explicit height, flex layout, z-index, and background on search elements. Also fixes click-to-exit by deferring DOM queries to DOMContentLoaded. Syncs header-builder.service.ts with main.html changes. Bunker Admin
This commit is contained in:
@@ -257,6 +257,19 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="cm-header-nav__mobile-links">
|
||||
<label for="__search" class="cm-header-nav__mobile-link" style="cursor:pointer">
|
||||
<span class="material-icons-outlined">search</span>
|
||||
<span>Search</span>
|
||||
</label>
|
||||
<button class="cm-header-nav__mobile-link cm-header-nav__utility-btn" id="cm-mobile-palette-toggle" type="button">
|
||||
<span class="material-icons-outlined">dark_mode</span>
|
||||
<span>Dark Mode</span>
|
||||
</button>
|
||||
<button class="cm-header-nav__mobile-link cm-header-nav__utility-btn" id="cm-docs-sidebar-toggle" type="button">
|
||||
<span class="material-icons-outlined">menu_book</span>
|
||||
<span>Docs Navigation</span>
|
||||
</button>
|
||||
<div class="cm-header-nav__mobile-divider"></div>
|
||||
<a href="#" data-path="/home" class="cm-header-nav__mobile-link" data-nav-id="home"><span class="material-icons-outlined">home</span><span>Home</span></a>
|
||||
<a href="#" data-path="/campaigns" class="cm-header-nav__mobile-link" data-nav-id="campaigns"><span class="material-icons-outlined">send</span><span>Campaigns</span></a>
|
||||
<a href="#" data-path="/map" class="cm-header-nav__mobile-link" data-nav-id="map"><span class="material-icons-outlined">place</span><span>Map</span></a>
|
||||
@@ -290,19 +303,6 @@
|
||||
<a href="/" class="cm-header-nav__mobile-link" data-nav-id="landing"><span class="material-icons-outlined">language</span><span>Website</span></a>
|
||||
<a href="/docs/" class="cm-header-nav__mobile-link" data-nav-id="docs"><span class="material-icons-outlined">menu_book</span><span>Docs</span></a>
|
||||
<div class="cm-header-nav__mobile-divider"></div>
|
||||
<label for="__search" class="cm-header-nav__mobile-link" style="cursor:pointer">
|
||||
<span class="material-icons-outlined">search</span>
|
||||
<span>Search</span>
|
||||
</label>
|
||||
<button class="cm-header-nav__mobile-link cm-header-nav__utility-btn" id="cm-mobile-palette-toggle" type="button">
|
||||
<span class="material-icons-outlined">dark_mode</span>
|
||||
<span>Dark Mode</span>
|
||||
</button>
|
||||
<button class="cm-header-nav__mobile-link cm-header-nav__utility-btn" id="cm-docs-sidebar-toggle" type="button">
|
||||
<span class="material-icons-outlined">menu_book</span>
|
||||
<span>Docs Navigation</span>
|
||||
</button>
|
||||
<div class="cm-header-nav__mobile-divider"></div>
|
||||
<a href="#" data-path="/login" class="cm-header-nav__mobile-link" id="cm-mobile-signin-link">
|
||||
<span class="material-icons-outlined">login</span>
|
||||
<span>Sign In</span>
|
||||
@@ -440,6 +440,7 @@
|
||||
// Close custom drawer when search label is clicked on mobile + auto-focus input
|
||||
document.querySelectorAll('label[for="__search"]').forEach(function(el) {
|
||||
el.addEventListener('click', function() {
|
||||
if (el.classList.contains('md-search__overlay')) return; // overlay has its own handler
|
||||
closeDrawer();
|
||||
setTimeout(function() {
|
||||
var input = document.querySelector('.md-search__input');
|
||||
@@ -447,51 +448,154 @@
|
||||
}, 150);
|
||||
});
|
||||
});
|
||||
// Search activation: mirror checkbox state as a body class for CSS targeting.
|
||||
// On desktop, Material's search input is always visible (overflow from collapsed
|
||||
// header). Typing directly into it triggers the search worker but never checks
|
||||
// the __search checkbox, so the results panel stays hidden. We fix this by
|
||||
// checking the checkbox on input focus/input events.
|
||||
var searchToggle = document.getElementById('__search');
|
||||
if (searchToggle) {
|
||||
function syncSearchClass() {
|
||||
document.body.classList.toggle('cm-search-active', searchToggle.checked);
|
||||
// Search activation: Material may open search via checkbox OR by focusing the
|
||||
// input directly (varies by version). Detect both and mirror as body class.
|
||||
// NOTE: search DOM elements render AFTER the announce block in the template,
|
||||
// so we must defer element queries until DOMContentLoaded.
|
||||
var searchToggle = null;
|
||||
var searchInput = null;
|
||||
// Apply search layout inline styles (CSS-in-stylesheet is unreliable due to
|
||||
// cross-origin Material stylesheets overriding !important rules)
|
||||
function applySearchLayout(active) {
|
||||
var inner = document.querySelector('.md-search__inner');
|
||||
var output = document.querySelector('.md-search__output');
|
||||
var scrollwrap = document.querySelector('.md-search__scrollwrap');
|
||||
if (!inner) return;
|
||||
var isDesktop = window.matchMedia('(min-width: 60em)').matches;
|
||||
if (active) {
|
||||
inner.style.setProperty('display', 'flex', 'important');
|
||||
inner.style.setProperty('flex-direction', 'column', 'important');
|
||||
inner.style.setProperty('overflow', 'hidden', 'important');
|
||||
// Firefox needs explicit height (not just max-height) for flex children to grow
|
||||
if (isDesktop) {
|
||||
inner.style.setProperty('height', 'calc(100vh - 64px)', 'important');
|
||||
}
|
||||
if (output) {
|
||||
output.style.setProperty('position', 'relative', 'important');
|
||||
output.style.setProperty('flex', '1 1 0px', 'important');
|
||||
output.style.setProperty('min-height', '0', 'important');
|
||||
output.style.setProperty('display', 'flex', 'important');
|
||||
output.style.setProperty('flex-direction', 'column', 'important');
|
||||
output.style.setProperty('overflow', 'hidden', 'important');
|
||||
output.style.setProperty('width', '100%', 'important');
|
||||
}
|
||||
if (scrollwrap) {
|
||||
scrollwrap.style.setProperty('max-height', 'none', 'important');
|
||||
scrollwrap.style.setProperty('flex', '1 1 0px', 'important');
|
||||
scrollwrap.style.setProperty('min-height', '0', 'important');
|
||||
scrollwrap.style.setProperty('overflow-y', 'auto', 'important');
|
||||
}
|
||||
// Force search result elements visible + ensure proper stacking (Firefox)
|
||||
var resultList = document.querySelector('.md-search-result__list');
|
||||
if (resultList) {
|
||||
resultList.style.setProperty('display', 'block', 'important');
|
||||
resultList.style.setProperty('visibility', 'visible', 'important');
|
||||
resultList.style.setProperty('opacity', '1', 'important');
|
||||
resultList.style.setProperty('max-height', 'none', 'important');
|
||||
resultList.style.setProperty('overflow', 'visible', 'important');
|
||||
resultList.style.setProperty('color', 'var(--md-default-fg-color)', 'important');
|
||||
}
|
||||
var resultContainer = document.querySelector('.md-search-result');
|
||||
if (resultContainer) {
|
||||
resultContainer.style.setProperty('display', 'block', 'important');
|
||||
resultContainer.style.setProperty('visibility', 'visible', 'important');
|
||||
resultContainer.style.setProperty('opacity', '1', 'important');
|
||||
}
|
||||
// Ensure scrollwrap has z-index above overlay
|
||||
if (scrollwrap) {
|
||||
scrollwrap.style.setProperty('position', 'relative', 'important');
|
||||
scrollwrap.style.setProperty('z-index', '1', 'important');
|
||||
scrollwrap.style.setProperty('background', 'var(--md-default-bg-color)', 'important');
|
||||
}
|
||||
} else {
|
||||
inner.style.removeProperty('display');
|
||||
inner.style.removeProperty('flex-direction');
|
||||
inner.style.removeProperty('overflow');
|
||||
inner.style.removeProperty('height');
|
||||
if (output) {
|
||||
output.style.removeProperty('position');
|
||||
output.style.removeProperty('flex');
|
||||
output.style.removeProperty('min-height');
|
||||
output.style.removeProperty('display');
|
||||
output.style.removeProperty('flex-direction');
|
||||
output.style.removeProperty('overflow');
|
||||
output.style.removeProperty('width');
|
||||
}
|
||||
if (scrollwrap) {
|
||||
scrollwrap.style.removeProperty('max-height');
|
||||
scrollwrap.style.removeProperty('flex');
|
||||
scrollwrap.style.removeProperty('min-height');
|
||||
scrollwrap.style.removeProperty('overflow-y');
|
||||
scrollwrap.style.removeProperty('position');
|
||||
scrollwrap.style.removeProperty('z-index');
|
||||
scrollwrap.style.removeProperty('background');
|
||||
}
|
||||
var resultList = document.querySelector('.md-search-result__list');
|
||||
if (resultList) resultList.removeAttribute('style');
|
||||
var resultContainer = document.querySelector('.md-search-result');
|
||||
if (resultContainer) resultContainer.removeAttribute('style');
|
||||
}
|
||||
searchToggle.addEventListener('change', syncSearchClass);
|
||||
syncSearchClass();
|
||||
// Activate search when the Material input is focused or typed into directly.
|
||||
// Uses event delegation because the search input is rendered after this
|
||||
// script (announce block runs before header block).
|
||||
document.addEventListener('focusin', function(e) {
|
||||
if (e.target && e.target.classList && e.target.classList.contains('md-search__input')) {
|
||||
if (!searchToggle.checked) {
|
||||
searchToggle.checked = true;
|
||||
searchToggle.dispatchEvent(new Event('change'));
|
||||
}
|
||||
}
|
||||
});
|
||||
document.addEventListener('input', function(e) {
|
||||
if (e.target && e.target.classList && e.target.classList.contains('md-search__input')) {
|
||||
if (!searchToggle.checked) {
|
||||
searchToggle.checked = true;
|
||||
searchToggle.dispatchEvent(new Event('change'));
|
||||
}
|
||||
}
|
||||
});
|
||||
// Click-outside to dismiss search
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!searchToggle.checked) return;
|
||||
var panel = document.querySelector('.md-search__inner');
|
||||
if (panel && panel.contains(e.target)) return;
|
||||
if (e.target.closest && e.target.closest('label[for="__search"]')) return;
|
||||
searchToggle.checked = false;
|
||||
syncSearchClass();
|
||||
});
|
||||
// Also sync on Escape key (Material toggles checkbox via JS)
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') setTimeout(syncSearchClass, 50);
|
||||
});
|
||||
}
|
||||
function activateSearch() {
|
||||
document.body.classList.add('cm-search-active');
|
||||
if (searchToggle) searchToggle.checked = true;
|
||||
applySearchLayout(true);
|
||||
}
|
||||
function deactivateSearch() {
|
||||
document.body.classList.remove('cm-search-active');
|
||||
if (searchToggle) searchToggle.checked = false;
|
||||
if (searchInput) searchInput.blur();
|
||||
applySearchLayout(false);
|
||||
}
|
||||
function isSearchActive() {
|
||||
return document.body.classList.contains('cm-search-active');
|
||||
}
|
||||
// Custom search labels in the cm-header-nav (these exist now, in announce block)
|
||||
document.querySelectorAll('label[for="__search"]').forEach(function(lbl) {
|
||||
lbl.addEventListener('click', function() {
|
||||
if (lbl.classList.contains('md-search__overlay')) return;
|
||||
setTimeout(function() { activateSearch(); if (searchInput) searchInput.focus(); }, 50);
|
||||
});
|
||||
});
|
||||
// Deferred bindings: attach handlers to search elements once they exist in the DOM
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
searchToggle = document.getElementById('__search');
|
||||
searchInput = document.querySelector('.md-search__input');
|
||||
// Detect search open via input focus
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('focus', activateSearch);
|
||||
}
|
||||
// Detect search open via checkbox
|
||||
if (searchToggle) {
|
||||
searchToggle.addEventListener('change', function() {
|
||||
if (searchToggle.checked) activateSearch(); else deactivateSearch();
|
||||
});
|
||||
}
|
||||
// Click on overlay (md-search__overlay label) to dismiss search
|
||||
var searchOverlay = document.querySelector('.md-search__overlay');
|
||||
if (searchOverlay) {
|
||||
searchOverlay.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (isSearchActive()) deactivateSearch();
|
||||
});
|
||||
}
|
||||
});
|
||||
// Click-outside to dismiss search (on document, works immediately)
|
||||
document.addEventListener('mousedown', function(e) {
|
||||
if (!isSearchActive()) return;
|
||||
var panel = document.querySelector('.md-search__inner');
|
||||
if (panel && panel.contains(e.target)) return;
|
||||
// Let the overlay's own click handler deal with it
|
||||
if (e.target.closest && e.target.closest('.md-search__overlay')) return;
|
||||
if (e.target.closest && e.target.closest('label[for="__search"]')) return;
|
||||
if (e.target.closest && e.target.closest('.cm-header-nav__utility')) return;
|
||||
deactivateSearch();
|
||||
});
|
||||
// Escape key to dismiss
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape' && isSearchActive()) setTimeout(deactivateSearch, 50);
|
||||
});
|
||||
// Init palette icon + observe changes
|
||||
setTimeout(updatePaletteIcon, 100);
|
||||
new MutationObserver(function() { updatePaletteIcon(); })
|
||||
@@ -500,12 +604,15 @@
|
||||
</script>
|
||||
<style>
|
||||
.md-banner {
|
||||
background: linear-gradient(135deg, #005a9c 0%, #007acc 100%) !important;
|
||||
background: transparent !important;
|
||||
color: #ffffff !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
overflow: visible !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
position: relative;
|
||||
z-index: 301;
|
||||
}
|
||||
.md-banner__inner {
|
||||
overflow: visible !important;
|
||||
@@ -738,7 +845,11 @@
|
||||
.cm-header-nav__hamburger { display: block; }
|
||||
.cm-header-nav__dropdown-menu { display: none !important; }
|
||||
}
|
||||
/* Hidden Material header — stays at 0 height normally */
|
||||
/* Tell Material that sidebar sticky offset = tabs height (blue header scrolls away) */
|
||||
:root {
|
||||
--md-header-height: 0px;
|
||||
}
|
||||
/* Hidden Material header — 0 height but search children overflow visibly */
|
||||
.md-header--cm-hidden {
|
||||
height: 0 !important;
|
||||
min-height: 0 !important;
|
||||
@@ -748,24 +859,33 @@
|
||||
overflow: visible !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
/* === DESKTOP SEARCH (>= 60em / 960px) === */
|
||||
@media screen and (min-width: 60em) {
|
||||
/* When search is active, make the search panel a fixed dropdown below custom header */
|
||||
/* Fixed dropdown panel — layout (flex) applied via JS inline styles */
|
||||
body.cm-search-active .md-header--cm-hidden .md-search__inner {
|
||||
position: fixed !important;
|
||||
top: 56px !important;
|
||||
top: 48px !important;
|
||||
right: 16px !important;
|
||||
left: auto !important;
|
||||
width: min(34rem, calc(100vw - 32px)) !important;
|
||||
max-height: calc(100vh - 64px) !important;
|
||||
background: var(--md-default-bg-color) !important;
|
||||
border-radius: 0 0 8px 8px !important;
|
||||
box-shadow: 0 4px 24px rgba(0,0,0,0.25) !important;
|
||||
z-index: 300 !important;
|
||||
opacity: 1 !important;
|
||||
transform: none !important;
|
||||
visibility: visible !important;
|
||||
pointer-events: auto !important;
|
||||
clip-path: none !important;
|
||||
}
|
||||
|
||||
/* Dark overlay behind search panel */
|
||||
/* Dark overlay behind search panel — catches clicks to dismiss */
|
||||
body.cm-search-active .md-header--cm-hidden .md-search__overlay {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
@@ -777,12 +897,14 @@
|
||||
z-index: 299 !important;
|
||||
border-radius: 0 !important;
|
||||
transform: none !important;
|
||||
cursor: default !important;
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* === MOBILE SEARCH (< 60em / 960px) === */
|
||||
@media screen and (max-width: 59.984375em) {
|
||||
/* Full-screen search takeover on mobile */
|
||||
/* Full-screen search takeover — layout (flex) applied via JS inline styles */
|
||||
body.cm-search-active .md-header--cm-hidden .md-search__inner {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
@@ -792,26 +914,42 @@
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
opacity: 1 !important;
|
||||
overflow: visible !important;
|
||||
transform: none !important;
|
||||
visibility: visible !important;
|
||||
pointer-events: auto !important;
|
||||
z-index: 300 !important;
|
||||
background: var(--md-default-bg-color) !important;
|
||||
clip-path: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Force search results to show when active (both breakpoints) */
|
||||
/* Force search elements visible when active (layout handled by JS inline styles) */
|
||||
body.cm-search-active .md-header--cm-hidden .md-search {
|
||||
display: block !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
body.cm-search-active .md-header--cm-hidden .md-search__output {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
body.cm-search-active .md-header--cm-hidden .md-search__scrollwrap {
|
||||
max-height: 75vh !important;
|
||||
visibility: visible !important;
|
||||
clip-path: none !important;
|
||||
transform: none !important;
|
||||
}
|
||||
.cm-palette-container {
|
||||
height: 0 !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
/* Hide Material tabs — custom header covers navigation */
|
||||
.md-tabs { display: none !important; }
|
||||
/* Material tabs: sticky at top (blue header scrolls away, tabs persist) */
|
||||
.md-tabs {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
/* On mobile, hide tabs (sidebar provides navigation) */
|
||||
@media (max-width: 768px) {
|
||||
.md-tabs { display: none; }
|
||||
}
|
||||
/* Utility icon styling */
|
||||
.cm-header-nav__utility {
|
||||
background: none;
|
||||
@@ -927,6 +1065,82 @@ body.cm-search-active .md-header--cm-hidden .md-search__scrollwrap {
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
|
||||
<div class="md-grid">
|
||||
<ul class="md-tabs__list">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href=".." class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Home
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../docs/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 21.5c-1.35-.85-3.8-1.5-5.5-1.5-1.65 0-3.35.3-4.75 1.05-.1.05-.15.05-.25.05-.25 0-.5-.25-.5-.5V6c.6-.45 1.25-.75 2-1 1.11-.35 2.33-.5 3.5-.5 1.95 0 4.05.4 5.5 1.5 1.45-1.1 3.55-1.5 5.5-1.5 1.17 0 2.39.15 3.5.5.75.25 1.4.55 2 1v14.6c0 .25-.25.5-.5.5-.1 0-.15 0-.25-.05-1.4-.75-3.1-1.05-4.75-1.05-1.7 0-4.15.65-5.5 1.5M12 8v11.5c1.35-.85 3.8-1.5 5.5-1.5 1.2 0 2.4.15 3.5.5V7c-1.1-.35-2.3-.5-3.5-.5-1.7 0-4.15.65-5.5 1.5m1 3.5c1.11-.68 2.6-1 4.5-1 .91 0 1.76.09 2.5.28V9.23c-.87-.15-1.71-.23-2.5-.23q-2.655 0-4.5.84zm4.5.17c-1.71 0-3.21.26-4.5.79v1.69c1.11-.65 2.6-.99 4.5-.99 1.04 0 1.88.08 2.5.24v-1.5c-.87-.16-1.71-.23-2.5-.23m2.5 2.9c-.87-.16-1.71-.24-2.5-.24-1.83 0-3.33.27-4.5.8v1.69c1.11-.66 2.6-.99 4.5-.99 1.04 0 1.88.08 2.5.24z"/></svg>
|
||||
|
||||
|
||||
Docs
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-tabs__item">
|
||||
<a href="../blog/" class="md-tabs__link">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Blog
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
@@ -1191,7 +1405,10 @@ body.cm-search-active .md-header--cm-hidden .md-search__scrollwrap {
|
||||
|
||||
<h1 id="test">Test<a class="headerlink" href="#test" title="Permanent link">¶</a></h1>
|
||||
<p>Testing page. </p>
|
||||
<p><a href="test-page/">test-page</a>]]</p>
|
||||
<p><a href="test-page/">test-page</a></p>
|
||||
<p>TEst</p>
|
||||
<p>test</p>
|
||||
<p>test</p>
|
||||
<div class="photo-block" data-photo-id="1" data-size="large" data-caption="" data-link-to-gallery="true" data-alignment="center">Loading...</div>
|
||||
|
||||
<div style="text-align: center; padding: 40px 20px; background: linear-gradient(135deg, #1a1a2e, #16213e); border-radius: 12px; margin: 16px 0;">
|
||||
|
||||
Reference in New Issue
Block a user