(function () {
// ==UserScript==
// @run-at document-start
// @name uso - Monkey Barrel
// @namespace http://userscripts.org/users/37004
// @description Enhanced menu system for Userscripts.org
// @copyright 2011+, Marti Martz (http://userscripts.org/users/37004)
// @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
// @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
// @version 0.1.13.1eol
// @icon https://raw.githubusercontent.com/Martii/UserScripts/master/src/uso/Monkey%20Barrel/res/icon48.png
// @homepageURL https://github.com/Martii/UserScripts/tree/master/src/uso/Monkey%20Barrel
// @homepageURL https://openuserjs.org/scripts/Marti/uso_-_Monkey_Barrel
// @homepageURL http://userscripts.org/scripts/show/114843
// @supportURL http://userscripts.org/topics/89959
// @include /^https?://userscripts\.org(?::\d{1,5})?/?.*/
// @include http://userscripts.org:8080/*
// @include http://userscripts.org/*
// @include https://userscripts.org/*
// @require https://raw.githubusercontent.com/Martii/UserScripts/master/lib/GM_setStyle/GM_setStyle.js
// @require https://raw.githubusercontent.com/Martii/GM_config/42d6367b3c8ccc1b8f32af7b23fce5078716ff14/gm_config.js
// @resource gmc https://raw.githubusercontent.com/sizzlemctwizzle/GM_config/master/gm_config_icon.png
// @grant GM_addStyle
// @grant GM_getResourceURL
// @grant GM_getValue
// @grant GM_log
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// ==/UserScript==
/*
Please note this script uses native JSON and native classList which requires Firefox 3.6.x+ and Greasemonkey 0.9.8+
*/
let protocol = "http" + (/^https:$/i.test(location.protocol) ? "s" : "") + ":";
function findlastPost(aTopicid) {
if (document && document.body)
document.body.style.cursor = "progress";
GM_xmlhttpRequest({
retry: 5,
url: "/topics/" + aTopicid + ".rss",
method: "GET",
onload: function (xhr) {
switch (xhr.status) {
case 502:
case 503:
if (--this.retry > 0)
setTimeout(GM_xmlhttpRequest, 3000 + Math.round(Math.random() * 5000), this);
else {
if (document && document.body)
document.body.style.cursor = "auto";
}
break;
case 200:
let doc = new DOMParser().parseFromString(xhr.responseText, "text/xml"),
xpr = doc.evaluate(
"//channel/item/link",
doc.documentElement,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (xpr && xpr.singleNodeValue) {
let thisNode = xpr.singleNodeValue;
if (/^https?:\/\/userscripts\.org(?::\d{1,5})?\/posts\/\d+\/?/i.test(thisNode.textContent)) {
let url = thisNode.textContent.replace(/http:/i, location.protocol);
GM_xmlhttpRequest({
retry: 5,
url: thisNode.textContent.replace(/http:/i, location.protocol),
method: "HEAD",
onload: function (xhr) {
// NOTE: Secure xhr is prevented currently on USO and GM_xhr currently has an issue with onreadystatechange in FF 7.0.1,
// so rely upon finalUrl in unsecure mode but redirect to secure
switch (xhr.status) {
case 502:
case 503:
if (--this.retry > 0)
setTimeout(GM_xmlhttpRequest, 3000 + Math.round(Math.random() * 5000), this);
else {
if (document && document.body)
document.body.style.cursor = "auto";
}
break;
case 200:
if (document && document.body) {
document.body.style.cursor = "auto";
location.assign(xhr.finalUrl.replace(/^http:/i, location.protocol));
}
else {
location.replace(xhr.finalUrl.replace(/^http:/i, location.protocol));
}
break;
default:
if (document && document.body)
document.body.style.cursor = "auto";
break;
}
}
});
}
}
break;
default:
if (document && document.body)
document.body.style.cursor = "auto";
break;
}
}
});
}
// ** Accelerator function event
function lastPost(ev) {
let topicid = ev.target.href.match(/\/topics\/(\d+)\#posts\-last/i);
if (!topicid)
return;
ev.preventDefault();
findlastPost(topicid[1]);
};
// ** "load into view" e.g. use accelerator if #posts-last in address bar
if (location.hash == "#posts-last") {
let topicid = location.pathname.match(/\/topics\/(\d+)/i);
if (topicid) {
stop();
findlastPost(topicid[1]);
}
else
history.replaceState({}, '', location.href.replace(/\#posts\-last$/, ""));
}
function onDOMContentLoaded() {
if (!document || !document.body)
return;
document.removeEventListener("DOMContentLoaded", onDOMContentLoaded, true);
if (location.hash == "#posts-last" && location.pathname.match(/\/topics\/\d+$/))
document.body.style.cursor = "progress";
let gCSS = GM_setStyle({
media: "screen, projection"
});
if (typeof GM_configStruct != "undefined") {
// Save some memory
delete GM_config;
var gmc = new GM_configStruct();
gmc.id = "gmc114843";
var divNode = document.getElementById("full_description");
if (divNode && !divNode.firstChild) {
var newdivNode = document.createElement("div");
divNode = divNode.appendChild(newdivNode);
}
else {
var newdivNode = document.createElement("div");
if (divNode)
divNode = divNode.insertBefore(newdivNode, divNode.firstChild);
else
divNode = document.body.appendChild(newdivNode);
}
/* Nearest fix for a glitch on USO */
let scriptNav = document.getElementById("script-nav");
if (scriptNav && divNode && scriptNav.clientWidth != divNode.clientWidth)
GM_setStyle({
node: gCSS,
data:
[
"div #full_description { width: 98.1%; }"
].join("\n")
});
let screenShots = document.getElementById("screenshots");
if (screenShots)
GM_setStyle({
node: gCSS,
data:
[
"#full_description { clear: left; }"
].join("\n")
});
/* Nearest fix for userscripts.org Alternate CSS */
let fullDescription = document.getElementById("full_description");
if (fullDescription && screenShots && fullDescription.clientWidth > parseInt(screenShots.clientWidth * 1.0275))
GM_setStyle({
node: gCSS,
data:
[
"#screenshots { width: 97.5% !important; }"
].join("\n")
});
GM_setStyle({
media: "print",
data:
[
".hid { display: none; }",
"#gmc114843 { display: none !important; }"
].join("\n")
});
let onInit = function (doc) {
/* Cleanup unused style in the GMC div portion of the DOM */
if (doc) {
let thisNode = doc.getElementById("gmc114843");
if (thisNode)
thisNode.removeAttribute("style");
}
}
gmc.init(
divNode,
// gmc.onInit, // NOTE: Destruction of this function occurs after initial open with GMC 7e5dfecf87- so don't currently use
[
'<img alt="Monkey Barrel" title="uso - Monkey Barrel" src="' + protocol + '//s3.amazonaws.com/uso_ss/icon/114843/large.png" />',
'<p>Preferences</p>',
'<span>',
'<a href="' + protocol + '//github.com/sizzlemctwizzle/GM_config/wiki/">',
'<img alt="GM_config" title="Powered in part by GM_config" src="' + GM_getResourceURL("gmc") + '" />',
'</a>',
'</span>'
].join(""),
/* Custom CSS */
GM_setStyle({
node: null,
data:
[
/* Homepage */
"@media screen, projection {",
/* GM_config USO styling fixups */
"#gmc114843 { position: static !important; z-index: 0 !important; width: auto !important; height: auto !important; max-height: none !important; max-width: none !important; margin: 0 0 0.5em 0 !important; border: 1px solid #ddd !important; clear: right !important; }",
"#gmc114843_header a { display: inline; }",
"#gmc114843_header img { max-height: 32px; margin-right: 0.125em; vertical-align: middle; }",
"#gmc114843_header > p { display: inline; margin: 0; vertical-align: middle; }",
"#gmc114843_header span { float: right; }",
"#gmc114843_header span > a { display: inline; margin-left: 0.25em; }",
"#gmc114843_wrapper { background-color: #eee; padding-bottom: 0.25em; }",
"#gmc114843 .config_header { background-color: #333; color: #fff; font-size: 1.57em; margin: 0; padding: 0 0.5em; text-align: left; }",
"#gmc114843 .config_var { clear: both; margin: 0.33em; padding: 0; }",
"#gmc114843 .field_label { color: #333; font-size: 100%; font-weight: normal; margin: 0 0.25em; position: relative; top: -0.2em; }",
"#gmc114843 .section_header_holder { margin: 0.25em 0.5em !important; }",
"#gmc114843 .section_desc { margin: 0.25em 1.5em !important; }",
".gmc-yellownote { background-color: #ffd; font-size: 0.66em !important; }",
"#gmc114843_section_header_0 { background-color: inherit !important; border-style: none !important; color: inherit !important; font-size: inherit !important; text-align: left !important; }",
"#gmc114843_section_0 { margin: 0 1.5em !important; }",
"#gmc114843_jsonMenus_var { margin: -1em 0 !important; }",
"#gmc114843_jsonMenus_field_label { margin: 1em 0 !important; }",
"#gmc114843_field_jsonMenus { font-size: 1em; height: 15.2em; margin-top: 1em; max-width: 98.68%; min-width: 98.68%; min-height: 15.2em; }",
"#gmc114843 .reset, #gmc114843 .reset a, #gmc114843_buttons_holder { text-align: inherit; }",
"#gmc114843_buttons_holder { margin: 0.5em; }",
"#gmc114843_saveBtn { margin: 0.5em !important; padding: 0 3.0em !important; }",
"#gmc114843_resetLink { margin-right: 1.5em; }",
"#gmc114843_closeBtn { display: none; }",
"}",
"@media print {",
".hid { display: none; }",
"#gmc114843 { display: none !important; }",
"}"
].join("\n")
}),
/* Settings object */
{
'jsonMenus': {
"section": ["Main menus"],
"type": 'textarea',
"label": "<p><em class='gmc-yellownote'>use <a href='http://json.org/'>JSON</a> data-interchange format.</em></p>",
"default": JSON.stringify(
JSON.parse(
[
'{',
'"Monkey Barrel": [',
'"/scripts/show/114843",',
'{',
'"recent posts": "/posts",',
'"recent topics": "/topics",',
'"recent comments": "/comments",',
'"recent images": "/images",',
'"": "",',
'"recent spam": "/spam",',
'"recent potential spam": "/posts?kind=all&spam=1",',
'"recent potential spam by score": "/posts?kind=all&spam=score",',
'"spam and malware \u00bb": "/topics/9#posts-last",',
'"cookie stealing scripts \u00bb": "/topics/704#posts-last",',
'" ": "",',
'"custom search": "/search"',
'}',
']',
'}'
].join("\n")
), null, " ")
},
'enableUnpin': {
"type": 'checkbox',
"label": 'Unpin submenus',
"default": true
},
'importGroups': {
"type": 'checkbox',
"label": 'Enable automatic import for subscribed Groups when clicked',
"default": true
},
'addLastPostLinks': {
"type": 'checkbox',
"label": 'Add last post links to the Recent Topics on a script homepage',
"default": true
}
}
);
gmc.onOpen = function () {
onInit(document);
gmc.fields["jsonMenus"].node.setAttribute("spellcheck", "false");
gmc.fields["jsonMenus"].node.textContent = JSON.stringify(JSON.parse(gmc.get("jsonMenus")), null, " ");
}
gmc.onSave = function () {
try {
gmc.set("jsonMenus", JSON.stringify(JSON.parse(gmc.get("jsonMenus")), null, ""));
gmc.write();
gmc.close();
gmc.open();
}
catch (e) {
alert('ERROR: Invalid JSON for main menu.\n\nPlease correct or reset to defaults');
}
}
if (location.pathname.match(/^\/scripts\/show\/114843/i)) {
gmc.open(); // NOTE: First open
}
// -------------------------------------------------------------------------------------------------------------------------------------------------
GM_setStyle({
node: gCSS,
data:
[
/* Fix USO */
"#header #mainmenu { padding-top: 0; }",
".hid { display: none; }",
".mainmenu- { position: fixed; z-index: 1; margin: 0; list-style: none outside none; border-left: 1px solid #888; border-right: 1px solid #888; border-bottom: 1px solid #888; padding-left: 0; }",
".mainmenu- li { -moz-border-radius: 0 !important; border-radius: 0 !important; margin: 0 !important; float: none !important; background: #000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAZCAQAAABamYz0AAAAAXNSR0IArs4c6QAAAB5JREFUCNdjuOfAxPCPieEvDP1D4v5DIv/iEEcIAgClTRkR4R/Z1AAAAABJRU5ErkJggg==) repeat-x scroll left top !important; }",
".mainmenu- li a { color: #fff !important; }",
".mainmenu- .sep { border-bottom: thin dashed #aaa !important; }"
].join("\n")
});
function onresize(ev) {
let xpr = document.evaluate(
"//div[@id='top']/div[@class='container']",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (xpr && xpr.singleNodeValue) {
let thisNode = xpr.singleNodeValue;
let width = parseFloat(getComputedStyle(thisNode, null).getPropertyValue("width").replace(/px$/i, "")); // NOTE: Returns normalized used instead of computed
if (width <= 950) {
let mainmenu = document.getElementById("mainmenu");
if (mainmenu)
mainmenu.style.setProperty("margin-right", (document.body.clientWidth - width) / 2 + "px", "");
}
else
return true;
}
if (!ev)
return false;
}
if (gmc.get("enableUnpin")) {
GM_setStyle({
node: gCSS,
data:
[
"#header > .container { position: static; }",
".mainmenu- { position: absolute; }"
].join("\n")
});
if (!onresize())
addEventListener("resize", onresize, false);
}
// ** Event listeners
function onmouseover(ev) {
let thatNode = this.firstChild.nextSibling;
while (thatNode) {
if (thatNode.tagName.toLowerCase() == "ul")
thatNode.classList.remove("hid");
thatNode = thatNode.nextSibling;
}
};
function onmouseout(ev) {
let thatNode = this.firstChild.nextSibling;
while (thatNode) {
if (thatNode.tagName.toLowerCase() == "ul")
thatNode.classList.add("hid");
thatNode = thatNode.nextSibling;
}
};
// ** Generator functions
function createMenuItem(aTextContent, aHref) {
if (aTextContent.trim() == "")
return undefined;
let aNode = document.createElement("a");
aNode.href = aHref;
aNode.textContent = aTextContent;
if (aNode.href.match(/\/topics\/\d+\#posts\-last$/i))
aNode.addEventListener("click", lastPost, false);
let liNode = document.createElement("li");
return liNode.appendChild(aNode).parentNode;
}
function createMenuItems(aList, aItems) {
for (let item in aItems) {
let menuItem = createMenuItem(item,aItems[item]);
if (menuItem)
aList.appendChild(menuItem);
else if (aList.lastChild)
aList.lastChild.classList.add("sep");
}
return aList;
}
function createMenu(aMenu) {
let ulNode = document.createElement("ul");
ulNode.className = "mainmenu-";
ulNode.classList.add("hid");
return createMenuItems(ulNode, aMenu[1]);
}
// ** Retrieve the stored menus
let mainmenu;
try {
mainmenu = JSON.parse(gmc.get("jsonMenus"));
}
catch (e) {
if (location.pathname != "/scripts/show/114843") {
alert('ERROR: Invalid JSON for main menu found in uso - Monkey Barrel.\n\nPlease correct or reset to defaults');
location.pathname = "/scripts/show/114843";
}
return;
}
// If on /groups and allowed then read in values from sidebar
if (gmc.get("importGroups") && location.pathname == "/groups") {
let xpr = document.evaluate(
"//div[@id='right']/h3[starts-with(.,'Groups you created')]/following-sibling::ul[1]/li/a"
+ "|//div[@id='right']/h3[starts-with(.,'Groups you joined')]/following-sibling::ul[1]/li/a",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
if (xpr.snapshotLength > 0) {
if (!mainmenu["Groups"])
mainmenu["Groups"] = [ "/groups", {} ];
for (let i = 0, thisNode; thisNode = xpr.snapshotItem(i++);) {
mainmenu["Groups"][1][thisNode.textContent] = thisNode.pathname;
}
// Resave the JSON menus silently
gmc.set("jsonMenus", JSON.stringify(mainmenu, null, ""));
gmc.write();
if (gmc.isOpen)
gmc.fields["jsonMenus"].node.textContent = JSON.stringify(JSON.parse(gmc.get("jsonMenus")), null, " ");
}
}
if (gmc.get("addLastPostLinks")) {
GM_setStyle({
node: gCSS,
data:
[
"#topics .postslast { padding: 0.125em 0.25em 0.125em 0.5em; }",
"#topics td.count { text-align: right; background-color: #eee; }"
].join("\n")
});
let xpr = document.evaluate(
"//div[@id='topics']//td/a[starts-with(@href, '/topics')]",
document.body,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
if (xpr && xpr.snapshotLength > 0) {
// NOTE: Assume table headers are present
for (let i = 0, thisNode; thisNode = xpr.snapshotItem(i++);) {
let aNode = document.createElement("a");
aNode.href = thisNode.href;
aNode.hash = "posts-last";
aNode.title = "last post";
aNode.textContent = thisNode.parentNode.nextSibling.textContent + "\u00a0\u00a0\u00bb";
aNode.classList.add("lastpost"); // NOTE: USO native
aNode.classList.add("postslast");
aNode.addEventListener("click", lastPost, false);
thisNode.parentNode.nextSibling.removeChild(thisNode.parentNode.nextSibling.firstChild);
aNode = thisNode.parentNode.parentNode.lastChild.appendChild(aNode);
// thisNode.parentNode.parentNode.lastChild.insertBefore(aNode, thisNode.parentNode.parentNode.lastChild.firstChild);
}
}
}
// ** Paint the menus
let mm = document.getElementById("mainmenu");
if (mm) {
// Remove Jetpacks mainmenu item, if present. from userscripts alternate CSS
let xpr = document.evaluate(
"./li/a[.='Jetpacks']",
mm,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
if (xpr && xpr.singleNodeValue) {
let thisNode = xpr.singleNodeValue;
thisNode.parentNode.parentNode.removeChild(thisNode.parentNode);
}
// Twiddle
document.evaluate(
"./li/a[.='Monkey Barrel']",
mm,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
xpr
);
if (xpr && xpr.singleNodeValue)
return;
mm.appendChild(createMenuItem("Monkey Barrel", "/scripts/show/114843"));
// Get existing menu items and then send off to functions
document.evaluate(
"./li",
mm,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
xpr
);
for (let i = 0, thisNode; thisNode = xpr.snapshotItem(i++);) {
let aNode = thisNode.firstChild;
if (mainmenu[aNode.textContent]) {
thisNode.appendChild(createMenu(mainmenu[aNode.textContent]));
thisNode.addEventListener("mouseover", onmouseover, false);
thisNode.addEventListener("mouseout", onmouseout, false);
}
}
}
}
}
document.addEventListener("DOMContentLoaded", onDOMContentLoaded, true);
})();
Donate for the site OpenUserJS
Are you sure you want to go to an external site to donate a monetary value?
WARNING: Some countries laws may supersede the payment processors policy such as the GDPR and PayPal. While it is highly appreciated to donate, please check with your countries privacy and identity laws regarding privacy of information first. Use at your utmost discretion.