User:Srilasyapragathi/tutorialFilter.js
Appearance
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');
})();