Compare commits
14 Commits
v0.0.1-poc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0086202aa5 | ||
|
|
3c3a7c8180 | ||
|
|
036cf4df77 | ||
|
|
a802f7952d | ||
|
|
7239df4613 | ||
|
|
16c7158763 | ||
|
|
8b89c267e3 | ||
|
|
6b6564ba01 | ||
| c0f11aa940 | |||
| 7b7f516b7a | |||
| 6a254ef49f | |||
| 9a0a848850 | |||
| 4be078da65 | |||
|
|
3625ea3bda |
18
README.md
@ -1,14 +1,8 @@
|
|||||||
# Steam Workshop Janitor
|
# Steam Janitor
|
||||||
_A userscript that makes browsing through thousands of mods viable_
|
_A userscript that makes browsing mods viable_
|
||||||
|
|
||||||
## [Install 0.0.1](https://github.com/Jetsparrow/steam-workshop-janitor/raw/main/steam-workshop-janitor.user.js)
|
[Demo, install links](https://jetsparrow.github.io/steam-janitor/)
|
||||||
|
|
||||||
**N.B.: this is a very crude, hacked together proof of concept. It doesn't even have a way to undo the filtering yet.**
|
* Adds a "hide" button to all items on the workshop browse page. Hides item forever, until unhidden.
|
||||||
|
* Adds a "filter" checkbox to the top paging controls, allowing to switch between filtered and unfiltered view.
|
||||||
## Filter mods
|
* Adds endless scrolling to workshop browse pages.
|
||||||
|
|
||||||
Adds a little "filter mod" X button to any workshop browse page. Use it, and you will no longer see the hundreds of miscellaneous translations to laguages you don't know, obsolete mods, etc.
|
|
||||||
|
|
||||||
## Endless scrolling
|
|
||||||
|
|
||||||
After the filter runs its course, you will be left with barely any mods. Wndless scrolling fixes that.
|
|
||||||
3
_config.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
theme: jekyll-theme-midnight
|
||||||
|
title: Steam Janitor
|
||||||
|
description: A userscript that makes browsing mods viable
|
||||||
27
index.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<img src="https://user-images.githubusercontent.com/37241560/153679204-15e543d6-f45d-401c-90da-591694240515.png">
|
||||||
|
|
||||||
|
# [Steam Janitor v0.0.4-alpha - install](https://github.com/Jetsparrow/steam-janitor/raw/main/steam-janitor.user.js)
|
||||||
|
_Requires a userscript extension for your browser, e.g. [Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en)_
|
||||||
|
|
||||||
|
**N.B.: this is an early alpha. Tested only in Tampermonkey on Google Chrome**
|
||||||
|
|
||||||
|
# How to use
|
||||||
|
Navigate to the browse tab of your game's workshop (`steamcommunity.com/workshop/browse/?appid=###`) and use the new buttons on the workshop items.
|
||||||
|
<video src="https://user-images.githubusercontent.com/37241560/153673942-b35b53e9-4c88-4695-8631-855243251740.mp4" autoplay muted loop style="max-width: 480px;" ></video>
|
||||||
|
|
||||||
|
# Features
|
||||||
|
## Filter unwanted items
|
||||||
|
|
||||||
|
A "hide" button is added to every item on a workshop browse page.
|
||||||
|
Clicking it will hide the item forever - until you turn off the filter and unhide it.
|
||||||
|
Translations to laguages you don't know, obsolete mods, gachimuchi memes, and mods that are just not quite your cup of tea - hide once and never see them again.
|
||||||
|
|
||||||
|
The "filter" checkbox at the top paging controls allows you to switch between the filtered and unfiltered view.
|
||||||
|
|
||||||
|
## Endless scrolling
|
||||||
|
|
||||||
|
After the filter runs its course, you will be left with barely any mods. Endless scrolling fixes that.
|
||||||
|
|
||||||
|
## Download button
|
||||||
|
|
||||||
|
Download the workshop item directly from the web as a .zip archive
|
||||||
BIN
res/filter_toggle_closed.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
res/filter_toggle_open.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
res/janitor_download.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
res/janitor_download_hover.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
res/janitor_hide.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
res/janitor_hide_hover.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
res/janitor_unhide.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
res/janitor_unhide_hover.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
res/source/filter_toggle.psd
Normal file
BIN
res/source/janitor_buttons.psd
Normal file
289
steam-janitor.user.js
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
// ==UserScript==
|
||||||
|
// @name Steam Janitor
|
||||||
|
// @namespace jetsparrow-steam-janitor
|
||||||
|
// @author Jetsparrow
|
||||||
|
// @description Hide unwanted user content in browse view, endless scrolling, downloads
|
||||||
|
// @match *://*.steamcommunity.com/workshop/browse/*
|
||||||
|
// @run-at document-end
|
||||||
|
// @version 0.0.4
|
||||||
|
// @grant GM_setValue
|
||||||
|
// @grant GM_getValue
|
||||||
|
// @grant GM_xmlhttpRequest
|
||||||
|
// @grant GM_download
|
||||||
|
// @connect ggntw.com
|
||||||
|
// @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",
|
||||||
|
downloadButton: "janitorDownloadButton"
|
||||||
|
};
|
||||||
|
|
||||||
|
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",
|
||||||
|
btnDownload:"https://jetsparrow.github.io/steam-janitor/res/janitor_download.png",
|
||||||
|
btnDownloadHover:"https://jetsparrow.github.io/steam-janitor/res/janitor_download_hover.png",
|
||||||
|
};
|
||||||
|
|
||||||
|
const janitorCss = `
|
||||||
|
.${cssClass.filterToggle} * { vertical-align: middle; }
|
||||||
|
|
||||||
|
.${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}")}
|
||||||
|
.workshopItem .${cssClass.hideButton} { visibility: hidden; }
|
||||||
|
.workshopItem:hover .${cssClass.hideButton} { visibility: visible; position: absolute; top: 4px; right: 6px;}
|
||||||
|
|
||||||
|
.${cssClass.downloadButton} {width:25px; height:25px;}
|
||||||
|
.${cssClass.downloadButton}:hover {background-image:url("${resource.btnDownloadHover}")}
|
||||||
|
.${cssClass.downloadButton} {background-image:url("${resource.btnDownload}")}
|
||||||
|
.workshopItem .${cssClass.downloadButton} { visibility: hidden; }
|
||||||
|
.workshopItem:hover .${cssClass.downloadButton} { visibility: visible; position: absolute; top: 4px; right: 35px;}
|
||||||
|
`;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
|
||||||
|
// Update classes on mod container when model changes
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When pressing the hide/unhide button on mod container
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When pressing the download button on mod container
|
||||||
|
const downloadMod = (doc, modId) => {
|
||||||
|
const id = modId.replace("sharedfile_", "");
|
||||||
|
GM_xmlhttpRequest(
|
||||||
|
{
|
||||||
|
url:"https://api.ggntw.com/steam.request",
|
||||||
|
method: "POST",
|
||||||
|
data: JSON.stringify(
|
||||||
|
{
|
||||||
|
url:"https://steamcommunity.com/sharedfiles/filedetails/?id=" + id
|
||||||
|
}),
|
||||||
|
headers:
|
||||||
|
{
|
||||||
|
"Content-type": "application/json; charset=UTF-8"
|
||||||
|
},
|
||||||
|
onload: function(response)
|
||||||
|
{
|
||||||
|
if (response.status>299) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
const res = JSON.parse(response.responseText);
|
||||||
|
console.log(res);
|
||||||
|
const name = res.url.substring(res.url.lastIndexOf('/') + 1);
|
||||||
|
GM_download(res.url, name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add hide butons to mod container
|
||||||
|
const addJanitorButtons = (doc, container, id) => {
|
||||||
|
const hideButton = htmlToElement(doc, `<div class="${cssClass.hideButton}"> </>`);
|
||||||
|
hideButton.onclick = (e) => {
|
||||||
|
e.cancelBubble = true;
|
||||||
|
toggleHidden(document, id);
|
||||||
|
};
|
||||||
|
container.append(hideButton);
|
||||||
|
|
||||||
|
const downloadButton = htmlToElement(doc, `<div class="${cssClass.downloadButton}"> </>`);
|
||||||
|
downloadButton.onclick = (e) => {
|
||||||
|
e.cancelBubble = true;
|
||||||
|
downloadMod(document, id);
|
||||||
|
};
|
||||||
|
container.append(downloadButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all loaded mod containers, update their visibility and add janitor buttons if necessary
|
||||||
|
const processContainers = (doc) => {
|
||||||
|
const filterOn = GM_getValue(setting.filterEnabled);
|
||||||
|
for (var el of doc.querySelectorAll(selector.ITEM_CONTAINER)){
|
||||||
|
const container = el.parentElement.parentElement;
|
||||||
|
const id = el.id;
|
||||||
|
updateHiddenClass(doc, id, filterOn);
|
||||||
|
|
||||||
|
if (container.janitorButtonsAdded) continue;
|
||||||
|
container.janitorButtonsAdded = true;
|
||||||
|
addJanitorButtons(doc, container, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadNextPage = (url) => {
|
||||||
|
fetch(url, { credentials: "same-origin" })
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(html => {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const newDoc = parser.parseFromString(html, "text/html");
|
||||||
|
processContainers(newDoc);
|
||||||
|
|
||||||
|
const newMods = newDoc.querySelectorAll(selector.ITEM_CONTAINER);
|
||||||
|
const modContainer = document.querySelector(selector.ITEMS_CONTAINER);
|
||||||
|
for (const mod of newMods) {
|
||||||
|
const container = mod.parentElement.parentElement;
|
||||||
|
modContainer.appendChild(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
const scripts = newDoc.querySelectorAll(selector.ITEMS_HOVERS);
|
||||||
|
for (const newScript of scripts){
|
||||||
|
const matches = newScript.innerHTML.match(/(sharedfile_\d+)/);
|
||||||
|
if (matches.length < 1) continue;
|
||||||
|
const data = loadModData(matches[0]);
|
||||||
|
if (data.hide) continue;
|
||||||
|
eval("try{ "+ newScript.innerHTML + " } catch {} ");
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextUrl = newDoc.querySelector(selector.NEXT_BUTTON)?.getAttribute("href");
|
||||||
|
const footer = document.getElementById(elemId.scrollTarget);
|
||||||
|
if (nextUrl) onVisible(footer, loadNextPage.bind(null, nextUrl));
|
||||||
|
window.history.pushState("", "", url);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// When the global filter toggle is pressed
|
||||||
|
function toggleFilter(checkbox) {
|
||||||
|
GM_setValue(setting.filterEnabled, checkbox.checked);
|
||||||
|
const doc = checkbox.ownerDocument;
|
||||||
|
doc.getElementById(elemId.filterToggleOff).hidden = checkbox.checked;
|
||||||
|
doc.getElementById(elemId.filterToggleOn).hidden = !checkbox.checked;
|
||||||
|
processContainers(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// main
|
||||||
|
(() => {
|
||||||
|
const load = () => {
|
||||||
|
addGlobalStyle(document, janitorCss);
|
||||||
|
|
||||||
|
document.querySelector(selector.PAGE_INFO)?.remove();
|
||||||
|
const filterToggleRoot = document.querySelector(selector.PAGING_INFO);
|
||||||
|
const toggle = htmlToElement(document, `
|
||||||
|
<div class="${cssClass.filterToggle}">
|
||||||
|
|
||||||
|
<input type="checkbox" id="${elemId.filterToggleCheckbox}">
|
||||||
|
|
||||||
|
<label for="${elemId.filterToggleCheckbox}">
|
||||||
|
<img src="${resource.iconEyeOpen}" id="${elemId.filterToggleOff}">
|
||||||
|
<img src="${resource.iconEyeClosed}" id="${elemId.filterToggleOn}">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
const checkbox = toggle.children[0];
|
||||||
|
checkbox.checked = GM_getValue(setting.filterEnabled, true);
|
||||||
|
checkbox.onclick = () => toggleFilter(checkbox);
|
||||||
|
filterToggleRoot.prepend(toggle);
|
||||||
|
toggleFilter(checkbox);
|
||||||
|
processContainers(document);
|
||||||
|
|
||||||
|
const nextUrl = document.querySelector(selector.NEXT_BUTTON)?.getAttribute("href");
|
||||||
|
if (!nextUrl) {
|
||||||
|
console.error(`Could not find nextUrl through "${selector.NEXT_BUTTON}"`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadNextPage(nextUrl);
|
||||||
|
|
||||||
|
document.querySelector(selector.PAGINATOR)?.remove();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
load();
|
||||||
|
})();
|
||||||
@ -1,156 +0,0 @@
|
|||||||
// ==UserScript==
|
|
||||||
// @name Steam Workshop Janitor
|
|
||||||
// @description Hide unwanted mods in the browse view, endless scrolling
|
|
||||||
// @match *://*.steamcommunity.com/workshop/browse/*
|
|
||||||
// @run-at document-end
|
|
||||||
// @version 0.0.1
|
|
||||||
// @grant GM_setValue
|
|
||||||
// @grant GM_getValue
|
|
||||||
// @updateURL https://raw.githubusercontent.com/Jetsparrow/steam-workshop-janitor/main/steam-workshop-janitor.js
|
|
||||||
// @downloadURL https://raw.githubusercontent.com/Jetsparrow/steam-workshop-janitor/main/steam-workshop-janitor.js
|
|
||||||
// ==/UserScript==
|
|
||||||
|
|
||||||
const selectors = {
|
|
||||||
ITEM_CONTAINER: ".workshopBrowseItems .workshopItemPreviewHolder",
|
|
||||||
ITEMS_CONTAINER: ".workshopBrowseItems",
|
|
||||||
ITEMS_HOVERS: ".workshopBrowseItems script",
|
|
||||||
NEXT_BUTTON: ".workshopBrowsePagingControls .pagebtn:last-child",
|
|
||||||
PAGINATOR: ".workshopBrowsePagingControls"
|
|
||||||
};
|
|
||||||
|
|
||||||
function htmlToElement(doc, html) {
|
|
||||||
var template = doc.createElement('template');
|
|
||||||
html = html.trim(); // Never return a text node of whitespace as the result
|
|
||||||
template.innerHTML = html;
|
|
||||||
return template.content.firstChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
const on_visible = (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);
|
|
||||||
};
|
|
||||||
|
|
||||||
function defaultModData()
|
|
||||||
{
|
|
||||||
var res = new Object();
|
|
||||||
res.hide = false;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
function loadModData(id){
|
|
||||||
var j = GM_getValue("modid:" + id, "");
|
|
||||||
return j == "" ? defaultModData() : JSON.parse(j);
|
|
||||||
}
|
|
||||||
function saveModData(id, data){
|
|
||||||
GM_setValue("modid:" + id, JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function hideId(id){
|
|
||||||
var d = loadModData(id);
|
|
||||||
d.hide = true;
|
|
||||||
saveModData(id, d);
|
|
||||||
var elem = document.getElementById(id);
|
|
||||||
if (elem){
|
|
||||||
elem.parentElement.parentElement.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sweepHidden(doc){
|
|
||||||
var containers = doc.querySelectorAll(selectors.ITEM_CONTAINER);
|
|
||||||
for (var container of containers)
|
|
||||||
{
|
|
||||||
var id = container.id;
|
|
||||||
var data = loadModData(id);
|
|
||||||
if (data.hide){
|
|
||||||
container.parentElement.parentElement.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addButtonToElement(doc, elem){
|
|
||||||
var janitorButton = htmlToElement(doc, `<a>X</a>`)
|
|
||||||
let id = elem.id;
|
|
||||||
janitorButton.onclick = function(){hideId(id);};
|
|
||||||
elem.parentElement.parentElement.prepend(janitorButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addButtons(doc){
|
|
||||||
var containers = doc.querySelectorAll(selectors.ITEM_CONTAINER);
|
|
||||||
for (var container of containers){
|
|
||||||
addButtonToElement(doc, container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const load_next = (url) => {
|
|
||||||
fetch(url, { credentials: "same-origin" })
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
const parser = new DOMParser();
|
|
||||||
const newDoc = parser.parseFromString(html, "text/html");
|
|
||||||
|
|
||||||
sweepHidden(newDoc);
|
|
||||||
addButtons(newDoc);
|
|
||||||
|
|
||||||
const newPaginator = newDoc.querySelector(selectors.PAGINATOR);
|
|
||||||
const oldPaginator = document.querySelector(selectors.PAGINATOR);
|
|
||||||
const pagParent = oldPaginator.parentElement;
|
|
||||||
oldPaginator.remove();
|
|
||||||
pagParent.append(newPaginator);
|
|
||||||
|
|
||||||
const newMods = newDoc.querySelectorAll(selectors.ITEM_CONTAINER);
|
|
||||||
const lastMod = newMods[newMods.length - 1];
|
|
||||||
|
|
||||||
const modContainer = document.querySelector(selectors.ITEMS_CONTAINER);
|
|
||||||
for (var mod of newMods) {
|
|
||||||
var container = mod.parentElement.parentElement;
|
|
||||||
modContainer.appendChild(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
const scripts = newDoc.querySelectorAll(selectors.ITEMS_HOVERS);
|
|
||||||
for (var newScript of scripts){
|
|
||||||
var matches = newScript.innerHTML.match(/(sharedfile_\d+)/);
|
|
||||||
if (matches.length < 1) continue;
|
|
||||||
var data = loadModData(matches[0]);
|
|
||||||
if (data.hide) continue;
|
|
||||||
eval("try{ "+ newScript.innerHTML + " } catch {} ");
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextButton = document.querySelector(selectors.NEXT_BUTTON);
|
|
||||||
|
|
||||||
if (lastMod && nextButton) {
|
|
||||||
const nextUrl = nextButton.getAttribute("href");
|
|
||||||
on_visible(lastMod, load_next.bind(null, nextUrl));
|
|
||||||
}
|
|
||||||
|
|
||||||
window.history.pushState("", "", url);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
(() => {
|
|
||||||
const load = () => {
|
|
||||||
const next_button = document.querySelector(selectors.NEXT_BUTTON);
|
|
||||||
|
|
||||||
if (!next_button) {
|
|
||||||
console.error(`Could not find "${selectors.NEXT_BUTTON}"`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sweepHidden(document);
|
|
||||||
addButtons(document);
|
|
||||||
|
|
||||||
const nextUrl = next_button.getAttribute("href");
|
|
||||||
load_next(nextUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
load();
|
|
||||||
})();
|
|
||||||