Reddit Enhancer

Extends Reddit and adds some useful Functions. (Requires frisch's UserScript Extender)

Pada tanggal 16 November 2016. Lihat %(latest_version_link).

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Reddit Enhancer
// @namespace    http://null.frisch-live.de/
// @version      1.54
// @description  Extends Reddit and adds some useful Functions. (Requires frisch's UserScript Extender)
// @author       Johannes
// @include        http://*.reddit.com/*
// @include        https://*.reddit.com/*
// @exclude        https://*.reddit.com/message/*
// @exclude        http://*.reddit.com/message/*
// @exclude        https://*.reddit.com/search?*
// @grant   GM_getValue
// @grant   GM_setValue
// @grant        GM_openInTab
// ==/UserScript==
console.log("Initializing Reddit Enhancer...");

// Variables - Start
var usersToHide = [];
var subsToHide = [];
var keywordsToHide = [];

var settings = {
    markNSFW: true,
    hideUsers: true,
    hideSubs: true,
    hideUsersNSFWonly: true,
    hideItemTimeout: 500,
    hideKeywords: true,
    replaceTopNew: false,
    autoExpandSelectedPost: true,
    sortByVotes: false,
    panelView: false, // work in progress, not implemented functionally yet
    removeDuplicates: true,
    accountName: "enter your account name here, e.g. mine is frisch85",
};

var jq = document.fExt.jq;

var loc = jq(location).attr('href');
var isSinglePost = location.href.indexOf("/comments/") > 0 || location.href.indexOf("/submit$") > 0;
var isUserPage = location.href.indexOf("/user/") > 0 || location.href.indexOf("/u/") > 0;
var isUserSubmittedPage = isUserPage && location.href.indexOf("/submitted") > 0;
var isMyMulti = location.href.indexOf("/me/m/") > 0;
var isFriendsPage = location.href.indexOf("/r/friends") > 0;
var isSubmitPage = location.href.indexOf("/submit?") > 0;
var isMySavedPage = location.href.indexOf(settings.myAccountPage + "/saved") > 0;
var hiderElements = [];
var upVoteLinks = jq(".up:not(.archived)");
var downVoteLinks = jq(".down:not(.archived)");
var headerHeight = jq("#header").outerHeight(true);
var hideLinks = [];
var userHideLinks = [];
var subHideLinks = [];
var duplicateLinks = [];
var keywordsHideLinks = [];
var subColors = ["#A0C0EE", "#A0AAE0", "#C0EECC", "#E0CCE0", "#EEE0E0", "#CCC0EE", "#A0C0CC", "#CCAAA0", "#E0AAE0", "#A0A0A0", "#AACCEE", "#E0E0EE", "#C0CCCC", "#C0A0EE", "#C0E0C0", "#EEAAEE", "#EEE0C0", "#AAAAAA", "#AAC0EE", "#C0C0EE", "#AAAACC", "#EEC0EE", "#EEEEAA", "#C0C0AA", "#AAC0AA", "#E0C0EE", "#CCCCEE", "#EECCEE", "#C0E0AA", "#CCA0E0", "#AAA0EE", "#CCEEC0", "#A0E0A0", "#C0C0CC", "#A0AAEE", "#A0C0AA", "#A0CCCC", "#C0AAAA", "#AAC0CC", "#C0A0E0", "#C0CCAA", "#CCC0A0", "#C0E0A0", "#C0A0C0", "#A0C0A0", "#AAE0EE", "#EEE0A0", "#E0AAEE", "#A0E0C0", "#AAEEE0", "#C0A0CC", "#CCE0C0", "#C0C0C0", "#CCA0A0", "#CCEEA0", "#E0E0A0", "#AAC0A0", "#E0E0C0", "#EEAAE0", "#C0CCE0", "#CCAAEE", "#E0EECC", "#CCE0A0", "#CCC0E0", "#C0E0EE", "#EEEECC", "#AAA0AA", "#CCEEE0", "#A0E0E0", "#CCA0C0", "#A0EEAA", "#E0A0EE", "#AACCCC", "#CCEEAA", "#C0AACC", "#E0C0E0", "#C0A0A0", "#AAEEAA", "#AAC0C0", "#AAAAEE", "#A0AAC0", "#AAEECC"];
var markedSubs = [];
var hasFocused = false;
var rSubRedditLinks = jq("a.subreddit");
var rAuthorLinks = jq("a.author");
var rTitleLinks;
var rEnhSub = document.fExt.ctxMenu.addSub("Reddit Enhancer","top");
var postLst = jq("#siteTable");
var pstItems = [];
var pstSelected, pstFirst, pstLast;
var isInputFocused = false;
var reloadCancelled = true;
var resourcesLinks = [];

// Images
var imgBooks = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTMyQTVEQUUyQTIyMTFFMTlGMThGNDk3QjgyMTJCNjUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTMyQTVEQUYyQTIyMTFFMTlGMThGNDk3QjgyMTJCNjUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFMzJBNURBQzJBMjIxMUUxOUYxOEY0OTdCODIxMkI2NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFMzJBNURBRDJBMjIxMUUxOUYxOEY0OTdCODIxMkI2NSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgQa4kwAAAGQSURBVHjazFaBjYMwDIQXAzACI4BYoN2AblA2oBO0neD5CWADukG7QAUbPCNkA95+HZKVJyGlIL0lK62d+OLLEfCHYfDYfN/3pixN0x0NFbl6Pp+J96KN9QPTBAIIafgkPxryEY8E3rsAfhiKZDR8W0AuyLeunQUTu2SadgjxbnPyEPkY+VjkOX4EtbdZIBS5j0XJrrTwonXRiLVX8pLiHMsQ8106qgDSkR9G7ie66NBlBPpCw/lW+HvQgcZCewJRmFyQn/UuUCQTwJ6FGaPqzjTZQ6EIMcUbwOJWxHV6CyjVLgZYMRH7QvFGioRAHhpVmZPqLFaDjvH3iekVVDWiS/fnSDcIQ9L1e4ZQYjsH8kpH0hoCUBBPaJiTC9UtBootuR5yVouoczQWRiKUuQkQn9seir1PURqsBKRfRd5WQO0q8nawWXmvKYb/B1RuUD//A0TyPCHxEA9cv3ADvC6hmvUY8Oe+gsQrYHAEueFmV05fQQuNb/XyXTHUDlSVb6uOiuR4lfcTG2CQzrb+R4ABALaxlqMMGvrUAAAAAElFTkSuQmCC";
var imgDuplicate = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDQxOEI0NzM3NDlBMTFFMTk1RDhCRjg3NzZFMkRGMjMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDQxOEI0NzQ3NDlBMTFFMTk1RDhCRjg3NzZFMkRGMjMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpENDE4QjQ3MTc0OUExMUUxOTVEOEJGODc3NkUyREYyMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpENDE4QjQ3Mjc0OUExMUUxOTVEOEJGODc3NkUyREYyMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph2iTEwAAAGJSURBVHjatFbBcYMwEBSEAsiXV0ogwydPpwPTgd0BVMCkAruDuAOnA7sBZsgvT//40oFzx6wyZwfQacA7cyMBkvZuTzoRGEKWZWtqdmQvZhp7so+6rjvjiQAkR485Ddm7L1mESOwC7O2XeQAiIdcoyRLSsnRX7tDHYIJktrSRYqJKWnKowNiU7ETPN2ThFAMNjjXSCkcsLFmsIpJwbRL6fr57dUMWOiZ3MzdbT+YVkRJDjqUU1S5akoUUeBb5XVHDVpEVoXkQkLO9z/Z2grxPsbVXkC9nIs4xfTOL5AgkJyTeRvDvgC8hHZ+zHNWgpPZAFg/VujmRHMWB3kKmDdl5ESIhV08Asli8K2cT3ZEc0F5ETWQJm9EcoUpr8LcgIvmEdWMkluiCfqUk4y18wIIlCNlex0isdCWS2ifX7vuJO4o934jEG83VHqIq5yIyF3K0hbjkGufPiSL5V0vg+z8hb2fNgfXNYX9hYmxl1wh8vJqB/Mk1om3bnyRJvqn7NlRaFGpsWfJfAQYApiSqoZCrNjYAAAAASUVORK5CYII=";
var imgDelCat = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAG5SURBVEiJ3ZaxbhRBDIY/r45yOtImokVKc+N5gm0okiIFxUVpUiHlEWgipeENkNIkDQI6CiK60zZ0Z6p7ACQKmvAGic4UzMBmdTmSvRUI/mZ31rP+x/5tayTG+MDdD6qqOnJ3ZQCIiC0Wi5ci8srMrgBG7n4gImfuPgQHAO6uLZ/nAFVVVUeDMXTQ9l0Nla5laPselRczkyFJVPWGFtWQzlfh/yMaLftY8lt06+b7NqzS+e9G1D3ZEBX5T2n0GXgLfDCzj63vx8CzslgnoivgRQjhsZk975BgZichhK2ylhjjjdP3QUpp4u57QBk5JiLvZrPZm7JnaeruClV9yI/pvNMxPXL3p6q6Dxya2bc+Gn0NIWw1TXPdIvkEbAIbec8l8CXbzoHdPhGdNk1znVKatEjqTDTNe+pMNAV2UkqT3n2UNSETbJrZXFXrvH+uqtvZhrvvraNREX4DmKpqbWZzgEwy5Vcq9c9NbxExgBjjk3v+a/l5CdQlXaq6nSOrsw3AZDweH4rI2T0Ijs3sJPfOa35fDFFE9qXHdetneavqe1aXdwQuzGxX1rlmrWjYggtyw65FVHCXEfQdGszctvjNerkAAAAASUVORK5CYII=";
var imgAbort = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDZCQkYwMzM2Q0ExMUUyQjY5RUUwNzIwODVEMzBFMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDZCQkYwNDM2Q0ExMUUyQjY5RUUwNzIwODVEMzBFMyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0NkJCRjAxMzZDQTExRTJCNjlFRTA3MjA4NUQzMEUzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0NkJCRjAyMzZDQTExRTJCNjlFRTA3MjA4NUQzMEUzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Mya9PgAAAUlJREFUeNpi/P//PwM9ACPdLWJkZMSqwNjYWBJIxQKxOxAbALEQVOodEF8A4p1AvPjs2bPPsemHm4/LIqAFfECqGYgzgZiVgIN/A/F0IK4FWviJaIuAlmgBqc1ArERiCN0DYl+gZdcIWgS15CAQi5AZHW+A2B5mGVaLoMF1ngyfYPOZISgYYeYzoSlopoIlDFAzmrGmOhMTE1DqekhExBMLQAlE/syZM8/RfRRLRUsYoGbFwjjIFrnTIJ/CzWRBEjTAolABiD+SYPB7NL4BNouEsGj8CEw5H4i1BZhq0YWEsAUdTQGyRe9oYP47bEEHKiCd0MMcS3CQAi5g89FOGvhoJzaLFkMzGQMVM+xiDIug9cl0Klo0HbmOQk91tdACkVJwD2oW7hqWLtUELSs+rBkWqtAQiCcRmUB+Q9UaIlsysI2TYdOuAwgwAC/sonL067x5AAAAAElFTkSuQmCC";
var imgDelUser = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWhJREFUeNrEVottgzAQxVEGcDdwN4jEAA0bZAPMBFEmiDJB1AkKE2QEvAAqGzQjMELP1SOyELbPMlKfdLL4nN/5Pg9EEUBZlkdazmR2lWQTmSH7HIbBFAkQARJNy1fAtyGyNouISA60fDP8K+7Jdp77Z2agNfdEPqIT0/+USySZ/jKXaHP8O9HI9B9zibjDaHKJOqZ/t4UyPCLta2hYqy2a4QJtW4O932yidRG9e+kchLeG8CqyJ2rXufIUa28VCcQG0ZNp512F6x7Pg6I6R6k9aXsnu3ueL9HSyRqxQnBFGny4ITV9QomqPQgkasERyRbBpKAWILHRHRgOE6XhjXx+nJqMnu6Uzp5Pe6IHk8SVHLdJLmsfP5RhTq/aR+qxxCtCh+xOm06RT8jfiVIgaVOFZtAL8qAm7lIUGNApGjdroiWqUlQY/xMjuq9gzpERiz8fW68P5PcYE1RMvo4Na1TrOOBq3a8AAwDKrW/Ty1UcbgAAAABJRU5ErkJggg==";
var imgTree = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6REIzNzg4NjJDMjdBMTFFMTgyQTdCNUFCM0MyNUJCMTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6REIzNzg4NjNDMjdBMTFFMTgyQTdCNUFCM0MyNUJCMTYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4REUwQTc2QkMyNzgxMUUxODJBN0I1QUIzQzI1QkIxNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4REUwQTc2Q0MyNzgxMUUxODJBN0I1QUIzQzI1QkIxNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqK2+9QAAAEGSURBVHjavJWNDYMgEIWFCewGHcHECRihG+gGdhLdQDdoN6ALkLpBR5AN2iM5EtI09fg5LyFEJH4+jnsnqgLRtu0GU/1ni5VVmaj33osCas4wvfb2iUyIU6JhNGygGIiLnByNCLGUzSJRzQxTh48KlZVVBJAhgPTGmAdBlRWUGoCPnRDiADOuX2F9ov6gpNQAQpoAssRAyEeHEB1A+tgjp+ZIo7LVHVnKBZIRFuMgCtRYTlB2UEEWi1Nzg5SHYbHygCAvLj/+pnUpMEmpaoTdv2BDDEgkWtAYWNBCcZcSpnqBcePsRx5mCTaW3WGfRzQ+f+1Xtsb3o6Vv7CCEvY/yut1a/AgwACqvUiICIj/gAAAAAElFTkSuQmCC";

// Variables - End

// Initialization - Start
GMLoadSettings();
GMLoad();

// Initialization - Styles - Start
document.fExt.createStyle("#header { z-index: 107; }");
document.fExt.createStyle("body.with-listing-chooser>.content, body.with-listing-chooser .footer-parent { margin-left: 0 !important; }");
document.fExt.createStyle("div.listing-chooser { left: 0; }");
document.fExt.createStyle("div.side { right: 0; }");
document.fExt.createStyle("div.side, div.listing-chooser { z-index: 106; position: fixed !important; height: auto; top: " + header + "px !important; margin: 0; border: 1px solid black; width: 50px !important; overflow-y: hidden !important; padding: 0 !important; }");
document.fExt.createStyle("div.side:hover { width: 500px !important; overflow-y: auto !important; max-height: 100vh; }");
document.fExt.createStyle("div.listing-chooser:hover { width: 500px !important; overflow-y: auto !important; max-height: 100vh; }");
document.fExt.createStyle("span.domain { font-weight: bold; }");

document.fExt.createStyle("div.content { padding-top: 80px  !important; }");
document.fExt.createStyle(".tabButton { color: #333333 !important; background-color: rgb(252, 255, 215) !important; border: 1px solid black; }");
document.fExt.createStyle(".spacerLi { width: 50px; }");
document.fExt.createStyle("#postNavigation { position: fixed !important; top: 24px; width: 250px; margin: 0 auto 0 auto; display: block; z-index: 108; font-size: 12px; font-weight: bold; left: 0; right: 0; } ");
document.fExt.createStyle("#postNavigation a { background-color: #ffffff;  border: 1px solid black;  padding: 8px 14px;  margin: 0 1px; }");
document.fExt.createStyle("#postNavigation a:hover { background-color: #dfdfdf; }");
document.fExt.createStyle(".pstSelected { border: 2px solid #dfdfff; }");
document.fExt.createStyle(".pstSelected, .pstSelected * { z-index: 105; }");

document.fExt.createStyle(".midcol { width: 32px !important; }");

if(!settings.panelView) {
    if(isSinglePost) {
        document.fExt.createStyle(".livePreview { width: 1600px !important; }");
        document.fExt.createStyle(".livePreview p, .livePreview ol { width: 1500px !important; }");
        document.fExt.createStyle("div.usertext-edit { max-width: 50%; };");
        document.fExt.createStyle("div.usertext-edit div.md { width: 100%; max-width: 100%; }");
        document.fExt.createStyle("div.usertext-edit div.md textarea { width: 100%; }");
    }
    else {
        document.fExt.createStyle(".md { max-width: none !important; }");
        document.fExt.createStyle(".madeVisible *,div.expando * { z-index: 105; }");
        document.fExt.createStyle("a.madeVisible img, a.madeVisible video { max-height: 100vh !important; max-width: 95vw !important;}");
        document.fExt.createStyle("body { margin-bottom: 650px !important; }");
        document.fExt.createStyle("img.RESImage { border-bottom: #000 solid 3px !important; padding: 0 !important; }");
        //document.fExt.createStyle("div.thing * { color: #ffffff !important; background-color: inherit !important; }");
        document.fExt.createStyle("div.thing { min-height: 80px; padding: 5px 0; margin: 0 50px; border-top: 1px solid lightgrey; }");
        document.fExt.createStyle("div.thing div.entry img, div.thing div.entry video { display: none !important; }");
        document.fExt.createStyle("div.thing.pstSelected div.entry img, div.thing.pstSelected div.entry video { display: block !important; }");
        if(settings.markNSFW) {
            document.fExt.createStyle(".NsfwItem { border: 4px solid rgb(255, 196, 196); }");
            document.fExt.createStyle(".NsfwItem .madeVisible { display: none; }");
            document.fExt.createStyle(".pstSelected .NsfwItem .madeVisible { display: initial !important; }");
            document.fExt.createStyle(".pstSelected .NsfwItem .madeVisible div { width: auto !important; }");
            document.fExt.createStyle(".pstSelected .NsfwItem * { z-index: 104 !important; }");
        }
        document.fExt.createStyle("a.subreddit { color: #000000 !important; margin: 10px; padding: 5px 20px 5px 0px !important; float: left; width: 100px; font-size: larger; }");
        document.fExt.createStyle("p.title { color: #000000 !important; padding: 13px 30px !important; float: left; margin: 0; font-weight: bold; font-size: 15px !important; }");
        document.fExt.createStyle("p.title a { color: #000000 !important; }");
        document.fExt.createStyle(".RES-keyNav-activeElement, .RES-keyNav-activeElement .md-container { background-color: transparent !important; }");
        document.fExt.createStyle("ul.flat-list.buttons { width: 800px; margin: 20px auto 0 auto; font-size: larger; text-align: center; left: 0; right: 0; clear: both; }");
        document.fExt.createStyle("ul.flat-list.buttons li { padding: 4px; background-color: #fff; margin: 2px; border: 1px solid #999; }");
        document.fExt.createStyle(".usertext * { z-index: 1; }");
        document.fExt.createStyle("div.thing div.entry div.expando { display: block !important; }");
        document.fExt.createStyle("div.thing div.entry div.expando span { display: none; }");
    }
    document.fExt.createStyle(".toggleHidden, div.thing.hidden { background: repeating-linear-gradient(45deg, transparent, transparent 35px, rgba(255,255,255,.5) 35px, rgba(255,255,255,.5) 70px); }");
    document.fExt.createStyle(".userHidden .author { text-decoration: line-through; }");
    document.fExt.createStyle(".subsHidden .subreddit { text-decoration: line-through; }");

    document.fExt.createStyle(".userHidden a.title, .subsHidden a.title, .duplicateHidden a.title { background-position: 0 !important; background-repeat: no-repeat !important; padding: 8px 8px 8px 26px; }");
    document.fExt.createStyle(".userHidden a.title { background-image: url('" + imgDelUser + "') !important; }");
    document.fExt.createStyle(".subsHidden a.title { background-image: url('" + imgDelCat + "') !important; }");
    document.fExt.createStyle(".duplicateHidden a.title { background-image: url('" + imgDuplicate + "') !important; }");
}
else {
    // New Panel View
    if(isSinglePost) {
        document.fExt.createStyle(".livePreview { width: 1600px !important; }");
        document.fExt.createStyle(".livePreview p, .livePreview ol { width: 1500px !important; }");
        document.fExt.createStyle("div.usertext-edit { max-width: 50%; };");
        document.fExt.createStyle("div.usertext-edit div.md { width: 100%; max-width: 100%; }");
        document.fExt.createStyle("div.usertext-edit div.md textarea { width: 100%; }");
    }
    else {
        document.fExt.createStyle(".sitetable { padding: 55px !important; padding: 0 60px; }");
        document.fExt.createStyle(".madeVisible *,div.expando * { z-index: 1; }");
        document.fExt.createStyle("a.madeVisible img, a.madeVisible video { max-height: 100vh !important; max-width: 95vw !important;}");
        document.fExt.createStyle("body { margin-bottom: 650px !important; }");
        document.fExt.createStyle("img.RESImage { border-bottom: #000 solid 3px !important; padding: 0 !important; }");
        //document.fExt.createStyle("div.thing * { color: #ffffff !important; background-color: inherit !important; }");
        document.fExt.createStyle("div.thing { float: left; width: 500px; height: 320px; position: relative; }");
        document.fExt.createStyle("div.thing div.entry img, div.thing div.entry video { display: none !important; }");
        document.fExt.createStyle("div.thing.pstSelected div.entry img, div.thing.pstSelected div.entry video { display: block !important; }");
        if(settings.markNSFW) {
            document.fExt.createStyle(".NsfwItem { border: 4px solid rgb(255, 196, 196); }");
            document.fExt.createStyle(".NsfwItem .madeVisible { display: none; }");
            document.fExt.createStyle(".pstSelected .NsfwItem .madeVisible { display: initial !important; }");
            document.fExt.createStyle(".pstSelected .NsfwItem .madeVisible div { width: auto !important; }");
            document.fExt.createStyle(".pstSelected .NsfwItem * { z-index: 101 !important; }");
        }
        document.fExt.createStyle("a.subreddit { color: #000000 !important; margin: 10px; padding: 5px 20px 5px 0px !important; float: left; width: 100px; font-size: larger; }");
        document.fExt.createStyle("p.title { color: #000000 !important; padding: 13px 30px !important; float: left; margin: 0; font-weight: bold; font-size: larger; }");
        document.fExt.createStyle("p.title a { color: #000000 !important; }");
        document.fExt.createStyle("flat-list buttons { font-size: larger; padding: 2px 4px; }");
        document.fExt.createStyle(".RES-keyNav-activeElement, .RES-keyNav-activeElement .md-container { background-color: transparent !important; }");
        document.fExt.createStyle("ul.flat-list.buttons { position: absolute; right: 0; bottom: 0; left: 0; font-size: larger; text-align: center; }");
        document.fExt.createStyle("ul.flat-list.buttons li { padding: 4px; background-color: #fff; margin: 2px; border: 1px solid #999; }");
        document.fExt.createStyle(".usertext * { z-index: 1; }");
        document.fExt.createStyle("div.thing div.entry div.expando { margin-top: 50px; display: block !important; }");
        document.fExt.createStyle("div.thing div.entry div.expando span { display: none; }");
    }
    document.fExt.createStyle(".toggleHidden { background: repeating-linear-gradient(45deg, transparent, transparent 35px, rgba(255,255,255,.5) 35px, rgba(255,255,255,.5) 70px); }");
    document.fExt.createStyle(".userHidden .author { text-decoration: line-through; }");
    document.fExt.createStyle(".subsHidden .subreddit { text-decoration: line-through; }");
}

jq("body").css("margin-bottom","0");
// Initialization - Styles - End

// Initialization - Controls - Start
var rPostNavigation = jq('<div id="postNavigation"><a href="#" id="topPost">Top</a><a href="#" id="frPost">&lt;&lt;</a><a href="#" id="prevPost">&lt;</a><a href="#" id="nextPost">&gt;</a><a href="#" id="ffPost">&gt;&gt;</a><a href="#" id="botPost">Bottom</a></div>');
rPostNavigation.appendTo("body");

var rTabMenu = jq("ul.tabmenu");
var rSpacerLi1 = jq('<li class="spacerLi" id="spacerLi1"></li>');
rSpacerLi1.appendTo(rTabMenu);

jq('<li><a href="#" class="choice tabButton" title="Downvotes all displayed posts" id="downvoter">downvote</a></li>').insertAfter(rSpacerLi1);
jq('<li><a href="#" class="choice tabButton" title="Updvotes all displayed posts" id="upvoter">upvote</a></li>').insertAfter(rSpacerLi1);

if(!isSinglePost){
    jq('<li><a href="#" class="choice tabButton" title="Expands all posts" id="expander">expand</a></li>').insertAfter(rSpacerLi1);

    var spacerLi2 = jq('<li class="spacerLi" id="spacerLi2"></li>');
    spacerLi2.appendTo(rTabMenu);
    jq('<li><a href="#" class="choice tabButton" style="background-color: rgb(175, 255, 171) !important;" title="Toggles the hidden User posts" id="toggleUserHidden">Toggle hidden Users</a></li>').insertAfter(spacerLi2);
    jq('<li><a href="#" class="choice tabButton" style="background-color: rgb(175, 255, 171) !important;" title="Toggles the hidden Sub posts" id="toggleSubsHidden">Toggle hidden Subs</a></li>').insertAfter(spacerLi2);
    jq('<li><a href="#" class="choice tabButton" style="background-color: rgb(175, 255, 171) !important;" title="Toggles the hidden Keyword posts" id="toggleKeywordsHidden">Toggle hidden Keywords</a></li>').insertAfter(spacerLi2);
    jq('<li><a href="#" class="choice tabButton" style="background-color: rgb(175, 255, 171) !important;" title="Toggles the duplicate posts" id="toggleDuplicateHidden">Toggle hidden Duplicates</a></li>').insertAfter(spacerLi2);
    jq('<li><a href="#" class="choice tabButton" style="background-color: rgb(255, 138, 138) !important;" title="Hides all displayed posts which prevents them from showing up again" id="hider">hide</a></li>').insertAfter(spacerLi2);

    var spacerLi3 = jq('<li class="spacerLi" id="spacerLi3"></li>');
    spacerLi3.appendTo(rTabMenu);
    if(loc.indexOf("show=all") < 0)
        jq('<li><a href="' + loc.replace('#','') + '?show=all" title="Show all posts (including the hidden posts)" class="choice tabButton" style="background-color: rgb(187, 187, 255) !important;" id="showAll">Show All</a></li>').insertAfter(spacerLi3);
}

document.fExt.createStyle("#rEnhSettings { position: fixed; top: 0; border: 1px solid black; display: block; width: 700px; padding: 12px; z-index: 1000; background-color: #FEFEFE; right: 0; left: 0; margin-right: auto; margin-left: auto; }");
document.fExt.createStyle("#rEnhSettings * { z-index: 1000; margin: 4px; }");
document.fExt.createStyle("#rEnhSettings a { padding: 4px; border: 1px solid grey; float: right; }");

// Initialization - Controls - Settings Dialog
var settingsDialog = '<div style="display:none" id="rEnhSettings">';
for(var key in settings) {
    if(key === "subsToHide" || key === "usersToHide" || key === "keywordsToHide")
        continue;

    var varType = typeof settings[key];
    switch(varType){
        case "boolean":
            settingsDialog += '<input type="checkbox"" class="settingsControl" name="' + key + '" id="' + key + '"> ' + key + '<br/>';
            break;
        case "number":
            settingsDialog += key + '<input type="number" class="settingsControl" name="' + key + '" id="' + key + '"><br/>';
            break;
        case "string":
            settingsDialog += key + '<input type="text" class="settingsControl" name="' + key + '" id="' + key + '"><br />';
            break;
        default:
            console.log("Cannot add setting " + key + " to settings dialog because unkown type " + varType);
            break;
    }
}

settingsDialog += '<label id="rEnhSettingsUserlistLabel" for="rEnhSettingsUserlist">Users to hide:</label><textarea name="rEnhSettingsUserlist" id="rEnhSettingsUserlist" cols="80" rows="10"></textarea><br/>';
settingsDialog += '<label id="rEnhSettingsSublistLabel" for="rEnhSettingsSublist">Subs to hide:</label><textarea name="rEnhSettingsSublist" id="rEnhSettingsSublist" cols="80" rows="10"></textarea><br/>';
settingsDialog += '<label id="rEnhSettingsKeywordlistLabel" for="rEnhSettingsKeywordlist">Keywords to hide:</label><textarea name="rEnhSettingsKeywordlist" id="rEnhSettingsKeywordlist" cols="80" rows="10"></textarea><br/>';
settingsDialog += '</br></br>';
settingsDialog += '<a href="#" id="renhSettingsClose">Close</a>';
settingsDialog += '<a href="#" id="renhSettingsSave">Save</a>';
settingsDialog += '</div>';
settingsDialog += '</div>';
jq("body").append(settingsDialog);
// Initialization - Controls - End

// Replacing images on imgur from those faggots who can't link properly
jq("a.thumbnail, a.imgScanned").each(function(index, item){
    var jqItem = jq(item);
    var href = jqItem.attr("href");
    if(href.indexOf("imgur") >= 0 && href.indexOf("gallery/") >= 0) {
        href = href.replace("gallery/", "");
        if(href.indexOf("/new") >= 0)
            href = href.replace("/new","");
        if(href.indexOf(".png") == -1 && href.indexOf(".jpg") == -1)
            href = href + ".png";

        jqItem.attr("href", href);
    }
});

// Holy crap that new outbound url remapping is annoying af... here let's fix this shit
jq("a[data-href-url]").each(function(){
    var jqThis = jq(this);
    jqThis.attr("data-outbound-url",jqThis.attr("data-href-url"))
        .attr("href",jqThis.attr("data-href-url"));
});

if(settings.replaceTopNew) {
    jq("a.subreddit").each(function(index, item){
        var jqItem = jq(item);
        var hrefLink = jqItem.attr("href");
        if(!hrefLink.match(".*/$")) {
            hrefLink = hrefLink + "/";
        }
        hrefLink = hrefLink + "new";
        jqItem.attr("href",hrefLink);
    });
}
if(settings.markNSFW) {
    jq("span.nsfw-stamp").each(function(index, item){
        jq(item).parents("div.entry").addClass("NsfwItem");
    });
}

jq("a.comments.empty").each(function(index, item){
    Mark(jq(item), "uncommented");
});

jq("span.domain a").each(function(index, item){
    var jqItem = jq(item);
    var parentItem = jqItem.parents("div.entry");
    var txt = jqItem.text();

    if(txt.indexOf("youtu") >= 0)
        Mark(parentItem, "video");
    else if(txt.indexOf("imgur") >= 0 || txt.indexOf("gfycat") >= 0)
        Mark(parentItem, "image");
});

// remove Gild and Share button
jq("li.give-gold-button, li.share").remove();

// highlight hide/unhide
var hideSubsFromLocation = false;
var hideUsersFromLocation = false;

if(!isMyMulti && !isMySavedPage && !isSinglePost && !isFriendsPage) {
    hideSubsFromLocation = true;
    hideUsersFromLocation = true;
}

if(!isSinglePost) {
    if(!isUserPage && settings.sortByVotes) {
        jq("div.deleted").fadeOut();

        var pstThings = postLst.children("#siteTable div.thing:visible");
        pstThings.sort(function(a, b) {
            var scoreA = parseInt(jq(a).find("div.score.unvoted").text());
            var scoreB = parseInt(jq(b).find("div.score.unvoted").text());

            if(isNaN(scoreA))
                scoreA = 0;
            else if(scoreA <= 0)
                scoreA -= 1;
            if(isNaN(scoreB))
                scoreB = 0;
            else if(scoreB <= 0)
                scoreB -= 1;


            if(scoreA > scoreB)
                return -1;
            else if(scoreA < scoreB)
                return 1;
            else
                return 0;
        });

        jq(postLst).prepend(pstThings);
        jq(postLst).append(pstThings);
    }

    postLst.children("#siteTable div.thing:visible").each(function(index, item){
        pstItems.push("#" + jq(item).attr("id"));
    });

    if(pstItems.length > 0) {
        pstFirst = pstItems[0];
        pstLast = pstItems[pstItems.length-1];
    }

    jq("a.title").each(function(){
        var jqThis = jq(this);
        var text = jqThis.text();
        if(text.length > 160) {
            var spacerInd = text.substring(0,140).lastIndexOf(" ");
            jqThis.attr("title","..." + text.substring(spacerInd));
            jqThis.text(text.substring(0,spacerInd) + "... (more)");
        }
    });

    jq("div.thing.promotedlink").each(function(){
        AddToHideLinks(jq(this));
    });

    if(settings.removeDuplicates){
        jq("span.RESdupeimg:visible").each(function(index, item) { Hide(jq(item).parents("div.thing"), false); });

        jq("div.thing").each(function(){
            var jqThis = jq(this);
            var resource = jqThis.find("a.title").attr("href");
            if(resourcesLinks.indexOf(resource) >= 0) {
                jqThis.addClass("duplicateHidden");
                AddToHideLinks(jqThis);
                duplicateLinks.push(jqThis);
            }
            else
                resourcesLinks.push(resource);
        });
    }

    if(!isFriendsPage && !isUserSubmittedPage){
        rAuthorLinks.each(function(index, item){
            var jqItem = jq(item);
            var userName = jqItem.text().replace("/r/","");
            var userIndex = jq.inArray(userName, usersToHide);
            var itemThing = jqItem.parents("div.thing");
            if(userIndex  >= 0) {
                var hideThisPost = settings.hideUsers &&
                    !isUserPage &&
                    (settings.hideUsersNSFWonly && jqItem.parents("div.entry").hasClass("NsfwItem") || !settings.hideUsersNSFWonly);

                if(hideThisPost)
                    AddToHideLinks(itemThing);

                userHideLinks.push(itemThing);
                itemThing.addClass("userHidden");
            }
        });
    }

    var hideThisPost = settings.hideKeywords && !isUserPage;
    jq(keywordsToHide).each(function(index, item) {
        if (item.length > 0) {
            jq("a.title:contains(" + item + ")").each(function(jndex, jtem){
                var jqItem = jq(jtem);
                var itemThing = jqItem.parents("div.thing");

                if(hideThisPost)
                    AddToHideLinks(itemThing);

                keywordsHideLinks.push(itemThing);
                itemThing.addClass("keywordsHidden");
            });
        }
    });
}

if(loc.indexOf("/r/all") >= 0) {
    rSubRedditLinks.each(function(index, item){
        var jqItem = jq(item);
        var subName = jqItem.text().replace("/r/","");
        var subIndex = jq.inArray(subName, subsToHide);
        var itemThing = jqItem.parents("div.thing");
        if(subIndex  >= 0) {
            if(hideSubsFromLocation)
                AddToHideLinks(itemThing);
            subHideLinks.push(itemThing);
            itemThing.addClass("subsHidden");
        }
    });
}

rAuthorLinks.each(function(index, item){ var jqItem = jq(item); jqItem.attr("href",jqItem.attr("href") + "/submitted/"); });

jq("#toggleSubsHidden").text("Show Subs (" + subHideLinks.length + ")");
jq("#toggleUserHidden").text("Show Users (" + userHideLinks.length + ")");
jq("#toggleKeywordsHidden").text("Show Keywords (" + keywordsHideLinks.length + ")");
jq("#toggleDuplicateHidden").text("Show Duplicates (" + duplicateLinks.length + ")");

jq(hideLinks).each(function(index, item) {
    jq(item).css("display","none");
});

HideAndAction(hideLinks, 0, null, "enhance");

if(!isSinglePost && !isSubmitPage) {
    if(document.hasFocus())
        MakeActivePost(undefined, pstFirst);
    else {
        focusFirstPost = function(){
            setTimeout(function(){
                MakeActivePost(undefined, pstFirst);
            }, 500);
            window.removeEventListener("focus", focusFirstPost, true);
        };
        window.addEventListener("focus", focusFirstPost, true);
    }

}

if(!isSinglePost) {
    var subs = jq("a.subreddit");
    if(subs.length > 0){
        subs.each(function(index, item){
            var jqItem = jq(item);
            var subText = jqItem.text().replace("/r/","");
            var subIndex = jq.inArray(subText, markedSubs);
            var eleParent = jqItem.parent().parent();

            if(subIndex < 0)
                subIndex = markedSubs.push(subText)- 1;

            var subColor = subColors[subIndex];
            jqItem.detach().prependTo(eleParent);
            jqItem.text(subText);

            jqItem.parents("div.thing").css("background-color", subColor);
        });
    }
    else {
        jq("span.domain a").each(function(index, item){
            var jqItem = jq(item);
            var subText = jqItem.text().replace("/r/","");
            var subIndex = jq.inArray(subText, markedSubs);
            var eleParent = jqItem.parent().parent();

            if(subIndex < 0)
                subIndex = markedSubs.push(subText) - 1;

            var subColor = subColors[subIndex];
            jqItem.parents("div.thing").css("background-color", subColor);
        });
    }
}

// Marks Rating of Posts
jq("div.thing div.midcol").each(function(index, item){
    var jqItem = jq(item);
    var pts = jqItem.find("div.score.unvoted").text();
    if(pts > 50) jqItem.css("background-color", "#99FF99");
    else if(pts > 0) jqItem.css("background-color", "#CCFFCC");
    else if(pts < -10) jqItem.css("background-color", "#FF9999");
    else if(pts < 0) jqItem.css("background-color", "#FFCCCC");
});

jq(".last-clicked").removeClass("last-clicked");
jq(".promotedlink").remove();
// Infomessages
document.fExt.popup(usersToHide.length + " Users in hidelist.");
document.fExt.popup(subsToHide.length + " Subs in hidelist.");
document.fExt.popup(keywordsToHide.length + " Keywords in hidelist.");

// Initialization - End

// Events - Start
jq("#fExtMessage").click(function(){
    reloadCancelled = true;
});

jq("#hider").click(function(){
    var siteTable = jq("#siteTable");
    siteTable.css("display","block");
    siteTable.css("height", siteTable.outerHeight(true) + "px");

    jq("div.thing:visible").each(function(index, thing){
        var jqThing = jq(thing);
        var offs = jqThing.offset();
        var top = parseInt(offs.top);
        var width = jqThing.width();
        var height = jqThing.height();

        setTimeout(function() {
            jqThing.css({
                top: top,
                left: 0,
                width: width,
                height: height,
                position: "absolute"
            });
        }, 500);
    });

    reloadCancelled = false;
    setTimeout(function(){
        HideAndAction(hiderElements, 0, null, "reload");
    },500);
    jq(this).hide();
    return false;
});


if(userHideLinks.length === 0)
    jq("#toggleUserHidden").attr("style","background-color: #808080 !important; color: #CFCFCF; border: 1px solid black;");
else {
    jq("#toggleUserHidden").click(function(e){
        ToggleVisibility(e, this, ".userHidden");
        return false;
    });
}
if(subHideLinks.length === 0)
    jq("#toggleSubsHidden").attr("style","background-color: #808080 !important; color: #CFCFCF; border: 1px solid black;");
else {
    jq("#toggleSubsHidden").click(function(e){
        ToggleVisibility(e, this, ".subsHidden");
        return false;
    });
}
if(duplicateLinks.length === 0)
    jq("#toggleDuplicateHidden").attr("style","background-color: #808080 !important; color: #CFCFCF; border: 1px solid black;");
else {
    jq("#toggleDuplicateHidden").click(function(e){
        ToggleVisibility(e, this, ".duplicateHidden");
        return false;
    });
}
if(keywordsHideLinks.length === 0)
    jq("#toggleKeywordsHidden").attr("style","background-color: #808080 !important; color: #CFCFCF; border: 1px solid black;");
else {
    jq("#toggleKeywordsHidden").click(function(e){
        ToggleVisibility(e, this, ".keywordsHidden");
        return false;
    });
}

// User Hider
var ctxItemUsrHdr = document.fExt.ctxMenu.addItem("Hide User", "hideUser", rEnhSub);
ctxItemUsrHdr.Action = function(event, sender, actor) {
    var user = actor.text();
    var selector = "a.author:contains(" + user + ")";
    var args = [usersToHide, "Users", user, selector];
    if(HideObject.apply(sender, args))
        AddUndo(UnhideObject, args, HideObject, args);
};

var ctxItemUsrHdrPg = document.fExt.ctxMenu.addItem("Hide User and open Userpage", "hideOpenUser", rEnhSub);
ctxItemUsrHdrPg.Action = function(event, sender, actor) {
    ctxItemUsrHdr.Action(event, sender, actor);
    GM_openInTab("https://www.reddit.com/u/" + actor.text() + "/submitted/", true);
};

var ctxItemUsrUnhdr = document.fExt.ctxMenu.addItem("Unhide User", "unhideUser", rEnhSub);
ctxItemUsrUnhdr.Action = function(event, sender, actor) {
    var user = actor.text();
    var selector = "a.author:contains(" + user + ")";
    var args = [usersToHide, "Users", user, selector];
    if(UnhideObject.apply(sender, args)){
        jq("a.author:contains(" + user + ")").parents("div.thing").each(function(index,item) {
            jq(item).show();
        });
        AddUndo(HideObject, args, UnhideObject, args);
    }
};

document.fExt.ctxMenu.addSeparator(rEnhSub);

var ctxItemSbHdr = document.fExt.ctxMenu.addItem("Hide Sub", "hideSub", rEnhSub);
ctxItemSbHdr.Action = function(event, sender, actor) {
    var sub = actor.text().replace("/r/","");
    var selector = "a.subreddit:contains(" + sub + ")";
    var args = [subsToHide, "Subs", sub, selector];
    if(HideObject.apply(sender, args))
        AddUndo(UnhideObject, args, HideObject, args);
};

var ctxItemSbUnhdr = document.fExt.ctxMenu.addItem("Unhide Sub", "unhideSub", rEnhSub);
ctxItemSbUnhdr.Action = function(event, sender, actor) {
    var sub = actor.text().replace("/r/","");
    var selector = "a.subreddit:contains(" + sub + ")";
    var args = [subsToHide, "Subs", sub, selector];
    if(UnhideObject.apply(sender, args)){
        jq(selector).parents("div.thing").each(function(index,item) {
            jq(item).show();
        });
        AddUndo(HideObject, args, UnhideObject, args);
    }
};

document.fExt.ctxMenu.addSeparator(rEnhSub);

var ctxItemKeywHdr = document.fExt.ctxMenu.addItem("Hide Keywords", "hideKeyw", rEnhSub);
ctxItemKeywHdr.Action = function(event, sender, actor) {
    var keyword = document.fExt.getSelection().trim();
    var selector = "a.title:contains(" + keyword + ")";
    var args = [keywordsToHide, "Keywords", keyword, selector];
    if(HideObject.apply(sender, args))
        AddUndo(UnhideObject, args, HideObject, args);
};

var ctxItemKeywUnhdr = document.fExt.ctxMenu.addItem("Unhide Keywords", "unhideKeyw", rEnhSub);
ctxItemKeywUnhdr.Action = function(event, sender, actor) {
    var keyword = document.fExt.getSelection();
    var selector = "a.title:contains(" + keyword + ")";
    var args = [keywordsToHide, "Keywords", keyword, selector];
    if(UnhideObject.apply(sender, args)){
        jq(selector).parents("div.thing").each(function(index,item) {
            jq(item).show();
        });
        AddUndo(HideObject, args, UnhideObject, args);
    }
};

document.fExt.ctxMenu.addSeparator(rEnhSub);

// Undo/Redo
var ctxUndo = document.fExt.ctxMenu.addSub("Undo", undefined, rEnhSub);
var ctxRedo = document.fExt.ctxMenu.addSub("Redo", undefined, rEnhSub);

document.fExt.ctxMenu.addSeparator(rEnhSub);

var ctxItemCpyHtml = document.fExt.ctxMenu.addItem("Copy HTML", "rEnhCopyToClipboard", rEnhSub);
ctxItemCpyHtml.Action = function(event, sender, actor) {
    document.fExt.clipboard("Copy", jq('div.content').html());
};

document.fExt.ctxMenu.addSeparator(rEnhSub);

var ctxItemSett = document.fExt.ctxMenu.addItem("REnhancer Settings", "rEnhSettings", rEnhSub);
ctxItemSett.Action = function() { OpenSettings(); };

// Kontext-Menü
jq("#fExtContextMenu").on("fExtContextMenuOpening", function(event, actor){
    var txt = actor.text();
    var usrIndex = jq.inArray(txt, usersToHide);
    var usrTxt = 'Select a User';
    var subIndex = jq.inArray(txt, subsToHide);
    var subTxt = 'Select a Subreddit';
    var bCanHide = actor.hasClass("author") && usrIndex < 0;
    var bCanUnhide = !bCanHide && actor.hasClass("author") && usrIndex >= 0;

    ctxItemUsrHdr.Toggle(bCanHide);
    ctxItemUsrHdrPg.Toggle(bCanHide);
    ctxItemUsrUnhdr.Toggle(bCanUnhide);
    if(actor.hasClass("author"))
        usrTxt = txt;

    ctxItemUsrHdr.ItemText("Hide User - " + usrTxt);
    ctxItemUsrHdrPg.ItemText("Hide User and open Page - " + usrTxt);
    ctxItemUsrUnhdr.ItemText("Unhide User - " + usrTxt);

    bCanHide = actor.hasClass("subreddit") && subIndex < 0;
    bCanUnhide = !bCanHide && actor.hasClass("subreddit") && subIndex >= 0;

    ctxItemSbHdr.Toggle(bCanHide);
    ctxItemSbUnhdr.Toggle(bCanUnhide);
    if(actor.hasClass("subreddit"))
        subTxt = txt;

    ctxItemSbHdr.ItemText("Hide Sub - " + subTxt);
    ctxItemSbUnhdr.ItemText("Unhide Sub - " + subTxt);

    txt = document.fExt.getSelection();
    var keywIndex = jq.inArray(txt, keywordsToHide);
    var keywTxt = 'Select word(s)';
    bCanHide = txt !== "" && keywIndex < 0;
    bCanUnhide = !bCanHide && txt !== "" && keywIndex >= 0;

    ctxItemKeywHdr.Toggle(bCanHide);
    ctxItemKeywUnhdr.Toggle(bCanUnhide);
    ctxItemKeywHdr.ItemText("Hide Keywords - '" + (txt || keywTxt) + "'");
    ctxItemKeywUnhdr.ItemText("Unhide Keywords - '" + (txt || keywTxt) + "'");

    ctxRedo.Toggle(ctxRedo.find("li.ctxItem").length > 0);
    ctxUndo.Toggle(ctxUndo.find("li.ctxItem").length > 0);
});

jq("#expander").click(function(e){
    e.preventDefault();
    ExpandAndNext(jq("div.expando-button.collapsed:visible"), 0);
    return false;
});
jq("#upvoter").click(function(e){
    e.preventDefault();
    VoteAndNext(jq(this), upVoteLinks, 0);
    return false;
});
jq("#downvoter").click(function(e){
    e.preventDefault();
    VoteAndNext(jq(this), downVoteLinks, 0);
    return false;
});

if(!isSinglePost && !isSubmitPage) {
    jq("div.thing").click(function(e){
        var jqTarget = jq(e.target);

        if(jqTarget && e.target.nodeName != "A" && !jqTarget.hasClass("arrow") && !jqTarget.hasClass("expando-button") && !jqTarget.hasClass("pstSelected")) {
            MakeActivePost(pstSelected,"#" + jq(this).attr("id"));
        }
    });

    jq("body").keydown(function(e) {
        if(isInputFocused)
            return true;

        switch(e.keyCode) {
            case 105: // num 9
                Vote(pstSelected, "up");
                break;
            case 104: // num 8
                jq("#prevPost").click();
                break;
            case 103: // num 7
                Vote(pstSelected, "down");
                break;
            case 102: // num 6
                jq(".pstSelected div.res-gallery-individual-controls div.res-gallery-next").get(0).click();
                break;
            case 101: // num 5
                if(pstSelected !== undefined)
                    jq(pstSelected).find(".expando-button").get(0).click();
                break;
            case 100: // num 4
                jq(".pstSelected div.res-gallery-individual-controls div.res-gallery-previous").get(0).click();
                break;
            case 99: // num 3
                if(pstSelected) {
                    Hide(jq(pstSelected), false);
                    setTimeout(function(){ jq("#nextPost").click(); }, settings.hideItemTimeout);
                }
                break;
            case 98: // num 2
                jq("#nextPost").click();
                break;
            case 97: // num 1
                if(reloadCancelled)
                    jq("#hider").click();
                else
                    reloadCancelled = true;
                break;
            case 107: // num +
                if(pstSelected)
                    jq(pstSelected).find("img, video, iframe").each(function(){ document.fExt.zoomIn(this, 20); });
                break;
            case 109: // num -
                if(pstSelected)
                    jq(pstSelected).find("img, video, iframe").each(function(){ document.fExt.zoomOut(this, 20); });
                break;
            case 111: // num /
                if(pstSelected)
                    jq(pstSelected).find("img, video, iframe").each(function(){ document.fExt.rotate(this, -90); });
                break;
            case 106: // num *
                if(pstSelected)
                    jq(pstSelected).find("img, video, iframe").each(function(){ document.fExt.rotate(this, 90); });
                break;
            default:
                return true;
        }
        return false;
    });

    jq("#topPost").click(function() {
        MakeActivePost(pstSelected, pstFirst);
    });

    jq("#botPost").click(function() {
        MakeActivePost(pstSelected, pstLast);
    });

    jq("#prevPost").click(function() {
        MakeActivePost(pstSelected, PrevPost(pstSelected));
    });

    jq("#nextPost").click(function() {
        MakeActivePost(pstSelected, NextPost(pstSelected));
    });

    jq("#frPost").click(function(){
        var pst = pstSelected;
        var pstNew = pst;
        for(i = 0;i < 5; i++)
            pstNew = PrevPost(pstNew);

        MakeActivePost(pst,pstNew);
        return false;
    });

    jq("#ffPost").click(function(){
        var pst = pstSelected;
        var pstNew = pst;
        for(i = 0;i < 5; i++)
            pstNew = NextPost(pstNew);

        MakeActivePost(pst,pstNew);
        return false;
    });
}

jq("input","textarea").focus(function(){
    isInputFocused = true;
},function(){
    isInputFocused = false;
});

// Events - Settings
function OpenSettings(){
    for(var key in settings) {
        if(key === "subsToHide" || key === "usersToHide" || key === "keywordsToHide")
            continue;

        var varType = typeof settings[key];
        var settingsElement = jq("#rEnhSettings").find("#" + key);

        switch(varType){
            case "boolean":
                if(settings[key])
                    settingsElement.attr("checked","checked");
                else
                    settingsElement.removeAttr("checked");
                break;
            case "number":
                settingsElement.val(settings[key]);
                break;
            case "string":
                settingsElement.val(settings[key]);
                break;
            default:
                console.log("Cannot get setting " + key + " to settings dialog because unkown type " + varType);
                break;
        }
    }

    jq("#rEnhSettingsUserlist").val(usersToHide.toString());
    jq("#rEnhSettingsSublist").val(subsToHide.toString());
    jq("#rEnhSettingsKeywordlist").val(keywordsToHide.toString());

    jq("#rEnhSettingsUserlistLabel").text('Users to hide (' + usersToHide.length + '):');
    jq("#rEnhSettingsSublistLabel").text('Subs to hide (' + subsToHide.length + '):');
    jq("#rEnhSettingsKeywordlistLabel").text('Keywords to hide (' + keywordsToHide.length + '):');

    jq("#rEnhSettings").show();
    return false;
}

jq("#renhSettingsClose").click(function(){
    jq("#rEnhSettings").hide();
    return false;
});

jq("#renhSettingsSave").click(function(){
    jq("input.settingsControl").each(function(){
        var key = jq(this).attr("id");
        var val = settings[key];
        var varType = typeof settings[key];

        settings[key] = val;

        if(varType === "boolean") {
            if(jq(this).is(":checked"))
                settings[key] = true;
            else
                settings[key] = false;
        }
        else if(varType === "number") {
            settings[key] = parseFloat(jq(this).val());
        }
        else {
            console.log("Cannot add setting " + key + " to settings dialog because unkown type " + varType);
        }
    });
    usersToHide = jq("#rEnhSettingsUserlist").val().toString().split(",");
    subsToHide = jq("#rEnhSettingsSublist").val().toString().split(",");
    keywordsToHide = jq("#rEnhSettingsKeywordlist").val().toString().split(",");
    for(i = 0; i < usersToHide.length; i++) { usersToHide[i] = usersToHide[i].trim(); }
    for(i = 0; i < subsToHide.length; i++) { subsToHide[i] = subsToHide[i].trim(); }
    for(i = 0; i < subsToHide.length; i++) { subsToHide[i] = subsToHide[i].trim(); }

    GMSaveSettings();
    GMSave();

    document.fExt.popup("Settings saved!");

    return false;
});

// Events - End

// Functions - Start
function InitializeHider(){
    jq("form.hide-button input[value=hidden]").each(function(index, item){
        hiderElements.push(jq(item).parents("div.thing"));
    });

    if(hiderElements.length === 0)
        jq("#hider").attr("style","background-color: #808080 !important; color: #CFCFCF; border: 1px solid black;");

    jq("#hider").text("Hide (" + hiderElements.length + ")");
}

function VoteAndNext(sender, voteLinks, ind) {
    var nextVoteItem = voteLinks[ind];
    jq(nextVoteItem).click();

    ind++;
    if(voteLinks.length > ind) {
        animateControl(sender);

        setTimeout(function(){
            VoteAndNext(sender, voteLinks, ind);
        },350);
    }
    else {
        jq("#downvoter").text("downvote");
        jq("#upvoter").text("upvote");
    }
}

function ExpandAndNext(expandLinks, ind) {
    var expandItem = expandLinks[ind];
    jq(expandItem).click();

    if(expandLinks.length > ind) {
        animateControl(jq("#expander"));
        setTimeout(function(){
            ExpandAndNext(expandLinks, ind+1);
        }, 500);
    }
    else jq("#expander").text("expand");
}

function animateControl(sender){
    var txt = jq(sender).text();
    if(txt.length >= 3)
        txt = ".";
    else
        txt = txt + ".";

    jq(sender).text(txt);
}

function HideAndAction(hideLinks, index, previousLink, action) {
    var jqLink = jq(previousLink);
    if(IsHidden(jqLink))
        jqLink.fadeOut(250);

    var item = hideLinks[index];
    if(jqLink.find("form.hide-button").length === 0){
        if(hideLinks.length > index) {
            var perc = index * 100 / hideLinks.length;
            document.fExt.setLoading(perc);
            if(action !== "hideObject")
                document.fExt.message(action + " (" + index + "/" + hideLinks.length + ") ...");

            if(!IsHidden(item)) {
                Hide(item, action === "reload" || (action == "enhance" && jq(item).find("a.author.friend").length > 0 && duplicateLinks.indexOf(item) < 0));

                setTimeout(function(){ HideAndAction(hideLinks, index + 1, previousLink, action); }, settings.hideItemTimeout);
            }
            else HideAndAction(hideLinks, index + 1, previousLink, action);
        }
        else {
            document.fExt.setLoading(100);
            switch(action){
                case "reload":
                    ReloadLooper(5);
                    break;
                case "enhance":
                    document.fExt.message(undefined);
                    if(jq("div.thing:visible").length === 0)
                        ReloadLooper(5);
                    else
                        InitializeHider();
                    break;
                case "nextPost":
                    document.fExt.message(undefined);
                    if(jq("div.thing:visible").length === 0)
                        ReloadLooper(5);
                    else
                        jq("#nextPost").click();
                    break;
                default:
                    break;
            }
        }
    }
    else setTimeout(function(){ HideAndAction(hideLinks, index, previousLink, action); }, settings.hideItemTimeout);
}

function ReloadLooper(loops) {
    if(reloadCancelled) {
        document.fExt.message();
        return;
    }
    else {
        if(loops === 0) {
            jq("html, body").animate({ scrollTop: 0 }, 0);

            document.fExt.message("Reloading...");
            setTimeout(function(){
                location.reload();
            }, 100);
        }
        else {
            var msg = "Reloading in " + loops + " seconds... (click to cancel)";
            document.fExt.message(msg);
            document.title = msg;
            setTimeout(function(){
                ReloadLooper(loops - 1);
            }, 1000);
        }
    }
}

function Hide(item, displayAfter){
    item.find("form.hide-button a").click();
    if(displayAfter) {
        setTimeout(function(){
            jq(item).show();
        }, settings.hideItemTimeout);
    }
}

function Mark(item, itemType) {
    item.addClass("markedItem");
    item.addClass(itemType);
}

function MakeActivePost(oldId, newId) {
    if(oldId !== undefined && newId !== undefined && oldId === newId)
        return false;

    if(oldId) {
        var jqOldPost = jq(oldId);
        jqOldPost.removeClass("pstSelected");

        if(settings.autoExpandSelectedPost) {
            var jsCollapser = jqOldPost.find(".expando-button.expanded").get(0);
            if(jsCollapser !== undefined)
                jsCollapser.click();
        }
    }

    if(newId) {
        pstSelected = newId;
        var jqNewPost = jq(pstSelected);
        if(!jqNewPost.hasClass("pstSelected"))
            jqNewPost.addClass("pstSelected");

        if(settings.autoExpandSelectedPost) {
            var jsExpander = jqNewPost.find(".expando-button.collapsed").get(0);
            if(jsExpander !== undefined)
                jsExpander.click();
        }

        var offs = jqNewPost.offset();
        var topPos = 0;
        if(offs)
            topPos = offs.top - jq("#header").height();

        jq("html, body").animate({ scrollTop: topPos }, 250);
    }
}

function NextPost(post){
    var pstIndex = jq.inArray(post, pstItems);
    var pstReturn;

    if(pstIndex + 1 === pstItems.length)
        pstReturn = pstFirst;
    else
        pstReturn = pstItems[pstIndex + 1];

    if(pstReturn && !jq(pstReturn).is(":visible"))
        pstReturn = NextPost(pstReturn);

    return pstReturn;
}

function PrevPost(post){
    var pstIndex = jq.inArray(post, pstItems);
    var pstReturn;

    if(pstIndex === 0)
        pstReturn = pstLast;
    else
        pstReturn = pstItems[pstIndex - 1];

    if(pstReturn && !jq(pstReturn).is(":visible"))
        pstReturn = PrevPost(pstReturn);

    return pstReturn;
}

function GMLoadSettings() {
    var lSettings = GM_getValue("settings");
    if(lSettings !== undefined){
        lSettings = JSON.parse(lSettings.toString());
        for(var k in lSettings) {
            settings[k] = lSettings[k];
        }
        document.fExt.popup("Settings loaded.");

        settings.hideItemTimeout = parseFloat(settings.hideItemTimeout);
    }
}

function GMSaveSettings() {
    GM_setValue("settings", JSON.stringify(settings));
    document.fExt.popup("Settings saved.");
}

function GMLoadValue(valueName){
    var ret = GM_getValue(valueName);
    if(ret !== undefined)
        return ret.toString().split(",");

    return [];
}

function GMLoad(){
    usersToHide = GMLoadValue("usersToHide");
    subsToHide = GMLoadValue("subsToHide");
    keywordsToHide = GMLoadValue("keywordsToHide");
}

function GMSave(){
    GM_setValue("usersToHide", usersToHide.toString());
    GM_setValue("subsToHide", subsToHide.toString());
    GM_setValue("keywordsToHide", keywordsToHide.toString());
}

function AddToHideLinks(elm){
    if(!elm.hasClass("toggleHidden"))
        elm.addClass("toggleHidden");

    if(jq.inArray(elm, hideLinks) < 0)
        hideLinks.push(elm);
}

function Vote(id, direction){
    if(id !== undefined) {
        var element;

        switch(direction){
            case "up":
                element = jq(id).find(".arrow.up, .arrow.upmod");
                break;
            case "down":
                element = jq(id).find(".arrow.down, .arrow.downmod");
                break;
            default:
                break;
        }

        if(element !== undefined){
            jq(element).click();
        }
    }
}

function IsHidden(item){
    var result = item.hasClass("hidden");
    result = result || item.find("a[text=hidden]").length === 1;
    return result;
}

function AddUndo(fnUndo, argsUndo, fnRedo, argsRedo) {
    var ctxItem = document.fExt.ctxMenu.addItem(fnRedo.name + " - " + argsUndo[2], "undo", ctxUndo);
    ctxItem.fnUndo = fnUndo;
    ctxItem.argsUndo = argsUndo;
    ctxItem.fnRedo = fnRedo;
    ctxItem.argsRedo = argsRedo;
    ctxItem.Action = function(event, sender, actor) {
        sender.fnUndo.apply(this, sender.argsUndo);
        AddRedo(sender.fnUndo, sender.argsUndo, sender.fnRedo, sender.argsRedo);
        sender.remove();
    };
}

function AddRedo(fnUndo, argsUndo, fnRedo, argsRedo) {
    var ctxItem = document.fExt.ctxMenu.addItem(fnUndo.name + " - " + argsRedo[2], "redo", ctxRedo);
    ctxItem.fnUndo = fnUndo;
    ctxItem.argsUndo = argsUndo;
    ctxItem.fnRedo = fnRedo;
    ctxItem.argsRedo = argsRedo;
    ctxItem.Action = function(event, sender, actor) {
        sender.fnRedo.apply(this, sender.argsRedo);
        AddUndo(sender.fnUndo, sender.argsUndo, sender.fnRedo, sender.argsRedo);
        sender.remove();
    };
}

function ToggleVisibility(event, sender, className){
    event.preventDefault();
    var jqThis = jq(sender);

    if(jqThis.text().indexOf('Show') >= 0) {
        jqThis.text(jqThis.text().replace("Show","Hide"));
        jq(className).show();
    }
    else {
        jqThis.text(jqThis.text().replace("Hide","Show"));
        jq(className).hide();
    }
};

function HideObject(containingArray, arrayName, text, selector){
    if(jq.inArray(text, containingArray) < 0) {
        document.fExt.popup("Adding '" + text + "' from '" + arrayName +"' to hide.");
        containingArray.push(text);
        GMSave();

        var links = [];
        var selectNext = false;

        jq(selector).parents("div.thing").each(function(index,item) {
            var jqItem = jq(item);
            selectNext = selectNext || "#" + jqItem.attr("id") === pstSelected;

            if(jqItem.find("form.hide-button").length > 0)
                links.push(jqItem);
        });

        HideAndAction(links, 0, null, "hideObject");

        if(selectNext) {
            setTimeout(function(){
                jq("#nextPost").click();
            },500);
        }
        return true;
    }
    return false;
}

function UnhideObject(containingArray, arrayName, text, selector){
    var arrayIndex = jq.inArray(text, containingArray);
    if(arrayIndex >= 0) {
        document.fExt.popup("Removing '" + text + "' from '" + arrayName + "'.");
        containingArray.splice(arrayIndex, 1);
        GMSave();
        return true;
    }
    return false;
}

// Functions - End