-
// ==UserScript==
-
// @name MLPFicReviews Extras
-
// @namespace http://ponepaste.org/5555
-
// @version 0.2
-
// @description Adds a few handy functions to mlpficreviews.org.uk
-
// @author Fillyanon
-
// @match http://www.mlpficreviews.org.uk/*
-
// @grant none
-
// ==/UserScript==
-
-
-
const style = `
-
body {
-
background-image: url("https://u.smutty.horse/mdqwfehyeeo.png");
-
background-attachment: fixed;
-
background-repeat: no-repeat;
-
background-size: 100%;
-
}
-
-
.page {
-
width: 1100px;
-
background: #eef2ff;
-
padding: 0;
-
}
-
-
h1 {
-
text-align: center;
-
font-size: 2.5rem;
-
padding: 1rem;
-
background: hsl(60, 60%, 90%);
-
}
-
-
h1::before {
-
content: url("https://static.fimfiction.net/images/logo-2x.png");
-
display: block;
-
}
-
-
a {
-
text-decoration: none;
-
}
-
-
h2 {
-
margin-top: 1rem;
-
text-align: center;
-
}
-
-
.sorter {
-
margin: 1rem auto;
-
display: block;
-
width: min-content;
-
}
-
-
.sorter button {
-
width: 100%;
-
height: 1.5rem;
-
}
-
-
ul {
-
position:relative;
-
display: grid;
-
grid-template-columns: repeat(3, calc(33% - 0.5rem));
-
/*grid-auto-rows: 1fr; ̇*/
-
grid-gap: 1rem;
-
margin-top: 1.5rem !important;
-
margin-bottom: 1rem !important;
-
padding-left: 1rem !important;
-
padding-right: 0.8rem !important;
-
}
-
-
.entries li {
-
margin: 0;
-
border: 1.5px solid hsl(60, 20%, 80%);
-
}
-
-
.entries li > a {
-
background: hsl(60, 20%, 90%);
-
border-bottom: 1px solid hsl(60, 20%, 80%);
-
display: block;
-
overflow: hidden;
-
text-overflow: ellipsis;
-
white-space: nowrap;
-
font-size: 18px;
-
padding: 0.3rem 0.2rem;
-
-
text-decoration: none;
-
}
-
-
.entries li sup a {
-
display: inline;
-
float: right;
-
}
-
-
li small {
-
display: block;
-
padding: 0.3rem 0.2rem;
-
background: #efefef;
-
}
-
-
li {
-
position: relative;
-
}
-
-
li .intro {
-
width: 100%;
-
box-sizing: border-box;
-
position: absolute;
-
height: 0;
-
text-overflow: hidden;
-
overflow: hidden;
-
z-index: 1;
-
border: 1px solid hsl(60, 20%, 80%);
-
-
background: #efefef;
-
-
margin: 0;
-
padding: 0;
-
-
transition: height 1s ease-in-out, padding 0.1s ease-out 1s, z-index 0s ease-out 1s;
-
}
-
-
li:hover .intro
-
{
-
height: 15rem;
-
z-index: 2;
-
-
padding: 0.4rem 0.2rem;
-
-
transition: height 1s ease-in-out, padding 0.1s ease-out 0s, z-index 0s ease-out 0s;
-
}
-
-
/* Review */
-
-
h2 ~ p {
-
text-align: center;
-
}
-
-
dt {
-
text-align: center;
-
margin-bottom: 0.5rem;
-
margin-top: 1.5rem;
-
}
-
-
dd {
-
margin: 0;
-
}
-
-
blockquote {
-
margin: 0;
-
text-align: justify;
-
padding-left: 1rem;
-
padding-right: 1rem;
-
}
-
-
blockquote br {
-
margin-bottom: 0.5rem;
-
}
-
`
-
-
const getIntro = async (url) =>
-
{
-
const content = await fetch(url).then(res => res.text())
-
const parser = new DOMParser()
-
const page = parser.parseFromString(content, "text/html")
-
-
const quote = page.querySelector("blockquote").innerText.trim().split(" ").filter(e => e)
-
const intro = quote.splice(0, Math.min(50, quote.length))
-
-
return intro.join(" ") + "..."
-
}
-
-
const addIntroLoader = () =>
-
{
-
const entryUL = document.querySelector(".entries")
-
const entries = [...entryUL.querySelectorAll("li")]
-
-
entries.forEach(entry =>
-
{
-
const p = document.createElement("p")
-
p.innerText = "Loading...";
-
p.className = "intro";
-
entry.appendChild(p)
-
-
let timeout = null;
-
-
entry.addEventListener("mouseover", () =>
-
{
-
if (entry.className.indexOf("handled") == -1)
-
{
-
const url = entry.querySelector("a").getAttribute("href");
-
-
if (localStorage.getItem(url) !== null)
-
{
-
entry.className += " handled"
-
p.innerText = localStorage.getItem(url);
-
}
-
else
-
{
-
timeout = setTimeout(() => {
-
entry.className += " handled"
-
getIntro(url).then(intro => {
-
p.innerText = intro;
-
localStorage.setItem(url, intro);
-
})
-
}, 500)
-
}
-
}
-
})
-
-
entry.addEventListener("mouseout", () =>
-
{
-
if (timeout !== null) clearTimeout(timeout)
-
})
-
})
-
}
-
-
const sortType = Object.freeze(
-
{
-
ALPHABETICAL: "Sort alphabetically",
-
DATENEW: "Sort by Date (Newest first)",
-
DATEOLD: "Sort by Date (Oldest first)",
-
COMMENTSMANY: "Sort by Most Comments",
-
COMMENTSFEW: "Sort by Least Comments",
-
}
-
)
-
-
const getSort = (elem, type) =>
-
{
-
switch (type)
-
{
-
case sortType.ALPHABETICAL:
-
return elem.querySelector("a").innerText;
-
-
case sortType.DATENEW:
-
return -Number(elem.querySelector("a").getAttribute("href").split("/")[2]);
-
-
case sortType.DATEOLD:
-
return Number(elem.querySelector("a").getAttribute("href").split("/")[2]);
-
-
case sortType.COMMENTSMANY:
-
return -Number(elem.querySelector("small").innerText.substring(1).split(" ")[0]);
-
-
case sortType.COMMENTSFEW:
-
return Number(elem.querySelector("small").innerText.substring(1).split(" ")[0]);
-
}
-
-
console.warn("Bad sortType!");
-
}
-
-
const injectStyle = () =>
-
{
-
const styleElem = document.createElement("style");
-
styleElem.innerText = style;
-
document.head.appendChild(styleElem);
-
}
-
-
const addSortBar = () =>
-
{
-
const page = document.querySelector(".page")
-
const entryUL = document.querySelector(".entries")
-
const entries = [...entryUL.querySelectorAll("li")]
-
-
let isSorted = false;
-
let isReverse = true;
-
-
const select = document.createElement("select");
-
-
for (let value of Object.values(sortType))
-
{
-
const option = document.createElement("option");
-
option.setAttribute("value", value);
-
option.innerText = value;
-
select.appendChild(option);
-
}
-
-
select.value = window.localStorage.getItem("selected") ?? sortType.DATENEW
-
-
const button = document.createElement("button")
-
button.textContent = "Sort"
-
-
button.addEventListener("click", () =>
-
{
-
entries.sort((first, second) => {
-
const f = getSort(first, select.value)
-
const s = getSort(second, select.value)
-
-
if (select.value != sortType.ALPHABETICAL)
-
return Math.sign(f - s)
-
-
return f.localeCompare(s);
-
})
-
-
while (entryUL.firstChild)
-
{
-
entryUL.firstChild.remove()
-
}
-
-
entries.forEach(e => entryUL.appendChild(e))
-
window.localStorage.setItem("selected", select.value)
-
})
-
-
button.click()
-
-
const div = document.createElement("div");
-
div.className = "sorter";
-
-
div.appendChild(select);
-
div.appendChild(button);
-
-
page.insertBefore(div, entryUL)
-
}
-
-
const fixLinks = () =>
-
{
-
const links = document.querySelectorAll("a");
-
-
links.forEach(link => {
-
const url = link.getAttribute("href")?.split("/")
-
if (url !== undefined && url[2] == "boards.4chan.org")
-
{
-
url[2] = "desuarchive.org";
-
-
// replace quote anchor's p with q for desuarchive.org
-
let anchor = url[url.length-1].split("#");
-
anchor[1] = "q" + anchor[1].substring(1)
-
url[url.length-1] = anchor.join("#")
-
-
link.setAttribute("href", url.join("/"))
-
}
-
})
-
}
-
-
const makeHeader = () =>
-
{
-
const lis = [...document.querySelectorAll(".entries li")];
-
const length = lis.length
-
const totalReviews = lis.map(e => Number(e.querySelector("small").innerText.split(" ")[0].split("(")[1])).reduce((prev, curr) => prev+curr)
-
-
document.querySelector("h2").innerHTML+= `<br><small>(${length} Fics / ${totalReviews} Reviews)</small>`
-
}
-
-
(function() {
-
'use strict';
-
-
injectStyle(style);
-
-
if (window.location.toString().split("/").length == 4)
-
{
-
addSortBar();
-
addIntroLoader();
-
makeHeader();
-
}
-
else
-
{
-
fixLinks()
-
}
-
})();
740 8.14 KB 356
by Fillyanon
by Fillyanon
by Fillyanon
by Fillyanon
by Fillyanon