User:Polygnotus/Scripts/NamespaceFilter.js: Difference between revisions

Content deleted Content added
Created page with '// <nowiki> // ==UserScript== // @name Wikipedia Namespace Filter // @namespace http://tampermonkey.net/ // @version 0.1 // @description Filter special page results by namespace // @match https://*.wikipedia.org/w/index.php?title=Special:LinkSearch* // @grant none // ==/UserScript== (function() { 'use strict'; function addStyles() { const style = document.createElement('style'); style.textContent = `...'
 
 
(7 intermediate revisions by the same user not shown)
Line 1:
// Very janky and not intended for real world use, does not make API calls just filters whatever is there on the page (so use limit=5000).
// <nowiki>
// I have requested something better:
// ==UserScript==
// https://meta.wikimedia.org/wiki/Community_Wishlist/Wishes/Add_Namespace_filter_to_all_Special:_pages_(where_applicable)
// @name Wikipedia Namespace Filter
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Filter special page results by namespace
// @match https://*.wikipedia.org/w/index.php?title=Special:LinkSearch*
// @grant none
// ==/UserScript==
 
(function() {
'use strict';
 
const STORAGE_KEY = 'wikipediaNamespaceFilter';
const ARTICLE_NAMES_ONLY_KEY = 'wikipediaArticleNamesOnly';
 
function addStyles() {
Line 23 ⟶ 20:
#namespace-filter label {
margin-right: 10px;
display: inline-block;
// @grant none }
#all-none-options, #display-options {
margin-bottom: 10px;
}
#all-none-options button {
margin-right: 10px;
}
.article-name-only .external {
display: none;
}
`;
Line 29 ⟶ 36:
 
function getNamespaces() {
const namespaces = new Set(['Main']);
document.querySelectorAll('ol.special li a:nth-child(2)').forEach(link => {
const text = link.textContent;
const namespacecolonIndex = text.splitindexOf(':')[0];
if (namespacecolonIndex && namespace !=== text-1) {
namespaces.add(namespace'Main');
} else {
const namespace = text.substring(0, colonIndex);
if (namespace) {
namespaces.add(namespace);
}
}
});
return Array.from(namespaces).sort((a, b) => a === 'Main' ? -1 : b === 'Main' ? 1 : a.localeCompare(b));
}
 
Line 44 ⟶ 56:
filterDiv.id = 'namespace-filter';
filterDiv.innerHTML = '<h4>Filter by namespace:</h4>';
 
// Add All/None options
const allNoneDiv = document.createElement('div');
allNoneDiv.id = 'all-none-options';
const allButton = document.createElement('button');
allButton.textContent = 'Select All';
allButton.addEventListener('click', () => setAllCheckboxes(true));
const noneButton = document.createElement('button');
noneButton.textContent = 'Select None';
noneButton.addEventListener('click', () => setAllCheckboxes(false));
allNoneDiv.appendChild(allButton);
allNoneDiv.appendChild(noneButton);
filterDiv.appendChild(allNoneDiv);
 
// Add Article Names Only option
const displayOptionsDiv = document.createElement('div');
displayOptionsDiv.id = 'display-options';
const articleNamesOnlyLabel = document.createElement('label');
const articleNamesOnlyCheckbox = document.createElement('input');
articleNamesOnlyCheckbox.type = 'checkbox';
articleNamesOnlyCheckbox.id = 'article-names-only';
articleNamesOnlyCheckbox.checked = localStorage.getItem(ARTICLE_NAMES_ONLY_KEY) === 'true';
articleNamesOnlyCheckbox.addEventListener('change', toggleArticleNamesOnly);
articleNamesOnlyLabel.appendChild(articleNamesOnlyCheckbox);
articleNamesOnlyLabel.appendChild(document.createTextNode('Show Article Names Only'));
displayOptionsDiv.appendChild(articleNamesOnlyLabel);
filterDiv.appendChild(displayOptionsDiv);
 
const savedFilters = getSavedFilters();
 
namespaces.forEach(namespace => {
Line 50 ⟶ 91:
checkbox.type = 'checkbox';
checkbox.value = namespace;
checkbox.checked = savedFilters ? savedFilters.includes(namespace) : true;
checkbox.addEventListener('change', filterResults(); => {
filterResults();
saveFilters();
});
label.appendChild(checkbox);
label.appendChild(document.createTextNode(namespace));
Line 59 ⟶ 103:
const ol = document.querySelector('ol.special');
ol.parentNode.insertBefore(filterDiv, ol);
 
// Apply initial article names only setting
toggleArticleNamesOnly();
}
 
function setAllCheckboxes(checked) {
document.querySelectorAll('#namespace-filter input[type="checkbox"]').forEach(cb => {
if (cb.id !== 'article-names-only') {
cb.checked = checked;
}
});
filterResults();
saveFilters();
}
 
function filterResults() {
const checkedNamespaces = Array.from(document.querySelectorAll('#namespace-filter input:checked:not(#article-names-only)')).map(cb => cb.value);
document.querySelectorAll('ol.special li').forEach(li => {
const link = li.querySelector('a:nth-child(2)');
const text = link.textContent;
const namespacecolonIndex = text.splitindexOf(':')[0];
ifconst (checkedNamespaces.includes(namespace) ||= !namespace || namespacecolonIndex === -1 ? 'Main' : text).substring(0, {colonIndex);
if (checkedNamespaces.includes(namespace)) {
li.style.display = '';
} else {
Line 73 ⟶ 131:
}
});
}
 
function toggleArticleNamesOnly() {
const isChecked = document.getElementById('article-names-only').checked;
document.querySelector('ol.special').classList.toggle('article-name-only', isChecked);
localStorage.setItem(ARTICLE_NAMES_ONLY_KEY, isChecked);
}
 
function saveFilters() {
const checkedNamespaces = Array.from(document.querySelectorAll('#namespace-filter input:checked:not(#article-names-only)')).map(cb => cb.value);
localStorage.setItem(STORAGE_KEY, JSON.stringify(checkedNamespaces));
}
 
function getSavedFilters() {
const savedFilters = localStorage.getItem(STORAGE_KEY);
return savedFilters ? JSON.parse(savedFilters) : null;
}
 
Line 80 ⟶ 154:
addStyles();
createFilterUI(namespaces);
filterResults(); // Apply filters on initial load
}
}