MediaWiki:Common.js: Difference between revisions

From CoraTO Wiki - Official Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 266: Line 266:
     // Export function for manual use if needed
     // Export function for manual use if needed
     window.initializeHighlightCards = makeCardsClickable;
     window.initializeHighlightCards = makeCardsClickable;
   
})();
/* ========================================
  RESPONSIVE TABS MENU SCRIPT
  Provides compact mobile-friendly navigation for MediaWiki tabs
  ======================================== */
(function() {
    'use strict';
   
    // Wait for DOM to be ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initResponsiveTabs);
    } else {
        initResponsiveTabs();
    }
   
    function initResponsiveTabs() {
        // Create toggle buttons for each tab container
        createToggleButtons();
       
        // Handle window resize
        window.addEventListener('resize', handleResize);
       
        // Initial setup
        handleResize();
    }
   
    function createToggleButtons() {
        const tabContainers = [
            { selector: '#p-namespaces ul', label: 'Namespaces ▼', id: 'namespace-dropdown' },
            { selector: '#p-views ul', label: 'Views ▼', id: 'views-dropdown' },
            { selector: '#p-cactions ul', label: 'Actions ▼', id: 'actions-dropdown' },
            { selector: '#p-personal ul', label: 'Personal ▼', id: 'personal-dropdown' }
        ];
       
        tabContainers.forEach(container => {
            const element = document.querySelector(container.selector);
            if (element && !element.previousElementSibling?.classList.contains('mw-tabs-toggle')) {
                createToggleButton(element, container.label, container.id);
            }
        });
    }
   
    function createToggleButton(tabContainer, label, id) {
        const toggle = document.createElement('button');
        toggle.className = 'mw-tabs-toggle';
        toggle.textContent = label;
        toggle.setAttribute('aria-expanded', 'false');
        toggle.setAttribute('aria-controls', id || 'tabs-menu');
        toggle.setAttribute('data-target', id);
       
        // Insert toggle before the tab container
        tabContainer.parentNode.insertBefore(toggle, tabContainer);
       
        // Add click event listener
        toggle.addEventListener('click', function(e) {
            e.preventDefault();
            toggleMenu(toggle, tabContainer);
        });
       
        // Close menu when clicking outside
        document.addEventListener('click', function(e) {
            if (!toggle.contains(e.target) && !tabContainer.contains(e.target)) {
                closeMenu(toggle, tabContainer);
            }
        });
    }
   
    function toggleMenu(toggle, tabContainer) {
        const isOpen = tabContainer.classList.contains('show');
       
        if (isOpen) {
            closeMenu(toggle, tabContainer);
        } else {
            openMenu(toggle, tabContainer);
        }
    }
   
    function openMenu(toggle, tabContainer) {
        // Close other open menus first
        document.querySelectorAll('#p-namespaces ul.show, #p-views ul.show, #p-cactions ul.show, #p-personal ul.show')
            .forEach(menu => {
                if (menu !== tabContainer) {
                    menu.classList.remove('show');
                    const relatedToggle = menu.previousElementSibling;
                    if (relatedToggle && relatedToggle.classList.contains('mw-tabs-toggle')) {
                        relatedToggle.setAttribute('aria-expanded', 'false');
                        const originalText = relatedToggle.textContent.replace(' ▲', ' ▼');
                        relatedToggle.textContent = originalText;
                    }
                }
            });
       
        tabContainer.classList.add('show');
        toggle.setAttribute('aria-expanded', 'true');
        const newText = toggle.textContent.replace(' ▼', ' ▲');
        toggle.textContent = newText;
    }
   
    function closeMenu(toggle, tabContainer) {
        tabContainer.classList.remove('show');
        toggle.setAttribute('aria-expanded', 'false');
        const originalText = toggle.textContent.replace(' ▲', ' ▼');
        toggle.textContent = originalText;
    }
   
    function handleResize() {
        const isSmallScreen = window.innerWidth <= 1366;
       
        // Show/hide toggle buttons based on screen size
        document.querySelectorAll('.mw-tabs-toggle').forEach(toggle => {
            toggle.style.display = isSmallScreen ? 'inline-block' : 'none';
        });
       
        // Reset menu state on larger screens
        if (!isSmallScreen) {
            document.querySelectorAll('#p-namespaces ul, #p-views ul, #p-cactions ul, #p-personal ul').forEach(menu => {
                menu.classList.remove('show');
                menu.style.display = '';
            });
           
            document.querySelectorAll('.mw-tabs-toggle').forEach(toggle => {
                toggle.setAttribute('aria-expanded', 'false');
                const originalText = toggle.textContent.replace(' ▲', ' ▼');
                toggle.textContent = originalText;
            });
        }
    }
   
    // Handle dropdown menus for overflow tabs
    function initDropdownMenus() {
        const dropdowns = document.querySelectorAll('.mw-tabs-dropdown');
       
        dropdowns.forEach(dropdown => {
            const trigger = dropdown.querySelector('.mw-tabs-dropdown-trigger');
            if (trigger) {
                trigger.addEventListener('click', function(e) {
                    e.preventDefault();
                    dropdown.classList.toggle('active');
                });
            }
        });
       
        // Close dropdowns when clicking outside
        document.addEventListener('click', function(e) {
            dropdowns.forEach(dropdown => {
                if (!dropdown.contains(e.target)) {
                    dropdown.classList.remove('active');
                }
            });
        });
    }
   
    // Initialize dropdown functionality
    initDropdownMenus();
   
    // Add keyboard navigation support
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape') {
            // Close all open menus on Escape
            document.querySelectorAll('#p-namespaces ul.show, #p-views ul.show, #p-cactions ul.show, #p-personal ul.show').forEach(menu => {
                menu.classList.remove('show');
                const toggle = menu.previousElementSibling;
                if (toggle && toggle.classList.contains('mw-tabs-toggle')) {
                    toggle.setAttribute('aria-expanded', 'false');
                    const originalText = toggle.textContent.replace(' ▲', ' ▼');
                    toggle.textContent = originalText;
                }
            });
           
            // Close dropdowns
            document.querySelectorAll('.mw-tabs-dropdown.active').forEach(dropdown => {
                dropdown.classList.remove('active');
            });
        }
    });
      
      
})();
})();

Revision as of 09:23, 8 August 2025

// Script to ensure the sidebar remains always visible
// Add this script to MediaWiki:Common.js or include in HTML

(function() {
    'use strict';
    
    // Function to force sidebar visibility
    function forceSidebarVisibility() {
        const sidebar = document.getElementById('mw-panel');
        if (sidebar) {
            sidebar.style.display = 'block';
            sidebar.style.visibility = 'visible';
            sidebar.style.opacity = '1';
            sidebar.style.position = 'fixed';
            sidebar.style.left = '0';
            sidebar.style.top = '0';
            sidebar.style.width = '180px';
            sidebar.style.height = '100vh';
            sidebar.style.zIndex = '100';
        }
    }
    
    // Function to force back-to-top button visibility and functionality
    function forceBackToTopButton() {
        const backToTopBtn = document.getElementById('back-to-top-btn');
        if (backToTopBtn) {
            // Force visibility styles
            backToTopBtn.style.position = 'fixed';
            backToTopBtn.style.bottom = '20px';
            backToTopBtn.style.right = '20px';
            backToTopBtn.style.zIndex = '99999';
            backToTopBtn.style.display = 'block';
            backToTopBtn.style.visibility = 'visible';
            backToTopBtn.style.opacity = '1';
            backToTopBtn.style.pointerEvents = 'auto';
            
            // Ensure the link inside is also visible
            const link = backToTopBtn.querySelector('a');
            if (link) {
                link.style.display = 'inline-block';
                link.style.visibility = 'visible';
                link.style.opacity = '1';
                link.style.pointerEvents = 'auto';
                
                // Add click event if not already present
                if (!link.hasAttribute('data-click-added')) {
                    link.addEventListener('click', function(e) {
                        e.preventDefault();
                        window.scrollTo({
                            top: 0,
                            behavior: 'smooth'
                        });
                    });
                    link.setAttribute('data-click-added', 'true');
                }
            }
        }
    }
    
    // Execute when DOM is loaded
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() {
            forceSidebarVisibility();
            forceBackToTopButton();
        });
    } else {
        forceSidebarVisibility();
        forceBackToTopButton();
    }
    
    // Execute when page is completely loaded
    window.addEventListener('load', function() {
        forceSidebarVisibility();
        forceBackToTopButton();
    });
    
    // Observe DOM changes to react to dynamic modifications
    const observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.type === 'attributes' && mutation.target.id === 'mw-panel') {
                forceSidebarVisibility();
            }
            if (mutation.type === 'attributes' && mutation.target.id === 'back-to-top-btn') {
                forceBackToTopButton();
            }
        });
    });
    
    // Start observation when element exists
    function startObserving() {
        const sidebar = document.getElementById('mw-panel');
        if (sidebar) {
            observer.observe(sidebar, {
                attributes: true,
                attributeFilter: ['style', 'class']
            });
        } else {
            // Try again after a small delay
            setTimeout(startObserving, 100);
        }
        
        const backToTopBtn = document.getElementById('back-to-top-btn');
        if (backToTopBtn) {
            observer.observe(backToTopBtn, {
                attributes: true,
                attributeFilter: ['style', 'class']
            });
        }
    }
    
    startObserving();
    
    // Execute functions periodically as backup
    setInterval(function() {
        forceSidebarVisibility();
        forceBackToTopButton();
    }, 1000);
    
    // Execute when window is resized
    window.addEventListener('resize', function() {
        forceSidebarVisibility();
        forceBackToTopButton();
    });
    
    // Execute when page visibility changes
    document.addEventListener('visibilitychange', function() {
        if (!document.hidden) {
            forceSidebarVisibility();
            forceBackToTopButton();
        }
    });
    
    // Execute when page is scrolled (for back-to-top button)
    window.addEventListener('scroll', forceBackToTopButton);
    
    // Execute after MediaWiki scripts load
    if (typeof mw !== 'undefined' && mw.loader) {
        mw.loader.using(['mediawiki.util'], function() {
            forceSidebarVisibility();
            forceBackToTopButton();
        });
    }
    
})();

/* ========================================
   CARDS NAVIGATION SCRIPT
   Makes highlight cards clickable
   ======================================== */

(function() {
    'use strict';
    
    // Function to make cards clickable
    function makeCardsClickable() {
        // Select all highlight cards
        const cards = document.querySelectorAll('.destaque-card[data-link]');
        
        cards.forEach(function(card) {
            // Add pointer cursor
            card.style.cursor = 'pointer';
            
            // Add click event
            card.addEventListener('click', function() {
                const linkTarget = this.getAttribute('data-link');
                
                if (linkTarget) {
                    // Check if it's an anchor link (starts with #)
                    if (linkTarget.startsWith('#')) {
                        // Navigate to section within the same page
                        const targetElement = document.querySelector(linkTarget);
                        if (targetElement) {
                            targetElement.scrollIntoView({
                                behavior: 'smooth',
                                block: 'start'
                            });
                        } else {
                            // Fallback: use window.location.hash
                            window.location.hash = linkTarget;
                        }
                    } else {
                        // Build MediaWiki page URL for external links
                        const pageUrl = linkTarget.replace(/\s+/g, '_');
                        
                        // Navigate to page
                        if (typeof mw !== 'undefined' && mw.config) {
                            // In MediaWiki - use MediaWiki API
                            const baseUrl = mw.config.get('wgServer') + mw.config.get('wgScriptPath');
                            window.location.href = baseUrl + '/index.php/' + encodeURIComponent(pageUrl);
                        } else {
                            // Fallback - assume standard MediaWiki structure
                            window.location.href = '/wiki/' + encodeURIComponent(pageUrl);
                        }
                    }
                }
            });
            
            // Add visual hover effect
            card.addEventListener('mouseenter', function() {
                this.style.transform = 'translateY(-8px)';
                this.style.boxShadow = '0 12px 40px rgba(255, 107, 157, 0.3)';
            });
            
            card.addEventListener('mouseleave', function() {
                this.style.transform = 'translateY(0)';
                this.style.boxShadow = '0 8px 32px rgba(255, 107, 157, 0.2)';
            });
        });
        
        console.log('Highlight cards made clickable:', cards.length + ' cards processed');
    }
    
    // Function to initialize when DOM is ready
    function initializeCards() {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', makeCardsClickable);
        } else {
            makeCardsClickable();
        }
    }
    
    // Observe DOM changes for dynamically added cards
    function observeChanges() {
        if (typeof MutationObserver !== 'undefined') {
            const observer = new MutationObserver(function(mutations) {
                let shouldReinitialize = false;
                
                mutations.forEach(function(mutation) {
                    if (mutation.type === 'childList') {
                        // Check if new cards were added
                        mutation.addedNodes.forEach(function(node) {
                            if (node.nodeType === 1) { // Element node
                                if (node.classList && node.classList.contains('destaque-card') ||
                                    node.querySelector && node.querySelector('.destaque-card')) {
                                    shouldReinitialize = true;
                                }
                            }
                        });
                    }
                });
                
                if (shouldReinitialize) {
                    setTimeout(makeCardsClickable, 100);
                }
            });
            
            // Observe changes in body
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        }
    }
    
    // Initialize the script
    initializeCards();
    
    // Start observing changes
    observeChanges();
    
    // Reinitialize after complete page load
    window.addEventListener('load', function() {
        setTimeout(makeCardsClickable, 500);
    });
    
    // Export function for manual use if needed
    window.initializeHighlightCards = makeCardsClickable;
    
})();

/* ========================================
   RESPONSIVE TABS MENU SCRIPT
   Provides compact mobile-friendly navigation for MediaWiki tabs
   ======================================== */

(function() {
    'use strict';
    
    // Wait for DOM to be ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initResponsiveTabs);
    } else {
        initResponsiveTabs();
    }
    
    function initResponsiveTabs() {
        // Create toggle buttons for each tab container
        createToggleButtons();
        
        // Handle window resize
        window.addEventListener('resize', handleResize);
        
        // Initial setup
        handleResize();
    }
    
    function createToggleButtons() {
        const tabContainers = [
            { selector: '#p-namespaces ul', label: 'Namespaces ▼', id: 'namespace-dropdown' },
            { selector: '#p-views ul', label: 'Views ▼', id: 'views-dropdown' },
            { selector: '#p-cactions ul', label: 'Actions ▼', id: 'actions-dropdown' },
            { selector: '#p-personal ul', label: 'Personal ▼', id: 'personal-dropdown' }
        ];
        
        tabContainers.forEach(container => {
            const element = document.querySelector(container.selector);
            if (element && !element.previousElementSibling?.classList.contains('mw-tabs-toggle')) {
                createToggleButton(element, container.label, container.id);
            }
        });
    }
    
    function createToggleButton(tabContainer, label, id) {
        const toggle = document.createElement('button');
        toggle.className = 'mw-tabs-toggle';
        toggle.textContent = label;
        toggle.setAttribute('aria-expanded', 'false');
        toggle.setAttribute('aria-controls', id || 'tabs-menu');
        toggle.setAttribute('data-target', id);
        
        // Insert toggle before the tab container
        tabContainer.parentNode.insertBefore(toggle, tabContainer);
        
        // Add click event listener
        toggle.addEventListener('click', function(e) {
            e.preventDefault();
            toggleMenu(toggle, tabContainer);
        });
        
        // Close menu when clicking outside
        document.addEventListener('click', function(e) {
            if (!toggle.contains(e.target) && !tabContainer.contains(e.target)) {
                closeMenu(toggle, tabContainer);
            }
        });
    }
    
    function toggleMenu(toggle, tabContainer) {
        const isOpen = tabContainer.classList.contains('show');
        
        if (isOpen) {
            closeMenu(toggle, tabContainer);
        } else {
            openMenu(toggle, tabContainer);
        }
    }
    
    function openMenu(toggle, tabContainer) {
        // Close other open menus first
        document.querySelectorAll('#p-namespaces ul.show, #p-views ul.show, #p-cactions ul.show, #p-personal ul.show')
            .forEach(menu => {
                if (menu !== tabContainer) {
                    menu.classList.remove('show');
                    const relatedToggle = menu.previousElementSibling;
                    if (relatedToggle && relatedToggle.classList.contains('mw-tabs-toggle')) {
                        relatedToggle.setAttribute('aria-expanded', 'false');
                        const originalText = relatedToggle.textContent.replace(' ▲', ' ▼');
                        relatedToggle.textContent = originalText;
                    }
                }
            });
        
        tabContainer.classList.add('show');
        toggle.setAttribute('aria-expanded', 'true');
        const newText = toggle.textContent.replace(' ▼', ' ▲');
        toggle.textContent = newText;
    }
    
    function closeMenu(toggle, tabContainer) {
        tabContainer.classList.remove('show');
        toggle.setAttribute('aria-expanded', 'false');
        const originalText = toggle.textContent.replace(' ▲', ' ▼');
        toggle.textContent = originalText;
    }
    
    function handleResize() {
        const isSmallScreen = window.innerWidth <= 1366;
        
        // Show/hide toggle buttons based on screen size
        document.querySelectorAll('.mw-tabs-toggle').forEach(toggle => {
            toggle.style.display = isSmallScreen ? 'inline-block' : 'none';
        });
        
        // Reset menu state on larger screens
        if (!isSmallScreen) {
            document.querySelectorAll('#p-namespaces ul, #p-views ul, #p-cactions ul, #p-personal ul').forEach(menu => {
                menu.classList.remove('show');
                menu.style.display = '';
            });
            
            document.querySelectorAll('.mw-tabs-toggle').forEach(toggle => {
                toggle.setAttribute('aria-expanded', 'false');
                const originalText = toggle.textContent.replace(' ▲', ' ▼');
                toggle.textContent = originalText;
            });
        }
    }
    
    // Handle dropdown menus for overflow tabs
    function initDropdownMenus() {
        const dropdowns = document.querySelectorAll('.mw-tabs-dropdown');
        
        dropdowns.forEach(dropdown => {
            const trigger = dropdown.querySelector('.mw-tabs-dropdown-trigger');
            if (trigger) {
                trigger.addEventListener('click', function(e) {
                    e.preventDefault();
                    dropdown.classList.toggle('active');
                });
            }
        });
        
        // Close dropdowns when clicking outside
        document.addEventListener('click', function(e) {
            dropdowns.forEach(dropdown => {
                if (!dropdown.contains(e.target)) {
                    dropdown.classList.remove('active');
                }
            });
        });
    }
    
    // Initialize dropdown functionality
    initDropdownMenus();
    
    // Add keyboard navigation support
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape') {
            // Close all open menus on Escape
            document.querySelectorAll('#p-namespaces ul.show, #p-views ul.show, #p-cactions ul.show, #p-personal ul.show').forEach(menu => {
                menu.classList.remove('show');
                const toggle = menu.previousElementSibling;
                if (toggle && toggle.classList.contains('mw-tabs-toggle')) {
                    toggle.setAttribute('aria-expanded', 'false');
                    const originalText = toggle.textContent.replace(' ▲', ' ▼');
                    toggle.textContent = originalText;
                }
            });
            
            // Close dropdowns
            document.querySelectorAll('.mw-tabs-dropdown.active').forEach(dropdown => {
                dropdown.classList.remove('active');
            });
        }
    });
    
})();