Skip to content

Instantly share code, notes, and snippets.

@Kethsar
Last active December 3, 2021 02:44
Show Gist options
  • Save Kethsar/6c3d9a821d53c00286aec7d863d869c2 to your computer and use it in GitHub Desktop.
Save Kethsar/6c3d9a821d53c00286aec7d863d869c2 to your computer and use it in GitHub Desktop.
Request window user script for meguca
// ==UserScript==
// @name Meguca Request Window
// @namespace KethRequest
// @version 0.5
// @description Show all requests that start with /r/
// @author Kethsar
// @match https://meguca.org/a/*
// @match https://megu.ca/a/*
// @match https://shamiko.org/a/*
// @match https://shamik.ooo/a/*
// @match https://monm.ooo/a/*
// @match https://suwak.ooo/a/*
// @match https://dind.in/a/*
// @match https://mcdoogle.cafe/a/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
var body = document.getElementsByTagName("body")[0],
html = document.getElementsByTagName("html")[0],
reqdiv = document.createElement("div"),
reqhead = document.createElement("div"),
reqbody = document.createElement("div"),
closeBtn = document.createElement("button"),
reqbottom = document.createElement("div"),
reqtable = document.createElement("table"),
rtheadtable = document.createElement("table"),
magich,
magicw,
refreshed = false,
postsRoot = document.getElementById("thread-container"),
reqRE = new RegExp('/r/(.*)', 'i'),
redditRE = new RegExp('reddit.com', 'i');
function init()
{
createReqWindow();
registerEventHandlers();
createStyles();
createOptionTab();
}
function createStyles()
{
let css = document.createElement("style"),
height = window.innerHeight / 2,
left = window.innerWidth - 425;
css.type = "text/css";
css.innerHTML = "#reqdiv { position: fixed; height: " + height + "px; width: 400px; border: 1px solid grey; background-color: inherit; top: 125px; left: " + left + "px; }\n" +
"#reqhead { height: 15px; background-color: grey; padding: 2px; cursor: move; text-align: center; }\n" +
"#reqbody { padding: 2px; overflow: auto; }\n" +
"#closeBtn { float: right; font-weight: bold; }\n" +
".reqBtn { height: 15px; background-color: darkgrey; border: none; cursor: pointer; }\n" +
"#reqbottom { height: 4px; cursor: ns-resize; }\n" +
"#reqtable { width: 100%; table-layout: fixed; }\n" +
".cbhead { width: 10%; }\n" +
".cbcell { width: 10%; text-align: center; }\n" +
"#rtext { width: 80%; }\n" +
"#rthead { width: 100%; }";
document.head.appendChild(css);
}
function createReqWindow()
{
reqdiv.id = "reqdiv";
reqhead.id = "reqhead";
reqbottom.id = "reqbottom";
reqtable.id = "reqtable";
reqbody.id = "reqbody";
rtheadtable.id = "rthead";
closeBtn.innerText = "X";
closeBtn.id = "closeBtn";
closeBtn.classList.add("reqBtn");
let rthead = document.createElement("tr"),
th1 = document.createElement("th"),
th2 = document.createElement("th"),
th3 = document.createElement("th");
th3.id = "rtext";
th1.classList.add("cbhead");
th2.classList.add("cbhead");
th1.innerText = "Q'd";
th2.innerText = "Skip";
th3.innerText = "Request";
rthead.append(th1);
rthead.append(th2);
rthead.append(th3);
rtheadtable.append(rthead);
reqhead.append("Requests");
reqhead.append(closeBtn);
reqbody.append(reqtable);
reqdiv.append(reqhead);
reqdiv.append(rtheadtable);
reqdiv.append(reqbody);
reqdiv.append(reqbottom);
hideRequestsWindow();
body.append(reqdiv);
}
function createOptionTab()
{
let opts = document.getElementById("options"),
tabButts = opts.getElementsByClassName("tab-butts")[0],
tabCont = opts.getElementsByClassName("tab-cont")[0];
let reqButt = document.createElement("a");
reqButt.classList.add("tab-link");
reqButt.dataset.id = tabButts.childElementCount;
reqButt.innerText = "Requests";
let reqCont = document.createElement("div");
reqCont.dataset.id = tabButts.childElementCount;
let reqa = document.createElement("a");
reqa.innerText = "Show Requests Window";
reqa.addEventListener("click", showRequestsWindow);
let reseta = document.createElement("a");
reseta.innerText = "Reset Window Position";
reseta.addEventListener("click", resetWindowPosition);
reqCont.append(reqa);
reqCont.append(document.createElement("br"));
reqCont.append(reseta);
tabCont.append(reqCont);
tabButts.append(reqButt);
}
function registerEventHandlers()
{
reqhead.addEventListener("mousedown", reqheadMouseDown);
window.addEventListener("mouseup", windowMouseUp);
html.addEventListener("mousemove", mouseMoveHandler);
reqbottom.addEventListener("mousedown", reqbottomMouseDown);
window.addEventListener("resize", resizeHandler);
closeBtn.addEventListener("click", hideRequestsWindow);
}
function reqbottomMouseDown(e)
{
e.preventDefault();
reqbottom.classList.add("drag");
}
function reqheadMouseDown(e)
{
e.preventDefault();
reqhead.classList.add("drag");
magicw = e.screenX - reqdiv.offsetLeft;
magich = e.screenY - reqdiv.offsetTop;
}
function windowMouseUp(e)
{
reqhead.classList.remove("drag");
reqbottom.classList.remove("drag");
}
function resizeReqWindowHeight(e)
{
e.preventDefault();
let reqheadH = reqhead.offsetHeight,
reqbotH = reqbottom.offsetHeight,
reqtbheadH = rtheadtable.offsetHeight,
reqTop = reqdiv.offsetTop,
mouseY = e.clientY,
newH = mouseY - reqTop;
newH = newH < 100 ? 100 : newH;
reqdiv.style.height = newH + "px";
reqbody.style.height = (newH - reqheadH - reqbotH - reqtbheadH) + "px";
}
function moveRequestWindow(e)
{
e.preventDefault();
let w = e.screenX - magicw,
h = e.screenY - magich,
reqw = window.innerWidth - reqdiv.offsetWidth,
reqh = window.innerHeight - reqdiv.offsetHeight;
if (h > reqh)
reqdiv.style.top = reqh + "px";
else if (h > 0)
reqdiv.style.top = h + "px";
else
reqdiv.style.top = "0px";
if (w > reqw)
reqdiv.style.left = reqw + "px";
else if (w > 0)
reqdiv.style.left = w + "px";
else
reqdiv.style.left = "0px";
}
function mouseMoveHandler(e)
{
if (reqhead.classList.contains("drag"))
{
moveRequestWindow(e);
}
else if (reqbottom.classList.contains("drag"))
{
resizeReqWindowHeight(e);
}
}
function resizeHandler(e)
{
if (reqdiv.offsetLeft + reqdiv.offsetWidth > window.innerWidth)
reqdiv.style.left = window.innerWidth - reqdiv.offsetWidth + "px";
if (reqdiv.offsetTop + reqdiv.offsetHeight > window.innerHeight)
reqdiv.style.top = window.innerHeight - reqdiv.offsetHeight + "px";
}
function showRequestsWindow()
{
let topH = 0,
rtheadH = 0,
reqbodyH = 0,
reqdH = 0;
reqdiv.style.display = "block";
topH = reqhead.offsetHeight + 6;
rtheadH = rtheadtable.offsetHeight;
reqdH = reqdiv.offsetHeight;
reqbodyH = reqdH - topH - rtheadH;
reqbody.style.height = reqbodyH + "px";
if (!refreshed)
{
refreshRequestList();
createObserver();
}
}
function hideRequestsWindow()
{
reqdiv.style.display = "none";
}
function resetWindowPosition()
{
reqdiv.style.top = "";
reqdiv.style.left = "";
}
function refreshRequestList()
{
if (refreshed)
return;
let posts = postsRoot.children,
i = 1;
while (i < posts.length)
{
let post = posts[i];
checkForRequest(post);
i++;
}
refreshed = true;
}
function checkForRequest(post)
{
let bquote = post.getElementsByTagName("blockquote")[0],
postText = null,
lines = null;
if (!bquote)
return;
postText = bquote.innerText;
lines = postText.split('\n');
for (let j = 0; j < lines.length; j++)
{
let match = lines[j].match(reqRE);
if(match && lines[j].search(redditRE) < 0)
addRequest(match[1].trim(), post.id);
}
}
function addRequest(text, postid)
{
let row = document.createElement("tr"),
qcell = document.createElement("td"),
nocell = document.createElement("td"),
reqcell = document.createElement("td"),
req = document.createElement("a");
if(!text)
text = "[empty, check post]";
qcell.innerHTML = '<input type="checkbox">';
qcell.classList.add("cbcell");
nocell.innerHTML = '<input type="checkbox">';
nocell.classList.add("cbcell");
req.href = "#" + postid;
req.innerText = text;
reqcell.append(req);
row.append(qcell);
row.append(nocell);
row.append(reqcell);
reqtable.append(row);
}
function createObserver()
{
let obsConfig = {
attributeFilter: ["class"],
attributes: true,
subtree: true,
attributeOldValue: true
};
let observer = new MutationObserver(observerCallback);
observer.observe(postsRoot, obsConfig);
}
function observerCallback(mutationsList, observer)
{
for (let i = 0; i < mutationsList.length; i++)
{
let mut = mutationsList[i],
target = mut.target;
if (target.localName == "article"
&& mut.oldValue.includes("editing")
&& !mut.oldValue.includes("reply-form")
&& !target.classList.contains("editing"))
{
checkForRequest(target);
}
}
}
init();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment