MediaWiki:Common.js: відмінності між версіями

нема опису редагування
Немає опису редагування
Немає опису редагування
Рядок 325: Рядок 325:
// 7. ФІЛЬТРИ НАД ТАБЛИЦЕЮ ІГОР
// 7. ФІЛЬТРИ НАД ТАБЛИЦЕЮ ІГОР
// ============================================================
// ============================================================
// 7b. BUILD GAMES FILTERS — простий надійний варіант
// 7b. BUILD GAMES FILTERS
// Завжди вставляє фільтри на початок $container
// ============================================================
// ============================================================
function buildGamesFilters($container, $table) {
function buildGamesFilters($container, $table) {
     // Collect events
 
    // Already added?
    if ($container.find('.mcc-games-filters').length) return;
 
    // Find table if not valid
    if (!$table || !$table.length) {
        $table = $container.find('table').first();
    }
    if (!$table.length) return;
 
    // Use ALL tr rows (with or without tbody)
    var $rows = $table.find('tr').filter(function () {
        return $(this).find('td').length > 0; // only data rows
    });
 
    if (!$rows.length) return;
 
     // Collect unique events from first td
     var events = [];
     var events = [];
     if ($table && $table.length) {
     $rows.each(function () {
        $table.find('tbody tr').each(function () {
        var ev = $(this).find('td').first().text().trim();
            var ev = $(this).find('td').eq(0).text().trim();
        if (ev && events.indexOf(ev) === -1) events.push(ev);
            if (ev && events.indexOf(ev) === -1) events.push(ev);
    });
        });
    }


    // Build event options
     var opts = '<option value="">Всі події</option>';
     var opts = '<option value="">Всі події</option>';
     events.forEach(function (e) {
     events.forEach(function (e) {
Рядок 343: Рядок 358:
     });
     });


     // Build filter bar and PREPEND to container
     // Build the filter bar HTML
     var $bar = $([
     var barHTML = '<div class="mcc-games-filters">'
        '<div class="mcc-games-filters" style="display:flex">',
         + '<div class="mcc-filter-group">'
         '<div class="mcc-filter-group">',
         '<span class="mcc-filter-label">Подія</span>'
         ' <span class="mcc-filter-label">Подія</span>',
         '<select class="mcc-filter-select mcc-fe">' + opts + '</select>'
         ' <select class="mcc-filter-select mcc-fe">' + opts + '</select>',
         + '</div>'
         '</div>',
         + '<div class="mcc-filter-group">'
         '<div class="mcc-filter-group">',
         '<span class="mcc-filter-label">Роль</span>'
         ' <span class="mcc-filter-label">Роль</span>',
         '<select class="mcc-filter-select mcc-fr">'
         ' <select class="mcc-filter-select mcc-fr">',
         +    '<option value="">Всі ролі</option>'
         '   <option value="">Всі ролі</option>',
         +    '<option value="Мир">Мирний</option>'
         '   <option value="Мир">Мирний</option>',
         +    '<option value="Шер">Шериф</option>'
         '   <option value="Шер">Шериф</option>',
         +    '<option value="Маф">Мафія</option>'
         '   <option value="Маф">Мафія</option>',
         +    '<option value="Дон">Дон</option>'
         '   <option value="Дон">Дон</option>',
         '</select>'
         ' </select>',
         + '</div>'
         '</div>',
         + '<div class="mcc-filter-group">'
         '<div class="mcc-filter-group">',
         '<span class="mcc-filter-label">Результат</span>'
         ' <span class="mcc-filter-label">Результат</span>',
         '<select class="mcc-filter-select mcc-frr">'
         ' <select class="mcc-filter-select mcc-frr">',
         +    '<option value="">Всі</option>'
         '   <option value="">Всі</option>',
         +    '<option value="В">Перемога</option>'
         '   <option value="В">Перемога</option>',
         +    '<option value="П">Поразка</option>'
         '   <option value="П">Поразка</option>',
         '</select>'
         ' </select>',
         + '</div>'
         '</div>',
         + '<div class="mcc-filter-group mcc-duration-group">'
         '<div class="mcc-filter-group mcc-duration-group">',
         '<span class="mcc-filter-label">Макс. тривалість</span>'
         ' <span class="mcc-filter-label">Макс. тривалість</span>',
         '<div class="mcc-slider-wrap">'
         ' <div class="mcc-slider-wrap">',
         +    '<input type="range" class="mcc-duration-range mcc-dur-rng" min="20" max="75" value="75" step="1">'
         '   <input type="range" class="mcc-duration-range mcc-dur-rng" min="20" max="75" value="75" step="1">',
         +    '<span class="mcc-slider-val mcc-dur-v">75:00</span>'
         '   <span class="mcc-slider-val mcc-dur-v">75:00</span>',
         '</div>'
         ' </div>',
         + '</div>'
         '</div>',
         + '<span class="mcc-filter-count mcc-fcnt"></span>'
         '<span class="mcc-filter-count mcc-fcnt"></span>',
         + '</div>';
         '</div>'
    ].join(''));


     // Prepend to tab content (always visible, before any table)
     // Insert at the very top of the container
     $container.prepend($bar);
     $container.prepend(barHTML);


     if (!$table || !$table.length) return;
     // Get reference to the just-added bar
    var $bar = $container.find('.mcc-games-filters').first();


     function toMins(s) {
     function toMins(s) {
         s = (s || '').trim();
         s = (s || '').trim();
         var m1 = s.match(/^(\d+):(\d+)$/);   if (m1) return +m1[1] + +m1[2]/60;
         var m1 = s.match(/^(\d+):(\d+)$/);
         var m2 = s.match(/(\d+)\s*хв\s*(\d+)/); if (m2) return +m2[1] + +m2[2]/60;
        if (m1) return parseInt(m1[1]) + parseInt(m1[2]) / 60;
         var m2 = s.match(/(\d+)\s*[хh]\s*[вv]\s*(\d+)/);
        if (m2) return parseInt(m2[1]) + parseInt(m2[2]) / 60;
         return 999;
         return 999;
     }
     }


     function doFilter() {
     function doFilter() {
         var ev  = $bar.find('.mcc-fe').val();
         var ev  = $bar.find('.mcc-fe').val() || '';
         var rol = $bar.find('.mcc-fr').val();
         var rol = $bar.find('.mcc-fr').val() || '';
         var res = $bar.find('.mcc-frr').val();
         var res = $bar.find('.mcc-frr').val() || '';
         var dur = +$bar.find('.mcc-dur-rng').val();
         var dur = parseFloat($bar.find('.mcc-dur-rng').val()) || 75;
         var n = 0;
         var n = 0;
         $table.find('tbody tr').each(function () {
 
             var td  = $(this).find('td');
         $rows.each(function () {
             var show = (!ev || td.eq(0).text().trim().indexOf(ev!== -1)
             var $tds = $(this).find('td');
                    && (!rol || td.eq(1).text().trim().indexOf(rol) !== -1)
             var evVal  = $tds.eq(0).text().trim();
                     && (!res || td.eq(3).text().trim().indexOf(res) !== -1)
            var rolVal = $tds.eq(1).text().trim();
                     && toMins(td.eq(2).text()) <= dur;
            var timeVal = $tds.eq(2).text().trim();
            var resVal = $tds.eq(3).text().trim();
 
            var show = (ev  === '' || evVal.indexOf(ev)   !== -1)
                     && (rol === '' || rolVal.indexOf(rol) !== -1)
                    && (res === '' || resVal.indexOf(res) !== -1)
                     && toMins(timeVal) <= dur;
 
             $(this).toggle(show);
             $(this).toggle(show);
             if (show) n++;
             if (show) n++;
Рядок 410: Рядок 433:


     $bar.find('.mcc-dur-rng').on('input', function () {
     $bar.find('.mcc-dur-rng').on('input', function () {
         var v = +$(this).val();
         var v = parseFloat($(this).val());
         $bar.find('.mcc-dur-v').text(v + ':00');
         $bar.find('.mcc-dur-v').text(v + ':00');
         $(this).css('background-size', ((v - 20) / 55 * 100) + '% 100%');
         $(this).css('background-size', ((v - 20) / 55 * 100) + '% 100%');
         doFilter();
         doFilter();
     });
     });
     $bar.find('select').on('change', doFilter);
     $bar.find('select').on('change', doFilter);
     $bar.find('.mcc-fcnt').text($table.find('tbody tr').length + '\u00a0ігор');
     $bar.find('.mcc-fcnt').text($rows.length + '\u00a0ігор');
     $bar.find('.mcc-dur-rng').css('background-size', '100% 100%');
     $bar.find('.mcc-dur-rng').css('background-size', '100% 100%');
}
}
Рядок 642: Рядок 666:
     function setRboxTop() {
     function setRboxTop() {
         var $hdr = $('.header-container.header-chrome');
         var $hdr = $('.header-container.header-chrome');
         var h = $hdr.length ? $hdr[0].getBoundingClientRect().bottom : 64;
         var h = $hdr.length ? ($hdr.outerHeight() + 4) : 66;
        h = Math.max(h, 56);
         $('.r-box, .tournament-box, .series-box').css('top', h + 'px');
         $('.r-box, .tournament-box, .series-box').css('top', h + 'px');
     }
     }
     // Run after full paint
     setRboxTop();
     setTimeout(setRboxTop, 0);
     setTimeout(setRboxTop, 300);
     $(window).on('resize', setRboxTop);
     $(window).on('resize', setRboxTop);
});
});
Рядок 751: Рядок 774:
         history.replaceState(null, null, window.location.pathname);
         history.replaceState(null, null, window.location.pathname);
});
});


// ============================================================
// ============================================================
// 17. BANNER SEARCH
// FILTERS FOR SEASON "Запис ігор" WIDE TABLE
// Runs on page load for static wiki tables
// ============================================================
// ============================================================
$(function () {
$(function () {
     var $container = $('#bannerSearchContainer');
    // Target the wide game records table on season/tournament pages
     if (!$container.length) return;
    var $table = $('.wikitable.wide-table').first();
    if (!$table.length) $table = $('.wikitable.full-width').first();
    if (!$table.length) return;
 
    // Collect rows (with or without tbody)
     var $rows = $table.find('tr').filter(function () {
        return $(this).find('td').length > 0;
    });
     if (!$rows.length) return;


     var $input = $('<input>', { type:'text', id:'bannerSearchInput', placeholder:'Пошук MCC...' });
     var results = [];
     var $btn  = $('<button>', { id:'bannerSearchBtn', text:'Пошук' });
    $rows.each(function () {
     $container.append($input).append($btn);
        var tds = $(this).find('td');
        // Result is second-to-last td (before the record button)
        var r = tds.eq(tds.length - 2).text().trim();
        if (r && results.indexOf(r) === -1) results.push(r);
    });
 
    // Build filter bar
    var resOpts = '<option value="">Всі результати</option>';
    results.forEach(function (r) {
        resOpts += '<option value="' + r + '">' + r + '</option>';
    });
 
     var $bar = $(
        '<div class="mcc-games-filters">' +
        '<div class="mcc-filter-group">' +
        '<span class="mcc-filter-label">Результат</span>' +
        '<select class="mcc-filter-select sg-res">' + resOpts + '</select>' +
        '</div>' +
        '<div class="mcc-filter-group mcc-duration-group">' +
        '<span class="mcc-filter-label">Макс. тривалість</span>' +
        '<div class="mcc-slider-wrap">' +
        '<input type="range" class="mcc-duration-range sg-dur" min="30" max="65" value="65" step="1">' +
        '<span class="mcc-slider-val sg-durv">65:00</span>' +
        '</div>' +
        '</div>' +
        '<span class="mcc-filter-count sg-cnt"></span>' +
        '</div>'
    );
 
    // Insert before the table's scroll wrapper (or table itself)
    var $target = $table.closest('.mcc-scroll-outer, .mcc-scroll-inner');
     ($target.length ? $target : $table).before($bar);
 
    function toMins(s) {
        s = (s || '').trim();
        var m = s.match(/(\d+)\s*хв\s*(\d+)/);
        if (m) return parseInt(m[1]) + parseInt(m[2]) / 60;
        m = s.match(/^(\d+):(\d+)$/);
        if (m) return parseInt(m[1]) + parseInt(m[2]) / 60;
        return 999;
    }


     function doSearch() {
     function doFilter() {
         var q = $input.val().trim();
         var res = $bar.find('.sg-res').val();
         if (q) window.location.href = '/index.php?title=Спеціальна:Пошук&search=' + encodeURIComponent(q);
        var dur = parseInt($bar.find('.sg-dur').val());
         var n = 0;
        $rows.each(function () {
            var tds = $(this).find('td');
            var timeVal = tds.eq(0).text().trim();
            var resVal  = tds.eq(tds.length - 2).text().trim();
            var show = (!res || resVal === res) && toMins(timeVal) <= dur;
            $(this).toggle(show);
            if (show) n++;
        });
        $bar.find('.sg-cnt').text(n + '\u00a0ігор');
     }
     }
     $btn.on('click', doSearch);
 
     $input.on('keydown', function (e) { if (e.keyCode === 13) { e.preventDefault(); doSearch(); } });
     $bar.find('.sg-dur').on('input', function () {
        var v = parseInt($(this).val());
        $bar.find('.sg-durv').text(v + ':00');
        $(this).css('background-size', ((v - 30) / 35 * 100) + '% 100%');
        doFilter();
    });
 
     $bar.find('.sg-res').on('change', doFilter);
    $bar.find('.sg-cnt').text($rows.length + '\u00a0ігор');
    $bar.find('.sg-dur').css('background-size', '100% 100%');
});
});
// ============================================================
// 17. BANNER SEARCH