2026-03-13 22:21:37 +01:00
|
|
|
/**
|
|
|
|
|
* Global search sidebar — debounced fetch with live result counts and Ctrl+K shortcut.
|
|
|
|
|
*/
|
2026-02-11 19:28:12 +01:00
|
|
|
import { requireEl, optionalEl, warnOnce } from '../core/app-dom.js';
|
2026-03-13 22:28:46 +01:00
|
|
|
import { isEditableTarget } from '../core/app-form-utils.js';
|
2026-02-11 19:28:12 +01:00
|
|
|
|
2026-03-13 23:01:04 +01:00
|
|
|
export function initGlobalSearch() {
|
|
|
|
|
const input = requireEl('#side-search', { module: 'global-search' });
|
|
|
|
|
const resultsEl = requireEl('[data-global-search-results]', { module: 'global-search' });
|
|
|
|
|
if (!input || !resultsEl) {return null;}
|
|
|
|
|
if (input.dataset.globalSearchBound === '1') {return null;}
|
|
|
|
|
input.dataset.globalSearchBound = '1';
|
2026-02-11 19:28:12 +01:00
|
|
|
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
const emptyStateEl = optionalEl('[data-global-search-empty]');
|
|
|
|
|
const emptyHintEl = optionalEl('[data-search-empty-hint-template]');
|
|
|
|
|
const shortcutEl = optionalEl('[data-search-shortcut]');
|
2026-02-11 19:28:12 +01:00
|
|
|
const panel = optionalEl('#aside-panel-search');
|
|
|
|
|
const toggleButton = optionalEl('[data-search-details-toggle]');
|
|
|
|
|
const toggleIcon = optionalEl('[data-search-details-icon]');
|
2026-02-04 23:31:53 +01:00
|
|
|
const appBase = window.APP_BASE || document.baseURI;
|
|
|
|
|
const endpoint = new URL('admin/search/data', appBase);
|
|
|
|
|
const resultsPage = new URL('search', appBase);
|
|
|
|
|
const minLength = 2;
|
|
|
|
|
let pending = null;
|
2026-02-11 19:28:12 +01:00
|
|
|
const shortcutLabel = /(Mac|iPhone|iPad|iPod)/i.test(navigator.platform || navigator.userAgent)
|
|
|
|
|
? '⌘K'
|
|
|
|
|
: 'Ctrl+K';
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
|
|
|
|
|
if (emptyHintEl) {
|
|
|
|
|
const template = emptyHintEl.getAttribute('data-search-empty-hint-template') || '';
|
|
|
|
|
emptyHintEl.textContent = template.replace('{shortcut}', shortcutLabel);
|
|
|
|
|
}
|
|
|
|
|
if (shortcutEl) {
|
|
|
|
|
shortcutEl.textContent = shortcutLabel;
|
2026-02-11 19:28:12 +01:00
|
|
|
}
|
2026-02-04 23:31:53 +01:00
|
|
|
|
|
|
|
|
const itemsByKey = new Map();
|
|
|
|
|
resultsEl.querySelectorAll('[data-search-key]').forEach((item) => {
|
|
|
|
|
const key = item.getAttribute('data-search-key');
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
if (key) {itemsByKey.set(key, item);}
|
2026-02-04 23:31:53 +01:00
|
|
|
});
|
|
|
|
|
if (itemsByKey.size === 0) {
|
2026-02-11 19:28:12 +01:00
|
|
|
warnOnce('UI_EL_MISSING', 'No [data-search-key] elements found in results container', { module: 'global-search' });
|
2026-02-04 23:31:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setLoadingState = (value) => {
|
|
|
|
|
resultsEl.querySelectorAll('[data-search-count]').forEach((el) => {
|
|
|
|
|
el.textContent = value;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
const setIdleState = (idle) => {
|
|
|
|
|
if (emptyStateEl) {
|
|
|
|
|
emptyStateEl.hidden = !idle;
|
|
|
|
|
}
|
|
|
|
|
resultsEl.hidden = idle;
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-04 23:31:53 +01:00
|
|
|
const render = (items, query) => {
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
const renderedKeys = new Set();
|
2026-02-04 23:31:53 +01:00
|
|
|
items.forEach((item) => {
|
|
|
|
|
const li = itemsByKey.get(item.key);
|
|
|
|
|
if (!li) {
|
2026-02-11 19:28:12 +01:00
|
|
|
warnOnce('UI_EL_MISSING', `No element found for key: ${item.key}`, { module: 'global-search' });
|
2026-02-04 23:31:53 +01:00
|
|
|
return;
|
|
|
|
|
}
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
renderedKeys.add(item.key);
|
2026-02-04 23:31:53 +01:00
|
|
|
const countEl = li.querySelector('[data-search-count]');
|
|
|
|
|
const link = li.querySelector('a');
|
|
|
|
|
const previewEl = li.querySelector('[data-search-preview]');
|
|
|
|
|
const base = item.key === 'pages' && item.url ? item.url : (li.getAttribute('data-search-base') || item.url);
|
|
|
|
|
const url = new URL(base, appBase);
|
|
|
|
|
if (item.key !== 'pages') {
|
|
|
|
|
url.searchParams.set('search', query);
|
|
|
|
|
}
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
if (countEl) {countEl.textContent = item.count.toString();}
|
2026-02-04 23:31:53 +01:00
|
|
|
if (link) {
|
|
|
|
|
link.href = item.count > 0 ? url.toString() : base;
|
|
|
|
|
link.setAttribute('aria-disabled', item.count > 0 ? 'false' : 'true');
|
|
|
|
|
}
|
|
|
|
|
if (previewEl) {
|
|
|
|
|
previewEl.innerHTML = '';
|
|
|
|
|
if (Array.isArray(item.items) && item.items.length > 0) {
|
|
|
|
|
item.items.forEach((previewItem, idx) => {
|
|
|
|
|
if (!previewItem || !previewItem.url) {
|
2026-02-11 19:28:12 +01:00
|
|
|
warnOnce('UI_DATA_MISSING', `Preview item missing url at index ${idx} for key: ${item.key}`, {
|
|
|
|
|
module: 'global-search',
|
|
|
|
|
item: previewItem
|
|
|
|
|
});
|
2026-02-04 23:31:53 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const previewLi = document.createElement('li');
|
|
|
|
|
const previewLink = document.createElement('a');
|
|
|
|
|
previewLink.href = previewItem.url;
|
|
|
|
|
previewLink.textContent = previewItem.label || '';
|
|
|
|
|
previewLi.appendChild(previewLink);
|
|
|
|
|
previewEl.appendChild(previewLi);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (item.count > 0) {
|
|
|
|
|
li.hidden = false;
|
|
|
|
|
} else {
|
|
|
|
|
li.hidden = true;
|
|
|
|
|
}
|
|
|
|
|
});
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
|
|
|
|
|
itemsByKey.forEach((li, key) => {
|
|
|
|
|
if (renderedKeys.has(key)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const countEl = li.querySelector('[data-search-count]');
|
|
|
|
|
const link = li.querySelector('a');
|
|
|
|
|
const previewEl = li.querySelector('[data-search-preview]');
|
|
|
|
|
const base = li.getAttribute('data-search-base') || '#';
|
|
|
|
|
if (countEl) {countEl.textContent = '0';}
|
|
|
|
|
if (link) {
|
|
|
|
|
link.href = base;
|
|
|
|
|
link.setAttribute('aria-disabled', 'true');
|
|
|
|
|
}
|
|
|
|
|
if (previewEl) {
|
|
|
|
|
previewEl.innerHTML = '';
|
|
|
|
|
}
|
|
|
|
|
li.hidden = true;
|
|
|
|
|
});
|
2026-02-04 23:31:53 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const clear = () => {
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
setIdleState(true);
|
2026-02-04 23:31:53 +01:00
|
|
|
setLoadingState('0');
|
|
|
|
|
resultsEl.querySelectorAll('a').forEach((link) => {
|
|
|
|
|
link.setAttribute('aria-disabled', 'true');
|
|
|
|
|
const base = link.closest('[data-search-base]')?.getAttribute('data-search-base');
|
|
|
|
|
link.setAttribute('href', base || '#');
|
|
|
|
|
});
|
|
|
|
|
resultsEl.querySelectorAll('[data-search-preview]').forEach((list) => {
|
|
|
|
|
list.innerHTML = '';
|
|
|
|
|
});
|
|
|
|
|
resultsEl.querySelectorAll('[data-search-key]').forEach((li) => {
|
|
|
|
|
li.hidden = false;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const fetchCounts = async (value) => {
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
setIdleState(false);
|
2026-02-04 23:31:53 +01:00
|
|
|
const url = new URL(endpoint.toString());
|
|
|
|
|
url.searchParams.set('q', value);
|
|
|
|
|
setLoadingState('…');
|
|
|
|
|
const response = await fetch(url.toString(), { headers: { 'Accept': 'application/json' } });
|
|
|
|
|
if (!response.ok) {
|
2026-02-11 19:28:12 +01:00
|
|
|
warnOnce('FETCH_FAILED', `Global search failed: ${response.status} ${response.statusText}`, {
|
|
|
|
|
module: 'global-search'
|
|
|
|
|
});
|
2026-02-04 23:31:53 +01:00
|
|
|
clear();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
if (Array.isArray(data)) {
|
|
|
|
|
render(data, value);
|
|
|
|
|
} else {
|
2026-02-11 19:28:12 +01:00
|
|
|
warnOnce('FETCH_INVALID', `Invalid response format for global search`, {
|
|
|
|
|
module: 'global-search',
|
|
|
|
|
type: typeof data
|
|
|
|
|
});
|
2026-02-04 23:31:53 +01:00
|
|
|
clear();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const submitSearch = () => {
|
|
|
|
|
const value = input.value.trim();
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
if (value.length < minLength) {return;}
|
2026-02-04 23:31:53 +01:00
|
|
|
resultsPage.searchParams.set('search', value);
|
|
|
|
|
window.location.href = resultsPage.toString();
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-11 19:28:12 +01:00
|
|
|
const focusSearch = () => {
|
|
|
|
|
window.requestAnimationFrame(() => {
|
|
|
|
|
input.focus();
|
|
|
|
|
input.select();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const openSearch = () => {
|
|
|
|
|
if (window.AppAsidePanels?.open) {
|
|
|
|
|
window.AppAsidePanels.open('search');
|
|
|
|
|
} else {
|
|
|
|
|
document.querySelector('[data-aside-target="search"]')?.click();
|
|
|
|
|
}
|
|
|
|
|
focusSearch();
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-13 23:01:04 +01:00
|
|
|
// --- Event handlers (named for cleanup) ---
|
|
|
|
|
|
|
|
|
|
const onInput = () => {
|
|
|
|
|
const value = input.value.trim();
|
|
|
|
|
if (value.length < minLength) {
|
|
|
|
|
clear();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (pending) {window.clearTimeout(pending);}
|
|
|
|
|
pending = window.setTimeout(() => {
|
|
|
|
|
fetchCounts(value).catch((err) => {
|
|
|
|
|
warnOnce('FETCH_ERROR', 'Global search fetch error', { module: 'global-search', err });
|
|
|
|
|
clear();
|
|
|
|
|
});
|
|
|
|
|
}, 300);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onInputKeydown = (event) => {
|
|
|
|
|
if (event.key !== 'Enter') {return;}
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
submitSearch();
|
|
|
|
|
};
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
|
2026-03-13 23:01:04 +01:00
|
|
|
const onDocumentKeydown = (event) => {
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
if (!(event.metaKey || event.ctrlKey)) {return;}
|
2026-02-11 19:28:12 +01:00
|
|
|
const key = event.key.toLowerCase();
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
if (key !== 'k' && key !== '/') {return;}
|
|
|
|
|
if (isEditableTarget(event.target) && event.target !== input) {return;}
|
2026-02-11 19:28:12 +01:00
|
|
|
event.preventDefault();
|
|
|
|
|
openSearch();
|
2026-03-13 23:01:04 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onEmptyStateClick = () => {
|
|
|
|
|
focusSearch();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onFormSubmit = (event) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
submitSearch();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onToggleClick = () => {
|
|
|
|
|
panel.classList.toggle('search-details-hidden');
|
|
|
|
|
if (toggleIcon) {
|
|
|
|
|
toggleIcon.classList.toggle('bi-dash-square');
|
|
|
|
|
toggleIcon.classList.toggle('bi-plus-square');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// --- Bind listeners ---
|
|
|
|
|
|
|
|
|
|
input.addEventListener('input', onInput);
|
|
|
|
|
input.addEventListener('keydown', onInputKeydown);
|
|
|
|
|
document.addEventListener('keydown', onDocumentKeydown);
|
|
|
|
|
|
|
|
|
|
if (emptyStateEl) {
|
|
|
|
|
emptyStateEl.addEventListener('click', onEmptyStateClick);
|
|
|
|
|
}
|
2026-02-11 19:28:12 +01:00
|
|
|
|
2026-02-04 23:31:53 +01:00
|
|
|
const form = input.closest('form');
|
|
|
|
|
if (form) {
|
2026-03-13 23:01:04 +01:00
|
|
|
form.addEventListener('submit', onFormSubmit);
|
2026-02-04 23:31:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (toggleButton && panel) {
|
2026-03-13 23:01:04 +01:00
|
|
|
toggleButton.addEventListener('click', onToggleClick);
|
2026-02-04 23:31:53 +01:00
|
|
|
}
|
|
|
|
|
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
// Seed from current URL search param if present.
|
2026-02-04 23:31:53 +01:00
|
|
|
const currentUrl = new URL(window.location.href);
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
const preset = (currentUrl.searchParams.get('search') || '').trim();
|
2026-02-04 23:31:53 +01:00
|
|
|
if (preset && !input.value) {
|
|
|
|
|
input.value = preset;
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const initialValue = input.value.trim();
|
|
|
|
|
if (initialValue.length >= minLength) {
|
|
|
|
|
fetchCounts(initialValue).catch((err) => {
|
|
|
|
|
warnOnce('FETCH_ERROR', 'Global search fetch error', { module: 'global-search', err });
|
|
|
|
|
clear();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
clear();
|
2026-02-04 23:31:53 +01:00
|
|
|
}
|
2026-03-13 23:01:04 +01:00
|
|
|
|
|
|
|
|
// --- Cleanup ---
|
|
|
|
|
|
|
|
|
|
const destroy = () => {
|
|
|
|
|
if (pending) {window.clearTimeout(pending);}
|
|
|
|
|
input.removeEventListener('input', onInput);
|
|
|
|
|
input.removeEventListener('keydown', onInputKeydown);
|
|
|
|
|
document.removeEventListener('keydown', onDocumentKeydown);
|
|
|
|
|
if (emptyStateEl) {
|
|
|
|
|
emptyStateEl.removeEventListener('click', onEmptyStateClick);
|
|
|
|
|
}
|
|
|
|
|
if (form) {
|
|
|
|
|
form.removeEventListener('submit', onFormSubmit);
|
|
|
|
|
}
|
|
|
|
|
if (toggleButton) {
|
|
|
|
|
toggleButton.removeEventListener('click', onToggleClick);
|
|
|
|
|
}
|
|
|
|
|
delete input.dataset.globalSearchBound;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return { destroy, openSearch, focusSearch };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Auto-initialize on load
|
|
|
|
|
if (document.readyState === 'loading') {
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => initGlobalSearch());
|
|
|
|
|
} else {
|
|
|
|
|
initGlobalSearch();
|
2026-02-04 23:31:53 +01:00
|
|
|
}
|