AO3: Kudosed and seen history

Highlight or hide works you kudosed/marked as seen.

  1. // ==UserScript==
  2. // @name AO3: Kudosed and seen history
  3. // @description Highlight or hide works you kudosed/marked as seen.
  4. // @namespace https://gf.qytechs.cn/scripts/5835-ao3-kudosed-and-seen-history
  5. // @author Min
  6. // @version 2.2.1
  7. // @history 2.2.1 - fix for bookmarked blurbs
  8. // @history 2.2 - separate kudosed and seen settings, smaller icons
  9. // @history 2.1 - fix for reversi
  10. // @history 2.0 - rewrite, click actions for blurbs, new highlighting
  11. // @history 1.5 - import/export seen list
  12. // @history 1.4 - thinner stripes, remembers bookmarks you left
  13. // @history 1.3 - option to collapse blurbs of seen works
  14. // @history 1.2.1 - double click on date marks work as seen
  15. // @history 1.2 - check for bookmarks you left, changes to the menu
  16. // @grant none
  17. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js
  18. // @include http://*archiveofourown.org/*
  19. // @include https://*archiveofourown.org/*
  20. // ==/UserScript==
  21.  
  22.  
  23. (function ($) {
  24.  
  25. var DEBUG = false;
  26.  
  27. // newest more-or-less major version, for the update notice
  28. var current_version = '2.02';
  29.  
  30. var kudos_history = {}, seen_buttons = {}, saved_settings = {};
  31. var main = $('#main');
  32.  
  33. // check if reversi
  34. var body_bg_color = window.getComputedStyle(document.body).backgroundColor;
  35. if (body_bg_color == 'rgb(51, 51, 51)') {
  36. main.addClass('kh-reversi');
  37. }
  38.  
  39. // uncomment the next five lines if you need to clear your local lists (then comment them again after refreshing the page once)
  40. // localStorage.removeItem('kudoshistory_kudosed');
  41. // localStorage.removeItem('kudoshistory_checked');
  42. // localStorage.removeItem('kudoshistory_seen');
  43. // localStorage.removeItem('kudoshistory_bookmarked');
  44. // localStorage.removeItem('kudoshistory_skipped');
  45.  
  46. var KHList = {
  47. init: function init(name, max_length) {
  48. this.name = name;
  49. this.max_length = max_length || 200000;
  50. this.list = localStorage.getItem('kudoshistory_' + this.name) || ',';
  51. return this;
  52. },
  53.  
  54. reload: function reload() {
  55. this.list = localStorage.getItem('kudoshistory_' + this.name) || this.list;
  56. return this;
  57. },
  58. save: function save() {
  59. try {
  60. localStorage.setItem('kudoshistory_' + this.name, this.list.slice(0, this.max_length));
  61. }
  62. catch (e) {
  63. localStorage.setItem('kudoshistory_' + this.name, this.list.slice(0, this.list.length * 0.9));
  64. }
  65. return this;
  66. },
  67. hasId: function hasId(work_id) {
  68.  
  69. if (this.list.indexOf(',' + work_id + ',') > -1) {
  70. this.list = ',' + work_id + this.list.replace(',' + work_id + ',', ',');
  71. return true;
  72. }
  73. else {
  74. return false;
  75. }
  76. },
  77. add: function add(work_id) {
  78. this.list = ',' + work_id + this.list.replace(',' + work_id + ',', ',');
  79. return this;
  80. },
  81. remove: function remove(work_id) {
  82. this.list = this.list.replace(',' + work_id + ',', ',');
  83. return this;
  84. },
  85. };
  86.  
  87. var KHSetting = {
  88. init: function init(setting) {
  89. this.name = setting.name;
  90. this.label = setting.label;
  91. this.description = setting.description;
  92. this.options = setting.options;
  93. this.current = saved_settings[this.name] || setting.default_value;
  94. return this;
  95. },
  96.  
  97. next: function next() {
  98. this.current = this.options[this.options.indexOf(this.current) + 1] || this.options[0];
  99. this.updateButton();
  100. this.save();
  101. addMainClass(true);
  102. },
  103. getButton: function getButton() {
  104. this.button_link = $('<a></a>').text(this.label + ': ' + this.current.toUpperCase()).prop('title', this.options.join(' / ').toUpperCase());
  105. this.button = $('<li class="kh-menu-setting"></li>').append(this.button_link);
  106. var this_setting = this;
  107. this.button.click(function () {
  108. this_setting.next();
  109. });
  110. return this.button;
  111. },
  112. updateButton: function updateButton() {
  113. this.button_link.text(this.label + ': ' + this.current.toUpperCase());
  114. },
  115. changeValue: function changeValue(value) {
  116. this.current = value;
  117. this.updateButton();
  118. this.updateSettingRow();
  119. this.save();
  120. addMainClass(true);
  121. },
  122. getSettingRow: function getSettingRow() {
  123. var setting_row_info = $('<p class="kh-setting-info kh-hide-element">' + this.description + '</p>');
  124. var setting_row_info_button = $('<a class="help symbol question kh-setting-info-button"><span class="symbol question"><span>?</span></span></a>');
  125. var setting_row_label = $('<span class="kh-setting-label">' + this.label + ': </span>').append(setting_row_info_button);
  126. this.setting_row_options = $('<span class="kh-setting-options"></span>');
  127. this.setting_row = $('<p class="kh-setting-row"></p>').append(setting_row_label, this.setting_row_options, setting_row_info);
  128. this.updateSettingRow();
  129. setting_row_info_button.click(function () {
  130. setting_row_info.toggleClass('kh-hide-element');
  131. });
  132. return this.setting_row;
  133. },
  134. updateSettingRow: function updateSettingRow() {
  135. var this_setting = this;
  136. this_setting.setting_row_options.empty();
  137. this.options.forEach(function (option) {
  138. var option_link = $('<a class="kh-setting-option"></a>');
  139. option_link.click(function () {
  140. this_setting.changeValue(option);
  141. });
  142.  
  143. if (this_setting.current == option) {
  144. option_link.html('<strong>' + option.toUpperCase() + '</strong>').addClass('kh-setting-option-selected');
  145. }
  146. else {
  147. option_link.text(option.toUpperCase());
  148. }
  149.  
  150. this_setting.setting_row_options.append(' ', option_link, ' <span class="kh-setting-separator">&bull;</span>');
  151. });
  152. },
  153. save: function save() {
  154. saved_settings[this.name] = this.current;
  155. localStorage.setItem('kudoshistory_settings', JSON.stringify(saved_settings));
  156. },
  157. check: function check(compare) {
  158. return (this.current === (compare || 'yes'));
  159. },
  160. };
  161.  
  162. var settings_list = [
  163. {
  164. name: 'kudosed_display',
  165. label: 'Kudosed works',
  166. description: 'Hide the works on lists, show the whole blurb, or show just the blurb header.',
  167. options: ['hide', 'show', 'collapse'],
  168. default_value: 'collapse',
  169. },
  170. {
  171. name: 'seen_display',
  172. label: 'Seen works',
  173. description: 'Hide the works on lists, show the whole blurb, or show just the blurb header.',
  174. options: ['hide', 'show', 'collapse'],
  175. default_value: 'collapse',
  176. },
  177. {
  178. name: 'skipped_display',
  179. label: 'Skipped works',
  180. description: 'Hide the works on lists, replace the blurb content with "Skipped", or show just the blurb header.',
  181. options: ['hide', 'placeholder', 'collapse'],
  182. default_value: 'placeholder',
  183. },
  184. {
  185. name: 'toggles_display',
  186. label: 'Blurb options',
  187. description: 'The controls on top right of the blurb that let you mark/unmark the work as seen or skipped from the list.',
  188. options: ['hide', 'show', 'on hover'],
  189. default_value: 'on hover',
  190. },
  191. {
  192. name: 'highlight_bookmarked',
  193. label: 'Highlight bookmarked',
  194. description: 'Show a striped stripe (yeah) on the right for works you\'ve bookmarked.',
  195. options: ['yes', 'no'],
  196. default_value: 'yes',
  197. },
  198. {
  199. name: 'highlight_new',
  200. label: 'Highlight new',
  201. description: 'Show a thin coloured stripe on the left of the blurb for works you\'re seeing for the first time. Only shows on the lists.',
  202. options: ['yes', 'no'],
  203. default_value: 'yes',
  204. },
  205. {
  206. name: 'autoseen',
  207. label: 'Mark as seen on open',
  208. description: 'Automatically mark as seen when you open the work page.',
  209. options: ['yes', 'no'],
  210. default_value: 'no',
  211. },
  212. ];
  213.  
  214. if (typeof (Storage) !== 'undefined') {
  215.  
  216. saved_settings = JSON.parse(localStorage.getItem('kudoshistory_settings')) || {};
  217.  
  218. kudos_history = {
  219. kudosed: Object.create(KHList).init('kudosed'),
  220. checked: Object.create(KHList).init('checked'),
  221. seen: Object.create(KHList).init('seen', 2000000),
  222. bookmarked: Object.create(KHList).init('bookmarked'),
  223. skipped: Object.create(KHList).init('skipped'),
  224.  
  225. username: localStorage.getItem('kudoshistory_username'),
  226.  
  227. saveLists: function () {
  228. DEBUG && console.log('saving lists');
  229. this.kudosed.save();
  230. this.checked.save();
  231. this.seen.save();
  232. this.bookmarked.save();
  233. this.skipped.save();
  234. },
  235. };
  236.  
  237. settings_list.forEach(function (setting) {
  238. kudos_history[setting.name] = Object.create(KHSetting).init(setting);
  239. });
  240.  
  241. var userlink = $('#greeting li.dropdown > a[href^="/users/"]');
  242.  
  243. if (!kudos_history.username) { localStorage.setItem('kudoshistory_lastver', current_version); }
  244.  
  245. // if logged in
  246. if (userlink.length) {
  247. var found_username = userlink.attr('href').split('/')[2];
  248. DEBUG && console.log('found username: ' + found_username);
  249.  
  250. if (kudos_history.username !== found_username) {
  251. kudos_history.username = found_username;
  252. localStorage.setItem('kudoshistory_username', kudos_history.username);
  253. }
  254. }
  255. // if not logged in, but remembers username
  256. else if (!!kudos_history.username) {
  257. DEBUG && console.log("didn't find username on page, saved username: " + kudos_history.username);
  258. }
  259. else {
  260. kudos_history.username = prompt('AO3: Kudosed and seen history\n\nYour AO3 username:');
  261. localStorage.setItem('kudoshistory_username', kudos_history.username);
  262. }
  263.  
  264. $(document).ajaxStop(function () {
  265. kudos_history.saveLists();
  266. });
  267.  
  268. // add css rules for kudosed works
  269. addCss();
  270.  
  271. var works_and_bookmarks = $('li.work.blurb, li.bookmark.blurb');
  272.  
  273. // if there's a list of works or bookmarks
  274. if (works_and_bookmarks.length) {
  275. addSeenMenu();
  276.  
  277. var blurb_index = $('.index');
  278.  
  279. // click on header to collapse/expand
  280. blurb_index.on('click', '.header', function (e) {
  281. if (!$(e.target).is('a') && !$(e.target).is('span')) {
  282. $(this).closest('.blurb').toggleClass('collapsed-blurb');
  283. e.stopPropagation();
  284. }
  285. });
  286.  
  287. // toggle seen/skipped
  288. blurb_index.on('click', '.kh-toggle', function (e) {
  289. changeBlurbStatus($(this).closest('.blurb'), $(this).data('list'), true);
  290. e.stopPropagation();
  291. });
  292.  
  293. // click on delete bookmark
  294. blurb_index.on('click', '.own.user a[data-method="delete"]', function () {
  295. var work_id = $(this).closest('.blurb').data('work_id');
  296.  
  297. if (work_id) {
  298. kudos_history.bookmarked.reload().remove(work_id).save();
  299. }
  300. });
  301.  
  302. // for each work and bookmark blurb
  303. works_and_bookmarks.not('.deleted').each(function () {
  304. blurbCheck($(this));
  305. });
  306. }
  307.  
  308. // if it's the first time after an update
  309. addNotice();
  310.  
  311. // if it's a work page
  312. if ($('#workskin').length) {
  313.  
  314. var work_meta = $('dl.work.meta.group');
  315.  
  316. // get work id
  317. var work_id = $('#kudo_commentable_id').val();
  318. DEBUG && console.log('work_id ' + work_id);
  319.  
  320. if (kudos_history.autoseen.check()) {
  321. kudos_history.seen.add(work_id);
  322. }
  323.  
  324. // check if work id is on the seen list
  325. var is_seen = kudos_history.seen.hasId(work_id);
  326.  
  327. if (is_seen) {
  328. work_meta.addClass('marked-seen');
  329. }
  330.  
  331. addSeenButtons();
  332.  
  333. // if work id is on the kudosed list
  334. if (kudos_history.kudosed.hasId(work_id)) {
  335. work_meta.addClass('has-kudos');
  336. DEBUG && console.log('- on kudosed list');
  337. }
  338. else {
  339. // check if there are kudos from the user
  340. var user_kudos = $('#kudos').find('[href="/users/' + kudos_history.username + '"]');
  341.  
  342. if (user_kudos.length) {
  343. // highlight blurb and add work id to kudosed list
  344. kudos_history.kudosed.add(work_id);
  345. kudos_history.checked.remove(work_id);
  346. work_meta.addClass('has-kudos');
  347. }
  348. else {
  349. // add work id to checked list
  350. kudos_history.checked.add(work_id);
  351.  
  352. $('#new_kudo').one('click', function () {
  353. kudos_history.kudosed.reload().add(work_id).save();
  354. kudos_history.checked.reload().remove(work_id).save();
  355. work_meta.addClass('has-kudos');
  356. });
  357. }
  358. }
  359.  
  360. // check if it's bookmarked
  361. var bookmark_button_text = $('a.bookmark_form_placement_open').filter(':first').text();
  362.  
  363. if (bookmark_button_text.indexOf('Edit') > -1) {
  364. // highlight blurb
  365. kudos_history.bookmarked.add(work_id);
  366. work_meta.addClass('is-bookmarked');
  367. }
  368. else {
  369. kudos_history.bookmarked.remove(work_id);
  370. }
  371. }
  372.  
  373. // save all lists
  374. kudos_history.saveLists();
  375. }
  376.  
  377. // check if work is on lists
  378. function blurbCheck(blurb) {
  379.  
  380. var work_id;
  381. var blurb_id = blurb.attr('id');
  382.  
  383. if (blurb.hasClass('work')) {
  384. work_id = blurb_id.replace('work_', '');
  385. }
  386. else if (blurb.hasClass('bookmark')) {
  387. var work_link = blurb.find('h4 a:first').attr('href');
  388.  
  389. // if it's not a deleted work and not a series or external bookmark
  390. if (!!work_link && work_link.indexOf('series') === -1 && work_link.indexOf('external_work') === -1) {
  391. work_id = work_link.split('/').pop();
  392.  
  393. // if it's your own bookmark
  394. var own_bookmark = blurb.find('div.own.user.module.group');
  395. if (own_bookmark.length) {
  396. kudos_history.bookmarked.add(work_id);
  397. }
  398. }
  399. }
  400.  
  401. blurb.data('work_id', work_id);
  402.  
  403. DEBUG && console.log('blurb check ' + blurb_id + ', work_id: ' + work_id);
  404.  
  405. if (!work_id) {
  406. return false;
  407. }
  408.  
  409. var found_on_list = false;
  410. var blurb_classes = 'blurb-with-toggles';
  411. blurb.prepend('<div class="kh-toggles">mark/unmark as: <a class="kh-toggle" data-list="seen">seen</a> &bull; <a class="kh-toggle" data-list="skipped">skipped</a>');
  412.  
  413. // if work id is on the kudosed list
  414. if (kudos_history.kudosed.hasId(work_id)) {
  415. DEBUG && console.log('- is kudosed');
  416. blurb_classes += ' has-kudos collapsed-blurb';
  417. found_on_list = true;
  418. }
  419.  
  420. // if work id is on the seen list
  421. if (kudos_history.seen.hasId(work_id)) {
  422. DEBUG && console.log('- is seen');
  423. blurb_classes += ' marked-seen collapsed-blurb';
  424. found_on_list = true;
  425. }
  426.  
  427. // not on the kudosed/seen list
  428. if (!found_on_list) {
  429.  
  430. // if work id is on the checked list
  431. if (kudos_history.checked.hasId(work_id)) {
  432. DEBUG && console.log('- is checked');
  433. }
  434. else {
  435. blurb_classes += ' new-blurb';
  436. loadKudos(blurb);
  437. }
  438. }
  439.  
  440. // if work id is on the bookmarked list
  441. if (kudos_history.bookmarked.hasId(work_id)) {
  442. DEBUG && console.log('- is bookmarked');
  443. blurb_classes += ' is-bookmarked';
  444. }
  445.  
  446. // if work id is on the skipped list
  447. if (kudos_history.skipped.hasId(work_id)) {
  448. DEBUG && console.log('- is skipped');
  449. blurb_classes += ' skipped-work collapsed-blurb';
  450. }
  451.  
  452. blurb.addClass(blurb_classes);
  453. }
  454.  
  455. // load kudos for blurb
  456. function loadKudos(blurb) {
  457.  
  458. var work_id = blurb.data('work_id');
  459.  
  460. if (!work_id) {
  461. return false;
  462. }
  463.  
  464. DEBUG && console.log('- loading kudos for ' + work_id);
  465.  
  466. // add a div to the blurb that will house the kudos
  467. var kudos_container = $('<div style="display: none;"></div>');
  468. blurb.append(kudos_container);
  469.  
  470. // retrieve a list of kudos from the work
  471. var work_url = window.location.protocol + '//' + window.location.hostname + '/works/' + work_id + '/kudos #kudos';
  472. kudos_container.load(work_url, function () {
  473. // check if there are kudos from the user
  474. var user_kudos = kudos_container.find('[href="/users/' + kudos_history.username + '"]');
  475.  
  476. if (user_kudos.length) {
  477. // highlight blurb and add work id to kudosed list
  478. blurb.addClass('has-kudos collapsed-blurb');
  479. kudos_history.kudosed.add(work_id);
  480. }
  481. else {
  482. // add work id to checked list
  483. kudos_history.checked.add(work_id);
  484. }
  485. });
  486. }
  487.  
  488. // mark all works on the page as seen
  489. function markPageSeen() {
  490.  
  491. kudos_history.seen.reload();
  492.  
  493. // for each blurb
  494. works_and_bookmarks.not('.marked-seen').not('.has-kudos').not('.deleted').each(function () {
  495. changeBlurbStatus($(this), 'seen', false, true);
  496. });
  497.  
  498. kudos_history.seen.save();
  499. }
  500.  
  501. // mark all works on the page as unseen
  502. function markPageUnseen() {
  503.  
  504. kudos_history.seen.reload();
  505.  
  506. // for each blurb
  507. works_and_bookmarks.not('.deleted').each(function () {
  508. changeBlurbStatus($(this), 'seen', false, false);
  509. });
  510.  
  511. kudos_history.seen.save();
  512. }
  513.  
  514. // mark/unmark blurb as X
  515. function changeBlurbStatus(blurb, list, save_list, add_to_list) {
  516.  
  517. var work_id = blurb.data('work_id');
  518.  
  519. if (work_id) {
  520.  
  521. save_list && kudos_history[list].reload();
  522.  
  523. var blurb_class = {
  524. seen: 'marked-seen',
  525. skipped: 'skipped-work'
  526. };
  527.  
  528. if (add_to_list == undefined) {
  529. add_to_list = !kudos_history[list].hasId(work_id);
  530. }
  531.  
  532. if (add_to_list) {
  533. DEBUG && console.log('marking as ' + list + ' ' + work_id);
  534. kudos_history[list].add(work_id);
  535. blurb.addClass(blurb_class[list] + ' collapsed-blurb');
  536. }
  537. else {
  538. DEBUG && console.log('unmarking as ' + list + ' ' + work_id);
  539. kudos_history[list].remove(work_id);
  540. blurb.removeClass(blurb_class[list]);
  541. }
  542.  
  543. save_list && kudos_history[list].save();
  544. }
  545. }
  546.  
  547. // re-check the page for kudos
  548. function recheckKudos() {
  549.  
  550. kudos_history.kudosed.reload();
  551. kudos_history.checked.reload();
  552.  
  553. // for each non-kudosed blurb
  554. works_and_bookmarks.not('.has-kudos').not('.deleted').each(function () {
  555. loadKudos($(this));
  556. });
  557. }
  558.  
  559. // check the page for bookmarks
  560. function checkForBookmarks() {
  561.  
  562. kudos_history.bookmarked.reload();
  563.  
  564. // for each work and bookmark blurb
  565. works_and_bookmarks.not('.deleted').each(function () {
  566.  
  567. var blurb = $(this);
  568. var work_id = blurb.data('work_id');
  569.  
  570. if (!work_id) {
  571. return false;
  572. }
  573.  
  574. DEBUG && console.log('- loading bookmark buttons for ' + work_id);
  575.  
  576. // add a div to the blurb that will house the kudos
  577. var bookmark_container = $('<div style="display: none;"></div>');
  578. blurb.append(bookmark_container);
  579.  
  580. // retrieve the bookmark button from the work
  581. var work_url = window.location.protocol + '//' + window.location.hostname + '/works/' + work_id + ' a.bookmark_form_placement_open:first';
  582. bookmark_container.load(work_url, function () {
  583. // check if there is a bookmark from the user
  584. var bookmark_button_text = bookmark_container.find('a').text();
  585.  
  586. if (bookmark_button_text.indexOf('Edit') > -1) {
  587. // highlight blurb
  588. blurb.addClass('is-bookmarked');
  589. kudos_history.bookmarked.add(work_id);
  590. }
  591. else {
  592. blurb.removeClass('is-bookmarked');
  593. kudos_history.bookmarked.remove(work_id);
  594. }
  595. });
  596. });
  597. }
  598.  
  599. // show the box with import/export options
  600. function importExport() {
  601.  
  602. var importexport_bg = $('<div id="importexport-bg"></div>');
  603.  
  604. var importexport_box = $('<div id="importexport-box"></div>');
  605.  
  606. var box_button_save = $('<input type="button" id="importexport-button-save" value="Import lists" />');
  607. box_button_save.click(function () {
  608.  
  609. var confirmed = confirm('Sure you want to replace your saved lists?');
  610.  
  611. if (confirmed) {
  612. var import_lists = JSON.parse($('#import-seen-list').val());
  613.  
  614. for (var list_name in import_lists) {
  615. if (kudos_history[list_name]) {
  616. kudos_history[list_name].list = import_lists[list_name];
  617. kudos_history[list_name].save();
  618. }
  619. }
  620.  
  621. $('#importexport-save').prepend('Lists imported! ');
  622. }
  623. });
  624.  
  625. var box_button_close = $('<input type="button" id="importexport-button-close" value="Close" />');
  626.  
  627. var export_lists = {
  628. kudosed: kudos_history.kudosed.reload().list,
  629. seen: kudos_history.seen.reload().list,
  630. bookmarked: kudos_history.bookmarked.reload().list,
  631. skipped: kudos_history.skipped.reload().list,
  632. checked: kudos_history.checked.reload().list,
  633. };
  634.  
  635. importexport_box.append(
  636. $('<p class="actions"></p>').append(box_button_close),
  637. $('<h3></h3>').text('Settings'),
  638. );
  639.  
  640. settings_list.forEach(function (setting) {
  641. importexport_box.append(kudos_history[setting.name].getSettingRow());
  642. });
  643.  
  644. importexport_box.append(
  645. $('<h3 style="margin-top: 1.5em;"></h3>').text('Export your saved lists'),
  646. $('<p></p>').text('Copy your current lists (kudosed, seen, bookmarked, skipped) from the field below and save wherever you want as a backup.'),
  647. $('<input type="text" id="export-seen-list" />').val(JSON.stringify(export_lists)),
  648. $('<h3 style="margin-top: 1.5em;"></h3>').text('Import your lists'),
  649. $('<p></p>').html('Put your saved lists in the field below and select the "Import lists" button. <strong>Warning:</strong> it will <u>replace</u> your current lists.'),
  650. $('<input type="text" id="import-seen-list" />'),
  651. $('<p class="actions" id="importexport-save"></p>').append(box_button_save),
  652. );
  653.  
  654. $('body').append(importexport_bg);
  655. main.append(importexport_box);
  656.  
  657. box_button_close.add(importexport_bg).click(function () {
  658. importexport_box.detach();
  659. importexport_bg.detach();
  660. });
  661. }
  662.  
  663. // add the seen/unseen buttons
  664. function addSeenButtons() {
  665.  
  666. seen_buttons = {
  667. is_seen: is_seen,
  668. buttons_links: [],
  669.  
  670. change: function () {
  671. DEBUG && console.log(this);
  672. this.is_seen = !this.is_seen;
  673. kudos_history.seen.reload();
  674.  
  675. if (this.is_seen) {
  676. kudos_history.seen.add(work_id);
  677. work_meta.addClass('marked-seen');
  678. }
  679. else {
  680. kudos_history.seen.remove(work_id);
  681. work_meta.removeClass('marked-seen');
  682. }
  683.  
  684. kudos_history.seen.save();
  685. this.updateButtons();
  686. DEBUG && console.log(this);
  687. },
  688. getButton: function () {
  689. var button_link = $('<a></a>').html(this.is_seen ? 'Unseen &cross;' : 'Seen &check;');
  690. var button = $('<li class="kh-seen-button"></li>').append(button_link);
  691. var this_setting = this;
  692. button.click(function () {
  693. this_setting.change();
  694. });
  695. this.buttons_links.push(button_link);
  696. return button;
  697. },
  698. updateButtons: function () {
  699. for (var i = 0; i < this.buttons_links.length; i++) {
  700. this.buttons_links[i].html(this.is_seen ? 'Unseen &cross;' : 'Seen &check;');
  701. }
  702. },
  703. };
  704.  
  705. $('li.bookmark').after(seen_buttons.getButton());
  706. $('#new_kudo').parent().after(seen_buttons.getButton());
  707. }
  708.  
  709. // attach the menu
  710. function addSeenMenu() {
  711.  
  712. // create a button for the menu
  713. function getMenuButton(button_text, on_click) {
  714. var button = $('<li><a>' + button_text + '</a></li>');
  715. if (on_click) {
  716. button.click(on_click);
  717. button.addClass('kh-menu-setting');
  718. }
  719. else {
  720. button.addClass('kh-menu-header');
  721. }
  722. return button;
  723. }
  724.  
  725. // get the header menu
  726. var header_menu = $('ul.primary.navigation.actions');
  727.  
  728. // create menu button
  729. var seen_menu = $('<li class="dropdown"></li>').html('<a>Seen works</a>');
  730.  
  731. // create dropdown menu
  732. var drop_menu = $('<ul class="menu dropdown-menu"></li>');
  733.  
  734. // append buttons to the dropdown menu
  735. drop_menu.append(
  736. getMenuButton('Settings and import/export', importExport),
  737. getMenuButton('&mdash; For all works on this page: &mdash;'),
  738. getMenuButton('Mark as seen', markPageSeen),
  739. getMenuButton('Unmark as seen', markPageUnseen),
  740. getMenuButton('Re-check for kudos', recheckKudos),
  741. getMenuButton('Check for bookmarks', checkForBookmarks),
  742. getMenuButton('&mdash; Settings (click to change): &mdash;'),
  743. );
  744.  
  745. settings_list.forEach(function (setting) {
  746. drop_menu.append(kudos_history[setting.name].getButton());
  747. });
  748.  
  749. seen_menu.append(drop_menu);
  750. header_menu.find('li.search').before(seen_menu);
  751. }
  752.  
  753. // add a notice about an update
  754. function addNotice() {
  755.  
  756. var last_version = localStorage.getItem('kudoshistory_lastver') || current_version;
  757.  
  758. if (last_version < current_version) {
  759.  
  760. var update_2_2 = "<h3>version 2.2</h3>\
  761. <p><b>&bull; Separate settings for kudosed and seen works.</b> Now you can hide/collapse one but not the other if you want.</p>\
  762. <p><b>&bull; Smaller icons on a collapsed blurb.</b> Saving us some screen space.</p>";
  763.  
  764. var update_notice = $('<div id="kudoshistory-update" class="notice"></div>');
  765.  
  766. update_notice.append("<h3><b>Kudosed and seen history userscript updated!</b></h3>", update_2_2, "<p style='text-align: right;'><b><a id='kudoshistory-hide-update'>Don't show this again</a></b></p>");
  767.  
  768. main.prepend(update_notice);
  769.  
  770. $('#kudoshistory-hide-update').click(function () {
  771. localStorage.setItem('kudoshistory_lastver', current_version);
  772. update_notice.detach();
  773. });
  774. }
  775. }
  776.  
  777. // add css rules to page head
  778. function addCss() {
  779. var css = '.has-kudos.marked-seen,.has-kudos{background:url("https://i.imgur.com/jK7d4jh.png") left no-repeat,url("https://i.imgur.com/ESdBCSX.png") left repeat-y !important;padding-left:50px !important}@media screen and (max-width: 42em){.has-kudos.marked-seen,.has-kudos{background-size:20px !important;padding-left:30px !important}}.marked-seen{background:url("https://i.imgur.com/ESdBCSX.png") left repeat-y !important;padding-left:50px !important}@media screen and (max-width: 42em){.marked-seen{background-size:20px !important;padding-left:30px !important}}.kh-highlight-bookmarked-yes .is-bookmarked,dl.is-bookmarked{background:url("https://i.imgur.com/qol1mWZ.png") right repeat-y !important;padding-right:50px !important}@media screen and (max-width: 42em){.kh-highlight-bookmarked-yes .is-bookmarked,dl.is-bookmarked{background-size:20px !important;padding-right:30px !important}}.kh-highlight-bookmarked-yes .is-bookmarked.has-kudos,dl.is-bookmarked.has-kudos,.kh-highlight-bookmarked-yes .is-bookmarked.has-kudos.marked-seen,dl.is-bookmarked.has-kudos.marked-seen{background:url("https://i.imgur.com/jK7d4jh.png") left no-repeat,url("https://i.imgur.com/ESdBCSX.png") left repeat-y,url("https://i.imgur.com/qol1mWZ.png") right repeat-y !important}@media screen and (max-width: 42em){.kh-highlight-bookmarked-yes .is-bookmarked.has-kudos,dl.is-bookmarked.has-kudos,.kh-highlight-bookmarked-yes .is-bookmarked.has-kudos.marked-seen,dl.is-bookmarked.has-kudos.marked-seen{background-size:20px !important}}.kh-highlight-bookmarked-yes .is-bookmarked.marked-seen,dl.is-bookmarked.marked-seen{background:url("https://i.imgur.com/ESdBCSX.png") left repeat-y,url("https://i.imgur.com/qol1mWZ.png") right repeat-y !important}@media screen and (max-width: 42em){.kh-highlight-bookmarked-yes .is-bookmarked.marked-seen,dl.is-bookmarked.marked-seen{background-size:20px !important}}#kudoshistory-update a,.kh-menu-setting a,.kh-seen-button a{cursor:pointer}.kh-menu-header a{padding:.5em .5em .25em !important;text-align:center;font-weight:bold}#kudoshistory-update{padding:.5em 1em 1em 1em}#kudoshistory-update img{max-width:300px;height:auto}#importexport-box{position:fixed;top:0px;bottom:0px;left:0px;right:0px;width:60%;height:80%;max-width:800px;margin:auto;overflow-y:auto;border:10px solid #eee;box-shadow:0px 0px 8px 0px rgba(0,0,0,.2);padding:0 20px;background-color:#fff;z-index:999}#importexport-box input[type=button]{height:auto;cursor:pointer}#importexport-box p.actions{float:none;text-align:right}#importexport-box .kh-setting-row{line-height:1.6em}#importexport-box .kh-setting-label{display:inline-block;min-width:13.5em}@media screen and (max-width: 42em){#importexport-box .kh-setting-label{display:block;min-width:auto}}#importexport-box .kh-setting-label .kh-setting-info-button{font-size:.8em;cursor:pointer}#importexport-box .kh-setting-option{padding:0 3px;border-radius:4px;border:0;color:#111;background:#eee;cursor:pointer}#importexport-box .kh-setting-option.kh-setting-option-selected{color:#fff;background:#900}#importexport-box .kh-setting-separator:last-child{display:none}#importexport-box .kh-setting-info{position:relative;border:1px solid;padding:1px 5px}#importexport-box .kh-setting-info:before{content:" ";position:absolute;top:-12px;border:6px solid transparent;border-bottom-color:initial}#importexport-bg{position:fixed;width:100%;height:100%;background-color:#000;opacity:.7;z-index:998}.kh-toggles{display:none;position:absolute;top:-22px;font-size:10px;line-height:10px;right:-1px;background:#fff;border:1px solid #ddd;padding:5px}.kh-toggles a{cursor:pointer}.kh-reversi #importexport-box{background-color:#333;border-color:#222}.kh-reversi #importexport-box .kh-setting-option-selected{background:#5998d6}.kh-reversi .kh-toggles{background:#333;border-color:#555}.kh-hide-element{display:none}.kh-highlight-bookmarked-yes .bookmark.is-bookmarked p.status{padding-right:40px}@media screen and (max-width: 42em){.kh-highlight-bookmarked-yes .bookmark.is-bookmarked p.status{padding-right:20px}}.kh-skipped-display-collapse .collapsed-blurb.skipped-work h6.landmark.heading,.kh-seen-display-collapse .collapsed-blurb.marked-seen h6.landmark.heading,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos h6.landmark.heading,.kh-skipped-display-collapse .collapsed-blurb.skipped-work>ul,.kh-seen-display-collapse .collapsed-blurb.marked-seen>ul,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos>ul,.kh-skipped-display-collapse .collapsed-blurb.skipped-work blockquote.userstuff.summary,.kh-seen-display-collapse .collapsed-blurb.marked-seen blockquote.userstuff.summary,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos blockquote.userstuff.summary,.kh-skipped-display-collapse .collapsed-blurb.skipped-work dl.stats,.kh-seen-display-collapse .collapsed-blurb.marked-seen dl.stats,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos dl.stats,.kh-skipped-display-collapse .collapsed-blurb.skipped-work .header .fandoms.heading,.kh-seen-display-collapse .collapsed-blurb.marked-seen .header .fandoms.heading,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos .header .fandoms.heading{display:none !important}.kh-skipped-display-collapse .collapsed-blurb.skipped-work .required-tags,.kh-seen-display-collapse .collapsed-blurb.marked-seen .required-tags,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos .required-tags,.kh-skipped-display-collapse .collapsed-blurb.skipped-work .mystery .icon,.kh-seen-display-collapse .collapsed-blurb.marked-seen .mystery .icon,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos .mystery .icon{opacity:.6;transform:scale(0.4);transform-origin:top left}.kh-skipped-display-collapse .collapsed-blurb.skipped-work .header,.kh-seen-display-collapse .collapsed-blurb.marked-seen .header,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos .header{min-height:22px;cursor:zoom-in}.kh-skipped-display-collapse .collapsed-blurb.skipped-work .header .heading,.kh-seen-display-collapse .collapsed-blurb.marked-seen .header .heading,.kh-kudosed-display-collapse .collapsed-blurb.has-kudos .header .heading{margin-left:32px}.kh-skipped-display-collapse .skipped-work:not(.collapsed-blurb) .header,.kh-seen-display-collapse .marked-seen:not(.collapsed-blurb) .header,.kh-kudosed-display-collapse .has-kudos:not(.collapsed-blurb) .header{cursor:zoom-out}.kh-kudosed-display-hide:not(.bookmarks-show) li.has-kudos{display:none !important}.kh-seen-display-hide:not(.bookmarks-show) li.marked-seen{display:none !important}.kh-skipped-display-hide .skipped-work{display:none}.kh-skipped-display-placeholder .skipped-work>*{display:none}.kh-skipped-display-placeholder .skipped-work:before{content:"Skipped"}.kh-highlight-new-yes li.new-blurb{border-left:5px solid #900}.kh-highlight-new-yes.kh-reversi#main li.new-blurb{border-left-color:#5998d6}.kh-toggles-display-on-hover li.blurb-with-toggles:hover>.kh-toggles{display:block}.kh-toggles-display-show li.blurb-with-toggles{margin-top:31px}.kh-toggles-display-show li.blurb-with-toggles .kh-toggles{display:block}';
  780.  
  781. var style = $('<style type="text/css"></style>').appendTo($('head'));
  782. style.html(css);
  783.  
  784. addMainClass();
  785. }
  786.  
  787. function addMainClass(update) {
  788.  
  789. var classes_to_remove = [];
  790. var classes_to_add = [];
  791.  
  792. settings_list.forEach(function (setting) {
  793. var setting_class_name = setting.name.replace('_', '-');
  794. classes_to_add.push('kh-' + setting_class_name + '-' + kudos_history[setting.name].current.replace(' ', '-'));
  795.  
  796. if (update) {
  797. setting.options.forEach(function (option) {
  798. classes_to_remove.push('kh-' + setting_class_name + '-' + option.replace(' ', '-'));
  799. });
  800. }
  801. });
  802.  
  803. if (update) {
  804. main.removeClass(classes_to_remove.join(' '));
  805. }
  806.  
  807. main.addClass(classes_to_add.join(' '));
  808. }
  809. })(jQuery);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址