Jump to content

User:Srilasyapragathi/tutorialFilter.js

From mediawiki.org

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
(function() {
    'use strict';
    if (mw.config.get('wgPageName') !== 'Wikimedia_tutorials') {
        return;
    }
    mw.hook('wikipage.content').add(function($content) {
        initTutorialsFilter($content);
    });

    function initTutorialsFilter($content) {
        if ($content.find('#tutorials-filter-container').length > 0) {
            return;
        }
        var topics = extractTopics($content);
        
        if (topics.length === 0) {
            console.log('No topics found on this page');
            return;
        }
        createFilterUI($content, topics);
        initializeFiltering($content, topics);
    }

    function extractTopics($content) {
        var topics = new Set();
 
        $content.find('[data-topic]').each(function() {
            var topicData = $(this).attr('data-topic');
            if (topicData) {
                var topicList = topicData.split(',');
                topicList.forEach(function(topic) {
                    var cleanTopic = topic.trim();
                    if (cleanTopic) {
                        topics.add(cleanTopic);
                    }
                });
            }
        });
        return Array.from(topics).sort();
    }

    function createFilterUI($content, topics) {
        var filterHTML = `
            <div id="tutorials-filter-container" style="
                background: #f8f9fa;
                border: 1px solid #a2a9b1;
                border-radius: 2px;
                padding: 15px;
                margin: 20px 0;
                box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            ">
                <h3 style="margin-top: 0; color: #0645ad;">Filter Tutorials by Topic</h3>
                
                <div style="margin-bottom: 15px;">
                    <input type="text" id="topic-search" placeholder="Search topics..." style="
                        width: 300px;
                        padding: 8px;
                        border: 1px solid #a2a9b1;
                        border-radius: 2px;
                        margin-right: 10px;
                    ">
                    <button id="clear-filters" style="
                        padding: 8px 15px;
                        background: #eaecf0;
                        border: 1px solid #a2a9b1;
                        border-radius: 2px;
                        cursor: pointer;
                    ">Clear All</button>
                </div>
                
                <div id="topic-filters" style="
                    max-height: 200px;
                    overflow-y: auto;
                    border: 1px solid #eaecf0;
                    padding: 10px;
                    background: white;
                    border-radius: 2px;
                ">
                    <!-- Topic checkboxes will be inserted here -->
                </div>
                
                <div id="filter-stats" style="
                    margin-top: 10px;
                    font-size: 0.9em;
                    color: #54595d;
                ">
                    <span id="visible-count">0</span> tutorials visible out of <span id="total-count">0</span>
                </div>
            </div>
        `;
        var $firstHeading = $content.find('h2').first();
        if ($firstHeading.length > 0) {
            $firstHeading.before(filterHTML);
        } else {
            $content.prepend(filterHTML);
        }
        var $topicFilters = $('#topic-filters');
        topics.forEach(function(topic) {
            var topicId = 'topic-' + topic.replace(/[^a-zA-Z0-9]/g, '-');
            var checkboxHTML = `
                <label style="
                    display: inline-block;
                    margin: 3px 10px 3px 0;
                    padding: 5px;
                    background: #f8f9fa;
                    border-radius: 3px;
                    cursor: pointer;
                    font-size: 0.9em;
                " title="Filter by ${topic}">
                    <input type="checkbox" id="${topicId}" data-topic="${topic}" style="margin-right: 5px;">
                    ${topic}
                </label>
            `;
            $topicFilters.append(checkboxHTML);
        });
    }

    function initializeFiltering($content, topics) {
        var $tutorials = getTutorialElements($content);
        var totalCount = $tutorials.length;
        $('#total-count').text(totalCount);
        $('#visible-count').text(totalCount);
        $('#topic-search').on('input', function() {
            var searchTerm = $(this).val().toLowerCase();
            $('#topic-filters label').each(function() {
                var topicText = $(this).text().toLowerCase();
                if (topicText.includes(searchTerm)) {
                    $(this).show();
                } else {
                    $(this).hide();
                }
            });
        });
        $('#clear-filters').on('click', function() {
            $('#topic-filters input[type="checkbox"]').prop('checked', false);
            $('#topic-search').val('');
            $('#topic-filters label').show();
            filterTutorials($content);
        });
        $('#topic-filters').on('change', 'input[type="checkbox"]', function() {
            filterTutorials($content);
        });
        $('#topic-filters').on('mouseenter', 'label', function() {
            var topic = $(this).find('input').data('topic');
            highlightTutorialsByTopic($content, topic, true);
        }).on('mouseleave', 'label', function() {
            removeHighlights($content);
        });
    }

    function getTutorialElements($content) {
        var $tutorials = $();
        $content.find('[data-topic]').each(function() {
            var $container = $(this).closest('.mw-tpl-colorbox, .mw-parser-output > div, section, .tutorial-item');
            
    
            if ($container.length === 0) {
                $container = $(this).closest('div, section').filter(function() {
                    return $(this).text().length > 50;
                });
                if ($container.length === 0) {
                    $container = $(this).closest('p, li, div');
                }
            }
            
            if ($container.length > 0 && $tutorials.index($container[0]) === -1) {
                $tutorials = $tutorials.add($container);
            }
        });

        return $tutorials;
    }

    function filterTutorials($content) {
        var selectedTopics = [];
        $('#topic-filters input[type="checkbox"]:checked').each(function() {
            selectedTopics.push($(this).data('topic'));
        });

        var $tutorials = getTutorialElements($content);
        var visibleCount = 0;

        $tutorials.each(function() {
            var $tutorial = $(this);
            var shouldShow = true;

            if (selectedTopics.length > 0) {
                shouldShow = false;
                var tutorialTopics = [];
                $tutorial.find('[data-topic]').each(function() {
                    var topicData = $(this).attr('data-topic');
                    if (topicData) {
                        var topics = topicData.split(',').map(function(t) { return t.trim(); });
                        tutorialTopics = tutorialTopics.concat(topics);
                    }
                });
                for (var i = 0; i < selectedTopics.length; i++) {
                    if (tutorialTopics.indexOf(selectedTopics[i]) !== -1) {
                        shouldShow = true;
                        break;
                    }
                }
            }

            if (shouldShow) {
                $tutorial.fadeIn(300);
                visibleCount++;
            } else {
                $tutorial.fadeOut(300);
            }
        });
        $('#visible-count').text(visibleCount);
    }

    function highlightTutorialsByTopic($content, topic, highlight) {
        if (highlight) {
            $content.find('[data-topic*="' + topic + '"]').closest(getTutorialElements($content).selector || 'div').each(function() {
                $(this).css({
                    'border': '2px solid #0645ad',
                    'border-radius': '4px',
                    'box-shadow': '0 0 8px rgba(6, 69, 173, 0.3)'
                });
            });
        }
    }

    function removeHighlights($content) {
        $content.find('*').css({
            'border': '',
            'border-radius': '',
            'box-shadow': ''
        });
    }
    mw.util.addCSS(`
        #tutorials-filter-container label:hover {
            background-color: #eaecf0 !important;
        }
        
        #tutorials-filter-container input[type="checkbox"]:checked + span {
            font-weight: bold;
        }
        
        .tutorial-highlight {
            border: 2px solid #0645ad !important;
            border-radius: 4px !important;
            box-shadow: 0 0 8px rgba(6, 69, 173, 0.3) !important;
        }
        
        @media (max-width: 768px) {
            #topic-search {
                width: 100% !important;
                margin-bottom: 10px !important;
            }
            
            #topic-filters {
                max-height: 150px !important;
            }
            
            #topic-filters label {
                display: block !important;
                margin: 5px 0 !important;
            }
        }
    `);

    console.log('Wikimedia Tutorials Filter script loaded successfully');

})();