Furaffinity Filter

Filters user-defined content while browsing FA.

当前为 2015-02-02 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Furaffinity Filter
  3. // @namespace fa-filter
  4. // @description Filters user-defined content while browsing FA.
  5. // @include *://www.furaffinity.net/*
  6. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
  7. // @version 1.1
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @grant GM_deleteValue
  11. // @grant GM_openInTab
  12. // ==/UserScript==
  13.  
  14. this.$ = this.jQuery = jQuery.noConflict(true);
  15.  
  16. // === INITIALIZE USER ARRAY ===
  17. var userArray = JSON.parse(GM_getValue('userList', '{}'));
  18.  
  19. // === FILTER ===
  20. var parseSettings = function() {
  21. if (!(userArray instanceof Array)) {
  22. $.each(userArray, function(username, data) {
  23. if (data['subs'] === 1) { hideSubmissions(username); }
  24. if (data['shouts'] === 1) { hideShouts(username); }
  25. if (data['coms'] === 1) { hideComments(username); }
  26. if (data['notifications'] === 1) { hideNotifications(username); }
  27. });
  28. }
  29. }
  30.  
  31. // === SAVE ===
  32. function writeSettings() {
  33. GM_setValue('userList', JSON.stringify(userArray));
  34. }
  35.  
  36. // === FUNCTIONS ===
  37. // Hide user submissions
  38. function hideSubmissions(username) {
  39. // Browse/Submissions
  40. var submission1 = $('.t-image a[href="/user/' + username + '/"]').closest('.t-image');
  41. stylizeHidden(submission1);
  42. // Mark Submissions as Checked
  43. submission1.children('small').children('input').prop('checked', true);
  44. submission1.addClass('hidden-sub').hide();
  45. // Favorites/Front Page
  46. var submission2 = $('b[id^="sid_"] img[src$="#' + username + '"]').closest('b');
  47. stylizeHidden(submission2);
  48. submission2.addClass('hidden-sub').hide();
  49. }
  50.  
  51. // Hide user shouts
  52. function hideShouts(username) {
  53. var shout = $('table[id^="shout-"] td.alt1 img[alt="' + username + '"]').closest('table[id^="shout-"]');
  54. shout.addClass('hidden-shout').hide();
  55. stylizeHidden(shout.find('table'));
  56. shout.next('br').addClass('hidden-shout-br').hide();
  57. }
  58.  
  59. // Hide user comments and threads
  60. function hideComments(username) {
  61. var comments = $('.container-comment td.icon img[alt="' + username + '"]').closest('.container-comment');
  62. $(comments).each(function() {
  63. // Hide comment and get width
  64. if (!($(this).hasClass('hidden-comment'))) {
  65. var width = Number($(this).addClass('hidden-comment').hide().attr('width').slice(0,-1));
  66. var current = $(this).next('.container-comment');
  67.  
  68. // Iterate through comments until there's a width that is greater than or equal
  69. while (true) {
  70. if (current.length) {
  71. if (Number(current.attr('width').slice(0,-1)) < width) {
  72. current.addClass('hidden-comment').hide();
  73. current = current.next('.container-comment');
  74. } else {
  75. break;
  76. }
  77. } else {
  78. break;
  79. }
  80. }
  81. }
  82. });
  83. }
  84. // Hide user notifications
  85. function hideNotifications(username) {
  86. var notification = $('.message-stream a[href="/user/' + username + '/"]').closest('li');
  87. stylizeHidden(notification);
  88. notification.addClass('hidden-notification').hide();
  89. }
  90. function stylizeHidden(item) {
  91. item.css('background-color', '#FFBBBB');
  92. item.css('color', '#FF0000');
  93. $('a:link', item).css('color', '#FF0000');
  94. $('a:visited', item).css('color', '#FF0000');
  95. }
  96.  
  97. // === UI ===
  98. // == Filtered Toggle ==
  99. // Submissions
  100. function filtersSubs() {
  101. if ($('.hidden-sub').length > 0) {
  102. $display = '<input style="float:right;" id="faf-toggle-subs" class="button" type="button" value="Toggle Filtered Submissions (' + $('.hidden-sub').length + ')"></input>';
  103. $('form').first().append($display);
  104. }
  105. }
  106.  
  107. // Followed Submissions
  108. function filtersSubsFollow() {
  109. if ($('.hidden-sub').length > 0) {
  110. $display = '<input id="faf-toggle-subs" class="button" type="button" value="Toggle Filtered Submissions (' + $('.hidden-sub').length + ')"></input>';
  111. $('.actions').append($display);
  112. }
  113. }
  114.  
  115. // Shouts
  116. function filtersShouts() {
  117. if ($('.hidden-shout').length > 0) {
  118. $display = '<center><input id="faf-toggle-shouts" class="button" type="button" value="Toggle Filtered Shouts (' + $('.hidden-shout').length + ')"></input></center>';
  119. // TODO: Find alternative to extremely hacky way to find shouts title.
  120. $('table[id^="shout-"]').first().prevAll('table.maintable:first').append($display);
  121. }
  122. }
  123.  
  124. // Comments
  125. function filtersComments() {
  126. if ($('.hidden-comment').length > 0) {
  127. $display = '<input style="float:right;" id="faf-toggle-comments" class="button" type="button" value="Toggle Filtered Comments (' + $('.hidden-comment').length + ')"></input>';
  128. // TODO: Find alternative to extremely hacky way to find comments title.
  129. $('table.container-comment').first().parent().parent().prev().children().append($display);
  130. }
  131. }
  132.  
  133. // Notifications
  134. function filtersNotifications() {
  135. if ($('.hidden-notification').length > 0) {
  136. $display = '<input id="faf-toggle-notifications" class="button" type="button" value="Toggle Filtered Notifications (' + $('.hidden-notification').length + ')"></input>';
  137. $('.global-controls').append($display);
  138. }
  139. }
  140.  
  141. // Show/Hide Submissions
  142. $(document.body).on('click', '#faf-toggle-subs', function() {
  143. $('.hidden-sub').toggle();
  144. });
  145.  
  146. // Show/Hide Shouts
  147. $(document.body).on('click', '#faf-toggle-shouts', function() {
  148. $('.hidden-shout').toggle();
  149. $('.hidden-shout-br').toggle();
  150. });
  151.  
  152. // Show/Hide Comments
  153. $(document.body).on('click', '#faf-toggle-comments', function() {
  154. $('.hidden-comment').toggle();
  155. })
  156.  
  157. // Show/Hide Notifications
  158. $(document.body).on('click', '#faf-toggle-notifications', function() {
  159. $('.hidden-notification').toggle();
  160. })
  161.  
  162. // == User Settings ==
  163. function displaySettings() {
  164. // Navbar link
  165. $('<li class="noblock"><a target="_blank" href="/controls/site-settings#fa-filter">FA Filter</a></li>').insertAfter($('li.sfw-toggle'));
  166. if (window.location.pathname.lastIndexOf('/controls/site-settings', 0) === 0) {
  167. // HTML Code (hacky, need to find better way)
  168. var settingsDisplay = '<table id="fa-filter" cellpadding="0" cellspacing="1" border="0" class="section maintable"><tbody>' +
  169. '<tr><td height="22" class="cat links">&nbsp;<strong>FA Filter</strong></td></tr>' +
  170. '<tr><td class="alt1 addpad ucp-site-settings" align="center">' +
  171. '<table cellspacing="1" cellpadding="0" border="0"><tbody>' +
  172. '<tr>' +
  173. '<th><strong>Add a User</strong></th>' +
  174. '<td><input type="text" id="faf-add-username" maxlength="50"></input>&nbsp;<input id="faf-add" class="button" type="button" value="Add User"></td>' +
  175. '<td class="option-description">' +
  176. '<h3>Hide a user\'s contributions to the site.</h3>' +
  177. '<p>Tired of seeing somebody\'s artwork on the site? Add them to your filter list!<br>Note: Enter in the username of the person you want to filter, which is the username that would appear after "furaffinity.net/user/".</p>' +
  178. '</td>' +
  179. '</tr>' +
  180. '<tr>' +
  181. '<th class="noborder" style="vertical-align: text-top;"><strong style="position: relative; top: 25px;">Modify Filters</strong></th>' +
  182. '<td class="noborder">' +
  183. '<table cellspacing="0" cellpadding="0" border="0" class="faf-list">' +
  184. '<tr><th><strong>Username</strong></th><th><strong>Submissions</strong></th><th><strong>Shouts</strong></th><th><strong>Comments</strong></th><th><strong>Notifications</strong></th></tr>' +
  185. '</table>' +
  186. '<br><br><input class="button" id="faf-update" type="button" value="Update Filters"> <span class="faf-update-status" style="font-weight: bold; color: #006600; display: none;">Update successful!</span>' +
  187. '</td>' +
  188. '<td class="option-description noborder">' +
  189. '<h3>Choose what items you don\'t want to see.</h3>' +
  190. '<p>If you still want to see some of the things that a user contributes, you can control that here.</p>' +
  191. '</td>' +
  192. '</tr>' +
  193. '</tbody></table>' +
  194. '</td></tr>' +
  195. '</tbody></table>';
  196. $('form').append(settingsDisplay);
  197. // Populate list
  198. $.each(userArray, function(username, data) {
  199. addFilterUser(username, data);
  200. });
  201. }
  202. }
  203.  
  204. // Display user in the filter table
  205. function addFilterUser(username, data) {
  206. var row = '<tr id="filter-' + username + '"><td class="noborder"><a class="fa-filter-remove" id="faf-rm-' + username + '" href="#!">[x]</a> ' + username + '</td>';
  207. if (data['subs'] === 1) { row += '<td class="noborder"><input id="faf-check-subs-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-subs-' + username + '" type="checkbox"></td>'; }
  208. if (data['shouts'] === 1) { row += '<td class="noborder"><input id="faf-check-shouts-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-shouts-' + username + '" type="checkbox"></td>'; }
  209. if (data['coms'] === 1) { row += '<td class="noborder"><input id="faf-check-coms-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-coms-' + username + '" type="checkbox"></td>'; }
  210. if (data['notifications'] === 1) { row += '<td class="noborder"><input id="faf-check-notifications-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-notifications-' + username + '" type="checkbox"></td>'; }
  211. row += '</tr>';
  212.  
  213. $('table.faf-list tr:last').after(row);
  214. }
  215.  
  216. // Add
  217. $(document.body).on('click', '#faf-add', function() {
  218. var username = $.trim($('#faf-add-username').val());
  219. $('#faf-add-username').val('');
  220. if (username !== '') {
  221. username = username.toLowerCase();
  222. if (!(username in userArray)) {
  223. userArray[username] = {'subs':1, 'shouts':1, 'coms':1, 'notifications':1};
  224. addFilterUser(username, userArray[username]);
  225. }
  226. }
  227. });
  228.  
  229. // Remove
  230. $(document.body).on('click', 'a.fa-filter-remove', function(event) {
  231. var username = event.target.id.substr(7);
  232. delete userArray[username];
  233. // Replace periods/colons with escaped versions. Who the fuck allows periods in usernames, seriously?
  234. userEsc = username.replace(/\./, '\\.');
  235. userEsc = userEsc.replace(/:/, '\:');
  236. console.log(userEsc)
  237. $('table.faf-list tr#filter-' + userEsc).remove();
  238. });
  239.  
  240. // Update
  241. $(document.body).on('click', '#faf-update', function() {
  242. $('.faf-list tr[id^="filter-"]').each(function() {
  243. var username = this.id.substr(7);
  244. var vals = {'subs':0, 'shouts':0, 'coms':0, 'notifications':0};
  245. // Replace periods/colons with escaped versions. Who the fuck allows periods in usernames, seriously?
  246. userEsc = username.replace(/\./, '\\.');
  247. userEsc = userEsc.replace(/:/, '\:');
  248. // Check checkboxes
  249. if ($('#faf-check-subs-' + userEsc).is(':checked')) { vals['subs'] = 1; }
  250. if ($('#faf-check-shouts-' + userEsc).is(':checked')) { vals['shouts'] = 1; }
  251. if ($('#faf-check-coms-' + userEsc).is(':checked')) { vals['coms'] = 1; }
  252. if ($('#faf-check-notifications-' + userEsc).is(':checked')) { vals['notifications'] = 1; }
  253. userArray[username] = vals;
  254. });
  255. // Save
  256. writeSettings();
  257. // Display message
  258. $('.faf-update-status').fadeIn('slow');
  259. setTimeout(function() {
  260. $('.faf-update-status').fadeOut('slow');
  261. }, 5000);
  262. });
  263.  
  264. displaySettings();
  265.  
  266. setTimeout(parseSettings, 50);
  267.  
  268. // Submissions
  269. if (window.location.pathname.lastIndexOf('/browse', 0) === 0) setTimeout(filtersSubs, 100);
  270. else if (window.location.pathname.lastIndexOf('/favorites', 0) === 0) setTimeout(filtersSubs, 100);
  271. else if (window.location.pathname.lastIndexOf('/msg/submissions', 0) === 0) setTimeout(filtersSubsFollow, 100);
  272. // Shouts
  273. else if (window.location.pathname.lastIndexOf('/user', 0) === 0) setTimeout(filtersShouts, 100);
  274. // Comments
  275. else if (window.location.pathname.lastIndexOf('/view', 0) === 0) setTimeout(filtersComments, 100);
  276. // Notifications
  277. else if (window.location.pathname.lastIndexOf('/msg/others', 0) === 0) setTimeout(filtersNotifications, 100);