NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @namespace https://openuserjs.org/users/Seishiin
// @name SteamWorkshopSearch
// @description Allows you to search for specific mods in your list of subscribed items
// @author Seishiin
// @version 1.5
// @copyright 2019, Seishiin
// @license MIT
// @include /https:\/\/steamcommunity\.com\/id\/.*\/myworkshopfiles\/\?appid=\d+.*&browsefilter=mysubscriptions.*/
// @icon https://img.icons8.com/color/48/000000/steam.png
// @grant none
// @noframes
// ==/UserScript==
(function () {
let iframeNextPage = null;
let iframeAllMods = null;
let currentPage = 1;
const leftContents = document.getElementById("leftContents");
let modList = null;
const css = `
#searchBar {
width: 251px;
padding-left: 8px;
padding-right: 8px;
background: #101822;
border-color: #30485c;
}
#loader {
width: 16px;
height: 16px;
position: relative;
bottom: 24px;
right: 3px;
float: right;
border: 4px solid;
border-radius: 50%;
border-color: rgb(160, 220, 240) rgb(65, 95, 125) rgb(65, 95, 125);
animation: spin 2s linear infinite;
}
@keyframes spin {
0% {transform: rotate(0deg);}
100% {transform: rotate(360deg);}
}
`;
///////////////////////
// Utility functions //
///////////////////////
RegExp.escape = function (s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
function getTotalPages() {
let pageinfo = document.getElementsByClassName("workshopBrowsePagingInfo")[0].innerText;
pageinfo = pageinfo.substring(pageinfo.indexOf("of") + 3, pageinfo.length);
pageinfo = pageinfo.substring(0, pageinfo.indexOf("entries") - 1);
// totalPages = Math.ceil(pageinfo / 30);
return Math.ceil(pageinfo / 30);
}
//////////////////////
// Search functions //
//////////////////////
function searchMods(e) {
let searchTerm = e.srcElement.value;
let modsFound = 0;
// escape special characters so it doesn't break the search
searchTerm = RegExp.escape(searchTerm);
// hide all mods currently displayed
for (let i = 0; i < leftContents.childElementCount; i++) {
if (leftContents.children[i].className.includes("workshopItemSubscription")) {
leftContents.children[i].style.display = "none";
}
}
// add mods matching the search string
for (let i = 0; i < modList.length; i++) {
modsFound = getSearchedMods(modList[i], searchTerm, modsFound);
}
// update the page info to display the amount of items shown correctly
document.getElementsByClassName("workshopBrowsePagingInfo")[0].innerText = "Showing " + modsFound + " of " + modList.length + " entries";
modsFound = 0;
}
function getSearchedMods(mod, searchTerm, modsFound) {
// get the title of the mod
let modTitle = mod.children[1].children[2].children[0].children[0].innerText;
// show only divs containing the search term
let regex = new RegExp(searchTerm, "i");
if (regex.test(modTitle)) {
document.getElementById(mod.id).style.display = "";
modsFound++;
}
return modsFound;
}
//////////////////////////////////////
// Modlist initialization functions //
//////////////////////////////////////
function initializeModList(totalPages) {
// create an iframe to load the next page with mods
iframeNextPage = document.createElement("iframe");
iframeNextPage.style.display = "none";
// go through each page and insert all mods into "iframeAllMods"
iframeNextPage.addEventListener("load", function () {
let currentModList = this.contentWindow.document.getElementsByClassName("workshopItemSubscription");
for (let i = 0; i < currentModList.length; i++) {
iframeAllMods.contentWindow.document.body.append(currentModList[i]);
}
// append the modlist after it has beend completely initialized
if (currentPage > totalPages) {
appendModList();
}
if (currentPage <= totalPages) {
updateIFrameSource();
}
});
document.body.appendChild(iframeNextPage);
// create an iframe to store all mods loaded in "iframeNextPage"
iframeAllMods = document.createElement("iframe");
iframeAllMods.style.display = "none";
iframeAllMods.src = "about:blank";
document.body.appendChild(iframeAllMods);
}
// change the url of "iframeNextPage" to the next page
function updateIFrameSource() {
let baseURL
if (iframeNextPage.baseURI.includes("&p="))
baseURL = iframeNextPage.baseURI.substring(0, iframeNextPage.baseURI.indexOf("&p="));
else
baseURL = iframeNextPage.baseURI;
iframeNextPage.src = baseURL + "&p=" + currentPage + "&numperpage=30";
currentPage++;
}
function appendModList() {
// load mods into the list
modList = iframeAllMods.contentWindow.document.getElementsByClassName("workshopItemSubscription");
// remove all mods from the list
for (let i = 0; i < leftContents.childElementCount; i++) {
if (leftContents.children[i].className.includes("workshopItemSubscription")) {
// if we do it only once it doesn't work
leftContents.children[i].remove();
leftContents.children[i].remove();
}
}
// insert all mods from modList into the website
// modList = iframeAllMods.contentWindow.document.getElementsByClassName("workshopItemSubscription");
for (let i = 0; i < modList.length; i++) {
// if we don't clone this, the corresponding element gets removed from modList
let clone = modList[i].cloneNode(true);
leftContents.append(clone);
}
// update the paging info
document.getElementsByClassName("workshopBrowsePagingInfo")[0].innerText = "Showing " + modList.length + " of " + modList.length + " entries";
// activate the searchbar and hide the loader after the modlist is loaded
document.getElementById("searchBar").disabled = false;
document.getElementById("loader").style.display = "none";
}
////////////////////////////////
// DOM modification functions //
////////////////////////////////
function hideMods() {
for (let i = 0; i < leftContents.childElementCount; i++) {
if (leftContents.children[i].className.includes("workshopItemSubscription")) {
leftContents.children[i].style.display = "none"
}
}
}
// remove the workshop banner and paginators + hrs, update the paging info
function modifyDivs() {
document.getElementsByClassName("workshopBrowsePagingControls")[0].style.display = "none";
document.getElementsByClassName("workshopBrowsePaging")[0].remove();
document.getElementsByClassName("greyHR2")[1].remove();
document.getElementsByClassName("greyHR2")[0].remove();
document.getElementsByClassName("workshopBrowsePagingWithBG")[0].style.marginBottom = "11px";
document.getElementsByClassName("workshopBrowsePagingInfo")[0].innerText = "Loading modlist...";
}
function addSearchbar() {
let searchBar = document.createElement("input");
searchBar.className = "searchTextContainer";
searchBar.id = "searchBar"
searchBar.disabled = true;
searchBar.addEventListener("input", searchMods);
document.getElementsByClassName("rightSectionHolder")[4].appendChild(searchBar);
}
function addLoader() {
// keyframe animation
let style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
document.head.appendChild(style);
// loader
let loader = document.createElement("div");
loader.id = "loader";
document.getElementsByClassName("workshopBrowsePagingWithBG")[0].appendChild(loader);
}
//////////////////
// Start script //
//////////////////
function init() {
// get the total amount of page if showing 30 items per page
let totalPages = getTotalPages();
// remove and update some divs
modifyDivs();
// hide mods before loading the modlist to avoid confusion
hideMods();
document.getElementsByClassName("rightSectionTopTitle")[0].innerText = "Search for mods:";
document.getElementsByClassName("rightDetailsBlock")[3].remove();
addSearchbar();
// inform the user that the modlist is still loading
addLoader();
// after all that is done start loading the mods
initializeModList(totalPages);
}
window.addEventListener('load', function () {
init()
}, false);
})();