// ==UserScript==
// @name [TS] Citrus GFork
// @namespace TimidScript
// @description Alters the interface of Greasy Fork to become more friendly for authors and users alike. Stores sort order, provides text icon to distinguish between Library, Unlisted and Deleted script. Works on Sets also.
// @author TimidScript
// @homepageURL https://openuserjs.org/users/TimidScript
// @copyright © 2014 TimidScript, All Rights Reserved.
// @license https://github.com/TimidScript/GreasyMonkey/blob/master/LICENSE.md
// @version 1.0.1
// @icon http://i.imgur.com/YKtX7ph.png
// @include https://greatest.deepsurf.us/*
// @exclude https://greatest.deepsurf.us/forum/*
// @require https://greatest.deepsurf.us/scripts/4334/code/4334.user.js
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// ==/UserScript==
/* Information
********************************************************************************************
Copyright © 2014 TimidScript, All Rights Reserved.
Script's Homepage: Check homepages below
TimidScript's Homepage: https://openuserjs.org/users/TimidScript
https://greatest.deepsurf.us/users/1455-timidscript
https://monkeyguts.com/author.php?un=timidscript
http://userscripts.org/users/TimidScript
http://userscripts-mirror.org/users/100610/scripts
----------------------------------------------
Version History
----------------------------------------------
1.0.1 (2014-08-18)
- Initial release. Released as good enough. May contain bugs but good for general usage.
**********************************************************************************************/
//#region TimidScript Library Functions
/*
Copy and paste the commented out code underneath into your script for quick reference
and auto-complete feature if available.
*********************************************************************************/
var TSL = new Object();
//Remove node from document. Accepts id or node object
TSL.removeNode = function (node, doc) { TimidScriptLibrary.removeNode(node, doc); };
// Creates document element. Default doc value is the document.
TSL.createElement = function (tag, attributes, doc) { return TimidScriptLibrary.createElement(tag, attributes, doc) };
// Creates document element using html code. Default doc value is the document.
TSL.createElementHTML = function (html, doc) { return TimidScriptLibrary.createElementHTML(html, doc) };
//Add CSS styles to document header. Document can be left empty.
TSL.addStyle = function (id, CSS, doc) { TimidScriptLibrary.addSyle(id, CSS, doc); };
//General Functions
TSL.makeStruct = function (names) { return TimidScriptLibrary.makeStruct(names); };
// Checks if mouse event is within an elements client area
TSL.isMouseEventInClientArea = function (event, element) { return TimidScriptLibrary.isMouseEventInClientArea(event, element); };
//Returns the thickness of the scrollbar
TSL.getScrollBarThickness = function () { return TimidScriptLibrary.getScrollBarThickness(); };
//Array containing NTFS illegal characters alternatives
TSL.ALTNTFSChars = [["<", "〉"], [">", "〈"], [":", ":"], ['"', "‟"], ["/", "∕"], ["\\", ""], ["?", ""], ["*", "✳"], ];
TSL.replaceNTFSIllegals = function (str) { return TimidScriptLibrary.replaceNTFSIllegals(str); };
TSL.escapeRegExp = function (str) { return TimidScriptLibrary.escapeRegExp(str); };
//String Padding
String.prototype.lPad = function (chr, length) { return TimidScriptLibrary.paddingLeft(this, chr[0], length); };
String.prototype.rPad = function (chr, length) { return TimidScriptLibrary.paddingRight(this, chr[0], length); };
/*
*********************************************************************************/
//#endregion
(function ()
{
OrangifyPage();
var scripts = new Array();
if (document.URL.match(/greasyfork\.org\/scripts\/\d+/)) //Script Page
{
TSL.addStyle("", "#script-content {background-color: #F9ECDB; margin: 0; padding-bottom: 5px;} #script-links > li:hover { background-color: yellow; } .current {background-color: #F9ECDB !important;}");
TSL.addStyle("", ".install-link {background-color: #F7A207;} .install-help-link {background-color: #F9C565 !important;}");
TSL.addStyle("", "#additional-info {border-radius: 5px;} #additional-info > div {background-color: white;");
TSL.addStyle("", "header:first-child {background-color:white; padding: 5px 10px;}");
}
else if (document.URL.match(/greasyfork\.org\/scripts/)) //Script Listing
{
getScripts();
createScriptTable();
populateScriptTable();
document.body.setAttribute("PageType", "ScriptPage");
document.body.insertBefore(document.getElementById("script-table"), document.getElementById("main-header").nextElementSibling);
var tag = GM_getValue("ScriptPage", "updated");
var m = document.URL.match(/[\?&]sort=(\w+)/);
m = (m) ? m[1] : "";
if (m != tag) document.querySelector(("td[tag='" + tag + "']")).click();
else document.querySelector(("td[tag='" + tag + "']")).setAttribute("class", "selectedHead");
TSL.removeNode("browse-script-list");
}
else if (document.URL.match(/\/users\/(\w|-)+/)) //Authors Profile Page
{
getScripts();
OrangifyUserPage();
createScriptTable();
populateScriptTable();
var pageType = (document.getElementById("#control-panel")) ? "PersonalProfile" : "UserProfile";
document.body.setAttribute("PageType", pageType);
var tag = GM_getValue(pageType, "updated");
var m = document.URL.match(/[\?&]sort=(\w+)/);
m = (m) ? m[1] : "";
if (m != tag) document.querySelector(("td[tag='" + tag + "']")).click();
else document.querySelector(("td[tag='" + tag + "']")).setAttribute("class", "selectedHead");
}
/*
---------------------------------------------------------------------------*/
function OrangifyPage()
{
var sname = document.getElementById("site-name");
sname.innerHTML = "";
var link = document.createElement("a");
link.href = "/";
link.innerHTML = '<img id="title-image" src="https://i.imgur.com/RqikjW1.jpg" /><span id="title-text">Greasy Fork</span>'
+ '<span style="color: yellow; font-size: 12px; text-decoration: none; position: absolute; left: 90px; top: 70px;">100% Citrusy Goodness</span>';
sname.appendChild(link);
TSL.removeNode("script-list-option-groups");
//#region Adding CSS Styles E3E2E2
TSL.addStyle("CitrusGF_Main", "#main-header {background-color: orange;}"
+ "#title-image {max-height: 60px; border-radius: 20px; margin-left: 5px;}"
+ "#title-text {font-size: 50px; color:black; font-family:'Open Sans',sans-serif; margin: 0 10px;}");
//#endregion
}
function OrangifyUserPage()
{
TSL.addStyle("CitrusGF_Shared", ".white-panel, #control-panel, #user-profile, #user-discussions-on-scripts-written {margin: 5px; border-radius: 8px; padding: 10px; }");
TSL.addStyle("CitrusGF_Profile", ".white-panel, #user-discussions-on-scripts-written, #control-panel, #user-profile {background-color: white; }");
TSL.addStyle("", "#user-control-panel, #control-panel h3 {margin: 0; padding: 0;} #user-control-panel > li { display: inline-block; margin: 0 5px; padding: 2px 5px; border-radius: 5px; background-color: #F5F2F2; border: 1px solid #404040; box-shadow: 3px 3px 2px #888888;} #user-control-panel a {text-decoration: none;} #user-control-panel li:hover {background-color: #FBEACA;}");
TSL.addStyle("", ".white-panel *, #user-discussions-on-scripts-written * {margin: 0;}");
var author = document.createElement("h1");
var name = document.getElementsByTagName("h2")[0];
var up = document.getElementById("user-profile");
if (!up)
{
up = document.createElement("section");
up.id = "user-profile";
up.textContent = "...";
name.parentElement.insertBefore(up, name);
}
up.innerHTML = "<h1 style='margin: 0 0 5px 0; color: orange;'>" + name.textContent + "'s Profile</h1>" + up.innerHTML;
TSL.removeNode(name);
var el = document.getElementById("user-script-sets");
el.parentElement.className = "white-panel";
el = document.getElementById("user-script-list");
if (el) TSL.removeNode(el.parentElement);
el = document.getElementById("user-deleted-script-list");
if (el) TSL.removeNode(el.parentElement);
}
function getScripts(doc)
{
if (!doc) doc = document;
var ids = ["user-script-list", "user-deleted-script-list", "browse-script-list"];
scripts = new Array();
for (var i = 0; i < ids.length; i++)
{
var el = doc.getElementById(ids[i]);
if (!el) continue;
var deleted = ids[i].indexOf("deleted") > 0;
var list = el.children;
for (var j = 0; j < list.length; j++)
{
var li = list[j];
var script = new Object();
script.name = li.getAttribute("data-script-name");
script.id = li.getAttribute("data-script-id");
script.author = li.getAttribute("data-script-author-name");
script.authorID = li.getAttribute("data-script-author-id");
script.description = li.getElementsByClassName("description")[0].textContent.trim();
script.fans = li.getAttribute("data-script-fan-score");
script.installsDaily = li.getAttribute("data-script-daily-installs");
script.installsTotal = li.getAttribute("data-script-total-installs");
script.dateCreated = li.getAttribute("data-script-created-date");
script.dateUpdated = li.getAttribute("data-script-updated-date");
script.type = li.getAttribute("data-script-type");
script.deleted = deleted;
scripts.push(script);
}
}
}
function createScriptTable()
{
var scriptTable = document.createElement("table");
scriptTable.id = "script-table";
var thead = scriptTable.createTHead();
var row = thead.insertRow(-1);
var headers = ["Name", "Fans", "Daily", "Total", "Created", "Updated"];
var tags = ["name", "fans", "", "total_installs", "created", "updated"];
for (var i = 0; i < headers.length; i++)
{
var cell = row.insertCell();
cell.innerHTML = headers[i];
cell.onclick = OnTableHeaderClick;
cell.setAttribute("tag", tags[i]);
}
scriptTable.createTBody();
document.body.appendChild(scriptTable);
TSL.addStyle("CitrusGS_Table", "#script-table {display: block; margin: 5px;} body {background-color: #EFEFB1; margin: 0;}"
+ "#script-table thead td {background-color: orange; border-radius: 0 0 5px 5px; box-shadow: 3px 3px 2px #888888;}"
+ "#script-table thead td:hover {cursor:pointer; background-color: yellow;}"
+ "#script-table td {width: auto; padding: 2px 5px; text-align:center;}"
+ "#script-table tbody tr td:first-child {text-align:left;}"
+ "#script-table td:first-child{width: 99%;}"
+ "#script-table tbody td {background-color: #FFFBDB;}"
+ "#script-table tbody td:first-child{width: 99%; background-color: white;}"
+ "#script-table tbody tr:hover td {background-color: yellow;}"
+ ".selectedHead {background-color: yellow !important;}"
+ ".type-library, .type-unlisted, .type-deleted {font-size:small; display: inline-block; border-radius: 3px; padding: 0 5px; border: 1px solid black; box-shadow: 2px 2px 1px #888888; margin: 2px 0 3px 0;}"
+ ".type-library {background-color: #CEE7F3; }"
+ ".type-deleted {background-color: #F77A7A; margin-left: 5px;}"
+ ".type-unlisted {background-color: #CEFD8A; }"
+ ".type-library:before {content: 'Library';}"
+ ".type-deleted:before {content: 'Deleted';}"
+ ".type-unlisted:before {content: 'Unlisted';}"
);
}
function populateScriptTable(clear)
{
var tbody = document.getElementById("script-table").getElementsByTagName("tbody")[0];
if (clear) tbody.innerHTML = "";
if (scripts.length == 0)
{
var row = tbody.insertRow(-1);
cell = row.insertCell();
cell.setAttribute("style", "text-align:center; font-weight: bold; font-style: oblique;");
cell.textContent = "No Scripts"
cell.setAttribute("colspan", 6);
}
for (var i = 0; i < scripts.length; i++)
{
var script = scripts[i];
row = tbody.insertRow(-1);
cell = row.insertCell();
var el = document.createElement("div");
el.style.marginBottom = "5px";
el.innerHTML = "<a href='https://greatest.deepsurf.us/scripts/"
+ script.id + "'><b>" + script.name + "</b></a>";
cell.appendChild(el);
el = document.createElement("div");
el.textContent = script.description;
cell.appendChild(el);
if (script.type == "library")
{
el = document.createElement("span");
el.className = "type-library";
cell.appendChild(el);
}
else if (script.type == "unlisted")
{
el = document.createElement("span");
el.className = "type-unlisted";
cell.appendChild(el);
}
if (script.deleted)
{
el = document.createElement("span");
el.className = "type-deleted";
cell.appendChild(el);
}
row.insertCell().textContent = script.fans;
row.insertCell().textContent = script.installsDaily;
row.insertCell().textContent = script.installsTotal;
row.insertCell().textContent = script.dateCreated;
row.insertCell().textContent = script.dateUpdated;
}
}
function OnTableHeaderClick(e)
{
if (this.className || this.parentElement.getAttribute("busy")) return;
this.parentElement.setAttribute("busy", true);
var header = this;
//https://greatest.deepsurf.us/scripts?per_page=200&sort=updated
//https://greatest.deepsurf.us/scripts?page=2&per_page=200&sort=updated
//https://greatest.deepsurf.us/scripts/search?q=google
//https://greatest.deepsurf.us/scripts/search?page=2&q=g
var url = document.URL.replace(/(\?|&)sort=\w+/, "");
var tag = this.getAttribute("tag");
if (tag) url += ((url.indexOf("?") > 1) ? "&" : "?") + "sort=" + tag;
console.log(url);
GM_xmlhttpRequest({
url: url,
method: "GET",
timeout: 15000,
headers: {
"User-agent": navigator.userAgent,
"Host": "greatest.deepsurf.us",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5"
},
onload: function (xhr)
{
if (xhr.status == 200)
{
GM_setValue(document.body.getAttribute("PageType"), tag);
var els = header.parentElement.getElementsByTagName("td");
for (var i = 0; i < els.length; i++) els[i].removeAttribute("class");
header.className = "selectedHead";
//stackoverflow.com/questions/19193335/change-the-url-in-browser-bar-without-reloading-page
window.history.pushState(null, "", xhr.finalUrl); //Change document URL
scripts = new Array();
//var doc = new DOMParser().parseFromString(xhr.responseText, 'text/xml');
dt = document.implementation.createDocumentType("html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd"),
doc = document.implementation.createDocument("", "", dt),
documentElement = doc.createElement("html");
documentElement.innerHTML = xhr.responseText;
doc.appendChild(documentElement);
TSL.removeNode(document.getElementsByClassName("pagination")[0]);
var pager = doc.getElementsByClassName("pagination")[0];
if (pager)
{
document.body.insertBefore(pager, document.getElementById("script-table").nextElementSibling);
}
getScripts(doc);
populateScriptTable(true);
}
header.parentElement.removeAttribute("busy");
}
})();
}
})();