// ==UserScript== // @name Steam Janitor // @namespace jetsparrow-steam-janitor // @author Jetsparrow // @description Hide unwanted user content in browse view, endless scrolling // @match *://*.steamcommunity.com/workshop/browse/* // @run-at document-end // @version 0.0.3 // @grant GM_setValue // @grant GM_getValue // @downloadURL https://jetsparrow.github.io/steam-janitor/steam-janitor.user.js // ==/UserScript== const addGlobalStyle = (doc, css) => { let head = doc.getElementsByTagName('head')[0]; if (!head) return null; let style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); return style; } const htmlToElement = (doc, html) => { var template = doc.createElement('template'); template.innerHTML = html.trim(); return template.content.firstChild; } const onVisible = (element, callback) => { const observer = new IntersectionObserver( (entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { callback(); observer.unobserve(entry.target); } }); }, { rootMargin: "0px 0px 200px 0px" } ); observer.observe(element); }; const selector = { PAGING_INFO: ".workshopBrowsePagingWithBG", ITEM_CONTAINER: ".workshopBrowseItems .workshopItemPreviewHolder", ITEMS_CONTAINER: ".workshopBrowseItems", ITEMS_HOVERS: ".workshopBrowseItems script", NEXT_BUTTON: ".workshopBrowsePagingControls .pagebtn:last-child", PAGINATOR: ".workshopBrowsePagingControls", PAGE_INFO: ".workshopBrowsePagingInfo", FOOTER: ".workshopBrowsePaging", }; const elemId = { scrollTarget: "footer", filterToggleCheckbox: "janitorFilterToggleCheckbox", filterToggleOn: "janitorFilterOnIcon", filterToggleOff: "janitorFilterOffIcon", }; const cssClass = { unhidden: "janitorItem", hiddenFiltered: "janitorItemHidden", hiddenUnfiltered: "janitorItemHiddenUnfiltered", hideButton: "janitorHideButton", showButton: "janitorShowButton", filterToggle: "janitorFilterToggle", hideButton: "janitorhideButton" }; const resource = { iconEyeOpen:"https://jetsparrow.github.io/steam-janitor/res/filter_toggle_open.png", iconEyeClosed:"https://jetsparrow.github.io/steam-janitor/res/filter_toggle_closed.png", btnHide:"https://jetsparrow.github.io/steam-janitor/res/janitor_hide.png", btnHideHover:"https://jetsparrow.github.io/steam-janitor/res/janitor_hide_hover.png", btnUnhide:"https://jetsparrow.github.io/steam-janitor/res/janitor_unhide.png", btnUnhideHover:"https://jetsparrow.github.io/steam-janitor/res/janitor_unhide_hover.png", }; const janitorCss = ` .${cssClass.hiddenFiltered} {display:none !important; } .${cssClass.hiddenUnfiltered} img {opacity: 0.25;} .${cssClass.hideButton} {width:25px; height:25px;} .${cssClass.hiddenUnfiltered} .${cssClass.hideButton}:hover {background-image:url("${resource.btnUnhideHover}")} .${cssClass.hiddenUnfiltered} .${cssClass.hideButton} {background-image:url("${resource.btnUnhide}")} .${cssClass.unhidden} .${cssClass.hideButton}:hover {background-image:url("${resource.btnHideHover}")} .${cssClass.unhidden} .${cssClass.hideButton} {background-image:url("${resource.btnHide}")} .${cssClass.filterToggle} * { vertical-align: middle; } .workshopItem .${cssClass.hideButton} { visibility: hidden; position: absolute; top: 4px; right: 6px; } .workshopItem:hover .${cssClass.hideButton} { visibility: visible; position: absolute; top: 4px; right: 6px;} `; const setting = { filterEnabled: "janitorFilterEnabled" }; const defaultModData = () => { let d = new Object(); d.hide = false; return d; } const loadModData = (modId) => { var j = GM_getValue("modid:" + modId, ""); return j == "" ? defaultModData() : JSON.parse(j); } const saveModData = (modId, data) => GM_setValue("modid:" + modId, JSON.stringify(data)); const updateHiddenClass = (doc, modId, filterOn) => { var container = doc.getElementById(modId)?.parentElement?.parentElement; if (!container) return; const d = loadModData(modId); container.classList.remove(cssClass.unhidden); container.classList.remove(cssClass.hiddenFiltered); container.classList.remove(cssClass.hiddenUnfiltered); if (!d.hide) container.classList.add(cssClass.unhidden); else if (filterOn) container.classList.add(cssClass.hiddenFiltered); else container.classList.add(cssClass.hiddenUnfiltered); } const toggleHidden = (doc, modId) => { var d = loadModData(modId); d.hide = !d.hide; saveModData(modId, d); const filterOn = GM_getValue(setting.filterEnabled); updateHiddenClass(doc, modId, filterOn); } const addHideButtons = (doc, container, id) => { const controls = htmlToElement(doc, `