FA Content Filter

Filters user-defined content while browsing Furaffinity.

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

  1. // ==UserScript==
  2. // @name FA Content Filter
  3. // @namespace fa-filter
  4. // @description Filters user-defined content while browsing Furaffinity.
  5. // @include *://www.furaffinity.net/*
  6. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
  7. // @version 1.5.5
  8. // @grant GM.getValue
  9. // @grant GM.setValue
  10. // @grant GM.deleteValue
  11. // @grant GM.openInTab
  12. // ==/UserScript==
  13.  
  14. // === WARNING ===
  15. // THE TAG FUNCTIONS ARE COMMENTED OUT IN ORDER TO PREVENT ACCIDENTAL DDoS DETECTION ON FURAFFINITY.
  16. this.$ = this.jQuery = jQuery.noConflict(true);
  17.  
  18. // Shitty workaround, but w/e
  19. async function main() {
  20. // === INITIALIZE USER ARRAY ===
  21. var userArray = JSON.parse(await GM.getValue('userList', '{}'));
  22. //var tagArray = JSON.parse(GM.getvalue('tagList', '{}'));
  23.  
  24. // === GENERAL TEMPORARY VARIABLES ===
  25. var filterEnabled = {['subs']:true, ['shouts']:true, ['coms']:true, ['notifications']:true};
  26.  
  27. // === FILTER ===
  28. var parseSettings = function() {
  29. if (!(userArray instanceof Array)) {
  30. $.each(userArray, function(username, data) {
  31. if (data['subs'] === 1) { hideSubmissions(username); }
  32. if (data['shouts'] === 1) { hideShouts(username); }
  33. if (data['coms'] === 1) { hideComments(username); }
  34. if (data['notifications'] === 1) { hideNotifications(username); }
  35. });
  36. }
  37. };
  38.  
  39. //var parseTagSettings = function() {
  40. // $('.t-image a[href^="/view"]').each(function() {
  41. // var url = $(this).attr('href');
  42. // console.log(url);
  43. // $.post(url, function(data) {
  44. // console.log($('#keywords', data).text());
  45. // });
  46. // });
  47. //}
  48.  
  49.  
  50. // === SAVE ===
  51. function writeSettings() {
  52. GM.setValue('userList', JSON.stringify(userArray));
  53. }
  54.  
  55. // === FUNCTIONS ===
  56. // Hide user submissions
  57. function hideSubmissions(username) {
  58. if ($('figure').length) {
  59. // Beta
  60. var submissionBeta = $('figure.u-' + escapeUsername(username));
  61. var submissionInboxBeta = $('a[href="/user/' + username + '"]').closest('figure');
  62.  
  63. stylizeHidden(submissionBeta);
  64. stylizeHidden(submissionInboxBeta);
  65.  
  66. submissionBeta.addClass('hidden-sub').hide();
  67. submissionInboxBeta.find('input').prop('checked', true);
  68. submissionInboxBeta.addClass('hidden-sub').hide();
  69.  
  70. if (!filterEnabled['subs']) {
  71. submissionBeta.show();
  72. submissionInboxBeta.show();
  73. }
  74. } else {
  75. // Classic
  76. // Browse/Submissions
  77. var submission1 = $('b[id^="sid_"] a[href="/user/' + username + '/"]').closest('b');
  78. stylizeHidden(submission1);
  79. // Mark Submissions as Checked
  80. submission1.children('small').children('input').prop('checked', true);
  81. submission1.addClass('hidden-sub').hide();
  82.  
  83. // Favorites/Front Page
  84. var submission2 = $('b[id^="sid_"] img[src$="#' + username + '"]').closest('b');
  85. stylizeHidden(submission2);
  86. submission2.addClass('hidden-sub').hide();
  87.  
  88. // Correspond to UI
  89. if (!filterEnabled['subs']) {
  90. submission1.show();
  91. submission2.show();
  92. }
  93. }
  94. }
  95.  
  96. function showSubmissions(username) {
  97. // Browse/Submissions
  98. var submission1 = $('b[id^="sid_"] a[href="/user/' + username + '/"]').closest('b');
  99. var submissionBeta = $('figure.u-' + escapeUsername(username));
  100. var submissionInboxBeta = $('a[href^="/user/' + username + '"]').closest('figure');
  101. undoStylize(submission1);
  102. undoStylize(submissionBeta);
  103. undoStylize(submissionInboxBeta);
  104. // Mark Submissions as Checked
  105. submission1.children('small').children('input').prop('checked', false);
  106. submission1.removeClass('hidden-sub').show();
  107. submissionBeta.removeClass('hidden-sub').show();
  108. submissionInboxBeta.removeClass('hidden-sub').show();
  109. submissionInboxBeta.find('input').prop('checked', false);
  110.  
  111. // Favorites/Front Page
  112. var submission2 = $('b[id^="sid_"] img[src$="#' + username + '"]').closest('b');
  113. undoStylize(submission2);
  114. submission2.removeClass('hidden-sub').show();
  115. }
  116.  
  117. // Hide user shouts
  118. function hideShouts(username) {
  119. // Classic
  120. var shout = $('table[id^="shout-"] td.alt1 img[alt="' + username + '"]').closest('table[id^="shout-"]');
  121. shout.addClass('hidden-shout').hide();
  122. stylizeHidden(shout.find('table'));
  123. shout.next('br').addClass('hidden-shout-br').hide();
  124.  
  125. // Beta
  126. var shoutBeta = $('.comment_container .shout-avatar img[alt="' + username +'"]').closest('.comment_container');
  127. shoutBeta.addClass('hidden-shout').hide();
  128. stylizeHidden(shoutBeta.find('.header'));
  129. stylizeHidden(shoutBeta.find('.body'));
  130.  
  131. // We want to only highlight and check
  132. var shoutManageBeta = $('table[id^="shout-"] .comments-flex-item-icon img[alt="' + username +'"]').closest('table[id^="shout-"]');
  133. shoutManageBeta.addClass('hidden-shout');
  134. stylizeHidden(shoutManageBeta.find('.comments-userline-flex'));
  135. stylizeHidden(shoutManageBeta.find('.comment_text'));
  136. shoutManageBeta.find('input[type="checkbox"]').prop('checked', true);
  137. }
  138.  
  139. // Hide user comments and threads
  140. function hideComments(username) {
  141. // Classic
  142. var comments = $('.container-comment td.icon img[alt="' + username + '"]').closest('.container-comment');
  143.  
  144. $(comments).each(function() {
  145. // Hide comment and get width
  146. if (!($(this).hasClass('hidden-comment'))) {
  147. var width = Number($(this).addClass('hidden-comment').hide().attr('width').slice(0,-1));
  148. var current = $(this).next('.container-comment');
  149.  
  150. // Iterate through comments until there's a width that is greater than or equal
  151. while (true) {
  152. if (current.length) {
  153. if (Number(current.attr('width').slice(0,-1)) < width) {
  154. current.addClass('hidden-comment').hide();
  155. current = current.next('.container-comment');
  156. } else {
  157. break;
  158. }
  159. } else {
  160. break;
  161. }
  162. }
  163. }
  164. });
  165.  
  166. // Beta
  167. var commentsBeta = $('.comment_container .avatar img[alt="' + username + '"]').closest('.comment_container');
  168. stylizeHidden(commentsBeta.find('.header'));
  169. stylizeHidden(commentsBeta.find('.body'));
  170.  
  171. $(commentsBeta).each(function() {
  172. // Get width, then hide comment
  173. if (!($(this).hasClass('hidden-comment'))) {
  174. var width = $(this).width();
  175. var current = $(this).next('.comment_container');
  176.  
  177. $(this).addClass('hidden-comment').hide();
  178.  
  179. // Iterate through the comments until there's a width that is greater than or equal
  180. while (true) {
  181. if (current.length) {
  182. if (current.width() < width) {
  183. current.addClass('hidden-comment').hide();
  184. current = current.next('.comment_container');
  185. } else {
  186. break;
  187. }
  188. } else {
  189. break;
  190. }
  191. }
  192. }
  193. });
  194. }
  195.  
  196. // Hide user notifications
  197. function hideNotifications(username) {
  198. var notification = $('.message-stream a[href="/user/' + username + '/"]').closest('li');
  199. notification.addClass('hidden-notification').hide();
  200. stylizeHidden(notification);
  201. notification.children('input').prop('checked', true);
  202.  
  203. // Classic only
  204. notification.children('table').children('tbody').children('tr').children('td').children('.checkbox').children('input').prop('checked', true);
  205. }
  206.  
  207. function stylizeHidden(item) {
  208. $(item).css('background-color', '#FFBBBB');
  209. $(item).css('color', '#FF0000');
  210. $('a:link', item).css('color', '#FF0000');
  211. $('a:visited', item).css('color', '#FF0000');
  212. }
  213.  
  214. function undoStylize(item) {
  215. $(item).css('background-color', '');
  216. $(item).css('color', '');
  217. $('a:link', item).css('color', '');
  218. $('a:visited', item).css('color', '');
  219. }
  220.  
  221. // === UI ===
  222. // == Filter Toggle ==
  223. // Submissions
  224. function filtersSubs() {
  225. // Remove all pre-existing UI for soft-refresh
  226. $('[id="faf-toggle-subs"]').remove();
  227. $('.faf-remove-user-external').parent().remove();
  228. $('.faf-add-user-external').parent().remove();
  229.  
  230. if ($('.hidden-sub').length > 0) {
  231. // Classic
  232. if (!$('li.lileft').length) {
  233. $display = '<input style="float:right;" id="faf-toggle-subs" class="button" type="button" value="Toggle Filtered Submissions (' + $('.hidden-sub').length + ')"></input>';
  234. $('form').first().append($display);
  235. // Beta
  236. } else {
  237. $display = '<li class="lileft"><a class="top-heading" id="faf-toggle-subs" href="#!"><div class="sprite-nuke menu-space-saver hideonmobile"></div>Toggle Filtered Submissions (' + $('.hidden-sub').length + ')</a></li>';
  238. $('.lileft').last().after($display);
  239. }
  240. } else {
  241. filterEnabled['subs'] = true;
  242. }
  243.  
  244. if ($('figure').length) {
  245. // Beta
  246. $('figure').each(function() {
  247. var username = $(this).attr('class').match('u-([^\\s]+)')[1];
  248. if (username) {
  249. if (username in userArray && userArray[username]['subs'] === 1) {
  250. $(this).find('figcaption').append('<p><a style="color: #FF5555!important;" class="faf-remove-user-external" id="faf-' + username + '" href="#!" title="Remove ' + username + ' from filter">[Unfilter]</a></p>');
  251. } else {
  252. $(this).find('figcaption').append('<p><a style="color: #FF5555!important;" class="faf-add-user-external" id="faf-' + username + '" href="#!" title="Add ' + username + ' to filter">[Filter]</a></p>');
  253. }
  254. }
  255. });
  256. } else {
  257. $('b[id^="sid_"]').each(function() {
  258. var username = $(this).find('small a').attr('href');
  259. username = username.match('/user/(.*)/');
  260. if (username) {
  261. if (username[1] in userArray && userArray[username[1]]['subs'] === 1) {
  262. $(this).find('small').append('<span>&nbsp;<a style="color: #FF5555!important;" class="faf-remove-user-external" id="faf-' + username[1] + '" href="#!" title="Remove ' + username[1] + ' from filter">[Unfilter]</a></span>');
  263. } else {
  264. $(this).find('small').append('<span>&nbsp;<a style="color: #FF5555!important;" class="faf-add-user-external" id="faf-' + username[1] + '" href="#!" title="Add ' + username[1] + ' to filter">[Filter]</a></span>');
  265. }
  266. }
  267. });
  268. }
  269. }
  270.  
  271. // Followed Submissions
  272. function filtersSubsFollow() {
  273. if ($('.hidden-sub').length > 0) {
  274. // Beta
  275. if ($('.button-nav-item').length) {
  276. $display = '<div class="button-nav-item"><button class="button mobile-button" id="faf-toggle-subs" type="button">Toggle Filtered Submissions (' + $('.hidden-sub').length + ')</button></div>';
  277. $('.actions').css('max-width', '700px');
  278. } else {
  279. $display = '<input id="faf-toggle-subs" class="button" type="button" value="Toggle Filtered Submissions (' + $('.hidden-sub').length + ')"></input>';
  280. }
  281. $('.actions').append($display);
  282. }
  283. }
  284.  
  285. // Shouts
  286. function filtersShouts() {
  287. if ($('.hidden-shout').length > 0) {
  288. $display = '<center><input id="faf-toggle-shouts" class="button" type="button" value="Toggle Filtered Shouts (' + $('.hidden-shout').length + ')"></input></center>';
  289. // Classic
  290. $('table[id^="shout-"]').first().prevAll('table.maintable:first').append($display);
  291. // Beta
  292. $($display).insertAfter('#shoutboxentry');
  293. }
  294. }
  295.  
  296. // Shouts (Controls, Beta Only)
  297. function filtersShoutsControl() {
  298. if ($('.hidden-shout').length > 0) {
  299. $display = '<button id="faf-toggle-shouts" class="button mobile-button" type="button" value="Toggle Filtered Shouts (' + $('.hidden-shout').length + ')">Toggle Filtered Shouts (' + $('.hidden-shout').length + ')</button>';
  300. $('.section-divider').last().append($display);
  301. $('.hidden-shout input').prop('checked', true);
  302. }
  303. }
  304.  
  305. // Comments
  306. function filtersComments() {
  307. if ($('.hidden-comment').length > 0) {
  308. $display = '<input style="float:right;" id="faf-toggle-comments" class="button" type="button" value="Toggle Filtered Comments (' + $('.hidden-comment').length + ')"></input>';
  309. if (!$('.flex-submission-container').length) {
  310. // Classic
  311. $('table.container-comment').first().parent().parent().prev().children().append($display);
  312. } else {
  313. // Beta
  314. $($display).insertAfter('.flex-submission-container');
  315. }
  316. }
  317. }
  318.  
  319. // Notifications
  320. function filtersNotifications() {
  321. if ($('.hidden-notification').length > 0) {
  322. $display = '<input id="faf-toggle-notifications" class="button" type="button" value="Toggle Filtered Notifications (' + $('.hidden-notification').length + ')"></input>';
  323. $('.global-controls').append($display);
  324. $('.global_controls').append($display);
  325.  
  326. // = Notification Count =
  327. // Classic
  328. if ($('fieldset[id^="messages-watches"] .hidden-notification').length > 0)
  329. $('fieldset[id^="messages-watches"] h3').append(' (' + $('fieldset[id^="messages-watches"] .hidden-notification').length + ' filtered)');
  330. if ($('fieldset[id^="messages-comments-submission"] .hidden-notification').length > 0)
  331. $('fieldset[id^="messages-comments-submission"] h3').append(' (' + $('fieldset[id^="messages-comments-submission"] .hidden-notification').length + ' filtered)');
  332. if ($('fieldset[id^="messages-shouts"] .hidden-notification').length > 0)
  333. $('fieldset[id^="messages-shouts"] h3').append(' (' + $('fieldset[id^="messages-shouts"] .hidden-notification').length + ' filtered)');
  334. if ($('fieldset[id^="messages-favorites"] .hidden-notification').length > 0)
  335. $('fieldset[id^="messages-favorites"] h3').append(' (' + $('fieldset[id^="messages-favorites"] .hidden-notification').length + ' filtered)');
  336.  
  337. // Beta
  338. if ($('div[id^="messages-watches"] .hidden-notification').length > 0)
  339. $('div[id^="messages-watches"] h2').append(' (' + $('div[id^="messages-watches"] .hidden-notification').length + ' filtered)');
  340. if ($('div[id^="messages-comments-submission"] .hidden-notification').length > 0)
  341. $('div[id^="messages-comments-submission"] h2').append(' (' + $('div[id^="messages-comments-submission"] .hidden-notification').length + ' filtered)');
  342. if ($('div[id^="messages-shouts"] .hidden-notification').length > 0)
  343. $('div[id^="messages-shouts"] h2').append(' (' + $('div[id^="messages-shouts"] .hidden-notification').length + ' filtered)');
  344. if ($('div[id^="messages-favorites"] .hidden-notification').length > 0)
  345. $('div[id^="messages-favorites"] h2').append(' (' + $('div[id^="messages-favorites"] .hidden-notification').length + ' filtered)');
  346. if ($('div[id^="messages-journals"] .hidden-notification').length > 0)
  347. $('div[id^="messages-journals"] h2').append(' (' + $('div[id^="messages-journals"] .hidden-notification').length + ' filtered)');
  348. }
  349. }
  350.  
  351. // == Buttons ==
  352. // Show/Hide Submissions
  353. $(document.body).on('click', '#faf-toggle-subs', function() {
  354. $('.hidden-sub').toggle();
  355. filterEnabled['subs'] = !filterEnabled['subs'];
  356. });
  357.  
  358. // Show/Hide Shouts
  359. $(document.body).on('click', '#faf-toggle-shouts', function() {
  360. $('.hidden-shout').toggle();
  361. $('.hidden-shout-br').toggle();
  362. filterEnabled['shouts'] = !filterEnabled['shouts'];
  363. });
  364.  
  365. // Show/Hide Comments
  366. $(document.body).on('click', '#faf-toggle-comments', function() {
  367. $('.hidden-comment').toggle();
  368. filterEnabled['coms'] = !filterEnabled['coms'];
  369. });
  370.  
  371. // Show/Hide Notifications
  372. $(document.body).on('click', '#faf-toggle-notifications', function() {
  373. $('.hidden-notification').toggle();
  374. filterEnabled['notifications'] = !filterEnabled['notifications'];
  375. });
  376.  
  377. // == External Filters ==
  378. // Add submission filter outside of settings
  379. $(document.body).on('click', '.faf-add-user-external', function() {
  380. var addUser = $(this).attr('id').match('faf-(.*)')[1];
  381.  
  382. // Add to array
  383. if (!(addUser in userArray)) {
  384. userArray[addUser] = {'subs':1, 'shouts':0, 'coms':0, 'notifications':0};
  385. } else {
  386. userArray[addUser]['subs'] = 1;
  387. }
  388.  
  389. // Hide, replace link, and save
  390. hideSubmissions(addUser);
  391. filtersSubs();
  392. writeSettings();
  393. });
  394.  
  395. // Remove submission filter outside of settings
  396. $(document.body).on('click', '.faf-remove-user-external', function() {
  397. var removeUser = $(this).attr('id').match('faf-(.*)')[1];
  398.  
  399. // Remove from array
  400. if (removeUser in userArray) {
  401. userArray[removeUser]['subs'] = 0;
  402. }
  403.  
  404. // Show, replace link, and save
  405. showSubmissions(removeUser);
  406. filtersSubs();
  407. writeSettings();
  408. });
  409.  
  410. // == User Settings ==
  411. function displaySettings() {
  412. // Navbar link
  413. $('<li class="noblock"><a target="_blank" href="/controls/site-settings#fa-filter">FA Filter</a></li>').insertAfter($('li.sfw-toggle'));
  414.  
  415. if (window.location.pathname.lastIndexOf('/controls/site-settings', 0) === 0) {
  416. // Brute forced, but there are no tables in the beta layout site-settings page. This is one of the major differences.
  417. if (!$('table').length) {
  418. // Beta HTML Code
  419. var settingsDisplay = '<section>' +
  420. '<div class="section-body">' +
  421. '<h2 id="fa-filter">FA Filter</h2>' +
  422. '<h4>Add a User</h4>' +
  423. '<div class="control-panel-option">' +
  424. '<div class="control-panel-item-1">' +
  425. '<p>Tired of seeing somebody\'s contributions on the site? Add them to your filter list!<br/><strong>Note:</strong> Enter in the username of the person you want to filter, which is the username that would appear after "furaffinity.net/user/".' +
  426. '</div>' +
  427. '<div class="control-panel-item-2">' +
  428. '<input class="textbox" type="text" id="faf-add-username" maxlength="50"></input>&nbsp;<input id="faf-add" class="button" type="button" value="Add" />' +
  429. '</div>' +
  430. '</div>' +
  431. '<h4>Validate Filters</h4>' +
  432. '<div class="control-panel-option">' +
  433. '<div class="control-panel-item-1">' +
  434. '<p>This double-checks to make sure that your filtered usernames are correct and, optionally, removes users that don\'t have any enabled filters.<br/><strong>Note:</strong> This automatically saves the list.</p>' +
  435. '</div>' +
  436. '<div class="control-panel-item-2">' +
  437. '<select name="faf-validate-options" id="select-faf-validate-options" class="styled">' +
  438. '<option value="v" selected="selected">Vaildate Filters Only</option>' +
  439. '<option value="vr">Validate and Remove Unused Filters</option>' +
  440. '</select><input id="faf-validate" class="button" type="button" value="Apply" /><br/>' +
  441. '<span class="faf-validate-status" style="font-weight: bold; color: #009900; display: none;">Validated! 0 user(s) have been modified or removed.</span>' +
  442. '</div>' +
  443. '</div>' +
  444. '<div class="maintable rounded">' +
  445. '<table class="sessions-list faf-list faf-list-beta" width="100%" cellspacing="0" cellpadding="0" border="0" style="padding:0 15px 10px 15px">' +
  446. '<tbody>' +
  447. '<tr>' +
  448. '<td class="p10t p5r p5b"><h3>Username</h3></td>' +
  449. '<td class="p10t p5r p5b" width="200px"><h3>Submissions</h3></td>' +
  450. '<td class="p10t p5r p5b" width="200px"><h3>Shouts</h3></td>' +
  451. '<td class="p10t p5r p5b" width="200px"><h3>Comments</h3></td>' +
  452. '<td class="p10t p5r p5b" width="200px"><h3>Notifications</h3></td>' +
  453. '</tr>' +
  454. '</tbody>' +
  455. '</table>' +
  456. '</div>' +
  457. '</div>' +
  458. '<div class="section-footer alignright">' +
  459. '<span class="faf-update-status" style="font-weight: bold; color: #006600; display: none;">Update successful!</span>&nbsp;&nbsp;<input class="button mobile-button" id="faf-update" type="button" value="Apply Filters (FA Filter)">' +
  460. '</div>' +
  461. '</section>';
  462. $(settingsDisplay).insertBefore($('section').last());
  463. } else {
  464. // Classic HTML Code
  465. var settingsDisplay = '<table id="fa-filter" cellpadding="0" cellspacing="1" border="0" class="section maintable"><tbody>' +
  466. '<tr><td height="22" class="cat links">&nbsp;<strong>FA Filter</strong></td></tr>' +
  467. '<tr><td class="alt1 addpad ucp-site-settings" align="center">' +
  468. '<table cellspacing="1" cellpadding="0" border="0"><tbody>' +
  469. '<tr>' +
  470. '<th><strong>Add a User</strong></th>' +
  471. '<td><input type="text" id="faf-add-username" maxlength="50"></input>&nbsp;<input id="faf-add" class="button" type="button" value="Add User"></td>' +
  472. '<td class="option-description">' +
  473. '<h3>Hide a user\'s contributions to the site.</h3>' +
  474. '<p>Tired of seeing somebody\'s contributions 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>' +
  475. '</td>' +
  476. '</tr>' +
  477. '<tr>' +
  478. '<th><strong>Validate Filters</strong></th>' +
  479. '<td>' +
  480. '<select name="faf-validate-options" id="select-faf-validate-options" class="styled">' +
  481. '<option value="v" selected="selected">Vaildate Filters Only</option>' +
  482. '<option value="vr">Validate and Remove Unused Filters</option>' +
  483. '</select>&nbsp;<input id="faf-validate" class="button" type="button" value="Apply" /><br/>' +
  484. '<span class="faf-validate-status" style="font-weight: bold; color: #009900; display: none;">Validated! 0 user(s) have been modified or removed.</span>' +
  485. '</td>' +
  486. '<td class="option-description">' +
  487. '<h3>Clean up everything and revalidate filtered usernames.</h3>' +
  488. '<p>This double-checks to make sure that your filtered usernames are correct and, optionally, removes users that don\'t have any enabled filters.<br/><strong>Note:</strong> This automatically saves the list.</p>' +
  489. '</td>' +
  490. '</tr>' +
  491. '<tr>' +
  492. '<th class="noborder" style="vertical-align: text-top;"><strong style="position: relative; top: 25px;">Modify Filters</strong></th>' +
  493. '<td class="noborder">' +
  494. '<table cellspacing="0" cellpadding="0" border="0" class="faf-list faf-list-classic">' +
  495. '<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>' +
  496. '</table>' +
  497. '<br><br><input class="button" id="faf-update" type="button" value="Apply Filters (FA Filter)"> <span class="faf-update-status" style="font-weight: bold; color: #006600; display: none;">Update successful!</span>' +
  498. '</td>' +
  499. '<td class="option-description noborder">' +
  500. '<h3>Choose what items you don\'t want to see.</h3>' +
  501. '<p>If you still want to see some of the things that a user contributes, you can control that here.</p>' +
  502. '</td>' +
  503. '</tr>' +
  504. '</tbody></table>' +
  505. '</td></tr>' +
  506. '</tbody></table>';
  507. $('form').append(settingsDisplay);
  508. }
  509.  
  510. // Populate list
  511. $.each(userArray, function(username, data) {
  512. addFilterUser(username, data);
  513. });
  514. }
  515. }
  516.  
  517. // Display user in the filter table
  518. function addFilterUser(username, data) {
  519. // Classic
  520. if ($('table.faf-list-classic').length) {
  521.  
  522. var row = '<tr class="checked" id="filter-' + username + '"><td class="noborder"><a class="fa-filter-remove fonthighlight" id="faf-rm-' + username + '" href="#!">[x]</a> ' + username + '</td>';
  523. 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>'; }
  524. 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>'; }
  525. 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>'; }
  526. 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>'; }
  527.  
  528. row += '</tr>';
  529.  
  530. $('table.faf-list tr:last').after(row);
  531. // Beta
  532. } else {
  533. var rowBeta = '<tr id="filter-' + username + '"><td class="p5r" valign="middle" width="auto"><a class="fa-filter-remove" id="faf-rm-' + username + '" href="#!">[x]</a> ' + username + '</td>';
  534. if (data['subs'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-subs-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-subs-' + username + '" type="checkbox"></td>'; }
  535. if (data['shouts'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-shouts-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-shouts-' + username + '" type="checkbox"></td>'; }
  536. if (data['coms'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-coms-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-coms-' + username + '" type="checkbox"></td>'; }
  537. if (data['notifications'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-notifications-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-notifications-' + username + '" type="checkbox"></td>'; }
  538.  
  539. rowBeta += '</tr>';
  540.  
  541. $('table.faf-list tr:last').after(rowBeta);
  542. }
  543. }
  544.  
  545. // Add
  546. $(document.body).on('click', '#faf-add', function() {
  547. var username = $.trim($('#faf-add-username').val());
  548. $('#faf-add-username').val('');
  549. if (username !== '') {
  550. username = username.toLowerCase();
  551. username = username.replace(/[_]/g, '');
  552. if (!(username in userArray)) {
  553. userArray[username] = {'subs':1, 'shouts':1, 'coms':1, 'notifications':1};
  554. addFilterUser(username, userArray[username]);
  555. }
  556. }
  557. });
  558.  
  559. // Remove
  560. $(document.body).on('click', 'a.fa-filter-remove', function(event) {
  561. var username = event.target.id.substr(7);
  562. delete userArray[username];
  563.  
  564. userEsc = escapeUsername(username);
  565.  
  566. $('table.faf-list tr#filter-' + userEsc).remove();
  567. });
  568.  
  569. // Update
  570. $(document.body).on('click', '#faf-update', function() {
  571. $('.faf-list tr[id^="filter-"]').each(function() {
  572. var username = this.id.substr(7);
  573. var vals = {'subs':0, 'shouts':0, 'coms':0, 'notifications':0};
  574.  
  575. userEsc = escapeUsername(username);
  576.  
  577. // Check checkboxes
  578. if ($('#faf-check-subs-' + userEsc).is(':checked')) { vals['subs'] = 1; }
  579. if ($('#faf-check-shouts-' + userEsc).is(':checked')) { vals['shouts'] = 1; }
  580. if ($('#faf-check-coms-' + userEsc).is(':checked')) { vals['coms'] = 1; }
  581. if ($('#faf-check-notifications-' + userEsc).is(':checked')) { vals['notifications'] = 1; }
  582.  
  583. userArray[username] = vals;
  584. });
  585.  
  586. // Save
  587. writeSettings();
  588.  
  589. // Display message
  590. $('.faf-update-status').fadeIn('slow');
  591. setTimeout(function() {
  592. $('.faf-update-status').fadeOut('slow');
  593. }, 5000);
  594. });
  595.  
  596. // Validate
  597. $(document.body).on('click', '#faf-validate', function() {
  598. var modCount = 0;
  599. // Validate
  600. $.each(userArray, function(username, data) {
  601. var tempUsername = username;
  602. tempUsername = tempUsername.trim();
  603. if (tempUsername !== '') {
  604. tempUsername = tempUsername.toLowerCase();
  605. tempUsername = tempUsername.replace(/[_ ]/g, '');
  606. if (tempUsername !== username) {
  607. userArray[tempUsername] = data;
  608. delete userArray[username];
  609. $('tr[id="filter-' + username + '"]').remove();
  610. modCount++;
  611. }
  612. }
  613. });
  614.  
  615. // Remove empty
  616. if ($('#select-faf-validate-options').val() === 'vr') {
  617. $.each(userArray, function(username, data) {
  618. var isEmpty = true;
  619. $.each(data, function(entity, value) {
  620. if (value === 1) {
  621. isEmpty = false;
  622. }
  623. });
  624. if (isEmpty) {
  625. delete userArray[username];
  626. $('tr[id="filter-' + username + '"]').remove();
  627. modCount++;
  628. }
  629. });
  630. }
  631.  
  632. // Save
  633. writeSettings();
  634.  
  635. // Display message
  636. $('.faf-validate-status').text('Validated! ' + modCount + ' user(s) have been modified or removed.');
  637. $('.faf-validate-status').fadeIn('slow');
  638. setTimeout(function() {
  639. $('.faf-validate-status').fadeOut('slow');
  640. }, 5000);
  641. });
  642.  
  643. // === UTILITIES ===
  644. function escapeUsername(username) {
  645. // Replace periods/colons/tildes with escaped versions. Who the fuck allows periods AND tildes in usernames, seriously?
  646. userEsc = username.replace(/\./g, '\\.');
  647. userEsc = userEsc.replace(/:/g, '\\:');
  648. userEsc = userEsc.replace(/~/g, '\\~');
  649. return userEsc;
  650. }
  651.  
  652. function updateCSS() {
  653. var newCSS = '<style type="text/css">' +
  654. 'section.gallery figure { padding-bottom: 62px; }' +
  655. '</style>';
  656. $('head').append(newCSS);
  657. }
  658.  
  659. displaySettings();
  660. updateCSS();
  661.  
  662. setTimeout(parseSettings, 50);
  663. //setTimeout(parseTagSettings, 100);
  664.  
  665. // Submissions
  666. if (window.location.pathname.lastIndexOf('/browse', 0) === 0) setTimeout(filtersSubs, 100);
  667. else if (window.location.pathname.lastIndexOf('/favorites', 0) === 0) setTimeout(filtersSubs, 100);
  668. else if (window.location.pathname.lastIndexOf('/msg/submissions', 0) === 0) setTimeout(filtersSubsFollow, 100);
  669. // Shouts
  670. else if (window.location.pathname.lastIndexOf('/user', 0) === 0) setTimeout(filtersShouts, 100);
  671. else if (window.location.pathname.lastIndexOf('/controls/shouts', 0) === 0) setTimeout(filtersShoutsControl, 100);
  672. // Comments
  673. else if (window.location.pathname.lastIndexOf('/view', 0) === 0) setTimeout(filtersComments, 100);
  674. // Notifications
  675. else if (window.location.pathname.lastIndexOf('/msg/others', 0) === 0) setTimeout(filtersNotifications, 100);
  676. else setTimeout(filtersSubs, 100);
  677. }
  678.  
  679. main();