MediaWiki:Common.js: различия между версиями

Удаление старой попытки кастомного поиска
Метка: ручная отмена
Постоянный поиск в верхней панели Citizen
Строка 140: Строка 140:
     window.setInterval(updateStatus, 30000);
     window.setInterval(updateStatus, 30000);
     window.setInterval(updateRoundTime, 1000);
     window.setInterval(updateRoundTime, 1000);
})();
/* RedStar persistent top search */
(() => {
    function installTopSearch() {
        if (document.querySelector('.rs-top-search')) {
            return true;
        }
        const header = document.querySelector('.citizen-header');
        const drawer = document.querySelector('.citizen-drawer');
        if (!header || !drawer) {
            return false;
        }
        const form = document.createElement('form');
        form.className = 'rs-top-search';
        form.method = 'get';
        form.action = '/index.php';
        form.setAttribute('role', 'search');
        const hiddenTitle = document.createElement('input');
        hiddenTitle.type = 'hidden';
        hiddenTitle.name = 'title';
        hiddenTitle.value = 'Special:Search';
        const icon = document.createElement('span');
        icon.className = 'rs-top-search__icon';
        icon.setAttribute('aria-hidden', 'true');
        const input = document.createElement('input');
        input.className = 'rs-top-search__input';
        input.type = 'search';
        input.name = 'search';
        input.placeholder = 'Искать в Красной Звезде';
        input.autocomplete = 'off';
        input.spellcheck = false;
        input.setAttribute('aria-label', 'Поиск по Красной Звезде');
        form.append(hiddenTitle, icon, input);
        drawer.insertAdjacentElement('afterend', form);
        return true;
    }
    if (!installTopSearch()) {
        const observer = new MutationObserver(() => {
            if (installTopSearch()) {
                observer.disconnect();
            }
        });
        observer.observe(document.documentElement, {
            childList: true,
            subtree: true
        });
    }
})();
})();

Версия от 15:54, 29 сентября 2026

(() => {
    const root = document.getElementById('rs-server-status');

    if (!root) {
        return;
    }
    const state = document.getElementById('rs-status-state');
    const map = document.getElementById('rs-status-map');
    const time = document.getElementById('rs-status-time');
    const preset = document.getElementById('rs-status-preset');
    const players = document.getElementById('rs-status-players');
    const maxPlayers = document.getElementById('rs-status-max');

    let roundStart = null;
    let runLevel = 0;

    function formatDuration(milliseconds) {
        if (!Number.isFinite(milliseconds) || milliseconds < 0) {
            return '—';
        }

        const totalMinutes = Math.floor(milliseconds / 60000);
        const hours = Math.floor(totalMinutes / 60);
        const minutes = totalMinutes % 60;

        if (hours > 0) {
            return `${hours} ч ${minutes} мин`;
        }

        return `${minutes} мин`;
    }

    function updateRoundTime() {
        if (runLevel !== 1 || roundStart === null) {
            time.textContent = '—';
            return;
        }

        time.textContent = formatDuration(Date.now() - roundStart);
    }

    function setOffline() {
        root.classList.add('rs-home-status--offline');
        state.textContent = 'Сервер недоступен';
        map.textContent = '—';
        time.textContent = '—';
        preset.textContent = '—';
        players.textContent = '0';
        maxPlayers.textContent = '0';

        roundStart = null;
        runLevel = 0;
    }

    function setOnline(data) {
        root.classList.remove('rs-home-status--offline');

        const currentPlayers =
            Number.isInteger(data.players)
                ? data.players
                : 0;

        const maximum =
            Number.isInteger(data.soft_max_players)
                ? data.soft_max_players
                : 0;

        runLevel =
            Number.isInteger(data.run_level)
                ? data.run_level
                : 0;

        switch (runLevel) {
            case 1:
                state.textContent = 'Идёт раунд';
                break;
            case 2:
                state.textContent = 'Раунд завершён';
                break;
            default:
                state.textContent = 'Ожидание раунда';
                break;
        }

        if (runLevel === 0) {
            map.textContent = '—';
        } else {
            map.textContent =
                typeof data.map === 'string' && data.map.trim()
                    ? data.map.trim()
                    : '—';
        }

        preset.textContent =
            typeof data.preset === 'string' && data.preset.trim()
                ? data.preset.trim()
                : '—';

        players.textContent = String(currentPlayers);
        maxPlayers.textContent = String(maximum);

        if (
            runLevel === 1 &&
            typeof data.round_start_time === 'string' &&
            data.round_start_time.length > 0
        ) {
            const parsed = Date.parse(data.round_start_time);
            roundStart = Number.isNaN(parsed) ? null : parsed;
        } else {
            roundStart = null;
        }

        updateRoundTime();

    }

    async function updateStatus() {
        try {
            const response = await fetch('/server-status', {
                cache: 'no-store',
                headers: {
                    Accept: 'application/json'
                }
            });

            if (!response.ok) {
                throw new Error(`HTTP ${response.status}`);
            }

            const data = await response.json();
            setOnline(data);
        } catch (error) {
            console.warn('RedStar server status unavailable:', error);
            setOffline();
        }
    }

    updateStatus();

    window.setInterval(updateStatus, 30000);
    window.setInterval(updateRoundTime, 1000);
})();

/* RedStar persistent top search */
(() => {
    function installTopSearch() {
        if (document.querySelector('.rs-top-search')) {
            return true;
        }

        const header = document.querySelector('.citizen-header');
        const drawer = document.querySelector('.citizen-drawer');

        if (!header || !drawer) {
            return false;
        }

        const form = document.createElement('form');
        form.className = 'rs-top-search';
        form.method = 'get';
        form.action = '/index.php';
        form.setAttribute('role', 'search');

        const hiddenTitle = document.createElement('input');
        hiddenTitle.type = 'hidden';
        hiddenTitle.name = 'title';
        hiddenTitle.value = 'Special:Search';

        const icon = document.createElement('span');
        icon.className = 'rs-top-search__icon';
        icon.setAttribute('aria-hidden', 'true');

        const input = document.createElement('input');
        input.className = 'rs-top-search__input';
        input.type = 'search';
        input.name = 'search';
        input.placeholder = 'Искать в Красной Звезде';
        input.autocomplete = 'off';
        input.spellcheck = false;
        input.setAttribute('aria-label', 'Поиск по Красной Звезде');

        form.append(hiddenTitle, icon, input);

        drawer.insertAdjacentElement('afterend', form);

        return true;
    }

    if (!installTopSearch()) {
        const observer = new MutationObserver(() => {
            if (installTopSearch()) {
                observer.disconnect();
            }
        });

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true
        });
    }
})();