Немає опису редагування
Немає опису редагування
Рядок 1: Рядок 1:
// ==================================================
// ============================================================
// RANDOM ARTICLES
// MediaWiki:Common.js — Mafia Closed Circle
// ==================================================
// Фінальна версія
$(document).ready(function() {
// ============================================================
 
// ============================================================
// 1. RANDOM ARTICLES
// ============================================================
$(document).ready(function () {
     var apiUrl = mw.config.get('wgScriptPath') + '/api.php';
     var apiUrl = mw.config.get('wgScriptPath') + '/api.php';
     $.getJSON(apiUrl, {
     $.getJSON(apiUrl, {
         action: 'query',
         action: 'query', format: 'json', list: 'random',
        format: 'json',
         rnnamespace: '0', rnlimit: '5',
        list: 'random',
         prop: 'extracts', exchars: '250', exlimit: 'max', explaintext: true
         rnnamespace: '0',
     }, function (data) {
        rnlimit: '5',
         prop: 'extracts',
        exchars: '250',
        exlimit: 'max',
        explaintext: true
     }, function(data) {
         var html = '';
         var html = '';
         $.each(data.query.random, function(i, article) {
         $.each(data.query.random, function (i, article) {
             html += '<div class="random-article-preview">';
             html += '<div class="random-article-preview">';
             html += '<h2><a href="/wiki/' + encodeURIComponent(article.title) + '">' + article.title + '</a></h2>';
             html += '<h2><a href="/wiki/' + encodeURIComponent(article.title) + '">' + article.title + '</a></h2>';
            html += '<p>' + article.extract + '</p>';
             html += '</div>';
             html += '</div>';
         });
         });
Рядок 26: Рядок 24:
});
});


// ==================================================
// ============================================================
// L-BOX NAVIGATION
// 2. L-BOX NAVIGATION
// ==================================================
// ============================================================
$(function() {
$(function () {
     var items = $('.l-box-item');
     var $lbox = $('.l-box');
     var sections = [];
    if ($lbox.length === 0) return;
   
 
    items.each(function() {
    var $items = $lbox.find('.l-box-item');
        var target = $(this).data('target');
 
        if (target === 'top') {
     function buildSectionMap() {
            sections.push({item: $(this), target: null, offset: 0});
        var map = [];
        } else {
        $items.each(function () {
            var el = document.getElementById(target);
            var target = $(this).data('target');
            if (el) {
            if (target === 'top') {
                sections.push({item: $(this), target: $(el), offset: $(el).offset().top});
                map.push({ $item: $(this), top: 0 });
            } else {
                var $el = $('#' + target);
                if ($el.length) {
                    map.push({ $item: $(this), top: $el.offset().top });
                }
             }
             }
        });
        map.sort(function (a, b) { return a.top - b.top; });
        return map;
    }
    function updateActive(map) {
        var scrollY = $(window).scrollTop() + 110;
        var current = null;
        for (var i = 0; i < map.length; i++) {
            if (map[i].top <= scrollY) current = map[i].$item;
         }
         }
    });
        $items.removeClass('active');
      
        if (current) current.addClass('active');
     items.on('click', function() {
     }
 
     $items.on('click', function () {
         var target = $(this).data('target');
         var target = $(this).data('target');
        var scrollTo = 0;
       
         if (target === 'top') {
         if (target === 'top') {
             scrollTo = 0;
             $('html, body').animate({ scrollTop: 0 }, 280);
         } else {
         } else {
             var el = document.getElementById(target);
             var $el = $('#' + target);
             if (el) {
             if ($el.length) {
                 scrollTo = $(el).offset().top - 100;
                 $('html, body').animate({ scrollTop: $el.offset().top - 75 }, 280);
             }
             }
         }
         }
       
        $('html, body').animate({scrollTop: scrollTo}, 300);
     });
     });
      
 
     $(window).on('scroll', function() {
     var sectionMap = buildSectionMap();
         var scrollPos = $(window).scrollTop() + 120;
 
        var current = null;
     $(document).on('mcc:content-loaded', function () {
       
         sectionMap = buildSectionMap();
         for (var i = 0; i < sections.length; i++) {
        updateActive(sectionMap);
             var checkPos = sections[i].target ? sections[i].target.offset().top : 0;
    });
            if (checkPos <= scrollPos) {
 
                 current = sections[i].item;
    var ticking = false;
             }
    $(window).on('scroll', function () {
        }
         if (!ticking) {
       
             window.requestAnimationFrame(function () {
        items.removeClass('active');
                updateActive(sectionMap);
        if (current) {
                 ticking = false;
             current.addClass('active');
             });
             ticking = true;
         }
         }
     });
     });
   
 
     $(window).trigger('scroll');
     $(window).on('resize', function () {
        sectionMap = buildSectionMap();
        updateActive(sectionMap);
    });
 
    updateActive(sectionMap);
});
});


// ==================================================
// ============================================================
// PROFILE ICONS
// 3. PROFILE ICONS — клік + inactive якщо немає URL
// ==================================================
// ============================================================
$(document).ready(function() {
$(document).ready(function () {
     $('.profile-icon').each(function() {
     $('.profile-icon').each(function () {
         var icon = $(this);
         var $icon = $(this);
         var url = icon.attr('data-url');
         var url = ($icon.attr('data-url') || '').trim();
         if (url && url.trim() !== '') {
 
             icon.css('cursor', 'pointer');
         if (url) {
             icon.on('click', function() {
             $icon.css('cursor', 'pointer');
             $icon.on('click', function () {
                 window.open(url, '_blank');
                 window.open(url, '_blank');
             });
             });
         } else {
         } else {
             icon.css({
             $icon.addClass('inactive');
                'opacity': '0.3',
                'filter': 'grayscale(100%)',
                '-webkit-filter': 'grayscale(100%)',
                'cursor': 'default'
            });
         }
         }
     });
     });
});
});


// ============================================================
// 4. ДИНАМІЧНІ ПОСИЛАННЯ НА ГОЛОВНІЙ
// ============================================================
$(document).ready(function () {
    if (!$('body').hasClass('page-Головна_сторінка')) return;


// ==================================================
     var block1Links = [{ title: 'Фінал Року', url: '/index.php/Фінал_Року' }];
// ДИНАМІЧНІ ПОСИЛАННЯ НА ГОЛОВНІЙ
    var block2Links = [
// ==================================================
        { title: 'Перша статистика', url: '/index.php/Перша_статистика' },
$(document).ready(function() {
        { title: 'Період',           url: '/index.php/Період' },
     // Тільки на головній сторінці
        { title: 'Друга статистика', url: '/index.php/Статистика' }
    if ($('body').hasClass('page-Головна_сторінка')) {
    ];
       
    var block3Links = [
        // Списки посилань для кожного блоку
        { title: 'Mafia Closed Cup I',       url: '/index.php/Mafia_Closed_Cup_I' },
        var block1Links = [
        { title: 'Mafia Closed Cup I Online', url: '/index.php/Mafia_Closed_Cup_I_Online' },
            { title: 'Фінал Року', url: '/index.php/Фінал_Року' }
        { title: 'My Closest Circle I',       url: '/index.php/My_Closest_Circle_I' }
        ];
    ];
       
 
        var block2Links = [
    function rand(arr) { return arr[Math.floor(Math.random() * arr.length)]; }
            { title: 'Перша статистика', url: '/index.php/Перша_статистика' },
 
            { title: 'Період', url: '/index.php/Період' },
    var $blocks = $('.home__block-image-block p');
            { title: 'Друга статистика', url: '/index.php/Статистика' }
    if ($blocks.length >= 3) {
        ];
        var l1 = rand(block1Links), l2 = rand(block2Links), l3 = rand(block3Links);
       
        $blocks.eq(0).html('<a href="' + l1.url + '">' + l1.title + '</a>');
        var block3Links = [
        $blocks.eq(1).html('<a href="' + l2.url + '">' + l2.title + '</a>');
            { title: 'Mafia Closed Cup I', url: '/index.php/Mafia_Closed_Cup_I' },
        $blocks.eq(2).html('<a href="' + l3.url + '">' + l3.title + '</a>');
            { title: 'Mafia Closed Cup I Online', url: '/index.php/Mafia_Closed_Cup_I_Online' },
            { title: 'My Closest Circle I', url: '/index.php/My_Closest_Circle_I' }
        ];
       
        // Функція випадкового вибору
        function getRandomItem(arr) {
            return arr[Math.floor(Math.random() * arr.length)];
        }
       
        // Знаходимо блоки і замінюємо посилання
        var $blocks = $('.home__block-image-block p');
       
        if ($blocks.length >= 3) {
            var link1 = getRandomItem(block1Links);
            var link2 = getRandomItem(block2Links);
            var link3 = getRandomItem(block3Links);
           
            $blocks.eq(0).html('<a href="' + link1.url + '">' + link1.title + '</a>');
            $blocks.eq(1).html('<a href="' + link2.url + '">' + link2.title + '</a>');
            $blocks.eq(2).html('<a href="' + link3.url + '">' + link3.title + '</a>');
        }
     }
     }
});
});


// ==================================================
// ============================================================
// PLAYER TABS WITH LAZY LOADING
// 5. PLAYER TABS + LAZY LOADING ІГОР
// ==================================================
// ============================================================
$(function() {
$(function () {
     var $tabs = $('.player-tab');
     var $tabs     = $('.player-tab');
     var $contents = $('.player-tab-content');
     var $contents = $('.player-tab-content');
     var $lbox = $('.l-box');
     var $lbox     = $('.l-box');
     var $rbox = $('.r-box');
     var $rbox     = $('.r-box');
   
 
     if ($tabs.length === 0) return;
     if ($tabs.length === 0) return;
   
 
    // Функція перевірки мобільної версії
     function isMobile() { return $(window).width() <= 768; }
     function isMobile() {
 
        return $(window).width() <= 768;
     $tabs.on('click', function () {
    }
         var $tab   = $(this);
   
         var tabId = $tab.data('tab');
     $tabs.on('click', function() {
         var $tab = $(this);
         var tabId = $tab.data('tab');
         var $content = $('#tab-' + tabId);
         var $content = $('#tab-' + tabId);
       
 
        // Перемикаємо активні класи
         $tabs.removeClass('active');
         $tabs.removeClass('active');
         $tab.addClass('active');
         $tab.addClass('active');
         $contents.removeClass('active');
         $contents.removeClass('active');
         $content.addClass('active');
         $content.addClass('active');
       
 
         // Ховаємо/показуємо l-box залежно від табу (на десктопі)
         // L-box — ховаємо на вкладці ігор
         if (tabId === 'games') {
         if (tabId === 'games') {
             $lbox.fadeOut(200);
             $lbox.fadeOut(200);
Рядок 182: Рядок 175:
             $lbox.fadeIn(200);
             $lbox.fadeIn(200);
         }
         }
       
 
         // Ховаємо/показуємо r-box на МОБІЛЬНИХ при переході на "games"
         // R-box на мобільних ховаємо при іграх
         if (isMobile()) {
         if (isMobile()) {
             if (tabId === 'games') {
             if (tabId === 'games') $rbox.slideUp(200);
                $rbox.slideUp(200);
             else                   $rbox.slideDown(200);
             } else {
                $rbox.slideDown(200);
            }
         }
         }
       
 
         // Lazy load для ігор
         // Lazy load
         if (tabId === 'games' && !$content.data('loaded')) {
         if (tabId === 'games' && !$content.data('loaded')) {
             var playerName = $content.data('player');
             var playerName = $content.data('player');
           
             if (!playerName) return;
             if (playerName) {
 
                // Показуємо loader
            $content.html('<div class="tab-loader">Завантаження...</div>');
                $content.html('<div class="tab-loader">Завантаження...</div>');
 
               
            $.ajax({
                $.ajax({
                url: mw.config.get('wgScriptPath') + '/api.php',
                    url: mw.config.get('wgScriptPath') + '/api.php',
                data: {
                    data: {
                    action: 'expandtemplates', format: 'json',
                        action: 'expandtemplates',
                    text: '{{#invoke:FetchData|player_games|player=' + playerName + '}}',
                        format: 'json',
                    prop: 'wikitext'
                        text: '{{#invoke:FetchData|player_games|player=' + playerName + '}}',
                },
                        prop: 'wikitext'
                dataType: 'json',
                    },
                success: function (response) {
                    dataType: 'json',
                    if (!response.expandtemplates || !response.expandtemplates.wikitext) return;
                    success: function(response) {
 
                        if (response.expandtemplates && response.expandtemplates.wikitext) {
                    $.ajax({
                            $.ajax({
                        url: mw.config.get('wgScriptPath') + '/api.php',
                                url: mw.config.get('wgScriptPath') + '/api.php',
                        data: {
                                data: {
                            action: 'parse', format: 'json',
                                    action: 'parse',
                            text: response.expandtemplates.wikitext,
                                    format: 'json',
                            contentmodel: 'wikitext',
                                    text: response.expandtemplates.wikitext,
                            disablelimitreport: true
                                    contentmodel: 'wikitext',
                        },
                                    disablelimitreport: true
                        dataType: 'json',
                                },
                        success: function (r) {
                                dataType: 'json',
                            if (r.parse && r.parse.text) {
                                success: function(parseResponse) {
                                $content.html(r.parse.text['*']);
                                    if (parseResponse.parse && parseResponse.parse.text) {
                                $content.data('loaded', true);
                                        $content.html(parseResponse.parse.text['*']);
                                $content.find('table.sortable').tablesorter();
                                        $content.data('loaded', true);
 
                                        $content.find('table.sortable').tablesorter();
                                // Запускаємо пост-обробку для нового контенту
                                    }
                                applyWinrateColors($content);
                                },
                                wrapWideTables($content);
                                error: function() {
                                $(document).trigger('mcc:content-loaded');
                                    $content.html('<p style="color: #ff7777; text-align: center;">Помилка завантаження. Спробуйте оновити сторінку.</p>');
                            }
                                }
                        },
                            });
                        error: function () {
                            $content.html('<p style="color:#ff7777;text-align:center">Помилка завантаження.</p>');
                         }
                         }
                     },
                     });
                    error: function() {
                },
                        $content.html('<p style="color: #ff7777; text-align: center;">Помилка завантаження. Спробуйте оновити сторінку.</p>');
                error: function () {
                    }
                    $content.html('<p style="color:#ff7777;text-align:center">Помилка завантаження.</p>');
                });
                }
             }
            });
        }
    });
 
    $(window).on('resize', function () {
        if (!isMobile()) $rbox.show();
    });
});
 
// ============================================================
// 6. АНІМАЦІЯ РЯДКІВ ПРИ СОРТУВАННІ
// ============================================================
$(function () {
    $(document).on('sortEnd', 'table.wikitable', function () {
        var $t = $(this);
        $t.addClass('mcc-sorting').removeClass('mcc-sorted');
        setTimeout(function () {
            $t.removeClass('mcc-sorting').addClass('mcc-sorted');
            setTimeout(function () { $t.removeClass('mcc-sorted'); }, 600);
        }, 20);
    });
});
 
// ============================================================
// 7. ГОРИЗОНТАЛЬНИЙ СКРОЛ ДЛЯ ШИРОКИХ ТАБЛИЦЬ
// ============================================================
function wrapWideTables($context) {
    var $root = $context || $(document);
 
    function wrap($table) {
        if ($table.closest('.mcc-scroll-inner').length) return;
 
        $table.wrap('<div class="mcc-scroll-inner"></div>');
        $table.closest('.mcc-scroll-inner').wrap('<div class="mcc-scroll-outer"></div>');
 
        var $inner = $table.closest('.mcc-scroll-inner');
        var $outer = $inner.closest('.mcc-scroll-outer');
 
        function check() {
             var atEnd = $inner[0].scrollLeft + $inner[0].clientWidth >= $inner[0].scrollWidth - 4;
            $outer.toggleClass('mcc-no-fade', atEnd);
        }
 
        $inner.on('scroll', check);
        check();
    }
 
    // Явно задані широкі класи
    $root.find('.wikitable.wide-table, .wikitable.mcc-wide, .wikitable.full-width').each(function () {
        wrap($(this));
    });
 
    // Таблиці з >8 колонок (Запис ігор)
    $root.find('.wikitable').each(function () {
        var $t = $(this);
        if ($t.closest('.mcc-scroll-inner').length) return;
        if ($t.find('thead tr:first th').length > 8) {
            $t.addClass('mcc-wide-table');
            wrap($t);
         }
         }
     });
     });
   
}
    // При зміні розміру вікна - показуємо r-box на десктопі
 
     $(window).on('resize', function() {
$(function () { wrapWideTables(); });
         if (!isMobile()) {
 
             $rbox.show();
// ============================================================
// 8. ВІНРЕЙТ — кольорове підсвічення клітинок з %
// ============================================================
function applyWinrateColors($context) {
     var $root = $context || $(document);
    $root.find('.wikitable tbody td').each(function () {
        var text = $(this).text().trim();
         if (/^\d+(\.\d+)?%$/.test(text)) {
             var val = parseFloat(text);
            if      (val >= 55) $(this).addClass('wr-hi');
            else if (val <= 33) $(this).addClass('wr-lo');
         }
         }
     });
     });
});
}


$(function () { applyWinrateColors(); });


// ==================================================
// ============================================================
// МОБІЛЬНИЙ ПОШУК
// 9. МОБІЛЬНИЙ ПОШУК
// ==================================================
// ============================================================
$(function() {
$(function () {
     if ($(window).width() > 768) return;
     if ($(window).width() > 768) return;
   
    // Перевіряємо чи вже створено
     if ($('.mobile-search-btn').length > 0) return;
     if ($('.mobile-search-btn').length > 0) return;
   
 
     var $searchBtn = $('<div class="mobile-search-btn">' +
     var $btn = $('<div class="mobile-search-btn">' +
         '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2">' +
         '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2">' +
         '<circle cx="11" cy="11" r="8"/>' +
         '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg></div>');
        '<path d="m21 21-4.35-4.35"/>' +
 
        '</svg>' +
    '</div>');
   
     var $overlay = $('<div class="mobile-search-overlay">' +
     var $overlay = $('<div class="mobile-search-overlay">' +
         '<input type="text" placeholder="Пошук..." autocomplete="off">' +
         '<input type="text" placeholder="Пошук..." autocomplete="off">' +
         '<div class="mobile-search-close">×</div>' +
         '<div class="mobile-search-close">×</div></div>');
    '</div>');
 
   
     $('.minerva-header .branding-box').after($btn);
     $('.minerva-header .branding-box').after($searchBtn);
     $('body').append($overlay);
     $('body').append($overlay);
   
 
     var $input = $overlay.find('input');
     var $input = $overlay.find('input');
     var $close = $overlay.find('.mobile-search-close');
     var $close = $overlay.find('.mobile-search-close');
   
 
     $searchBtn.on('click', function(e) {
     $btn.on('click', function (e) {
         e.preventDefault();
         e.preventDefault(); e.stopPropagation();
        e.stopPropagation();
         $overlay.addClass('active');
         $overlay.addClass('active');
         setTimeout(function() { $input.focus(); }, 100);
         setTimeout(function () { $input.focus(); }, 100);
     });
     });
   
 
     $close.on('click', function() {
     $close.on('click', function () {
         $overlay.removeClass('active');
         $overlay.removeClass('active'); $input.val('');
        $input.val('');
     });
     });
   
 
     $input.on('keydown', function(e) {
     $input.on('keydown', function (e) {
         if (e.keyCode === 13) {
         if (e.keyCode === 13) {
             var query = $input.val().trim();
             var q = $input.val().trim();
             if (query) {
             if (q) window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(q);
                window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(query);
            }
        }
        if (e.keyCode === 27) {
            $overlay.removeClass('active');
            $input.val('');
         }
         }
        if (e.keyCode === 27) { $overlay.removeClass('active'); $input.val(''); }
     });
     });
   
 
     $overlay.on('click', function(e) {
     $overlay.on('click', function (e) {
         if (e.target === this) {
         if (e.target === this) { $overlay.removeClass('active'); $input.val(''); }
            $overlay.removeClass('active');
            $input.val('');
        }
     });
     });
});
});


// ==================================================
// ============================================================
// БЛОКУВАННЯ MINERVA SEARCH OVERLAY (ДЕСКТОП)
// 10. БЛОКУВАННЯ MINERVA SEARCH OVERLAY (ДЕСКТОП)
// ==================================================
// ============================================================
$(function() {
$(function () {
    // Тільки для десктопа
     if ($(window).width() <= 768) return;
     if ($(window).width() <= 768) return;
   
 
     var $searchInput = $('#searchInput');
     var $searchInput = $('#searchInput');
     if ($searchInput.length === 0) return;
     if ($searchInput.length === 0) return;
   
 
    // Затримка щоб DOM завантажився
     setTimeout(function () {
     setTimeout(function() {
        // Змінюємо placeholder
         $searchInput.attr('placeholder', 'Пошук...');
         $searchInput.attr('placeholder', 'Пошук...');
       
 
        // Клонуємо input щоб прибрати всі event listeners
         var $newInput = $searchInput.clone(false);
         var $newInput = $searchInput.clone(false);
         $searchInput.replaceWith($newInput);
         $searchInput.replaceWith($newInput);
         $searchInput = $newInput;
         $searchInput = $newInput;
       
 
        // Прибираємо readonly і класи тригера
         $searchInput.prop('readonly', false).removeAttr('readonly')
         $searchInput.prop('readonly', false);
            .removeClass('skin-minerva-search-trigger');
        $searchInput.removeAttr('readonly');
 
        $searchInput.removeClass('skin-minerva-search-trigger');
         $searchInput.on('focus click', function (e) {
       
        // При фокусі - блокуємо overlay
         $searchInput.on('focus click', function(e) {
             e.stopPropagation();
             e.stopPropagation();
           
            // Прибираємо overlay класи з body
             $('body').removeClass('overlay-enabled search-enabled');
             $('body').removeClass('overlay-enabled search-enabled');
           
            // Видаляємо overlay елементи
             $('.overlay, .search-overlay').hide();
             $('.overlay, .search-overlay').hide();
           
            // Прибираємо hash
             if (window.location.hash === '#/search') {
             if (window.location.hash === '#/search') {
                 history.replaceState(null, null, window.location.pathname);
                 history.replaceState(null, null, window.location.pathname);
             }
             }
         });
         });
       
 
        // При Enter - перехід на сторінку пошуку
         $searchInput.on('keydown', function (e) {
         $searchInput.on('keydown', function(e) {
             if (e.which === 13) {
             if (e.which === 13 || e.keyCode === 13) {
                 e.preventDefault();
                 e.preventDefault();
                 var query = $(this).val().trim();
                 var q = $(this).val().trim();
                 if (query) {
                 if (q) window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(q);
                    window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(query);
                }
                 return false;
                 return false;
             }
             }
         });
         });
       
     }, 100);
     }, 100);
   
 
    // Блокуємо hashchange на #/search
     $(window).on('hashchange', function () {
     $(window).on('hashchange', function(e) {
         if (window.location.hash === '#/search') {
         if (window.location.hash === '#/search') {
            e.preventDefault();
             history.replaceState(null, null, window.location.pathname);
             history.replaceState(null, null, window.location.pathname);
             $('body').removeClass('overlay-enabled search-enabled');
             $('body').removeClass('overlay-enabled search-enabled');
Рядок 375: Рядок 400:
         }
         }
     });
     });
   
 
    // Перевіряємо hash при завантаженні
     if (window.location.hash === '#/search') {
     if (window.location.hash === '#/search') {
         history.replaceState(null, null, window.location.pathname);
         history.replaceState(null, null, window.location.pathname);
Рядок 382: Рядок 406:
});
});


// ==================================================
// ============================================================
// BANNER SEARCH (LIQUIPEDIA STYLE)
// 11. BANNER SEARCH
// ==================================================
// ============================================================
$(function() {
$(function () {
     var $container = $('#bannerSearchContainer');
     var $container = $('#bannerSearchContainer');
     if ($container.length === 0) return;
     if ($container.length === 0) return;
   
    // Створюємо елементи через JS
    var $input = $('<input>', {
        type: 'text',
        id: 'bannerSearchInput',
        placeholder: 'Пошук MCC...'
    });
   
    var $btn = $('<button>', {
        id: 'bannerSearchBtn',
        text: 'Пошук'
    });
   
    $container.append($input).append($btn);
   
    // Функція пошуку
    function doSearch() {
        var query = $input.val().trim();
        if (query) {
            window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(query);
        }
    }
   
    $btn.on('click', doSearch);
   
    $input.on('keydown', function(e) {
        if (e.keyCode === 13) {
            e.preventDefault();
            doSearch();
        }
    });
});


// ==================================================
    var $input = $('<input>', { type: 'text', id: 'bannerSearchInput', placeholder: 'Пошук MCC...' });
// MCC DESIGN SYSTEM v2 — append to Common.js
    var $btn  = $('<button>', { id: 'bannerSearchBtn', text: 'Пошук' });
// ==================================================


// --------------------------------------------------
     $container.append($input).append($btn);
// 1. АНІМАЦІЯ РЯДКІВ ПРИ СОРТУВАННІ ТАБЛИЦЬ
//    Хукається на jQuery tablesorter sortEnd
// --------------------------------------------------
$(function () {
    // Чекаємо поки tablesorter ініціалізується
     $(document).on('sortEnd', 'table.wikitable', function () {
        var $table = $(this);
        // Спочатку прибираємо анімацію
        $table.addClass('mcc-sorting').removeClass('mcc-sorted');
        // Після мікро-затримки запускаємо знову
        setTimeout(function () {
            $table.removeClass('mcc-sorting').addClass('mcc-sorted');
            // Прибираємо клас після завершення останньої анімації
            setTimeout(function () {
                $table.removeClass('mcc-sorted');
            }, 600);
        }, 20);
    });
});


// --------------------------------------------------
     function doSearch() {
// 2. ГОРИЗОНТАЛЬНИЙ СКРОЛ + ГРАДІЄНТ-ПІДКАЗКА
         var q = $input.val().trim();
//    Обгортає широкі таблиці в .mcc-scroll-outer
         if (q) window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(q);
// --------------------------------------------------
$(function () {
    // Класи таблиць, які треба загорнути
    var WIDE_SELECTORS = [
        '.wikitable.wide-table',      // існуючий клас
        '.mcc-wide',                  // новий клас для розмітки
        // Запис ігор — таблиця з класом full-width або в секції Запис ігор
        '.wikitable.full-width'
    ].join(', ');
 
     function wrapScrollable($table) {
        // Не загортаємо двічі
        if ($table.closest('.mcc-scroll-inner').length) return;
 
         var $outer = $('<div class="mcc-scroll-outer"></div>');
        var $inner = $('<div class="mcc-scroll-inner"></div>');
 
        $table.wrap($inner);
         $table.closest('.mcc-scroll-inner').wrap($outer);
 
        var $scrollEl = $table.closest('.mcc-scroll-inner');
        var $outerEl  = $scrollEl.closest('.mcc-scroll-outer');
 
        function checkFade() {
            var atEnd = $scrollEl[0].scrollLeft + $scrollEl[0].clientWidth >= $scrollEl[0].scrollWidth - 4;
            $outerEl.toggleClass('mcc-no-fade', atEnd);
        }
 
        $scrollEl.on('scroll', checkFade);
        checkFade();
     }
     }


    // Широкі таблиці (існуючі класи)
     $btn.on('click', doSearch);
     $(WIDE_SELECTORS).each(function () {
     $input.on('keydown', function (e) { if (e.keyCode === 13) { e.preventDefault(); doSearch(); } });
        wrapScrollable($(this));
    });
 
    // Таблиця "Запис ігор" — знаходимо по кількості колонок (> 8)
    $('.wikitable').each(function () {
        var $t = $(this);
        if ($t.closest('.mcc-scroll-inner').length) return; // вже загорнута
        var cols = $t.find('thead tr:first th').length;
        if (cols > 8) {
            $t.addClass('mcc-wide-table');
            wrapScrollable($t);
        }
    });
});
 
// --------------------------------------------------
// 3. ПІДСВІЧУВАННЯ ВІНРЕЙТУ В ТАБЛИЦЯХ
//    Автоматично додає клас .wr-hi / .wr-lo до клітинок %
// --------------------------------------------------
$(function () {
    $('.wikitable tbody tr').each(function () {
        var $cells = $(this).find('td');
        $cells.each(function () {
            var text = $(this).text().trim();
            // Якщо клітинка містить відсоток
            if (/^\d+(\.\d+)?%$/.test(text)) {
                var val = parseFloat(text);
                if (val >= 55) {
                    $(this).addClass('wr-hi');
                } else if (val <= 33) {
                    $(this).addClass('wr-lo');
                }
            }
        });
    });
});
 
// --------------------------------------------------
// 4. PROFILE ICONS — inactive якщо немає URL
//    (доповнює існуючий код, не замінює)
// --------------------------------------------------
$(function () {
    $('.profile-icon').each(function () {
        var $icon = $(this);
        var url  = $icon.attr('data-url') || '';
        if (!url.trim()) {
            $icon.addClass('inactive');
        }
    });
});
 
// ==================================================
// L-BOX NAVIGATION — замінює існуючий блок у Common.js
// ==================================================
$(function () {
 
     var $lbox = $('.l-box');
    if ($lbox.length === 0) return;
 
    var $items = $lbox.find('.l-box-item');
 
    // ── Будуємо карту секцій ──
    // Перераховуємо при кожному activate щоб врахувати
    // динамічний контент (таби, lazy load)
    function buildSectionMap() {
        var map = [];
        $items.each(function () {
            var target = $(this).data('target');
            if (target === 'top') {
                map.push({ $item: $(this), top: 0 });
            } else {
                // MediaWiki генерує id для h2 — пробіли замінює на _
                var $el = $('#' + target);
                if ($el.length) {
                    map.push({ $item: $(this), top: $el.offset().top });
                }
            }
        });
        // Сортуємо за позицією (на всяк випадок)
        map.sort(function (a, b) { return a.top - b.top; });
        return map;
    }
 
    // ── Оновлення активного пункту ──
    function updateActive(map) {
        var scrollY  = $(window).scrollTop() + 110; // offset для header
        var current  = null;
 
        for (var i = 0; i < map.length; i++) {
            if (map[i].top <= scrollY) {
                current = map[i].$item;
            }
        }
 
        $items.removeClass('active');
        if (current) current.addClass('active');
    }
 
    // ── Клік — скрол до секції ──
    $items.on('click', function () {
        var target = $(this).data('target');
 
        if (target === 'top') {
            $('html, body').animate({ scrollTop: 0 }, 280);
        } else {
            var $el = $('#' + target);
            if ($el.length) {
                var offset = $el.offset().top - 75;
                $('html, body').animate({ scrollTop: offset }, 280);
            }
        }
    });
 
    // ── Ініціалізація та підписка на scroll ──
    var sectionMap = buildSectionMap();
 
    // Перебудовуємо після можливого lazy-load (таби)
    $(document).on('mcc:content-loaded', function () {
        sectionMap = buildSectionMap();
        updateActive(sectionMap);
    });
 
    var ticking = false;
    $(window).on('scroll', function () {
        if (!ticking) {
            window.requestAnimationFrame(function () {
                updateActive(sectionMap);
                ticking = false;
            });
            ticking = true;
        }
    });
 
    // Перший виклик
    updateActive(sectionMap);
 
    // Перебудовуємо після resize (позиції можуть змінитись)
    $(window).on('resize', function () {
        sectionMap = buildSectionMap();
        updateActive(sectionMap);
    });
});
});

Версія за 15:17, 6 квітня 2026

// ============================================================
// MediaWiki:Common.js — Mafia Closed Circle
// Фінальна версія
// ============================================================

// ============================================================
// 1. RANDOM ARTICLES
// ============================================================
$(document).ready(function () {
    var apiUrl = mw.config.get('wgScriptPath') + '/api.php';
    $.getJSON(apiUrl, {
        action: 'query', format: 'json', list: 'random',
        rnnamespace: '0', rnlimit: '5',
        prop: 'extracts', exchars: '250', exlimit: 'max', explaintext: true
    }, function (data) {
        var html = '';
        $.each(data.query.random, function (i, article) {
            html += '<div class="random-article-preview">';
            html += '<h2><a href="/wiki/' + encodeURIComponent(article.title) + '">' + article.title + '</a></h2>';
            html += '</div>';
        });
        $('#random-articles-container').html(html);
    });
});

// ============================================================
// 2. L-BOX NAVIGATION
// ============================================================
$(function () {
    var $lbox = $('.l-box');
    if ($lbox.length === 0) return;

    var $items = $lbox.find('.l-box-item');

    function buildSectionMap() {
        var map = [];
        $items.each(function () {
            var target = $(this).data('target');
            if (target === 'top') {
                map.push({ $item: $(this), top: 0 });
            } else {
                var $el = $('#' + target);
                if ($el.length) {
                    map.push({ $item: $(this), top: $el.offset().top });
                }
            }
        });
        map.sort(function (a, b) { return a.top - b.top; });
        return map;
    }

    function updateActive(map) {
        var scrollY = $(window).scrollTop() + 110;
        var current = null;
        for (var i = 0; i < map.length; i++) {
            if (map[i].top <= scrollY) current = map[i].$item;
        }
        $items.removeClass('active');
        if (current) current.addClass('active');
    }

    $items.on('click', function () {
        var target = $(this).data('target');
        if (target === 'top') {
            $('html, body').animate({ scrollTop: 0 }, 280);
        } else {
            var $el = $('#' + target);
            if ($el.length) {
                $('html, body').animate({ scrollTop: $el.offset().top - 75 }, 280);
            }
        }
    });

    var sectionMap = buildSectionMap();

    $(document).on('mcc:content-loaded', function () {
        sectionMap = buildSectionMap();
        updateActive(sectionMap);
    });

    var ticking = false;
    $(window).on('scroll', function () {
        if (!ticking) {
            window.requestAnimationFrame(function () {
                updateActive(sectionMap);
                ticking = false;
            });
            ticking = true;
        }
    });

    $(window).on('resize', function () {
        sectionMap = buildSectionMap();
        updateActive(sectionMap);
    });

    updateActive(sectionMap);
});

// ============================================================
// 3. PROFILE ICONS — клік + inactive якщо немає URL
// ============================================================
$(document).ready(function () {
    $('.profile-icon').each(function () {
        var $icon = $(this);
        var url = ($icon.attr('data-url') || '').trim();

        if (url) {
            $icon.css('cursor', 'pointer');
            $icon.on('click', function () {
                window.open(url, '_blank');
            });
        } else {
            $icon.addClass('inactive');
        }
    });
});

// ============================================================
// 4. ДИНАМІЧНІ ПОСИЛАННЯ НА ГОЛОВНІЙ
// ============================================================
$(document).ready(function () {
    if (!$('body').hasClass('page-Головна_сторінка')) return;

    var block1Links = [{ title: 'Фінал Року', url: '/index.php/Фінал_Року' }];
    var block2Links = [
        { title: 'Перша статистика', url: '/index.php/Перша_статистика' },
        { title: 'Період',           url: '/index.php/Період' },
        { title: 'Друга статистика', url: '/index.php/Статистика' }
    ];
    var block3Links = [
        { title: 'Mafia Closed Cup I',        url: '/index.php/Mafia_Closed_Cup_I' },
        { title: 'Mafia Closed Cup I Online', url: '/index.php/Mafia_Closed_Cup_I_Online' },
        { title: 'My Closest Circle I',       url: '/index.php/My_Closest_Circle_I' }
    ];

    function rand(arr) { return arr[Math.floor(Math.random() * arr.length)]; }

    var $blocks = $('.home__block-image-block p');
    if ($blocks.length >= 3) {
        var l1 = rand(block1Links), l2 = rand(block2Links), l3 = rand(block3Links);
        $blocks.eq(0).html('<a href="' + l1.url + '">' + l1.title + '</a>');
        $blocks.eq(1).html('<a href="' + l2.url + '">' + l2.title + '</a>');
        $blocks.eq(2).html('<a href="' + l3.url + '">' + l3.title + '</a>');
    }
});

// ============================================================
// 5. PLAYER TABS + LAZY LOADING ІГОР
// ============================================================
$(function () {
    var $tabs     = $('.player-tab');
    var $contents = $('.player-tab-content');
    var $lbox     = $('.l-box');
    var $rbox     = $('.r-box');

    if ($tabs.length === 0) return;

    function isMobile() { return $(window).width() <= 768; }

    $tabs.on('click', function () {
        var $tab   = $(this);
        var tabId  = $tab.data('tab');
        var $content = $('#tab-' + tabId);

        $tabs.removeClass('active');
        $tab.addClass('active');
        $contents.removeClass('active');
        $content.addClass('active');

        // L-box — ховаємо на вкладці ігор
        if (tabId === 'games') {
            $lbox.fadeOut(200);
        } else {
            $lbox.fadeIn(200);
        }

        // R-box — на мобільних ховаємо при іграх
        if (isMobile()) {
            if (tabId === 'games') $rbox.slideUp(200);
            else                   $rbox.slideDown(200);
        }

        // Lazy load
        if (tabId === 'games' && !$content.data('loaded')) {
            var playerName = $content.data('player');
            if (!playerName) return;

            $content.html('<div class="tab-loader">Завантаження...</div>');

            $.ajax({
                url: mw.config.get('wgScriptPath') + '/api.php',
                data: {
                    action: 'expandtemplates', format: 'json',
                    text: '{{#invoke:FetchData|player_games|player=' + playerName + '}}',
                    prop: 'wikitext'
                },
                dataType: 'json',
                success: function (response) {
                    if (!response.expandtemplates || !response.expandtemplates.wikitext) return;

                    $.ajax({
                        url: mw.config.get('wgScriptPath') + '/api.php',
                        data: {
                            action: 'parse', format: 'json',
                            text: response.expandtemplates.wikitext,
                            contentmodel: 'wikitext',
                            disablelimitreport: true
                        },
                        dataType: 'json',
                        success: function (r) {
                            if (r.parse && r.parse.text) {
                                $content.html(r.parse.text['*']);
                                $content.data('loaded', true);
                                $content.find('table.sortable').tablesorter();

                                // Запускаємо пост-обробку для нового контенту
                                applyWinrateColors($content);
                                wrapWideTables($content);
                                $(document).trigger('mcc:content-loaded');
                            }
                        },
                        error: function () {
                            $content.html('<p style="color:#ff7777;text-align:center">Помилка завантаження.</p>');
                        }
                    });
                },
                error: function () {
                    $content.html('<p style="color:#ff7777;text-align:center">Помилка завантаження.</p>');
                }
            });
        }
    });

    $(window).on('resize', function () {
        if (!isMobile()) $rbox.show();
    });
});

// ============================================================
// 6. АНІМАЦІЯ РЯДКІВ ПРИ СОРТУВАННІ
// ============================================================
$(function () {
    $(document).on('sortEnd', 'table.wikitable', function () {
        var $t = $(this);
        $t.addClass('mcc-sorting').removeClass('mcc-sorted');
        setTimeout(function () {
            $t.removeClass('mcc-sorting').addClass('mcc-sorted');
            setTimeout(function () { $t.removeClass('mcc-sorted'); }, 600);
        }, 20);
    });
});

// ============================================================
// 7. ГОРИЗОНТАЛЬНИЙ СКРОЛ ДЛЯ ШИРОКИХ ТАБЛИЦЬ
// ============================================================
function wrapWideTables($context) {
    var $root = $context || $(document);

    function wrap($table) {
        if ($table.closest('.mcc-scroll-inner').length) return;

        $table.wrap('<div class="mcc-scroll-inner"></div>');
        $table.closest('.mcc-scroll-inner').wrap('<div class="mcc-scroll-outer"></div>');

        var $inner = $table.closest('.mcc-scroll-inner');
        var $outer = $inner.closest('.mcc-scroll-outer');

        function check() {
            var atEnd = $inner[0].scrollLeft + $inner[0].clientWidth >= $inner[0].scrollWidth - 4;
            $outer.toggleClass('mcc-no-fade', atEnd);
        }

        $inner.on('scroll', check);
        check();
    }

    // Явно задані широкі класи
    $root.find('.wikitable.wide-table, .wikitable.mcc-wide, .wikitable.full-width').each(function () {
        wrap($(this));
    });

    // Таблиці з >8 колонок (Запис ігор)
    $root.find('.wikitable').each(function () {
        var $t = $(this);
        if ($t.closest('.mcc-scroll-inner').length) return;
        if ($t.find('thead tr:first th').length > 8) {
            $t.addClass('mcc-wide-table');
            wrap($t);
        }
    });
}

$(function () { wrapWideTables(); });

// ============================================================
// 8. ВІНРЕЙТ — кольорове підсвічення клітинок з %
// ============================================================
function applyWinrateColors($context) {
    var $root = $context || $(document);
    $root.find('.wikitable tbody td').each(function () {
        var text = $(this).text().trim();
        if (/^\d+(\.\d+)?%$/.test(text)) {
            var val = parseFloat(text);
            if      (val >= 55) $(this).addClass('wr-hi');
            else if (val <= 33) $(this).addClass('wr-lo');
        }
    });
}

$(function () { applyWinrateColors(); });

// ============================================================
// 9. МОБІЛЬНИЙ ПОШУК
// ============================================================
$(function () {
    if ($(window).width() > 768) return;
    if ($('.mobile-search-btn').length > 0) return;

    var $btn = $('<div class="mobile-search-btn">' +
        '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2">' +
        '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg></div>');

    var $overlay = $('<div class="mobile-search-overlay">' +
        '<input type="text" placeholder="Пошук..." autocomplete="off">' +
        '<div class="mobile-search-close">×</div></div>');

    $('.minerva-header .branding-box').after($btn);
    $('body').append($overlay);

    var $input = $overlay.find('input');
    var $close = $overlay.find('.mobile-search-close');

    $btn.on('click', function (e) {
        e.preventDefault(); e.stopPropagation();
        $overlay.addClass('active');
        setTimeout(function () { $input.focus(); }, 100);
    });

    $close.on('click', function () {
        $overlay.removeClass('active'); $input.val('');
    });

    $input.on('keydown', function (e) {
        if (e.keyCode === 13) {
            var q = $input.val().trim();
            if (q) window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(q);
        }
        if (e.keyCode === 27) { $overlay.removeClass('active'); $input.val(''); }
    });

    $overlay.on('click', function (e) {
        if (e.target === this) { $overlay.removeClass('active'); $input.val(''); }
    });
});

// ============================================================
// 10. БЛОКУВАННЯ MINERVA SEARCH OVERLAY (ДЕСКТОП)
// ============================================================
$(function () {
    if ($(window).width() <= 768) return;

    var $searchInput = $('#searchInput');
    if ($searchInput.length === 0) return;

    setTimeout(function () {
        $searchInput.attr('placeholder', 'Пошук...');

        var $newInput = $searchInput.clone(false);
        $searchInput.replaceWith($newInput);
        $searchInput = $newInput;

        $searchInput.prop('readonly', false).removeAttr('readonly')
            .removeClass('skin-minerva-search-trigger');

        $searchInput.on('focus click', function (e) {
            e.stopPropagation();
            $('body').removeClass('overlay-enabled search-enabled');
            $('.overlay, .search-overlay').hide();
            if (window.location.hash === '#/search') {
                history.replaceState(null, null, window.location.pathname);
            }
        });

        $searchInput.on('keydown', function (e) {
            if (e.which === 13) {
                e.preventDefault();
                var q = $(this).val().trim();
                if (q) window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(q);
                return false;
            }
        });
    }, 100);

    $(window).on('hashchange', function () {
        if (window.location.hash === '#/search') {
            history.replaceState(null, null, window.location.pathname);
            $('body').removeClass('overlay-enabled search-enabled');
            $('.overlay, .search-overlay').hide();
        }
    });

    if (window.location.hash === '#/search') {
        history.replaceState(null, null, window.location.pathname);
    }
});

// ============================================================
// 11. BANNER SEARCH
// ============================================================
$(function () {
    var $container = $('#bannerSearchContainer');
    if ($container.length === 0) return;

    var $input = $('<input>', { type: 'text', id: 'bannerSearchInput', placeholder: 'Пошук MCC...' });
    var $btn   = $('<button>', { id: 'bannerSearchBtn', text: 'Пошук' });

    $container.append($input).append($btn);

    function doSearch() {
        var q = $input.val().trim();
        if (q) window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(q);
    }

    $btn.on('click', doSearch);
    $input.on('keydown', function (e) { if (e.keyCode === 13) { e.preventDefault(); doSearch(); } });
});