MediaWiki:Gadget-april-fools.js

Материал из Абсурдопедии
Версия от 22:13, 31 марта 2026; Тэйтанка-птекила (обсуждение | вклад) (Новая страница: «* * Первоапрельский гаджет * Заменяет содержимое заглавной страницы на объявление: ( function () { 'use strict'; // Проверяем, что это заглавная страница var title = mw.config.get( 'wgTitle' ); var isMainPage = ( title === 'Заглавная страница' || title === 'Main_Page' ); // Проверяем дату...»)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигации Перейти к поиску

Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.

  • Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
  • Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
  • Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
  • Opera: Нажмите Ctrl+F5.
/**
 * Первоапрельский гаджет
 * Заменяет содержимое заглавной страницы на объявление
 */

( function () {
    'use strict';
    
    // Проверяем, что это заглавная страница
    var title = mw.config.get( 'wgTitle' );
    var isMainPage = ( title === 'Заглавная страница' || title === 'Main_Page' );
    
    // Проверяем дату
    var today = new Date();
    var isAprilFools = ( today.getMonth() === 3 && today.getDate() === 1 );
    
    // Проверяем, не отключен ли гаджет через URL (?april=off)
    var urlParams = new URLSearchParams( window.location.search );
    var isDisabled = ( urlParams.get( 'april' ) === 'off' );
    
    // Если не подходит — выходим
    if ( !isMainPage || !isAprilFools || isDisabled ) {
        return;
    }
    
    // Добавляем класс на body для активации стилей
    document.body.classList.add( 'april-fools-active' );
    
    // Ключ для localStorage (чтобы запомнить оторванный корешок)
    var STORAGE_KEY = 'april_fools_ticket_ripped';
    var isTicketRipped = localStorage.getItem( STORAGE_KEY ) === 'true';
    
    // Функция создания HTML структуры
    function buildAprilFoolsHTML() {
        return `
            <div class="april-notice">
                <div class="tape-corner top-left"></div>
                <div class="tape-corner top-right"></div>
                <div class="tape-corner bottom-left"></div>
                <div class="tape-corner bottom-right"></div>
                
                <div class="april-header">
                    <span>⚠️ В Н И М А Н И Е ⚠️</span>
                </div>
                
                <div class="april-content">
                    <h2>Absurdopedia.wiki</h2>
                    <div class="subhead">энциклопедия, которую мы потеряли</div>
                    
                    <p><strong>ВРЕМЕННО НАХОДИТСЯ</strong></p>
                    
                    <div class="april-address" data-action="address">
                        🏠 ул. Логическая, д. 0, кв. ∞
                    </div>
                    <div class="address-hint" style="font-size: 0.7rem; color: #9b8a60; margin-top: -0.5rem;">
                        (домофон не работает. кричите «абсурд» — откроют)
                    </div>
                    
                    <div class="april-reason">
                        <strong>📋 Причина:</strong> плановая замена смыслов.<br>
                        Работы проводятся с 00:00 до <strong>никогда</strong>.<br>
                        Приносим извинения за неудобства, <span style="text-decoration: line-through;">которых</span> не существует.
                    </div>
                    
                    <div class="april-support" data-action="support">
                        <strong>📞 Техподдержка:</strong><br>
                        позвоните по номеру, который вы сейчас придумали в голове.
                        <div class="support-hint">
                            (если не придумали — значит, всё в порядке)
                        </div>
                    </div>
                    
                    <div class="april-ticket" id="april-ticket-container">
                        ${isTicketRipped ? 
                            '<div class="ticket-ripped-message"><s>корешок оторван</s><br>✨ вы свободны. или нет. проверьте карманы ✨</div>' : 
                            '<button class="ticket-button" data-action="ticket">[ ОТОРВАТЬ КОРЕШОК ]</button>'
                        }
                        <div class="ticket-note" style="font-size: 0.65rem; margin-top: 0.8rem; color: #9b8a60;">
                            *корешок существует только в вашем воображении.<br>
                            но это не освобождает вас от ответственности
                        </div>
                    </div>
                </div>
                
                <div class="april-footer">
                    <p>📌 Объявление расклеено:<br>
                    • на всех подъездах вашего разума<br>
                    • в лифте вашего внимания<br>
                    • на холодильнике вашей совести</p>
                    <p class="small">*если вы читаете это объявление второй раз — ничего страшного, это нормальная петля времени<br>
                    *если вы читаете это объявление третий раз — вы нам нравитесь. оставайтесь. мы вас запомнили</p>
                    <p class="small" style="margin-top: 0.8rem;">🔍 вернуться к обычной версии: <a href="?april=off" style="color: #8b5a2b;">?april=off</a></p>
                </div>
            </div>
        `;
    }
    
    // Функция создания модального окна
    function showModal( content, buttonText, callback ) {
        // Удаляем существующее модальное окно, если есть
        var existingModal = document.getElementById( 'april-modal' );
        if ( existingModal ) {
            existingModal.remove();
        }
        
        var modal = document.createElement( 'div' );
        modal.id = 'april-modal';
        modal.className = 'april-modal';
        modal.innerHTML = `
            <div class="april-modal-content">
                ${content}
                <button class="april-modal-close">${buttonText || 'Закрыть'}</button>
            </div>
        `;
        
        document.body.appendChild( modal );
        modal.style.display = 'flex';
        
        var closeBtn = modal.querySelector( '.april-modal-close' );
        closeBtn.addEventListener( 'click', function () {
            modal.style.display = 'none';
            modal.remove();
            if ( callback ) callback();
        } );
        
        // Закрытие по клику вне окна
        modal.addEventListener( 'click', function ( e ) {
            if ( e.target === modal ) {
                modal.style.display = 'none';
                modal.remove();
                if ( callback ) callback();
            }
        } );
    }
    
    // Обработка отрывания корешка
    function handleTicketRip( button ) {
        if ( isTicketRipped ) return;
        
        isTicketRipped = true;
        localStorage.setItem( STORAGE_KEY, 'true' );
        
        // Заменяем кнопку на сообщение
        var container = document.getElementById( 'april-ticket-container' );
        if ( container ) {
            container.innerHTML = `
                <div class="ticket-ripped-message">
                    <s>корешок оторван</s><br>
                    ✨ вы свободны. или нет. проверьте карманы ✨
                </div>
                <div class="ticket-note" style="font-size: 0.65rem; margin-top: 0.8rem; color: #9b8a60;">
                    *корешок существует только в вашем воображении.<br>
                    но это не освобождает вас от ответственности
                </div>
            `;
        }
        
        // Показываем модальное окно
        showModal(
            '<p><strong>📄 КОРЕШОК ОТОРВАН</strong></p>' +
            '<p>Вы совершили необратимое действие.<br>' +
            'Корешок у вас. Что с ним делать — мы не знаем. Это ваша проблема теперь.</p>' +
            '<p>В соответствии с пунктом 0 статьи ∞ правил внутреннего распорядка,<br>' +
            'вы обязаны:</p>' +
            '<p>• написать статью про то, <strong>почему вы это сделали</strong><br>' +
            '• срок — до конца жизни<br>' +
            '• объём — от одного слова до бесконечности</p>' +
            '<p style="font-size: 0.8rem; color: #8b7a5a;">(подсказка: можно начать с фразы «потому что...»)</p>',
            'Я понял, что наделал'
        );
    }
    
    // Обработка клика по адресу
    function handleAddressClick() {
        if ( typeof console !== 'undefined' ) {
            console.log( '%c📍 вы ищете то, что не ищется. достойно уважения', 'color: #b89a40; font-size: 12px;' );
        }
        showModal(
            '<p><strong>🏠 ул. Логическая, д. 0, кв. ∞</strong></p>' +
            '<p>На картах этого адреса нет.<br>' +
            'Но вы всё равно попробуйте найти.<br>' +
            'Мы будем следить.</p>' +
            '<p style="font-size: 0.8rem;">🗺️ подсказка: идите туда, где заканчиваются мысли</p>',
            'Понял, продолжу поиски'
        );
    }
    
    // Обработка клика по техподдержке
    function handleSupportClick() {
        showModal(
            '<p><strong>📞 ЗВОНОК ТЕХПОДДЕРЖКЕ</strong></p>' +
            '<p>Вы набрали номер... какой вы набрали?<br>' +
            'Ах да, тот самый.</p>' +
            '<p>— Алло?<br>' +
            '— ...<br>' +
            '— Мы не работаем сегодня.<br>' +
            'И вчера не работали. И завтра не будем.<br>' +
            'Но спасибо, что спросили.</p>' +
            '<p>— ...<br>' +
            '— Да, с праздником.</p>' +
            '<p><em>*гудки*</em></p>',
            'ПОЛОЖИТЬ ТРУБКУ'
        );
    }
    
    // Основная функция
    function init() {
        // Находим контейнер с содержимым
        var contentDiv = document.getElementById( 'mw-content-text' );
        if ( !contentDiv ) {
            // Пробуем альтернативные селекторы для разных скинов
            contentDiv = document.querySelector( '#content #mw-content-text' ) ||
                        document.querySelector( '.mw-body-content' );
        }
        
        if ( contentDiv ) {
            // Сохраняем оригинальное содержимое (на случай, если понадобится)
            contentDiv.setAttribute( 'data-april-original', 'true' );
            contentDiv.innerHTML = buildAprilFoolsHTML();
            
            // Навешиваем обработчики событий
            var ticketBtn = document.querySelector( '[data-action="ticket"]' );
            if ( ticketBtn ) {
                ticketBtn.addEventListener( 'click', function () {
                    handleTicketRip( ticketBtn );
                } );
            }
            
            var addressEl = document.querySelector( '[data-action="address"]' );
            if ( addressEl ) {
                addressEl.addEventListener( 'click', handleAddressClick );
            }
            
            var supportEl = document.querySelector( '[data-action="support"]' );
            if ( supportEl ) {
                supportEl.addEventListener( 'click', handleSupportClick );
            }
        }
        
        // Консольное сообщение при открытии DevTools (детекция)
        var devtools = /Chrome|Firefox/.test( navigator.userAgent );
        if ( devtools ) {
            setTimeout( function () {
                console.log( '%c================================================\n🕵️‍♂️  А вы любопытный.\n\nЕсли вы ищете, где спрятаны статьи —\nони там же, где были всегда.\n\nА если вы ищете смысл —\nон под ковриком. нет, не тем. тем, который\nлежит в квартире вашей бабушки.\n\nС Первым апреля.\n================================================', 'color: #b89a40; font-size: 12px;' );
            }, 1000 );
        }
        
        // Защита копирования с умным сообщением
        document.addEventListener( 'copy', function ( e ) {
            var selection = window.getSelection().toString();
            if ( selection && selection.length > 0 && document.querySelector( '.april-notice' ) ) {
                e.preventDefault();
                e.clipboardData.setData( 'text/plain', '📋 вы скопировали объявление. теперь оно существует в двух местах. это удваивает вашу ответственность. не благодарите.\n\n(оригинал всё ещё на ул. Логической, д. 0)' );
            }
        } );
    }
    
    // Ждём загрузки DOM
    if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', init );
    } else {
        init();
    }
} )();