(function() {
'use strict';
// Project-picker dropdown for the archive browser.
//
// In multi-project mode (HTTP source against zddc-server, OR ?projects=
// present in the URL), this dropdown lets the user toggle which projects
// are scanned. Toggling a checkbox updates window.app.projectFilter, pushes
// the new ?projects= state to the URL, and triggers a re-scan.
//
// In single-project mode the dropdown is hidden — only one project is ever
// in scope, so picking is meaningless.
let isOpen = false;
// The set of project names currently shown in the dropdown.
function getKnownProjects() {
if (window.app.availableProjects && window.app.availableProjects.length > 0) {
return window.app.availableProjects.slice();
}
// Fall back to whatever is in the URL filter — useful when the server's
// ProjectInfo endpoint isn't reachable but ?projects= names the set.
return Array.from(window.app.projectFilter || []);
}
// Visibility-only filter: change visibleProjects, push URL state, re-render
// UI. No rescan — already-scanned data stays in memory. URL is updated via
// history.replaceState (same mechanism as every other UI control).
function applyVisibility(names) {
window.app.visibleProjects = new Set(names);
window.app.modules.urlState.push();
window.app.modules.app.updateUI();
window.app.modules.filtering.applyFilters();
renderDropdown();
}
function escapeHtml(text) {
var div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
function renderDropdown() {
var dropdown = document.getElementById('presetDropdown');
if (!dropdown) return;
var selected = new Set(window.app.visibleProjects || []);
var known = getKnownProjects().slice().sort();
var projectsHtml = known.map(name => {
var checked = selected.has(name) ? ' checked' : '';
var n = escapeHtml(name);
return '
'
+ ''
+ '
';
}).join('');
if (!projectsHtml) {
projectsHtml = '
No projects available
';
}
dropdown.innerHTML =
'
'
+ '
Projects:
'
+ '
' + projectsHtml + '
'
+ '
';
}
function toggleDropdown() {
var dropdown = document.getElementById('presetDropdown');
if (isOpen) { closeDropdown(); return; }
isOpen = true;
if (dropdown) dropdown.classList.remove('hidden');
renderDropdown();
}
function closeDropdown() {
isOpen = false;
var dropdown = document.getElementById('presetDropdown');
if (dropdown) dropdown.classList.add('hidden');
}
function setupDropdownDelegation() {
var dropdown = document.getElementById('presetDropdown');
if (!dropdown) return;
dropdown.addEventListener('click', function(e) {
e.stopPropagation();
var checkbox = e.target.closest('.preset-checkbox');
if (!checkbox) return;
var projectName = checkbox.getAttribute('data-name');
if (!projectName) return;
var sel = new Set(window.app.visibleProjects || []);
if (checkbox.checked) sel.add(projectName);
else sel.delete(projectName);
applyVisibility(Array.from(sel));
});
}
function setupOutsideClickHandler() {
document.addEventListener('click', function(e) {
var section = document.getElementById('presetSection');
var dropdown = document.getElementById('presetDropdown');
if (isOpen && section && dropdown && !section.contains(e.target)) {
closeDropdown();
}
});
}
function init() {
var section = document.getElementById('presetSection');
if (!section) return;
// Hide the dropdown entirely outside multi-project mode.
if (!window.app.isMultiProject) {
section.classList.add('hidden');
return;
}
section.classList.remove('hidden');
var btn = document.getElementById('presetBtn');
if (!btn || btn.dataset.presetInit) return;
btn.dataset.presetInit = '1';
btn.title = 'Project picker';
btn.textContent = '▾ Projects';
btn.addEventListener('click', function(e) {
e.stopPropagation();
toggleDropdown();
});
setupDropdownDelegation();
setupOutsideClickHandler();
}
window.app.modules.presets = {
init: init,
toggleDropdown: toggleDropdown,
closeDropdown: closeDropdown,
// No-op kept so existing callers (events.js after grouping-folder click)
// don't need to null-check; preset dirty state was removed with the
// saved-presets feature.
checkDirty: function() {}
};
})();