diff --git a/public/js/learningHub.js b/public/js/learningHub.js index 8fe7867..15e7f78 100644 --- a/public/js/learningHub.js +++ b/public/js/learningHub.js @@ -13,7 +13,7 @@ // ── Load when tab activated ──────────────────────────────── document.addEventListener('tabChanged', function(e) { if (e.detail && e.detail.tab === 'learning') { - if (!loaded) { loadFeed(); loadCategories(); loaded = true; } + if (!loaded) { loadFeed(); loadCategories(); loaded = true; wireSearch(); } } // Load CMS when Content Manager tab is opened if (e.detail && e.detail.tab === 'cms') { @@ -134,15 +134,20 @@ if (rmOpt) { var row = rmOpt.closest('.lh-option-row'); if (row) row.remove(); return; } }); - // Search - var searchTimeout = null; - var searchEl = document.getElementById('lh-search'); - if (searchEl) { + // wireSearch() called after component is in DOM + var _searchTimeout = null; + function wireSearch() { + var searchEl = document.getElementById('lh-search'); + if (!searchEl || searchEl._wired) return; + searchEl._wired = true; searchEl.addEventListener('input', function() { - clearTimeout(searchTimeout); + clearTimeout(_searchTimeout); var q = searchEl.value.trim(); if (!q) { loadFeed(); return; } - searchTimeout = setTimeout(function() { searchContent(q); }, 300); + _searchTimeout = setTimeout(function() { searchContent(q); }, 350); + }); + searchEl.addEventListener('keydown', function(e) { + if (e.key === 'Escape') { searchEl.value = ''; loadFeed(); } }); } @@ -198,13 +203,46 @@ var feedEl = document.getElementById('lh-feed'); if (!feedEl) return; showFeed(); + feedEl.innerHTML = + '
' + + ' Searching for "' + esc(q) + '"…' + + '
'; fetch('/api/learning/search?q=' + encodeURIComponent(q), { headers: getAuthHeaders() }) .then(function(r) { return r.json(); }) .then(function(data) { - if (!data.success) return; - renderFeed(data.content, feedEl); - }); + if (!data.success) { feedEl.innerHTML = '

Search failed

'; return; } + var header = '
' + + '' + + (data.content.length > 0 + ? '' + data.content.length + ' result' + (data.content.length !== 1 ? 's' : '') + ' for "' + esc(q) + '"' + : 'No results for "' + esc(q) + '"') + + '' + + '' + + '
'; + + if (data.content.length === 0) { + feedEl.innerHTML = header + + '
' + + '' + + 'Try different keywords or browse by category' + + '
'; + } else { + var tempEl = document.createElement('div'); + renderFeed(data.content, tempEl); + feedEl.innerHTML = header + tempEl.innerHTML; + } + + var clearBtn = document.getElementById('lh-search-clear'); + if (clearBtn) { + clearBtn.addEventListener('click', function() { + var s = document.getElementById('lh-search'); + if (s) s.value = ''; + loadFeed(); + }); + } + }) + .catch(function() { feedEl.innerHTML = '

Search error

'; }); } function renderFeed(items, feedEl) { @@ -250,26 +288,28 @@ function showFeed() { currentView = 'feed'; - var feedEl = document.getElementById('lh-feed'); - var viewerEl = document.getElementById('lh-viewer'); - var catsEl = document.getElementById('lh-categories'); - var searchWrap = document.getElementById('lh-search'); - if (feedEl) feedEl.classList.remove('hidden'); - if (viewerEl) viewerEl.classList.add('hidden'); - if (catsEl) catsEl.classList.remove('hidden'); - if (searchWrap) searchWrap.closest('.card').classList.remove('hidden'); + var feedEl = document.getElementById('lh-feed'); + var viewerEl = document.getElementById('lh-viewer'); + var catsEl = document.getElementById('lh-categories'); + var searchEl = document.getElementById('lh-search'); + // Use style.display — classList.add('hidden') is overridden by .lh-feed{display:flex} + // and .lh-category-bar{display:flex} which are defined later in CSS + if (feedEl) feedEl.style.display = 'flex'; + if (viewerEl) viewerEl.style.display = 'none'; + if (catsEl) catsEl.style.display = 'flex'; + if (searchEl) { var sc = searchEl.closest('.card'); if (sc) sc.style.display = ''; } } function showViewer(item) { currentView = 'viewer'; - var feedEl = document.getElementById('lh-feed'); - var viewerEl = document.getElementById('lh-viewer'); - var catsEl = document.getElementById('lh-categories'); - var searchWrap = document.getElementById('lh-search'); - if (feedEl) feedEl.classList.add('hidden'); - if (viewerEl) viewerEl.classList.remove('hidden'); - if (catsEl) catsEl.classList.add('hidden'); - if (searchWrap) searchWrap.closest('.card').classList.add('hidden'); + var feedEl = document.getElementById('lh-feed'); + var viewerEl = document.getElementById('lh-viewer'); + var catsEl = document.getElementById('lh-categories'); + var searchEl = document.getElementById('lh-search'); + if (feedEl) feedEl.style.display = 'none'; + if (viewerEl) viewerEl.style.display = 'block'; + if (catsEl) catsEl.style.display = 'none'; + if (searchEl) { var sc = searchEl.closest('.card'); if (sc) sc.style.display = 'none'; } var titleEl = document.getElementById('lh-viewer-title'); var metaEl = document.getElementById('lh-viewer-meta');