Jump to content

MediaWiki:Mobile.js: Difference between revisions

From Vanipedia
Kashya (talk | contribs)
No edit summary
Kashya (talk | contribs)
No edit summary
Line 1: Line 1:
/* ==========================================================================
/* ==========================================================================
   DEFINITIVE MOBILE & DESKTOP VANI-SEARCH CONTROLLER
   STANDALONE VANI-SEARCH INPUT (DEFEATS MINERVA FOCUS-STEALING & OVERLAY)
  Defeats Minerva's #/search blank overlay and provides a direct search bar
   ========================================================================== */
   ========================================================================== */
(function() {
(function() {
     // 1. If Minerva's #/search hash is in the URL, strip it immediately so the blank overlay closes
     function installCleanVaniSearch() {
    if (window.location.hash === '#/search') {
        // 1. Mobile Minerva Header: Replace Minerva's rigged input with a clean standalone input
         history.replaceState(null, document.title, window.location.pathname + window.location.search);
        var minervaForm = document.querySelector('form.minerva-search-form');
    }
         if (minervaForm && !minervaForm.dataset.vaniCleanInstalled) {
    window.addEventListener('hashchange', function() {
            minervaForm.dataset.vaniCleanInstalled = 'true';
        if (window.location.hash === '#/search') {
             minervaForm.setAttribute('action', '/wiki/Special:VaniSearch');
             history.replaceState(null, document.title, window.location.pathname + window.location.search);
 
             $('.search-overlay, .minerva-search-overlay').remove();
             var searchBox = minervaForm.querySelector('.search-box');
             $('body').removeClass('search-enabled overlay-enabled');
             if (searchBox) {
        }
                // Wipe Minerva's decoy input and left icon so Minerva JS cannot hijack focus
    });
                searchBox.innerHTML = '';


    // 2. Build a dedicated, always-visible mobile search drawer right under the 52px top bar
                var cleanInput = document.createElement('input');
    function toggleVaniMobileSearch() {
                cleanInput.type = 'text';
        var existing = document.getElementById('vani-custom-mobile-search');
                 cleanInput.name = 'search';
        if (existing) {
                 cleanInput.className = 'vani-clean-search-input';
            if (existing.style.display === 'none') {
                 cleanInput.placeholder = 'Search Vanipedia';
                 existing.style.display = 'flex';
                cleanInput.autocomplete = 'off';
                 existing.querySelector('input').focus();
            } else {
                 existing.style.display = 'none';
            }
            return;
        }


        var bar = document.createElement('div');
                var goBtn = document.createElement('button');
        bar.id = 'vani-custom-mobile-search';
                goBtn.type = 'button';
        bar.style.cssText = 'position:fixed !important; top:52px !important; left:0 !important; right:0 !important; height:54px !important; background:#1f3e45 !important; border-bottom:2px solid #b1873d !important; z-index:2147483647 !important; display:flex !important; align-items:center !important; padding:0 12px !important; gap:8px !important; box-shadow:0 6px 16px rgba(0,0,0,0.45) !important; box-sizing:border-box !important;';
                goBtn.className = 'vani-inline-go';
                goBtn.innerHTML = '🔍';
                goBtn.style.cssText = 'position:absolute !important; right:8px !important; top:50% !important; transform:translateY(-50%) !important; background:none !important; border:none !important; font-size:15px !important; cursor:pointer !important; padding:0 !important; line-height:1 !important; z-index:20 !important;';


        var input = document.createElement('input');
                function submitMobileVaniSearch(e) {
        input.type = 'text';
                    if (e) {
        input.placeholder = 'Search Vanipedia...';
                        e.preventDefault();
        input.autocomplete = 'off';
                        e.stopPropagation();
        input.style.cssText = 'flex:1 1 auto !important; height:36px !important; background:#ffffff !important; color:#1e353b !important; -webkit-text-fill-color:#1e353b !important; border:1.5px solid #f5d77f !important; border-radius:18px !important; padding:0 14px !important; font-size:16px !important; outline:none !important; display:block !important; visibility:visible !important; opacity:1 !important;';
                        e.stopImmediatePropagation();
                    }
                    var val = cleanInput.value.trim();
                    if (val !== '') {
                        window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                    }
                }


        var goBtn = document.createElement('button');
                goBtn.addEventListener('click', submitMobileVaniSearch, true);
        goBtn.type = 'button';
        goBtn.innerHTML = '🔍';
        goBtn.style.cssText = 'flex:0 0 38px !important; width:38px !important; height:36px !important; border-radius:50% !important; background:#b1873d !important; color:#ffffff !important; border:none !important; font-size:18px !important; cursor:pointer !important; display:flex !important; align-items:center !important; justify-content:center !important;';


        function runSearch() {
                cleanInput.addEventListener('keydown', function(e) {
            var val = input.value.trim();
                    // Stop Minerva from listening to keystrokes
            if (val !== '') {
                    e.stopPropagation();
                window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                    if (e.key === 'Enter' || e.keyCode === 13) {
            }
                        submitMobileVaniSearch(e);
        }
                    }
                }, true);


        goBtn.addEventListener('click', function(e) {
                // Stop clicks/focus on our input from bubbling up to Minerva's overlay launcher
            e.preventDefault();
                ['click', 'focus', 'focusin', 'touchstart', 'input'].forEach(function(evt) {
            e.stopPropagation();
                    cleanInput.addEventListener(evt, function(e) {
            runSearch();
                        e.stopPropagation();
        });
                    }, true);
                });


        input.addEventListener('keydown', function(e) {
                 searchBox.appendChild(cleanInput);
            if (e.key === 'Enter' || e.keyCode === 13) {
                 searchBox.appendChild(goBtn);
                 e.preventDefault();
                 e.stopImmediatePropagation();
                runSearch();
             }
             }
         });
         }


         bar.appendChild(input);
         // 2. Desktop Vector Header: Route Enter & add single right-side 🔍 icon
         bar.appendChild(goBtn);
         var desktopForm = document.querySelector('#p-search form, form#searchform');
         document.body.appendChild(bar);
         if (desktopForm && !desktopForm.classList.contains('minerva-search-form') && !desktopForm.dataset.vaniDesktopBound) {
        setTimeout(function() { input.focus(); }, 50);
            desktopForm.dataset.vaniDesktopBound = 'true';
    }
            desktopForm.setAttribute('action', '/wiki/Special:VaniSearch');


    // 3. Intercept the Minerva mobile magnifying glass (#searchIcon) BEFORE Minerva's router sees it
            var dInput = desktopForm.querySelector('input[type="search"], input[name="search"], #searchInput');
    document.addEventListener('click', function(e) {
            if (dInput) {
        var searchTrigger = e.target.closest('#searchIcon, .minerva-header .minerva-search-form, .minerva-icon--search');
                dInput.setAttribute('autocomplete', 'off');
        if (searchTrigger && (window.innerWidth <= 999 || document.body.classList.contains('skin-minerva'))) {
                var wrap = dInput.parentElement;
            e.preventDefault();
                if (wrap && !wrap.querySelector('.vani-inline-go')) {
            e.stopPropagation();
                    wrap.style.position = 'relative';
            e.stopImmediatePropagation();
                    var dBtn = document.createElement('button');
            toggleVaniMobileSearch();
                    dBtn.type = 'button';
            return false;
                    dBtn.className = 'vani-inline-go';
        }
                    dBtn.innerHTML = '🔍';
    }, true); // Capture phase = true beats Minerva's native click handler
                    dBtn.style.cssText = 'position:absolute !important; right:8px !important; top:50% !important; transform:translateY(-50%) !important; background:none !important; border:none !important; font-size:15px !important; cursor:pointer !important; padding:0 !important; line-height:1 !important; z-index:20 !important;';
                    dBtn.addEventListener('click', function(e) {
                        e.preventDefault();
                        var val = dInput.value.trim();
                        if (val !== '') {
                            window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                        }
                    });
                    wrap.appendChild(dBtn);
                }


    // 4. Desktop Search Bar: Add 🔍 icon and route Enter key to Special:VaniSearch
                dInput.addEventListener('keydown', function(e) {
    document.addEventListener('keydown', function(e) {
                    if (e.key === 'Enter' || e.keyCode === 13) {
        if (e.key === 'Enter' || e.keyCode === 13) {
                        e.preventDefault();
            var el = e.target;
                        e.stopImmediatePropagation();
            if (el && el.tagName === 'INPUT' && (el.type === 'search' || el.name === 'search' || el.id === 'searchInput')) {
                        var val = dInput.value.trim();
                e.preventDefault();
                        if (val !== '') {
                e.stopImmediatePropagation();
                            window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                var val = el.value.trim();
                        }
                if (val !== '') {
                    }
                    window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                 }, true);
                 }
             }
             }
         }
         }
     }, true);
     }
 
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', installCleanVaniSearch);
    } else {
        installCleanVaniSearch();
    }
    setTimeout(installCleanVaniSearch, 300);
    setTimeout(installCleanVaniSearch, 1000);
})();
})();

Revision as of 01:58, 13 November 2026

/* ==========================================================================
   STANDALONE VANI-SEARCH INPUT (DEFEATS MINERVA FOCUS-STEALING & OVERLAY)
   ========================================================================== */
(function() {
    function installCleanVaniSearch() {
        // 1. Mobile Minerva Header: Replace Minerva's rigged input with a clean standalone input
        var minervaForm = document.querySelector('form.minerva-search-form');
        if (minervaForm && !minervaForm.dataset.vaniCleanInstalled) {
            minervaForm.dataset.vaniCleanInstalled = 'true';
            minervaForm.setAttribute('action', '/wiki/Special:VaniSearch');

            var searchBox = minervaForm.querySelector('.search-box');
            if (searchBox) {
                // Wipe Minerva's decoy input and left icon so Minerva JS cannot hijack focus
                searchBox.innerHTML = '';

                var cleanInput = document.createElement('input');
                cleanInput.type = 'text';
                cleanInput.name = 'search';
                cleanInput.className = 'vani-clean-search-input';
                cleanInput.placeholder = 'Search Vanipedia';
                cleanInput.autocomplete = 'off';

                var goBtn = document.createElement('button');
                goBtn.type = 'button';
                goBtn.className = 'vani-inline-go';
                goBtn.innerHTML = '🔍';
                goBtn.style.cssText = 'position:absolute !important; right:8px !important; top:50% !important; transform:translateY(-50%) !important; background:none !important; border:none !important; font-size:15px !important; cursor:pointer !important; padding:0 !important; line-height:1 !important; z-index:20 !important;';

                function submitMobileVaniSearch(e) {
                    if (e) {
                        e.preventDefault();
                        e.stopPropagation();
                        e.stopImmediatePropagation();
                    }
                    var val = cleanInput.value.trim();
                    if (val !== '') {
                        window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                    }
                }

                goBtn.addEventListener('click', submitMobileVaniSearch, true);

                cleanInput.addEventListener('keydown', function(e) {
                    // Stop Minerva from listening to keystrokes
                    e.stopPropagation();
                    if (e.key === 'Enter' || e.keyCode === 13) {
                        submitMobileVaniSearch(e);
                    }
                }, true);

                // Stop clicks/focus on our input from bubbling up to Minerva's overlay launcher
                ['click', 'focus', 'focusin', 'touchstart', 'input'].forEach(function(evt) {
                    cleanInput.addEventListener(evt, function(e) {
                        e.stopPropagation();
                    }, true);
                });

                searchBox.appendChild(cleanInput);
                searchBox.appendChild(goBtn);
            }
        }

        // 2. Desktop Vector Header: Route Enter & add single right-side 🔍 icon
        var desktopForm = document.querySelector('#p-search form, form#searchform');
        if (desktopForm && !desktopForm.classList.contains('minerva-search-form') && !desktopForm.dataset.vaniDesktopBound) {
            desktopForm.dataset.vaniDesktopBound = 'true';
            desktopForm.setAttribute('action', '/wiki/Special:VaniSearch');

            var dInput = desktopForm.querySelector('input[type="search"], input[name="search"], #searchInput');
            if (dInput) {
                dInput.setAttribute('autocomplete', 'off');
                var wrap = dInput.parentElement;
                if (wrap && !wrap.querySelector('.vani-inline-go')) {
                    wrap.style.position = 'relative';
                    var dBtn = document.createElement('button');
                    dBtn.type = 'button';
                    dBtn.className = 'vani-inline-go';
                    dBtn.innerHTML = '🔍';
                    dBtn.style.cssText = 'position:absolute !important; right:8px !important; top:50% !important; transform:translateY(-50%) !important; background:none !important; border:none !important; font-size:15px !important; cursor:pointer !important; padding:0 !important; line-height:1 !important; z-index:20 !important;';
                    dBtn.addEventListener('click', function(e) {
                        e.preventDefault();
                        var val = dInput.value.trim();
                        if (val !== '') {
                            window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                        }
                    });
                    wrap.appendChild(dBtn);
                }

                dInput.addEventListener('keydown', function(e) {
                    if (e.key === 'Enter' || e.keyCode === 13) {
                        e.preventDefault();
                        e.stopImmediatePropagation();
                        var val = dInput.value.trim();
                        if (val !== '') {
                            window.location.href = '/wiki/Special:VaniSearch?search=' + encodeURIComponent(val);
                        }
                    }
                }, true);
            }
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', installCleanVaniSearch);
    } else {
        installCleanVaniSearch();
    }
    setTimeout(installCleanVaniSearch, 300);
    setTimeout(installCleanVaniSearch, 1000);
})();