/** * View Controls Manager - handles switching between grid, list-large, and list-compact views */ export class ViewManager { constructor() { this.currentView = 'grid'; this.init(); } /** * Initialize view controls */ init() { this.setupViewButtons(); this.loadSavedView(); this.updateControlsVisibility(); } /** * Update visibility of view controls based on plot content */ updateControlsVisibility() { const plotContainer = document.getElementById('plotContainer'); const controlsContainer = document.querySelector('.controls-container'); if (!plotContainer || !controlsContainer) return; const hasPlots = plotContainer.children.length > 0; controlsContainer.style.display = hasPlots ? 'flex' : 'none'; } /** * Setup view toggle buttons */ setupViewButtons() { const viewButtons = document.querySelectorAll('.view-btn'); viewButtons.forEach(button => { button.addEventListener('click', (e) => { const newView = button.getAttribute('data-view'); this.switchView(newView); }); }); } /** * Switch to a different view mode */ switchView(viewMode) { if (viewMode === this.currentView) return; const plotContainer = document.getElementById('plotContainer'); const viewButtons = document.querySelectorAll('.view-btn'); if (!plotContainer) return; // Remove current view class plotContainer.classList.remove( 'grid-view', 'list-large-view', 'list-compact-view' ); // Add new view class switch (viewMode) { case 'grid': plotContainer.classList.add('grid-view'); break; case 'list-large': plotContainer.classList.add('list-large-view'); break; case 'list-compact': plotContainer.classList.add('list-compact-view'); break; default: plotContainer.classList.add('grid-view'); viewMode = 'grid'; } // Update button states viewButtons.forEach(btn => { if (btn.getAttribute('data-view') === viewMode) { btn.classList.add('active'); } else { btn.classList.remove('active'); } }); // Save the preference this.currentView = viewMode; this.saveViewPreference(viewMode); // Trigger any necessary layout updates this.onViewChanged(viewMode); } /** * Save view preference to localStorage */ saveViewPreference(viewMode) { try { localStorage.setItem('gallery-view-mode', viewMode); } catch (e) { // Ignore localStorage errors } } /** * Load saved view preference */ loadSavedView() { try { const savedView = localStorage.getItem('gallery-view-mode'); if (savedView && ['grid', 'list-large', 'list-compact'].includes(savedView)) { this.switchView(savedView); } } catch (e) { // Ignore localStorage errors, use default } } /** * Handle view change events - can be extended for additional functionality */ onViewChanged(viewMode) { // Dispatch custom event for other components that might need to know const event = new CustomEvent('viewChanged', { detail: { viewMode } }); document.dispatchEvent(event); // Update any other UI elements that depend on view mode this.updateUIForView(viewMode); } /** * Update UI elements based on current view */ updateUIForView(viewMode) { // You can add view-specific UI updates here // For example, adjusting search result highlighting, etc. // Update any tooltips or help text const viewButtons = document.querySelectorAll('.view-btn'); viewButtons.forEach(btn => { const btnView = btn.getAttribute('data-view'); if (btnView === viewMode) { btn.style.transform = 'scale(1.05)'; } else { btn.style.transform = 'scale(1)'; } }); } /** * Get current view mode */ getCurrentView() { return this.currentView; } /** * Refresh controls visibility (call this when gallery content changes) */ refresh() { this.updateControlsVisibility(); } /** * Check if current view is grid mode */ isGridView() { return this.currentView === 'grid'; } /** * Check if current view is list mode (either variant) */ isListView() { return this.currentView === 'list-large' || this.currentView === 'list-compact'; } /** * Cycle through view modes (useful for keyboard shortcuts) */ cycleView() { const views = ['grid', 'list-large', 'list-compact']; const currentIndex = views.indexOf(this.currentView); const nextIndex = (currentIndex + 1) % views.length; this.switchView(views[nextIndex]); } }