From 01310463d8c9b0aef8b46e5d9ef3644f6b9137fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Andreas=20Nilsen?= Date: Thu, 2 Oct 2025 13:52:12 +0200 Subject: [PATCH] ajax searches are performed on account and group searches now --- bas-search.user.js | 123 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 112 insertions(+), 11 deletions(-) diff --git a/bas-search.user.js b/bas-search.user.js index 770546b..46023bd 100644 --- a/bas-search.user.js +++ b/bas-search.user.js @@ -34,7 +34,7 @@ inputBox.style.border = '2px solid #007acc'; inputBox.style.borderRadius = '4px'; inputBox.style.outline = 'none'; - inputBox.style.width = '300px'; + inputBox.style.width = '560px'; inputBox.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)'; inputBox.placeholder = 'Search accounts, groups (g:name)...'; searchContainer.appendChild(inputBox); @@ -59,6 +59,7 @@ let searchResultLinks = []; let selectedResultIndex = -1; let searchResultsActive = false; + let searchTimeout = null; // Function to setup title click handler function setupTitleClickHandler() { @@ -262,29 +263,124 @@ } } - // Function to populate dropdown menu with tabs - function populateDropdown() { - const tabview = document.getElementById('tabview'); - if (!tabview) return; + // Function to populate dropdown menu with search results + function populateDropdown(searchQuery = '') { + dropdown.innerHTML = ''; + menuItems = []; - const tabs = tabview.querySelectorAll('.yui-nav li a'); + // Clear any existing timeout + if (searchTimeout) { + clearTimeout(searchTimeout); + } + + if (searchQuery.length >= 3) { + // Debounce the search - wait 300ms after user stops typing + searchTimeout = setTimeout(() => { + performAjaxSearch(searchQuery); + }, 300); + } + + adjustContainerPosition(); + } + + // Function to perform AJAX search + function performAjaxSearch(query) { + const lowerQuery = query.toLowerCase(); + let searchType = 'account'; // default to account search + let actualQuery = query; + + // Check for prefixes + if (lowerQuery.startsWith('g:') || lowerQuery.startsWith('g ')) { + searchType = 'group'; + actualQuery = query.substring(2).trim(); + } else if (lowerQuery.startsWith('p:') || lowerQuery.startsWith('p ')) { + // Person search - we'll skip AJAX for this as it's not in the API + return; + } else if (lowerQuery.startsWith('a:') || lowerQuery.startsWith('a ')) { + actualQuery = query.substring(2).trim(); + } + + if (actualQuery.length < 3) return; + + const url = searchType === 'group' + ? `https://bas.ntnu.no/ajax/search?query=${encodeURIComponent(actualQuery)}&type=group` + : `https://bas.ntnu.no/ajax/search?query=${encodeURIComponent(actualQuery)}&output=account`; + + fetch(url) + .then(response => response.json()) + .then(data => { + displaySearchResults(data.ResultSet || [], searchType); + }) + .catch(err => { + console.error('Search failed:', err); + }); + } + + // Function to display search results in dropdown + function displaySearchResults(results, type) { dropdown.innerHTML = ''; menuItems = []; - tabs.forEach((tab, index) => { + if (results.length === 0) { + const noResults = document.createElement('div'); + noResults.style.padding = '8px 12px'; + noResults.style.fontStyle = 'italic'; + noResults.style.color = '#666'; + noResults.textContent = 'No results found'; + dropdown.appendChild(noResults); + return; + } + + results.slice(0, 10).forEach((result, index) => { // Limit to 10 results const menuItem = document.createElement('div'); menuItem.style.padding = '8px 12px'; menuItem.style.cursor = 'pointer'; - menuItem.style.borderBottom = index < tabs.length - 1 ? '1px solid #eee' : 'none'; - menuItem.textContent = tab.textContent.trim(); - menuItem.setAttribute('data-href', tab.href); + menuItem.style.borderBottom = index < Math.min(results.length, 10) - 1 ? '1px solid #eee' : 'none'; + menuItem.style.display = 'flex'; + menuItem.style.justifyContent = 'space-between'; + menuItem.style.alignItems = 'center'; + + const nameSpan = document.createElement('span'); + nameSpan.textContent = result.name; + nameSpan.style.fontWeight = 'bold'; + + const typeSpan = document.createElement('span'); + if (type === 'account' && result.owner && result.owner.name) { + typeSpan.textContent = result.owner.name; + } else if (type === 'group') { + // Extract description from group name (format: "groupname: description") + const colonIndex = result.name.indexOf(': '); + if (colonIndex !== -1) { + const description = result.name.substring(colonIndex + 2); + // Decode HTML entities + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = description; + typeSpan.textContent = tempDiv.textContent || tempDiv.innerText || description; + nameSpan.textContent = result.name.substring(0, colonIndex); + } else { + typeSpan.textContent = 'GROUP'; + } + } else { + typeSpan.textContent = type.toUpperCase(); + } + typeSpan.style.fontSize = '0.8em'; + typeSpan.style.color = '#666'; + + menuItem.appendChild(nameSpan); + menuItem.appendChild(typeSpan); + + const targetUrl = type === 'group' + ? `https://bas.ntnu.no/group/view?id=${result.id}` + : `https://bas.ntnu.no/account/view?id=${result.id}`; + + menuItem.setAttribute('data-href', targetUrl); menuItem.addEventListener('mouseenter', () => { selectMenuItem(index); }); menuItem.addEventListener('click', () => { - window.location.href = tab.href; + window.location.href = targetUrl; }); dropdown.appendChild(menuItem); @@ -451,6 +547,11 @@ }); // Input box event handlers + inputBox.addEventListener('input', function(event) { + const searchQuery = inputBox.value.trim(); + populateDropdown(searchQuery); + }); + inputBox.addEventListener('keydown', function(event) { if (event.key === 'Enter') { const searchQuery = inputBox.value.trim();