// ==UserScript==
// @name Trim Reddit
// @namespace stgeorge
// @description Trimmer for Reddit
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @match *://old.reddit.com/*
// @match *://www.reddit.com/*
// @grant GM.xmlHttpRequest
// @grant GM.getValue
// @grant GM.setValue
// @grant GM.deleteValue
// @version 2.13
// @license MIT
// @run-at document-end
// ==/UserScript==
(() => {
let side = null;
let DONT_MATCH = [
/\/r\/\w+\/comments\//,
/\/login/,
/\/over18/,
];
const OPT_NEW_LINKS = true;
// 0 => load links in same tab
// 1 => image links in new tab
// 2 => all links in new tab.
const OPT_LINK_LOAD = 2;
const IMG_LINKS = $([
'imgur.com',
'i.imgur.com',
'preview.redd.it',
'youtube.com'
]);
function trim() {
$(`<style>
.selected .choice {
color: red !important;
}
.choice {
color: black !important;
}
#search {
text-align: center;
padding: 5px;
position: revert !important;
margin-top: 0 !important;
width: 80% !important;
transform:none !important;
}
#search input {
max-width: revert !important;
min-width: revert !important;
position: revert !important;
margin: 0 !important;
}
.tabmenu {
margin: 10px 0 10px 0;
position: revert !important;
}
.tabmenu li a {
font-weight: normal !important;
}
#body-wrapper {
display: flex;
background: white;
height: calc(100vh - 50px);
}
#header {
height: revert !important;
position: sticky !important;
font-size: 0.7rem;
background: white !important;
color: black !important;
border-bottom: solid 1px black !important;
padding: 0 !important;
}
#header * {
background-color: #fefefe !important;
color: black !important;
}
#newr,#lgn {
color: red !important;
}
#header::after {
position: revert !important;
}
.thing {
background-color:white !important;
}
.thing .title {
color: revert !important;
}
.link {
margin: 0 !important;
}
.link * {
padding: 3px 2px 0px 2px !important;
margin-right: revert !important;
}
.link .rank,.title::before,.midcol {
display: none !important;
}
.linkflairlabel {
cursor: pointer;
}
.entry {
margin-left: 2px !important;
}
body div.content {
margin: 5px !important;
}
.sitetable {
border-bottom: 0 !important;
border-left: 0 !important;
border-right:solid 1px #eeeeff !important;
margin-right: revert !important;
}
.linklisting.sitetable {
margin-right: 0 !important;
}
.listing-page #siteTable {
margin-right: 0;
}
#siteTable::before {
padding: 0 !important;
margin: 5px 0 5px 0 !important;
content: '' !important;
height: 0 !important;
width: 0 important;
border: none !important;
}
.curauthor {
color: red !important;
font-weight: bold !important;
}
.side {
margin: 0 !important;
z-index: 100 !important;
background: url('') !important;
background-color: transparent !important;
box-shadow: revert !important;
width:100% !important;
overflow-y:auto !important;
padding-top: 0 !important;
border-left: solid 1px black !important;
}
.side::before {
content: revert !important;
background: revert !important;
}
.side:after {
content: '';
}
.side * {
font-size: 16px !important;
text-align: left !important;
}
.side a {
background-color: revert !important;
}
a.title {
background: url('') !important;
}
.side .usertext p {
background-color: revert !important;
color: black !important;
padding: 0 !important;
}
.side .md blockquote {
position: relative !important;
}
.side .commentarea {
margin-right: revert !important;
}
.awardings-bar {
position: revert !important;
}
.sidemenu {
padding:2px 2px 5px 5px;
margin:2px;
background-color:#eee;
position:sticky;
top:0;
z-index:999;
}
.sidemenu-button {
font-weight:bold;
cursor:pointer;
}
.expando {
position: revert !important;
}
.expando-button {
display: none !important;
}
.md {
background: white !important;
}
div.md>blockquote>p {
position: inherit !important;
}
.md p::before {
width:0 !important;
}
.content:before {
background-color: revert !important;
background-image: revert !important;
height:0px !important;
}
.clicked {
background-color: #f8fefe !important;
border: solid 1px black !important;
border-radius:10px;
}
.ui-resizable-e {
cursor: e-resize;
width: 2px;
right: -1px;
top: 0;
bottom: 0;
background-color: blue !important;
}
#popup {
position: fixed;
top: 0;
left:0;
background:rgba(0,0,0,0.75);
width:100%;
height:100%;
display:none;
}
.searchpane,.search-result-group-header {
display:none !important;
}
.search-result-listing {
margin: revert !important;
}
.search-result-group {
max-width: 100% !important;
min-width: 100% !important;
padding-left: 5px !important;
padding-right: 5px !important;
}
.disabled {
cursor:not-allowed;
}
.hide {
display:none !important;
}
.menuarea,a[name="content"] {
visibility:hidden;
display:none;
}
</style>`).appendTo('head');
let tabmenu = $('.tabmenu').detach();
$('.infobar').remove();
$('.footer-parent').remove();
$('#sr-header-area').siblings().remove();
let content = $('.content[role="main"]');
content.css({
width:'35%',
// height: '1000px',
'overflow-y': 'auto',
resize:'horizontal',
margin: '0',
});
//
// We make the right-hand side sidebar (.side) bigger and empty its
// contents. Then, we make the main pane (.content) thinner and
// use it show the list of articles. (We mark it as resizable horizontally
// so that it can be widened.) When an article is clicked on in
// the .content pane, we show its threaded comments in the .side pane.
//
// +----------------------------------------------------+
// | #header |
// +----------------------------------------------------+
// | #body-wrapper (new) |
// | +-------------+----------------------------------+ |
// | | .content | .side | |
// | |+-----------+| | |
// | || tabmenu || | |
// | |+-----------+| | |
// | || #search || Post and comments | |
// | |+-----------+| | |
// | || Post list || | |
// | || ... || | |
// | |+-----------+| | |
// | +-------------+----------------------------------+ |
// +----------------------------------------------------+
//
if (document.URL.indexOf('old.reddit.com') != -1) {
$('body').css({'overflow-y':'hidden'});
}
let wrapper = $('<div id="body-wrapper"></div>');
$('#header').after(wrapper);
wrapper.append(content);
let search = $('#search').detach();
content.prepend(search);
search.find('label').detach();
let subs = /r\/(\w+)\//i.exec(top.location.href);
if (subs && subs.length > 1)
$('#search').children('input[name="q"]').first().val('subreddit:'+subs[1]+' ');
content.prepend(tabmenu);
side = $('.side');
side.empty();
wrapper.append(side);
$('.linkflairlabel').each(function(k,v) {
let t = $(this);
t.on('click', function(e) {
let url = document.URL.replace('old','www');
m = url.match(/(.*\/r\/.*?)\//);
top.location.href = m[1] + '?f=flair_name%3A%22'+encodeURIComponent(t.children('span:first').text())+'%22';
});
});
let curbg = 'white';
let first = null;
retargetLinks($('.entry').add('.search-result'));
$('.entry a').add('.search-result a').add('a.title')
.each(function(k,v) {
let t = $(this).closest('.thing');
if (t.length == 0)
t = $(this).closest('.search-result');
let a = $(this);
a.attr('title', a.text());
let href = a.attr('href');
if (href.indexOf('/comments/') != -1) {
a.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
t.css({'background-color':'#ffeeee'});
t.addClass('clicked');
t.siblings().css({'background-color':curbg});
t.siblings().removeClass('clicked');
href = href.replace('www.reddit.com', 'old.reddit.com').
replace('//reddit.com', '//www.reddit.com');
(async () => {await GM.setValue('lastseen', href)})();
loadComment(href+'?sort=new');
});
if (first === null && !t.hasClass('stickied')) {
first = a;
}
}
});
(async() => {
let last_seen = await GM.getValue('lastseen', null);
GM.deleteValue('lastseen');
let l = null;
if (last_seen) {
l = $('a[href="'+last_seen+'"]');
}
let to_show = (l && l.length > 0) ? l : first;
if (to_show) {
to_show.click();
}
})();
}
function canRetarget(href) {
do_retarget = false;
if (href) {
if (OPT_LINK_LOAD == 1) {
IMG_LINKS.each(function(x,y) {
if (href.indexOf('/'+y+'/') != -1) {
do_retarget = true;
return false;
}
});
} else if (OPT_LINK_LOAD == 2) {
do_retarget = (href.startsWith('http://') || href.startsWith('https://')) && (
(href.indexOf('.reddit.com/') == -1) || (
(href.indexOf('/comments/') == -1) && (
(href.indexOf('/user/') != -1) ||
(href.indexOf('/r/') != -1)
)
)
);
}
}
return do_retarget;
}
function retargetLinks(div) {
div.find('a').each(function(k,v) {
let anchor = $(this);
let href = anchor.attr('href');
if (canRetarget(href)) {
anchor.attr('rel','noopener');
anchor.attr('target','_new');
}
});
}
function toggleComments(expand) {
$('.commentarea').find('.comment').each(function(k,v) {
let cur = $(v);
let p = cur.parents('.comment');
if (p.length == 0) {
let children = cur.find('.comment');
if (expand) {
children.removeClass('collapsed').addClass('noncollapsed');
} else {
children.addClass('collapsed').removeClass('noncollapsed');
}
cur.removeClass('collapsed').addClass('noncollapsed');
}
});
}
function loadComment(u) {
GM.xmlHttpRequest({
method: "GET",
url: u+'?sort=new',
onload: function(response) {
side.html($.parseHTML(response.responseText));
let c = side.find('.content[role="main"]').detach();
side.empty();
side.append(`
<div class="sidemenu">
<span class="sidemenu-button" title="Expand/collapse lower levels" id="toggleall">[+/-]</span>
<span style="margin-left:1em" title="Next entry by user" class="hide sidemenu-button" id="fnext">[▼]</span>
<span class="hide sidemenu-button" title="Previous entry by user" id="fprev">[▲]</span>
</div>
</div>
`);
side.append(c);
c.css({margin:'10px'});
side.find('.infobar').detach();
let toggle_expand = false;
$('#toggleall').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
toggleComments(toggle_expand);
toggle_expand = !toggle_expand;
});
retargetLinks(side);
let all = [];
let all_index = -1;
let url = document.URL.replace(/\?.*/, '');
if (url.indexOf('/user/') != -1) {
side.find('a[href="'+url+'"]').each(function(k,v) {
let a = $(this);
all.push(a);
a.addClass('curauthor');
});
if (all.length > 0) {
$('.sidemenu-button').removeClass('hide');
$('#fnext').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (++all_index >= all.length)
all_index = 0;
scrollTo(side, all[all_index]);
});
$('#fprev').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (--all_index < 0)
all_index = all.length - 1;
scrollTo(side, all[all_index]);
});
}
}
setTimeout(function() {
$(document).scrollTop(0);
side.scrollTop(0);
// $('#toggleall').click();
}, 500);
}
});
}
function enable(x, v) {
if (v) {
$(x).removeClass('disabled');
} else {
$(x).addClass('disabled');
}
}
function scrollTo(p, el) {
if (!el) return;
setTimeout(function() {
p.scrollTop(el.offset().top - p.offset().top + p.scrollTop() - 50);
}, 500);
}
function fixHeader() {
//
// If OPT_NEW_LINKS is set, we add a 'new' link to to the header
// to toggle between old and new reddits and a 'login' link.
if (OPT_NEW_LINKS) {
let bars = $('#sr-bar');
let i = 0;
bars.find('li').each(function(k,v) {
if (i++ == 1) {
let li = $(this);
bars.prepend(addLink(li, 'newr', 'new',
top.location.href.replace('old','www'), 'New Reddit'));
bars.prepend(addLink(li, 'lgn', 'login',
top.location.href.replace(/\.com\/.*/, '.com/login'), 'Login'));
return false;
}
});
}
}
function addLink(template, new_id, new_text, new_url, new_title) {
let x = template.clone(true);
let span = x.find('span').first();
let a = x.find('a').first();
a.text(new_text);
a.attr('id', new_id);
a.attr('href', new_url);
a.attr('title', new_title);
span.before(a);
return x;
}
function addOldButton() {
//
// If we're in the 'new' reddit, add an 'Old' button to help
// us switch to old reddit.
//
if (document.URL.indexOf('www.reddit.com') != -1) {
let x = $('#email-verification-tooltip-id');
$('#email-verification-tooltip-id').
before($('<button title="Old Reddit" id="old-button" type="button">Old</button>'));
let old = $('#old-button');
old.css({
margin: '10px',
border: 'solid 1px #0079d3',
padding: '8px',
width: '120px',
'border-radius': '9999px',
color: '#0079d3',
'font-weight': 'bold',
});
old.on('click', function() {
top.location.hostname = 'old.reddit.com';
});
return;
}
}
// Main.
// The setTimeout is there to handle race conditions to run our
// script after reddit loads all its scripts. Doesn't seem to work
// always :-(
//
setTimeout(function() {
addOldButton();
let do_trim = true;
$(DONT_MATCH).each(function(k,v) {
if (document.URL.match(v)) {
do_trim = false;
return false;
}
});
if (do_trim) {
trim();
fixHeader();
}
}, 1000);
})();