// ==UserScript== // @name GreasyFork Bullshit Filter - for TS Citrus Gfork // @namespace darkred // @version 2020.7.31 // @description Hides scripts for popular browser games and social networks as well as scripts that use "foreign" characters in descriptions. Applies to posts in Forum too. // @author kuehlschrank, darkred, valacar, Graphen // @license MIT // @icon https://raw.githubusercontent.com/darkred/Userscripts/master/GreasyFork_Bullshit_Filter_-_for_TS_Citrus_Gfork/large.png // @include /^https:\/\/(greasy|sleazy)fork\.org\/(.*\/)?(scripts|discussions|users).*$/ // @exclude /^https:\/\/(greasy|sleazy)fork\.org\/(.*\/)?(scripts\/[0-9]+.*(? .filter-switches { display: block !important; position: fixed; top: calc(1.7%); left: calc(14%); } .filter-on, .filter-off { display: block !important; width: 105px; } .filter-switches a { text-decoration: none !important; color: inherit; cursor: pointer; } .filter-switches a { margin-left: 8px; padding: 0 4px; } a.filter-on { background-color: #ea6e6e; color: #333333; text-decoration: line-through !important; } a.filter-off { background-color: #6da46b; color: #333333; } `; const isOnForum = /discussions|feedback/.test(window.location.href); const site = {}; if (isOnForum) { site.css = '.discussion-list-item.filtered { display: none; } .filter-on, .filter-off { color: black; } ' + commonCss; site.cssDebug = '.discussion-list-item.filtered { background-color: khaki !important; } ' + commonCss; site.filterStatusLocation = '#main-header'; site.itemsToCheck = '.discussion-list-item'; site.itemType = 'discussions'; site.removeFilter = function(el) { el.classList.remove('filtered'); }; site.applyFilter = function(el, activeFilter) { let temp = el.children[1].innerText; if(temp && temp.match(activeFilter)) { el.classList.add('filtered'); return true; } return false; }; } else { // Is in script listings site.css = 'tr.filtered, li.filtered { display: none; } ' + commonCss; site.cssDebug = 'tr.filtered td, li.filtered { background-color: khaki !important; } ' + commonCss; site.filterStatusLocation = '#main-header'; site.itemsToCheck = `tbody > tr > td > div.thetitle, #browse-script-list > li`; site.itemType = 'scripts'; site.removeFilter = function(el) { if (window.location.href.indexOf('/libraries') === -1) { el.parentNode.parentNode.classList.remove('filtered'); } else { el.classList.remove('filtered'); } }; site.applyFilter = function(el, activeFilter) { if (window.location.href.indexOf('/libraries') === -1) { var temp = el.parentNode.firstChild.firstChild.textContent + ' ' + el.parentNode.lastChild.textContent; // store script's name and description (with a space between) to variable 'temp' } else { temp = el.getAttribute('data-script-name') + ' ' + el.firstElementChild.firstElementChild.children[3].innerText; } if (temp && temp.match(activeFilter)) { if (window.location.href.indexOf('/libraries') === -1) { el.parentNode.parentNode.classList.add('filtered'); } else { el.classList.add('filtered'); } return true; } return false; }; } insertStyle(); insertStatus(); filterScripts(); insertSwitches(); if (!isOnForum){ const target = document.querySelector('#script-table > tbody:nth-child(2)'); const observer = new MutationObserver((mutations) => { insertStyle(); if (!document.querySelector('.filter-status')){ insertStatus(); } filterScripts(); if (!document.querySelector('.filter-switches')){ insertSwitches(); } }), config = { childList: true, subtree: true, }; observer.observe(target, config); } function insertStyle() { const style = document.createElement('style'); style.textContent = DEBUGGING ? site.cssDebug : site.css; style.type = 'text/css'; document.head.appendChild(style); } function insertStatus() { const p = document.querySelector(site.filterStatusLocation); if (p) { const status = document.createElement('span'); status.className = 'filter-status'; p.appendChild(status); } } function filterScripts() { const activeFilters = []; for (let filterType of Object.keys(filters)) { if (configGetValue(filterType, 'on') === 'on') { activeFilters.push(filters[filterType]); } } const nodes = document.querySelectorAll(site.itemsToCheck); let numFiltered = 0; for (let node of nodes) { site.removeFilter(node); for (let activeFilter of activeFilters) { let filtered = site.applyFilter(node, activeFilter); if (filtered) { numFiltered++; break; } } } const filterStatus = document.querySelector('.filter-status'); if (filterStatus) { const numUnfiltered = document.querySelectorAll(site.itemsToCheck).length - numFiltered; filterStatus.textContent = `${numUnfiltered} ${site.itemType} (${numFiltered} filtered)`; } } function insertSwitches() { const span = document.createElement('span'); span.className = 'filter-switches'; for (let filterType of Object.keys(filters)) { span.appendChild(createSwitch(filterType, configGetValue(filterType, 'on') === 'on')); } const filterStatus = document.querySelector('.filter-status'); if (filterStatus) { filterStatus.parentNode.appendChild(span); } } function createSwitch(label, isOn) { const a = document.createElement('a'); a.className = isOn ? 'filter-on' : 'filter-off'; a.textContent = label; a.addEventListener('click', function(e) { if (this.className === 'filter-on') { this.className = 'filter-off'; configSetValue(this.textContent, 'off'); } else { this.className = 'filter-on'; configSetValue(this.textContent, 'on'); } filterScripts(); e.preventDefault(); }, false); return a; } function configSetValue(name, value) { localStorage.setItem(name, value); } function configGetValue(name, defaultValue) { const value = localStorage.getItem(name); return value ? value : defaultValue; } })();