// ==UserScript==
// @name GreasyFork - filter discussions on scripts by review type and author
// @namespace darkred
// @version 2017.4.19
// @description Filter discussions on scripts by review type and author via filter buttons, a hoverable dropdown menu or an autocomplete searchbox
// @author darkred
// @contributor decembre
// @license MIT
// @include https://greasyfork.org/*/scripts/*/feedback*
// @include https://greasyfork.org/*/users/*
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_getResourceText
// @require https://code.jquery.com/jquery-3.1.1.min.js
// @require https://code.jquery.com/ui/1.12.1/jquery-ui.min.js
// @resource jquery-ui.css http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css
// This is partially based on this script (http://userscripts-mirror.org/scripts/show/97145) by kuehlschrank.
// Thanks a lot to kuehlschrank for making another great script.
// @supportURL https://github.com/darkred/Userscripts/issues
// ==/UserScript==
// the list of discussion authors
var allAuthorsRefs = $('#discussions > li > a:nth-child(2), #user-discussions-on-scripts-written > ul > li a:nth-child(3)');
var allAuthorsUnique = [];
$.each(allAuthorsRefs, function(index, el) {
let title = el.innerHTML;
if (allAuthorsUnique.indexOf(title) === -1){
allAuthorsUnique.push(title);
}
});
// allAuthorsUnique.sort();
var filters = {
'All' : '',
'Questions' : 'discussion-question',
'Bad' : 'discussion-bad',
'Ok' : 'discussion-ok',
'Good' : 'discussion-good',
};
// -----------------------------------------------------------------------------------------------------------------------
// the filter buttons
function insertStyle() {
var style = document.createElement('style');
// style.textContent = 'li#filtered { display:none !important; } .filter-status { margin-left: 6px; position: absolute; top: 209px; right: 272px; } .filter-switches { display:initial; position: absolute; top: 240px; left: calc(79%); background: white; right: 287px; } *:hover > .filter-switches { display:block !important; position: absolute; top: 240px; background: white; right: 287px; } .filter-on, .filter-off {display:block !important; width: 97px;}} .filter-switches a { text-decoration:none !important; color:inherit; cursor:pointer; } .filter-switches a { margin-left: 8px; padding: 0 4px; } a.filter-on { background-color: white; color: #e6e6e6; } a.filter-off { background-color:#ccffcc; color:#333333 } ';
style.textContent = 'li#filtered { display:none !important; } .filter-status { margin-left: 6px; position: absolute; top: calc(24%); left: calc(77%) } .filter-switches { display:initial; position: absolute; top: calc(26.5%); left: calc(77.5%); background: white; right: 287px; } .filter-on, .filter-off {display:block !important; width: 97px;}} .filter-switches a { text-decoration:none !important; color:inherit; cursor:pointer; } .filter-switches a { margin-left: 8px; padding: 0 4px; } a.filter-on { background-color: white; color: #e6e6e6; } a.filter-off { background-color:#ccffcc; color:#333333 } ';
style.type = 'text/css';
document.querySelector('head').appendChild(style);
}
function insertStatus() {
// CITRUS TWEAK (contribution of decembre)
var p = $(` #script-content > h3:nth-child(1),
#script-content > h3:first-of-type,
#user-discussions-on-scripts-written > header:nth-child(1) > h3:nth-child(1)`); // --- > working on Script discussions
if (p) {
var status = document.createElement('span');
status.className = 'filter-status';
$(p).append(status);
}
}
function insertSwitches() {
var span = document.createElement('span');
span.className = 'filter-switches';
for (var filter in filters) {
if (filters.hasOwnProperty(filter)) {
span.appendChild(createSwitch(filter, GM_getValue(filter, 'on') == 'on'));
}
}
// CITRUS TWEAK (contribution of decembre)
var k = $( `#script-content > h3:nth-child(1), \
#script-content > h3:first-of-type, \
#control-panel > header:nth-child(1) > h3:nth-child(1)`);
$(k).append(span);
}
function createSwitch(label, isOn) {
var a = document.createElement('a');
a.className = isOn ? 'filter-on' : 'filter-off';
a.textContent = label;
a.addEventListener('click', function(e) {
// console.log(this);
if (this.innerHTML !== 'All'){
if (this.className === 'filter-on') {
this.className = 'filter-off';
GM_setValue(this.textContent, 'off');
} else {
this.className = 'filter-on';
GM_setValue(this.textContent, 'on');
}
$('.filter-switches > a:nth-child(1)').attr('class', 'filter-on');
GM_setValue('All', 'on');
filterScripts();
} else if (this.innerHTML === 'All' && this.className === 'filter-on'){
this.className = 'filter-off';
GM_setValue(this.textContent, 'off');
$('.filter-switches > a:nth-child(2)').attr('class', 'filter-off');
GM_setValue('Questions', 'off');
$('.filter-switches > a:nth-child(3)').attr('class', 'filter-off');
GM_setValue('Bad', 'off');
$('.filter-switches > a:nth-child(4)').attr('class', 'filter-off');
GM_setValue('Ok', 'off');
$('.filter-switches > a:nth-child(5)').attr('class', 'filter-off');
GM_setValue('Good', 'off');
var nodes = $('#discussions > li, .discussion-list > li');
$.each(nodes, function(index, val) {
$(val).attr('id', '');
});
var hidden = $('#discussions > li:hidden, .discussion-list > li:hidden').length;
var nodesLength = nodes.length;
if (nodes[nodes.length - 1].className === 'more-discussions'){
--nodesLength;
}
$('.filter-status').text((nodesLength - hidden) + ' (' + hidden + ' filtered)');
}
e.preventDefault();
}, false);
return a;
}
function filterScripts() {
var activeFilters = [];
for (var filter in filters) {
if (filters.hasOwnProperty(filter) && GM_getValue(filter, 'on') == 'on') {
activeFilters.push(filters[filter]);
}
}
var nodes = $('#discussions > li, .discussion-list > li'),
numActiveFilters = activeFilters.length;
for (var i = 0, numNodes = nodes.length, td = null; i < numNodes && (td = nodes[i]); i++) {
td.id = '';
for (var j = 0; j < numActiveFilters; j++) {
if (td.className === activeFilters[j]) {
td.id = 'filtered';
break;
}
}
}
var hidden = $('#discussions > li:hidden, .discussion-list > li:hidden').length;
var nodesLength = nodes.length;
if (nodes[nodes.length - 1].className === 'more-discussions'){
--nodesLength;
}
$('.filter-status').text((nodesLength - hidden) + ' (' + hidden + ' filtered)');
}
insertStyle();
insertStatus();
filterScripts();
insertSwitches();
var target = document.querySelector('.filter-status');
var observer = new MutationObserver((mutations) => {
if ($('.filter-switches > a:nth-child(2)').attr('class') === 'filter-off' &&
$('.filter-switches > a:nth-child(3)').attr('class') === 'filter-off' &&
$('.filter-switches > a:nth-child(4)').attr('class') === 'filter-off' &&
$('.filter-switches > a:nth-child(5)').attr('class') === 'filter-off'){
$('.filter-switches > a:nth-child(1)').attr('class', 'filter-off');
GM_setValue('All', 'off');
let nodes = $('#discussions > li, .discussion-list > li');
$.each(nodes, function(index, val) {
$(val).attr('id', '');
});
}
}),
config = {
childList: true,
};
observer.observe(target, config);
// -----------------------------------------------------------------------------------------------------------------------
// the hoverable dropdown menu
// CITRUS TWEAK (contribution of decembre)
var parentElement = document.querySelector('#script-content > h3:nth-child(1)') || document.querySelector('#script-content > h3:first-of-type') || document.querySelector('#control-panel > header:nth-child(1) > h3:nth-child(1)');
var theFirstChild = parentElement.firstChild;
var div = document.createElement('div');
parentElement.insertBefore(div, theFirstChild);
// the two last properties (height and oveerflow) ware adeed to the dropdown menu
GM_addStyle(`
/* Dropdown Button */
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
position: absolute !important;
display: inline-block;
top: calc(29%); /* extra */
left: calc(86%); /* extra */
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute !important;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
height: 400px;
width: -moz-max-content; /* extra */
overflow: auto;
}
/* Links inside the dropdown */
.dropdown-content a {
color: black;
/* padding: 12px 16px; */
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #f1f1f1}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block;
}
/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {
background-color: #3e8e41;
}
div.ui-widget {
position: absolute !important;
display: inline-block;
position: absolute !important;
top: calc(24.2%);
left: calc(86%);
}
`);
var a = '<div class="dropdown">\
<button onclick="myFunction()" class="dropbtn">Filter by author</button>\
<div id="myDropdown" class="dropdown-content">';
a += `<a onclick="showOnly('All')">All</a>`;
for (var i = 0; i < allAuthorsUnique.length; i++) {
a += '<a onclick="showOnly(\'' + (allAuthorsUnique[i]) + '\')">' + allAuthorsUnique[i] + '</a>';
}
a += '</div></div>';
div.innerHTML = a;
var el = $('#myDropdown > a:nth-child(1)');
$(el).click(function(event) {
document.querySelector('#authors').value = '';/* Act on the event */
});
var myF = `
function showOnly(author){
$('.dropbtn').html('Filter by author (All)');
if (author === 'All'){
document.querySelector('.dropbtn').innerHTML = 'Filter by author (All)';
var a = '#discussions > li > a:nth-child(2), #user-discussions-on-scripts-written > ul > li a:nth-child(3)';
$(a).parent().show();
let nodes = $('#discussions > li, .discussion-list > li');
let hidden = $('#discussions > li:hidden, .discussion-list > li:hidden').length;
let nodesLength = nodes.length;
if (nodes[nodes.length - 1].className === 'more-discussions'){
--nodesLength;
}
$('.filter-status').text((nodesLength - hidden) + ' (' + hidden + ' filtered)');
return;
} else {
$('.dropbtn').html('Filter by author (' + author + ')');
a = '#discussions > li > a:nth-child(2), #user-discussions-on-scripts-written > ul > li a:nth-child(3)';
$(a).parent().show();
a = '#discussions > li > a:nth-child(2)';
$(a).not(a + ':contains("' + author + '")' ).parent().hide();
a = '#user-discussions-on-scripts-written > ul > li a:nth-child(3)';
$(a).not(a + ':contains("' + author + '")' ).parent().hide();
let nodes = $('#discussions > li, .discussion-list > li');
let hidden = $('#discussions > li:hidden, .discussion-list > li:hidden').length;
let nodesLength = nodes.length;
if (nodes[nodes.length - 1].className === 'more-discussions'){
--nodesLength;
}
$('.filter-status').text((nodesLength - hidden) + ' (' + hidden + ' filtered)');
}
}
`;
var newScript = document.createElement('script');
newScript.innerHTML = myF;
document.body.appendChild(newScript);
// --------------------------------------------------------------------------------------
// the autocomplete searchbox
var cssTxt = GM_getResourceText ('jquery-ui.css');
GM_addStyle (cssTxt);
$('.dropdown').before(`
<div class="ui-widget">
<form id="myform">
<label for="authors">Enter an author:</label>
<input type="text" id="authors" name="valueId" /></p>
</form>
</div>
`);
// allAuthorsUnique.sort(); // sort array case sensitive
allAuthorsUnique.sort(function (a, b) { // sort array case insensitive
return a.toLowerCase().localeCompare(b.toLowerCase());
});
$( `#authors` ).autocomplete({source: allAuthorsUnique });
$('#myform').on('submit', function(e){
e.preventDefault();
showOnly($('#authors').val());
});
function showOnly(author){
$('.dropbtn').html('Filter by author (All)');
if (author === 'All'){
document.querySelector('.dropbtn').innerHTML = 'Filter by author (All)';
var a = '#discussions > li > a:nth-child(2), #user-discussions-on-scripts-written > ul > li a:nth-child(3)';
$(a).parent().show();
} else {
$('.dropbtn').html('Filter by author (' + author + ')');
a = '#discussions > li > a:nth-child(2), #user-discussions-on-scripts-written > ul > li a:nth-child(3)';
$(a).parent().show();
a = '#discussions > li > a:nth-child(2)';
$(a).not(a + ':contains("' + author + '")' ).parent().hide();
a = '#user-discussions-on-scripts-written > ul > li a:nth-child(3)';
$(a).not(a + ':contains("' + author + '")' ).parent().hide();
}
let nodes = $('#discussions > li, .discussion-list > li');
let hidden = $('#discussions > li:hidden, .discussion-list > li:hidden').length;
// $('.filter-status').text( (nodes.length - hidden) + ' (' + hidden + ' filtered)');
let nodesLength = nodes.length;
if (nodes[nodes.length - 1].className === 'more-discussions'){
--nodesLength;
}
$('.filter-status').text((nodesLength - hidden) + ' (' + hidden + ' filtered)');
}