Filter beatmap by favorites (過濾 beatmap 依照收藏數) (osu! website only) (僅限 osu! 網站)
当前为
// ==UserScript==
// @name osu beatmap filter
// @namespace https://greasyfork.org/zh-TW/users/891293
// @version 0.2
// @description Filter beatmap by favorites (過濾 beatmap 依照收藏數) (osu! website only) (僅限 osu! 網站)
// @author Archer_Wn
// @match https://osu.ppy.sh/beatmapsets
// @match https://osu.ppy.sh/beatmapsets?*
// @grant none
// ==/UserScript==
// Options (選項)
const options = {
// global options (全域選項)
global: {
// opacity of filtered beatmap [0~1] (過濾後的 beatmap 透明度 [0~1])
opacity: 0.15,
},
// favorites filter (收藏數過濾)
favorites: {
// enable or disable [true/false] (啟用或停用 [true/false])
enable: true,
// favorites (收藏數)
favorites: 100,
},
};
(function () {
"use strict";
// wait for beatmapList loaded
waitForElement(".beatmapsets__items", 0).then(() => {
main();
});
// main function
function main() {
// get beatmap list
const beatmapList = document.querySelector(".beatmapsets__items");
// filter beatmap items that already loaded
const beatmapItems = beatmapList.querySelectorAll(".beatmapsets__item");
for (const beatmapItem of beatmapItems) {
const beatmapInfo = beatmapParser(beatmapItem);
filterBeatmap(beatmapItem, beatmapInfo);
}
// filter new beatmap items
new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type !== "childList") return;
if (mutation.addedNodes.length < 1) return;
for (const beatmapItem of mutation.addedNodes[0].querySelectorAll(
".beatmapsets__item"
)) {
const beatmapInfo = beatmapParser(beatmapItem);
filterBeatmap(beatmapItem, beatmapInfo);
}
});
}).observe(beatmapList, {
attributes: true,
childList: true,
subtree: true,
});
}
})();
/**
* Wait for an element before resolving a promise
* @param {String} querySelector - Selector of element to wait for
* @param {Integer} timeout - Milliseconds to wait before timing out, or 0 for no timeout
* @returns {Promise}
*
* @ref https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script
*/
function waitForElement(querySelector, timeout) {
return new Promise((resolve, reject) => {
var timer = false;
if (document.querySelectorAll(querySelector).length) return resolve();
const observer = new MutationObserver(() => {
if (document.querySelectorAll(querySelector).length) {
observer.disconnect();
if (timer !== false) clearTimeout(timer);
return resolve();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
if (timeout) {
timer = setTimeout(() => {
observer.disconnect();
reject();
}, timeout);
}
});
}
// beatmap parser
function beatmapParser(beatmapItem) {
const beatmapInfo = {};
// Extract necessary information
beatmapInfo.favoriteCount = parseInt(
beatmapItem.querySelectorAll(
".beatmapset-panel__stats-item--favourite-count span"
)[1].textContent
);
return beatmapInfo;
}
// filter beatmap
function filterBeatmap(beatmapItem, beatmapInfo) {
let setOpacity = false;
// filter by favorites
if (options.favorites.enable) {
if (beatmapInfo.favoriteCount < options.favorites.favorites) {
setOpacity = true;
}
}
// set opacity
if (setOpacity) {
beatmapItem.style.opacity = options.global.opacity;
}
}